mappers.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import { Tools } from 'babylonjs';
  2. import { ViewerConfiguration } from './configuration';
  3. import { kebabToCamel } from '../helper';
  4. export interface IMapper {
  5. map(rawSource: any): ViewerConfiguration;
  6. }
  7. class HTMLMapper implements IMapper {
  8. map(element: HTMLElement): ViewerConfiguration {
  9. let config = {};
  10. for (let attrIdx = 0; attrIdx < element.attributes.length; ++attrIdx) {
  11. let attr = element.attributes.item(attrIdx);
  12. // map "object.property" to the right configuration place.
  13. let split = attr.nodeName.split('.');
  14. split.reduce((currentConfig, key, idx) => {
  15. //convert html-style to json-style
  16. let camelKey = kebabToCamel(key);
  17. if (idx === split.length - 1) {
  18. let val: any = attr.nodeValue; // firefox warns nodeValue is deprecated, but I found no sign of it anywhere.
  19. if (val === "true") {
  20. val = true;
  21. } else if (val === "false") {
  22. val = false;
  23. } else {
  24. var isnum = /^\d+$/.test(val);
  25. if (isnum) {
  26. let number = parseFloat(val);
  27. if (!isNaN(number)) {
  28. val = number;
  29. }
  30. }
  31. }
  32. currentConfig[camelKey] = val;
  33. } else {
  34. currentConfig[camelKey] = currentConfig[camelKey] || {};
  35. }
  36. return currentConfig[camelKey];
  37. }, config);
  38. }
  39. return config;
  40. }
  41. }
  42. class JSONMapper implements IMapper {
  43. map(rawSource: any) {
  44. return JSON.parse(rawSource);
  45. }
  46. }
  47. // TODO - Dom configuration mapper.
  48. class DOMMapper implements IMapper {
  49. map(baseElement: HTMLElement): ViewerConfiguration {
  50. let htmlMapper = new HTMLMapper();
  51. let config = htmlMapper.map(baseElement);
  52. let traverseChildren = function (element: HTMLElement, partConfig) {
  53. let children = element.children;
  54. if (children.length) {
  55. for (let i = 0; i < children.length; ++i) {
  56. let item = <HTMLElement>children.item(i);
  57. let configMapped = htmlMapper.map(item);
  58. let key = kebabToCamel(item.nodeName.toLowerCase());
  59. if (item.attributes.getNamedItem('array') && item.attributes.getNamedItem('array').nodeValue === 'true') {
  60. partConfig[key] = [];
  61. } else {
  62. if (element.attributes.getNamedItem('array') && element.attributes.getNamedItem('array').nodeValue === 'true') {
  63. partConfig.push(configMapped)
  64. } else if (partConfig[key]) {
  65. //exists already! problem... probably an array
  66. element.setAttribute('array', 'true');
  67. let oldItem = partConfig[key];
  68. partConfig = [oldItem, configMapped]
  69. } else {
  70. partConfig[key] = configMapped;
  71. }
  72. }
  73. traverseChildren(item, partConfig[key] || configMapped);
  74. }
  75. }
  76. return partConfig;
  77. }
  78. traverseChildren(baseElement, config);
  79. return config;
  80. }
  81. }
  82. export class MapperManager {
  83. private _mappers: { [key: string]: IMapper };
  84. public static DefaultMapper = 'json';
  85. constructor() {
  86. this._mappers = {
  87. "html": new HTMLMapper(),
  88. "json": new JSONMapper(),
  89. "dom": new DOMMapper()
  90. }
  91. }
  92. public getMapper(type: string) {
  93. if (!this._mappers[type]) {
  94. Tools.Error("No mapper defined for " + type);
  95. }
  96. return this._mappers[type] || this._mappers[MapperManager.DefaultMapper];
  97. }
  98. public registerMapper(type: string, mapper: IMapper) {
  99. this._mappers[type] = mapper;
  100. }
  101. public dispose() {
  102. this._mappers = {};
  103. }
  104. }
  105. export let mapperManager = new MapperManager();