@babylonjs/viewer 5.0.0 → 5.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/configuration/configuration.d.ts +107 -107
- package/configuration/configuration.js +15 -15
- package/configuration/configurationCompatibility.d.ts +8 -8
- package/configuration/configurationCompatibility.js +65 -65
- package/configuration/configurationContainer.d.ts +10 -10
- package/configuration/configurationContainer.js +9 -9
- package/configuration/globals.d.ts +6 -6
- package/configuration/globals.js +17 -17
- package/configuration/index.d.ts +2 -2
- package/configuration/index.js +3 -3
- package/configuration/interfaces/cameraConfiguration.d.ts +31 -31
- package/configuration/interfaces/cameraConfiguration.js +1 -1
- package/configuration/interfaces/colorGradingConfiguration.d.ts +81 -81
- package/configuration/interfaces/colorGradingConfiguration.js +1 -1
- package/configuration/interfaces/defaultRenderingPipelineConfiguration.d.ts +20 -20
- package/configuration/interfaces/defaultRenderingPipelineConfiguration.js +1 -1
- package/configuration/interfaces/environmentMapConfiguration.d.ts +22 -22
- package/configuration/interfaces/environmentMapConfiguration.js +1 -1
- package/configuration/interfaces/groundConfiguration.d.ts +24 -24
- package/configuration/interfaces/groundConfiguration.js +1 -1
- package/configuration/interfaces/imageProcessingConfiguration.d.ts +43 -43
- package/configuration/interfaces/imageProcessingConfiguration.js +1 -1
- package/configuration/interfaces/index.d.ts +15 -15
- package/configuration/interfaces/index.js +15 -15
- package/configuration/interfaces/lightConfiguration.d.ts +60 -60
- package/configuration/interfaces/lightConfiguration.js +1 -1
- package/configuration/interfaces/modelAnimationConfiguration.d.ts +26 -26
- package/configuration/interfaces/modelAnimationConfiguration.js +1 -1
- package/configuration/interfaces/modelConfiguration.d.ts +65 -65
- package/configuration/interfaces/modelConfiguration.js +1 -1
- package/configuration/interfaces/observersConfiguration.d.ts +5 -5
- package/configuration/interfaces/observersConfiguration.js +1 -1
- package/configuration/interfaces/sceneConfiguration.d.ts +48 -48
- package/configuration/interfaces/sceneConfiguration.js +1 -1
- package/configuration/interfaces/sceneOptimizerConfiguration.d.ts +23 -23
- package/configuration/interfaces/sceneOptimizerConfiguration.js +1 -1
- package/configuration/interfaces/skyboxConfiguration.d.ts +21 -21
- package/configuration/interfaces/skyboxConfiguration.js +1 -1
- package/configuration/interfaces/templateConfiguration.d.ts +67 -67
- package/configuration/interfaces/templateConfiguration.js +1 -1
- package/configuration/interfaces/vrConfiguration.d.ts +16 -16
- package/configuration/interfaces/vrConfiguration.js +1 -1
- package/configuration/loader.d.ts +4 -4
- package/configuration/loader.js +16 -16
- package/configuration/mappers.d.ts +42 -42
- package/configuration/mappers.js +190 -190
- package/configuration/renderOnlyLoader.d.ts +33 -33
- package/configuration/renderOnlyLoader.js +161 -161
- package/configuration/types/default.d.ts +6 -6
- package/configuration/types/default.js +120 -120
- package/configuration/types/environmentMap.d.ts +5 -5
- package/configuration/types/environmentMap.js +13 -13
- package/configuration/types/extended.d.ts +6 -6
- package/configuration/types/extended.js +316 -316
- package/configuration/types/index.d.ts +13 -13
- package/configuration/types/index.js +49 -49
- package/configuration/types/minimal.d.ts +6 -6
- package/configuration/types/minimal.js +42 -42
- package/configuration/types/renderOnlyDefault.d.ts +30 -30
- package/configuration/types/renderOnlyDefault.js +30 -30
- package/configuration/types/shadowLight.d.ts +9 -9
- package/configuration/types/shadowLight.js +63 -63
- package/helper/index.d.ts +26 -26
- package/helper/index.js +62 -62
- package/index.d.ts +30 -30
- package/index.js +45 -45
- package/initializer.d.ts +11 -11
- package/initializer.js +34 -34
- package/interfaces.d.ts +5 -5
- package/interfaces.js +1 -1
- package/labs/environmentSerializer.d.ts +126 -126
- package/labs/environmentSerializer.js +190 -190
- package/labs/texture.d.ts +183 -183
- package/labs/texture.js +300 -300
- package/labs/viewerLabs.d.ts +51 -51
- package/labs/viewerLabs.js +133 -133
- package/loader/modelLoader.d.ts +47 -47
- package/loader/modelLoader.js +189 -189
- package/loader/plugins/applyMaterialConfig.d.ts +12 -12
- package/loader/plugins/applyMaterialConfig.js +15 -15
- package/loader/plugins/extendedMaterialLoaderPlugin.d.ts +9 -9
- package/loader/plugins/extendedMaterialLoaderPlugin.js +15 -15
- package/loader/plugins/index.d.ts +18 -18
- package/loader/plugins/index.js +42 -42
- package/loader/plugins/loaderPlugin.d.ts +24 -24
- package/loader/plugins/loaderPlugin.js +1 -1
- package/loader/plugins/msftLodLoaderPlugin.d.ts +12 -12
- package/loader/plugins/msftLodLoaderPlugin.js +20 -20
- package/loader/plugins/telemetryLoaderPlugin.d.ts +12 -12
- package/loader/plugins/telemetryLoaderPlugin.js +35 -35
- package/managers/observablesManager.d.ts +66 -66
- package/managers/observablesManager.js +34 -34
- package/managers/sceneManager.d.ts +243 -243
- package/managers/sceneManager.js +1388 -1388
- package/managers/telemetryManager.d.ts +57 -57
- package/managers/telemetryManager.js +113 -113
- package/model/modelAnimation.d.ts +215 -215
- package/model/modelAnimation.js +232 -232
- package/model/viewerModel.d.ts +228 -228
- package/model/viewerModel.js +669 -669
- package/optimizer/custom/extended.d.ts +11 -11
- package/optimizer/custom/extended.js +98 -98
- package/optimizer/custom/index.d.ts +8 -8
- package/optimizer/custom/index.js +24 -24
- package/package.json +5 -5
- package/renderOnlyIndex.d.ts +11 -11
- package/renderOnlyIndex.js +17 -17
- package/templating/eventManager.d.ts +35 -35
- package/templating/eventManager.js +65 -65
- package/templating/plugins/hdButtonPlugin.d.ts +9 -9
- package/templating/plugins/hdButtonPlugin.js +21 -21
- package/templating/plugins/printButton.d.ts +9 -9
- package/templating/plugins/printButton.js +40 -40
- package/templating/templateManager.d.ts +190 -190
- package/templating/templateManager.js +553 -553
- package/templating/viewerTemplatePlugin.d.ts +21 -21
- package/templating/viewerTemplatePlugin.js +68 -68
- package/viewer/defaultViewer.d.ts +122 -122
- package/viewer/defaultViewer.js +665 -665
- package/viewer/renderOnlyViewer.d.ts +8 -8
- package/viewer/renderOnlyViewer.js +43 -43
- package/viewer/viewer.d.ts +254 -254
- package/viewer/viewer.js +777 -777
- package/viewer/viewerManager.d.ts +55 -55
- package/viewer/viewerManager.js +87 -87
- package/viewer/viewerWithTemplate.d.ts +9 -9
- package/viewer/viewerWithTemplate.js +19 -19
|
@@ -1,554 +1,554 @@
|
|
|
1
|
-
import { Observable } from "@babylonjs/core/Misc/observable.js";
|
|
2
|
-
import { Tools } from "@babylonjs/core/Misc/tools.js";
|
|
3
|
-
// eslint-disable-next-line import/no-internal-modules
|
|
4
|
-
import { isUrl, camelToKebab, kebabToCamel, deepmerge } from "../helper/index.js";
|
|
5
|
-
import * as Handlebars from "handlebars";
|
|
6
|
-
import { EventManager } from "./eventManager.js";
|
|
7
|
-
/**
|
|
8
|
-
* The template manager, a member of the viewer class, will manage the viewer's templates and generate the HTML.
|
|
9
|
-
* The template manager managers a single viewer and can be seen as the collection of all sub-templates of the viewer.
|
|
10
|
-
*/
|
|
11
|
-
var TemplateManager = /** @class */ (function () {
|
|
12
|
-
function TemplateManager(containerElement) {
|
|
13
|
-
this.containerElement = containerElement;
|
|
14
|
-
this._templates = {};
|
|
15
|
-
this.onTemplateInit = new Observable();
|
|
16
|
-
this.onTemplateLoaded = new Observable();
|
|
17
|
-
this.onTemplateStateChange = new Observable();
|
|
18
|
-
this.onAllLoaded = new Observable();
|
|
19
|
-
this.onEventTriggered = new Observable();
|
|
20
|
-
this.eventManager = new EventManager(this);
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Initialize the template(s) for the viewer. Called bay the Viewer class
|
|
24
|
-
* @param templates the templates to be used to initialize the main template
|
|
25
|
-
*/
|
|
26
|
-
TemplateManager.prototype.initTemplate = function (templates) {
|
|
27
|
-
var _this = this;
|
|
28
|
-
var internalInit = function (dependencyMap, name, parentTemplate) {
|
|
29
|
-
//init template
|
|
30
|
-
var template = _this._templates[name];
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
32
|
-
Object.keys(dependencyMap).map(function (childName) {
|
|
33
|
-
return internalInit(dependencyMap[childName], childName, template);
|
|
34
|
-
});
|
|
35
|
-
// register the observers
|
|
36
|
-
//template.onLoaded.add(() => {
|
|
37
|
-
var addToParent = function () {
|
|
38
|
-
var lastElements = parentTemplate && parentTemplate.parent.querySelectorAll(camelToKebab(name));
|
|
39
|
-
var containingElement = (lastElements && lastElements.length && lastElements.item(lastElements.length - 1)) || _this.containerElement;
|
|
40
|
-
template.appendTo(containingElement);
|
|
41
|
-
_this._checkLoadedState();
|
|
42
|
-
};
|
|
43
|
-
if (parentTemplate && !parentTemplate.parent) {
|
|
44
|
-
parentTemplate.onAppended.add(function () {
|
|
45
|
-
addToParent();
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
addToParent();
|
|
50
|
-
}
|
|
51
|
-
//});
|
|
52
|
-
return template;
|
|
53
|
-
};
|
|
54
|
-
//build the html tree
|
|
55
|
-
return this._buildHTMLTree(templates).then(function (htmlTree) {
|
|
56
|
-
if (_this._templates["main"]) {
|
|
57
|
-
internalInit(htmlTree, "main");
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
_this._checkLoadedState();
|
|
61
|
-
}
|
|
62
|
-
return;
|
|
63
|
-
});
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
*
|
|
67
|
-
* This function will create a simple map with child-dependencies of the template html tree.
|
|
68
|
-
* It will compile each template, check if its children exist in the configuration and will add them if they do.
|
|
69
|
-
* It is expected that the main template will be called main!
|
|
70
|
-
*
|
|
71
|
-
* @param templates
|
|
72
|
-
*/
|
|
73
|
-
TemplateManager.prototype._buildHTMLTree = function (templates) {
|
|
74
|
-
var _this = this;
|
|
75
|
-
var promises = Object.keys(templates).map(function (name) {
|
|
76
|
-
// if the template was overridden
|
|
77
|
-
if (!templates[name]) {
|
|
78
|
-
return Promise.resolve(false);
|
|
79
|
-
}
|
|
80
|
-
// else - we have a template, let's do our job!
|
|
81
|
-
var template = new Template(name, templates[name]);
|
|
82
|
-
template.onLoaded.add(function () {
|
|
83
|
-
_this.onTemplateLoaded.notifyObservers(template);
|
|
84
|
-
});
|
|
85
|
-
template.onStateChange.add(function () {
|
|
86
|
-
_this.onTemplateStateChange.notifyObservers(template);
|
|
87
|
-
});
|
|
88
|
-
_this.onTemplateInit.notifyObservers(template);
|
|
89
|
-
// make sure the global onEventTriggered is called as well
|
|
90
|
-
template.onEventTriggered.add(function (eventData) { return _this.onEventTriggered.notifyObservers(eventData); });
|
|
91
|
-
_this._templates[name] = template;
|
|
92
|
-
return template.initPromise;
|
|
93
|
-
});
|
|
94
|
-
return Promise.all(promises).then(function () {
|
|
95
|
-
var templateStructure = {};
|
|
96
|
-
// now iterate through all templates and check for children:
|
|
97
|
-
var buildTree = function (parentObject, name) {
|
|
98
|
-
_this._templates[name].isInHtmlTree = true;
|
|
99
|
-
var childNodes = _this._templates[name].getChildElements().filter(function (n) { return !!_this._templates[n]; });
|
|
100
|
-
childNodes.forEach(function (element) {
|
|
101
|
-
parentObject[element] = {};
|
|
102
|
-
buildTree(parentObject[element], element);
|
|
103
|
-
});
|
|
104
|
-
};
|
|
105
|
-
if (_this._templates["main"]) {
|
|
106
|
-
buildTree(templateStructure, "main");
|
|
107
|
-
}
|
|
108
|
-
return templateStructure;
|
|
109
|
-
});
|
|
110
|
-
};
|
|
111
|
-
/**
|
|
112
|
-
* Get the canvas in the template tree.
|
|
113
|
-
* There must be one and only one canvas inthe template.
|
|
114
|
-
*/
|
|
115
|
-
TemplateManager.prototype.getCanvas = function () {
|
|
116
|
-
return this.containerElement.querySelector("canvas");
|
|
117
|
-
};
|
|
118
|
-
/**
|
|
119
|
-
* Get a specific template from the template tree
|
|
120
|
-
* @param name the name of the template to load
|
|
121
|
-
*/
|
|
122
|
-
TemplateManager.prototype.getTemplate = function (name) {
|
|
123
|
-
return this._templates[name];
|
|
124
|
-
};
|
|
125
|
-
TemplateManager.prototype._checkLoadedState = function () {
|
|
126
|
-
var _this = this;
|
|
127
|
-
var done = Object.keys(this._templates).length === 0 ||
|
|
128
|
-
Object.keys(this._templates).every(function (key) {
|
|
129
|
-
return (_this._templates[key].isLoaded && !!_this._templates[key].parent) || !_this._templates[key].isInHtmlTree;
|
|
130
|
-
});
|
|
131
|
-
if (done) {
|
|
132
|
-
this.onAllLoaded.notifyObservers(this);
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
/**
|
|
136
|
-
* Dispose the template manager
|
|
137
|
-
*/
|
|
138
|
-
TemplateManager.prototype.dispose = function () {
|
|
139
|
-
var _this = this;
|
|
140
|
-
// dispose all templates
|
|
141
|
-
Object.keys(this._templates).forEach(function (template) {
|
|
142
|
-
_this._templates[template].dispose();
|
|
143
|
-
});
|
|
144
|
-
this._templates = {};
|
|
145
|
-
this.eventManager.dispose();
|
|
146
|
-
this.onTemplateInit.clear();
|
|
147
|
-
this.onAllLoaded.clear();
|
|
148
|
-
this.onEventTriggered.clear();
|
|
149
|
-
this.onTemplateLoaded.clear();
|
|
150
|
-
this.onTemplateStateChange.clear();
|
|
151
|
-
};
|
|
152
|
-
return TemplateManager;
|
|
153
|
-
}());
|
|
154
|
-
export { TemplateManager };
|
|
155
|
-
// register a new helper. modified https://stackoverflow.com/questions/9838925/is-there-any-method-to-iterate-a-map-with-handlebars-js
|
|
156
|
-
Handlebars.registerHelper("eachInMap", function (map, block) {
|
|
157
|
-
var out = "";
|
|
158
|
-
Object.keys(map).map(function (prop) {
|
|
159
|
-
var data = map[prop];
|
|
160
|
-
if (typeof data === "object") {
|
|
161
|
-
data.id = data.id || prop;
|
|
162
|
-
out += block.fn(data);
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
out += block.fn({ id: prop, value: data });
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
return out;
|
|
169
|
-
});
|
|
170
|
-
Handlebars.registerHelper("add", function (a, b) {
|
|
171
|
-
var out = a + b;
|
|
172
|
-
return out;
|
|
173
|
-
});
|
|
174
|
-
Handlebars.registerHelper("eq", function (a, b) {
|
|
175
|
-
var out = a == b;
|
|
176
|
-
return out;
|
|
177
|
-
});
|
|
178
|
-
Handlebars.registerHelper("or", function (a, b) {
|
|
179
|
-
var out = a || b;
|
|
180
|
-
return out;
|
|
181
|
-
});
|
|
182
|
-
Handlebars.registerHelper("not", function (a) {
|
|
183
|
-
var out = !a;
|
|
184
|
-
return out;
|
|
185
|
-
});
|
|
186
|
-
Handlebars.registerHelper("count", function (map) {
|
|
187
|
-
return map.length;
|
|
188
|
-
});
|
|
189
|
-
Handlebars.registerHelper("gt", function (a, b) {
|
|
190
|
-
var out = a > b;
|
|
191
|
-
return out;
|
|
192
|
-
});
|
|
193
|
-
/**
|
|
194
|
-
* This class represents a single template in the viewer's template tree.
|
|
195
|
-
* An example for a template is a single canvas, an overlay (containing sub-templates) or the navigation bar.
|
|
196
|
-
* A template is injected using the template manager in the correct position.
|
|
197
|
-
* The template is rendered using Handlebars and can use Handlebars' features (such as parameter injection)
|
|
198
|
-
*
|
|
199
|
-
* For further information please refer to the documentation page, https://doc.babylonjs.com
|
|
200
|
-
*/
|
|
201
|
-
var Template = /** @class */ (function () {
|
|
202
|
-
function Template(name, _configuration) {
|
|
203
|
-
var _this = this;
|
|
204
|
-
this.name = name;
|
|
205
|
-
this._configuration = _configuration;
|
|
206
|
-
this.onLoaded = new Observable();
|
|
207
|
-
this.onAppended = new Observable();
|
|
208
|
-
this.onStateChange = new Observable();
|
|
209
|
-
this.onEventTriggered = new Observable();
|
|
210
|
-
this.onParamsUpdated = new Observable();
|
|
211
|
-
this.onHTMLRendered = new Observable();
|
|
212
|
-
this._loadRequests = [];
|
|
213
|
-
this.isLoaded = false;
|
|
214
|
-
this.isShown = false;
|
|
215
|
-
this.isInHtmlTree = false;
|
|
216
|
-
var htmlContentPromise = this._getTemplateAsHtml(_configuration);
|
|
217
|
-
this.initPromise = htmlContentPromise.then(function (htmlTemplate) {
|
|
218
|
-
if (htmlTemplate) {
|
|
219
|
-
_this._htmlTemplate = htmlTemplate;
|
|
220
|
-
var compiledTemplate = Handlebars.compile(htmlTemplate, { noEscape: _this._configuration.params && !!_this._configuration.params.noEscape });
|
|
221
|
-
var config = _this._configuration.params || {};
|
|
222
|
-
_this._rawHtml = compiledTemplate(config);
|
|
223
|
-
try {
|
|
224
|
-
_this._fragment = document.createRange().createContextualFragment(_this._rawHtml);
|
|
225
|
-
}
|
|
226
|
-
catch (e) {
|
|
227
|
-
var test_1 = document.createElement(_this.name);
|
|
228
|
-
test_1.innerHTML = _this._rawHtml;
|
|
229
|
-
_this._fragment = test_1;
|
|
230
|
-
}
|
|
231
|
-
_this.isLoaded = true;
|
|
232
|
-
_this.isShown = true;
|
|
233
|
-
_this.onLoaded.notifyObservers(_this);
|
|
234
|
-
}
|
|
235
|
-
return _this;
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Some templates have parameters (like background color for example).
|
|
240
|
-
* The parameters are provided to Handlebars which in turn generates the template.
|
|
241
|
-
* This function will update the template with the new parameters
|
|
242
|
-
*
|
|
243
|
-
* Note that when updating parameters the events will be registered again (after being cleared).
|
|
244
|
-
*
|
|
245
|
-
* @param params the new template parameters
|
|
246
|
-
* @param append
|
|
247
|
-
*/
|
|
248
|
-
Template.prototype.updateParams = function (params, append) {
|
|
249
|
-
if (append === void 0) { append = true; }
|
|
250
|
-
if (append) {
|
|
251
|
-
this._configuration.params = deepmerge(this._configuration.params, params);
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
254
|
-
this._configuration.params = params;
|
|
255
|
-
}
|
|
256
|
-
// update the template
|
|
257
|
-
if (this.isLoaded) {
|
|
258
|
-
// this.dispose();
|
|
259
|
-
}
|
|
260
|
-
var compiledTemplate = Handlebars.compile(this._htmlTemplate);
|
|
261
|
-
var config = this._configuration.params || {};
|
|
262
|
-
this._rawHtml = compiledTemplate(config);
|
|
263
|
-
try {
|
|
264
|
-
this._fragment = document.createRange().createContextualFragment(this._rawHtml);
|
|
265
|
-
}
|
|
266
|
-
catch (e) {
|
|
267
|
-
var test_2 = document.createElement(this.name);
|
|
268
|
-
test_2.innerHTML = this._rawHtml;
|
|
269
|
-
this._fragment = test_2;
|
|
270
|
-
}
|
|
271
|
-
if (this.parent) {
|
|
272
|
-
this.appendTo(this.parent, true);
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
Template.prototype.redraw = function () {
|
|
276
|
-
this.updateParams({});
|
|
277
|
-
};
|
|
278
|
-
Object.defineProperty(Template.prototype, "configuration", {
|
|
279
|
-
/**
|
|
280
|
-
* Get the template'S configuration
|
|
281
|
-
*/
|
|
282
|
-
get: function () {
|
|
283
|
-
return this._configuration;
|
|
284
|
-
},
|
|
285
|
-
enumerable: false,
|
|
286
|
-
configurable: true
|
|
287
|
-
});
|
|
288
|
-
/**
|
|
289
|
-
* A template can be a parent element for other templates or HTML elements.
|
|
290
|
-
* This function will deliver all child HTML elements of this template.
|
|
291
|
-
*/
|
|
292
|
-
Template.prototype.getChildElements = function () {
|
|
293
|
-
var childrenArray = [];
|
|
294
|
-
//Edge and IE don't support frage,ent.children
|
|
295
|
-
var children = this._fragment && this._fragment.children;
|
|
296
|
-
if (!this._fragment) {
|
|
297
|
-
var fragment = this.parent.querySelector(this.name);
|
|
298
|
-
if (fragment) {
|
|
299
|
-
children = fragment.querySelectorAll("*");
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
if (!children) {
|
|
303
|
-
// casting to HTMLCollection, as both NodeListOf and HTMLCollection have 'item()' and 'length'.
|
|
304
|
-
children = this._fragment.querySelectorAll("*");
|
|
305
|
-
}
|
|
306
|
-
for (var i = 0; i < children.length; ++i) {
|
|
307
|
-
var child = children.item(i);
|
|
308
|
-
if (child) {
|
|
309
|
-
childrenArray.push(kebabToCamel(child.nodeName.toLowerCase()));
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
return childrenArray;
|
|
313
|
-
};
|
|
314
|
-
/**
|
|
315
|
-
* Appending the template to a parent HTML element.
|
|
316
|
-
* If a parent is already set and you wish to replace the old HTML with new one, forceRemove should be true.
|
|
317
|
-
* @param parent the parent to which the template is added
|
|
318
|
-
* @param forceRemove if the parent already exists, shoud the template be removed from it?
|
|
319
|
-
*/
|
|
320
|
-
Template.prototype.appendTo = function (parent, forceRemove) {
|
|
321
|
-
var _this = this;
|
|
322
|
-
if (this.parent) {
|
|
323
|
-
if (forceRemove && this._addedFragment) {
|
|
324
|
-
/*let fragement = this.parent.querySelector(this.name)
|
|
325
|
-
if (fragement)
|
|
326
|
-
this.parent.removeChild(fragement);*/
|
|
327
|
-
this.parent.innerHTML = "";
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
this.parent = parent;
|
|
334
|
-
if (this._configuration.id) {
|
|
335
|
-
this.parent.id = this._configuration.id;
|
|
336
|
-
}
|
|
337
|
-
if (this._fragment) {
|
|
338
|
-
this.parent.appendChild(this._fragment);
|
|
339
|
-
this._addedFragment = this._fragment;
|
|
340
|
-
}
|
|
341
|
-
else {
|
|
342
|
-
this.parent.insertAdjacentHTML("beforeend", this._rawHtml);
|
|
343
|
-
}
|
|
344
|
-
this.onHTMLRendered.notifyObservers(this);
|
|
345
|
-
// appended only one frame after.
|
|
346
|
-
setTimeout(function () {
|
|
347
|
-
_this._registerEvents();
|
|
348
|
-
_this.onAppended.notifyObservers(_this);
|
|
349
|
-
});
|
|
350
|
-
};
|
|
351
|
-
/**
|
|
352
|
-
* Show the template using the provided visibilityFunction, or natively using display: flex.
|
|
353
|
-
* The provided function returns a promise that should be fulfilled when the element is shown.
|
|
354
|
-
* Since it is a promise async operations are more than possible.
|
|
355
|
-
* See the default viewer for an opacity example.
|
|
356
|
-
* @param visibilityFunction The function to execute to show the template.
|
|
357
|
-
*/
|
|
358
|
-
Template.prototype.show = function (visibilityFunction) {
|
|
359
|
-
var _this = this;
|
|
360
|
-
if (this._isHiding) {
|
|
361
|
-
return Promise.resolve(this);
|
|
362
|
-
}
|
|
363
|
-
return Promise.resolve()
|
|
364
|
-
.then(function () {
|
|
365
|
-
_this._isShowing = true;
|
|
366
|
-
if (visibilityFunction) {
|
|
367
|
-
return visibilityFunction(_this);
|
|
368
|
-
}
|
|
369
|
-
else {
|
|
370
|
-
// flex? box? should this be configurable easier than the visibilityFunction?
|
|
371
|
-
_this.parent.style.display = "flex";
|
|
372
|
-
// support old browsers with no flex:
|
|
373
|
-
if (_this.parent.style.display !== "flex") {
|
|
374
|
-
_this.parent.style.display = "";
|
|
375
|
-
}
|
|
376
|
-
return _this;
|
|
377
|
-
}
|
|
378
|
-
})
|
|
379
|
-
.then(function () {
|
|
380
|
-
_this.isShown = true;
|
|
381
|
-
_this._isShowing = false;
|
|
382
|
-
_this.onStateChange.notifyObservers(_this);
|
|
383
|
-
return _this;
|
|
384
|
-
});
|
|
385
|
-
};
|
|
386
|
-
/**
|
|
387
|
-
* Hide the template using the provided visibilityFunction, or natively using display: none.
|
|
388
|
-
* The provided function returns a promise that should be fulfilled when the element is hidden.
|
|
389
|
-
* Since it is a promise async operations are more than possible.
|
|
390
|
-
* See the default viewer for an opacity example.
|
|
391
|
-
* @param visibilityFunction The function to execute to show the template.
|
|
392
|
-
*/
|
|
393
|
-
Template.prototype.hide = function (visibilityFunction) {
|
|
394
|
-
var _this = this;
|
|
395
|
-
if (this._isShowing) {
|
|
396
|
-
return Promise.resolve(this);
|
|
397
|
-
}
|
|
398
|
-
return Promise.resolve()
|
|
399
|
-
.then(function () {
|
|
400
|
-
_this._isHiding = true;
|
|
401
|
-
if (visibilityFunction) {
|
|
402
|
-
return visibilityFunction(_this);
|
|
403
|
-
}
|
|
404
|
-
else {
|
|
405
|
-
// flex? box? should this be configurable easier than the visibilityFunction?
|
|
406
|
-
_this.parent.style.display = "none";
|
|
407
|
-
return _this;
|
|
408
|
-
}
|
|
409
|
-
})
|
|
410
|
-
.then(function () {
|
|
411
|
-
_this.isShown = false;
|
|
412
|
-
_this._isHiding = false;
|
|
413
|
-
_this.onStateChange.notifyObservers(_this);
|
|
414
|
-
return _this;
|
|
415
|
-
});
|
|
416
|
-
};
|
|
417
|
-
/**
|
|
418
|
-
* Dispose this template
|
|
419
|
-
*/
|
|
420
|
-
Template.prototype.dispose = function () {
|
|
421
|
-
this.onAppended.clear();
|
|
422
|
-
this.onEventTriggered.clear();
|
|
423
|
-
this.onLoaded.clear();
|
|
424
|
-
this.onStateChange.clear();
|
|
425
|
-
this.isLoaded = false;
|
|
426
|
-
// remove from parent
|
|
427
|
-
try {
|
|
428
|
-
this.parent.removeChild(this._fragment);
|
|
429
|
-
}
|
|
430
|
-
catch (e) {
|
|
431
|
-
//noop
|
|
432
|
-
}
|
|
433
|
-
this._loadRequests.forEach(function (request) {
|
|
434
|
-
request.abort();
|
|
435
|
-
});
|
|
436
|
-
if (this._registeredEvents) {
|
|
437
|
-
this._registeredEvents.forEach(function (evt) {
|
|
438
|
-
evt.htmlElement.removeEventListener(evt.eventName, evt.function);
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
};
|
|
442
|
-
Template.prototype._getTemplateAsHtml = function (templateConfig) {
|
|
443
|
-
var _this = this;
|
|
444
|
-
if (!templateConfig) {
|
|
445
|
-
return Promise.reject("No templateConfig provided");
|
|
446
|
-
}
|
|
447
|
-
else if (templateConfig.html && !templateConfig.location) {
|
|
448
|
-
return Promise.resolve(templateConfig.html);
|
|
449
|
-
}
|
|
450
|
-
else {
|
|
451
|
-
var location_1 = this._getTemplateLocation(templateConfig);
|
|
452
|
-
if (isUrl(location_1)) {
|
|
453
|
-
return new Promise(function (resolve, reject) {
|
|
454
|
-
var fileRequest = Tools.LoadFile(location_1, function (data) {
|
|
455
|
-
resolve(data);
|
|
456
|
-
}, undefined, undefined, false, function (request, error) {
|
|
457
|
-
reject(error);
|
|
458
|
-
});
|
|
459
|
-
_this._loadRequests.push(fileRequest);
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
else {
|
|
463
|
-
location_1 = location_1.replace("#", "");
|
|
464
|
-
var element = document.getElementById(location_1);
|
|
465
|
-
if (element) {
|
|
466
|
-
return Promise.resolve(element.innerHTML);
|
|
467
|
-
}
|
|
468
|
-
else {
|
|
469
|
-
return Promise.reject("Template ID not found");
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
};
|
|
474
|
-
Template.prototype._registerEvents = function () {
|
|
475
|
-
var _this = this;
|
|
476
|
-
this._registeredEvents = this._registeredEvents || [];
|
|
477
|
-
if (this._registeredEvents.length) {
|
|
478
|
-
// first remove the registered events
|
|
479
|
-
this._registeredEvents.forEach(function (evt) {
|
|
480
|
-
evt.htmlElement.removeEventListener(evt.eventName, evt.function);
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
if (this._configuration.events) {
|
|
484
|
-
var _loop_1 = function (eventName) {
|
|
485
|
-
if (this_1._configuration.events && this_1._configuration.events[eventName]) {
|
|
486
|
-
var functionToFire_1 = function (selector, event) {
|
|
487
|
-
_this.onEventTriggered.notifyObservers({ event: event, template: _this, selector: selector });
|
|
488
|
-
};
|
|
489
|
-
// if boolean, set the parent as the event listener
|
|
490
|
-
if (typeof this_1._configuration.events[eventName] === "boolean") {
|
|
491
|
-
var selector = this_1.parent.id;
|
|
492
|
-
if (selector) {
|
|
493
|
-
selector = "#" + selector;
|
|
494
|
-
}
|
|
495
|
-
else {
|
|
496
|
-
selector = this_1.parent.tagName;
|
|
497
|
-
}
|
|
498
|
-
var binding = functionToFire_1.bind(this_1, selector);
|
|
499
|
-
this_1.parent.addEventListener(eventName, binding, false);
|
|
500
|
-
this_1._registeredEvents.push({
|
|
501
|
-
htmlElement: this_1.parent,
|
|
502
|
-
eventName: eventName,
|
|
503
|
-
function: binding,
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
else if (typeof this_1._configuration.events[eventName] === "object") {
|
|
507
|
-
var selectorsArray = Object.keys(this_1._configuration.events[eventName] || {});
|
|
508
|
-
// strict null check is working incorrectly, must override:
|
|
509
|
-
var event_1 = this_1._configuration.events[eventName] || {};
|
|
510
|
-
selectorsArray
|
|
511
|
-
.filter(function (selector) { return typeof event_1 !== "boolean" && event_1[selector]; })
|
|
512
|
-
.forEach(function (selector) {
|
|
513
|
-
var htmlElement = _this.parent.querySelector(selector);
|
|
514
|
-
if (!htmlElement) {
|
|
515
|
-
// backcompat, fallback to id
|
|
516
|
-
if (selector && selector.indexOf("#") !== 0) {
|
|
517
|
-
selector = "#" + selector;
|
|
518
|
-
}
|
|
519
|
-
try {
|
|
520
|
-
htmlElement = _this.parent.querySelector(selector);
|
|
521
|
-
}
|
|
522
|
-
catch (e) { }
|
|
523
|
-
}
|
|
524
|
-
if (htmlElement) {
|
|
525
|
-
var binding = functionToFire_1.bind(_this, selector);
|
|
526
|
-
htmlElement.addEventListener(eventName, binding, false);
|
|
527
|
-
_this._registeredEvents.push({
|
|
528
|
-
htmlElement: htmlElement,
|
|
529
|
-
eventName: eventName,
|
|
530
|
-
function: binding,
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
};
|
|
537
|
-
var this_1 = this;
|
|
538
|
-
for (var eventName in this._configuration.events) {
|
|
539
|
-
_loop_1(eventName);
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
};
|
|
543
|
-
Template.prototype._getTemplateLocation = function (templateConfig) {
|
|
544
|
-
if (!templateConfig || typeof templateConfig === "string") {
|
|
545
|
-
return templateConfig;
|
|
546
|
-
}
|
|
547
|
-
else {
|
|
548
|
-
return templateConfig.location;
|
|
549
|
-
}
|
|
550
|
-
};
|
|
551
|
-
return Template;
|
|
552
|
-
}());
|
|
553
|
-
export { Template };
|
|
1
|
+
import { Observable } from "@babylonjs/core/Misc/observable.js";
|
|
2
|
+
import { Tools } from "@babylonjs/core/Misc/tools.js";
|
|
3
|
+
// eslint-disable-next-line import/no-internal-modules
|
|
4
|
+
import { isUrl, camelToKebab, kebabToCamel, deepmerge } from "../helper/index.js";
|
|
5
|
+
import * as Handlebars from "handlebars";
|
|
6
|
+
import { EventManager } from "./eventManager.js";
|
|
7
|
+
/**
|
|
8
|
+
* The template manager, a member of the viewer class, will manage the viewer's templates and generate the HTML.
|
|
9
|
+
* The template manager managers a single viewer and can be seen as the collection of all sub-templates of the viewer.
|
|
10
|
+
*/
|
|
11
|
+
var TemplateManager = /** @class */ (function () {
|
|
12
|
+
function TemplateManager(containerElement) {
|
|
13
|
+
this.containerElement = containerElement;
|
|
14
|
+
this._templates = {};
|
|
15
|
+
this.onTemplateInit = new Observable();
|
|
16
|
+
this.onTemplateLoaded = new Observable();
|
|
17
|
+
this.onTemplateStateChange = new Observable();
|
|
18
|
+
this.onAllLoaded = new Observable();
|
|
19
|
+
this.onEventTriggered = new Observable();
|
|
20
|
+
this.eventManager = new EventManager(this);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Initialize the template(s) for the viewer. Called bay the Viewer class
|
|
24
|
+
* @param templates the templates to be used to initialize the main template
|
|
25
|
+
*/
|
|
26
|
+
TemplateManager.prototype.initTemplate = function (templates) {
|
|
27
|
+
var _this = this;
|
|
28
|
+
var internalInit = function (dependencyMap, name, parentTemplate) {
|
|
29
|
+
//init template
|
|
30
|
+
var template = _this._templates[name];
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
32
|
+
Object.keys(dependencyMap).map(function (childName) {
|
|
33
|
+
return internalInit(dependencyMap[childName], childName, template);
|
|
34
|
+
});
|
|
35
|
+
// register the observers
|
|
36
|
+
//template.onLoaded.add(() => {
|
|
37
|
+
var addToParent = function () {
|
|
38
|
+
var lastElements = parentTemplate && parentTemplate.parent.querySelectorAll(camelToKebab(name));
|
|
39
|
+
var containingElement = (lastElements && lastElements.length && lastElements.item(lastElements.length - 1)) || _this.containerElement;
|
|
40
|
+
template.appendTo(containingElement);
|
|
41
|
+
_this._checkLoadedState();
|
|
42
|
+
};
|
|
43
|
+
if (parentTemplate && !parentTemplate.parent) {
|
|
44
|
+
parentTemplate.onAppended.add(function () {
|
|
45
|
+
addToParent();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
addToParent();
|
|
50
|
+
}
|
|
51
|
+
//});
|
|
52
|
+
return template;
|
|
53
|
+
};
|
|
54
|
+
//build the html tree
|
|
55
|
+
return this._buildHTMLTree(templates).then(function (htmlTree) {
|
|
56
|
+
if (_this._templates["main"]) {
|
|
57
|
+
internalInit(htmlTree, "main");
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
_this._checkLoadedState();
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* This function will create a simple map with child-dependencies of the template html tree.
|
|
68
|
+
* It will compile each template, check if its children exist in the configuration and will add them if they do.
|
|
69
|
+
* It is expected that the main template will be called main!
|
|
70
|
+
*
|
|
71
|
+
* @param templates
|
|
72
|
+
*/
|
|
73
|
+
TemplateManager.prototype._buildHTMLTree = function (templates) {
|
|
74
|
+
var _this = this;
|
|
75
|
+
var promises = Object.keys(templates).map(function (name) {
|
|
76
|
+
// if the template was overridden
|
|
77
|
+
if (!templates[name]) {
|
|
78
|
+
return Promise.resolve(false);
|
|
79
|
+
}
|
|
80
|
+
// else - we have a template, let's do our job!
|
|
81
|
+
var template = new Template(name, templates[name]);
|
|
82
|
+
template.onLoaded.add(function () {
|
|
83
|
+
_this.onTemplateLoaded.notifyObservers(template);
|
|
84
|
+
});
|
|
85
|
+
template.onStateChange.add(function () {
|
|
86
|
+
_this.onTemplateStateChange.notifyObservers(template);
|
|
87
|
+
});
|
|
88
|
+
_this.onTemplateInit.notifyObservers(template);
|
|
89
|
+
// make sure the global onEventTriggered is called as well
|
|
90
|
+
template.onEventTriggered.add(function (eventData) { return _this.onEventTriggered.notifyObservers(eventData); });
|
|
91
|
+
_this._templates[name] = template;
|
|
92
|
+
return template.initPromise;
|
|
93
|
+
});
|
|
94
|
+
return Promise.all(promises).then(function () {
|
|
95
|
+
var templateStructure = {};
|
|
96
|
+
// now iterate through all templates and check for children:
|
|
97
|
+
var buildTree = function (parentObject, name) {
|
|
98
|
+
_this._templates[name].isInHtmlTree = true;
|
|
99
|
+
var childNodes = _this._templates[name].getChildElements().filter(function (n) { return !!_this._templates[n]; });
|
|
100
|
+
childNodes.forEach(function (element) {
|
|
101
|
+
parentObject[element] = {};
|
|
102
|
+
buildTree(parentObject[element], element);
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
if (_this._templates["main"]) {
|
|
106
|
+
buildTree(templateStructure, "main");
|
|
107
|
+
}
|
|
108
|
+
return templateStructure;
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Get the canvas in the template tree.
|
|
113
|
+
* There must be one and only one canvas inthe template.
|
|
114
|
+
*/
|
|
115
|
+
TemplateManager.prototype.getCanvas = function () {
|
|
116
|
+
return this.containerElement.querySelector("canvas");
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Get a specific template from the template tree
|
|
120
|
+
* @param name the name of the template to load
|
|
121
|
+
*/
|
|
122
|
+
TemplateManager.prototype.getTemplate = function (name) {
|
|
123
|
+
return this._templates[name];
|
|
124
|
+
};
|
|
125
|
+
TemplateManager.prototype._checkLoadedState = function () {
|
|
126
|
+
var _this = this;
|
|
127
|
+
var done = Object.keys(this._templates).length === 0 ||
|
|
128
|
+
Object.keys(this._templates).every(function (key) {
|
|
129
|
+
return (_this._templates[key].isLoaded && !!_this._templates[key].parent) || !_this._templates[key].isInHtmlTree;
|
|
130
|
+
});
|
|
131
|
+
if (done) {
|
|
132
|
+
this.onAllLoaded.notifyObservers(this);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Dispose the template manager
|
|
137
|
+
*/
|
|
138
|
+
TemplateManager.prototype.dispose = function () {
|
|
139
|
+
var _this = this;
|
|
140
|
+
// dispose all templates
|
|
141
|
+
Object.keys(this._templates).forEach(function (template) {
|
|
142
|
+
_this._templates[template].dispose();
|
|
143
|
+
});
|
|
144
|
+
this._templates = {};
|
|
145
|
+
this.eventManager.dispose();
|
|
146
|
+
this.onTemplateInit.clear();
|
|
147
|
+
this.onAllLoaded.clear();
|
|
148
|
+
this.onEventTriggered.clear();
|
|
149
|
+
this.onTemplateLoaded.clear();
|
|
150
|
+
this.onTemplateStateChange.clear();
|
|
151
|
+
};
|
|
152
|
+
return TemplateManager;
|
|
153
|
+
}());
|
|
154
|
+
export { TemplateManager };
|
|
155
|
+
// register a new helper. modified https://stackoverflow.com/questions/9838925/is-there-any-method-to-iterate-a-map-with-handlebars-js
|
|
156
|
+
Handlebars.registerHelper("eachInMap", function (map, block) {
|
|
157
|
+
var out = "";
|
|
158
|
+
Object.keys(map).map(function (prop) {
|
|
159
|
+
var data = map[prop];
|
|
160
|
+
if (typeof data === "object") {
|
|
161
|
+
data.id = data.id || prop;
|
|
162
|
+
out += block.fn(data);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
out += block.fn({ id: prop, value: data });
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return out;
|
|
169
|
+
});
|
|
170
|
+
Handlebars.registerHelper("add", function (a, b) {
|
|
171
|
+
var out = a + b;
|
|
172
|
+
return out;
|
|
173
|
+
});
|
|
174
|
+
Handlebars.registerHelper("eq", function (a, b) {
|
|
175
|
+
var out = a == b;
|
|
176
|
+
return out;
|
|
177
|
+
});
|
|
178
|
+
Handlebars.registerHelper("or", function (a, b) {
|
|
179
|
+
var out = a || b;
|
|
180
|
+
return out;
|
|
181
|
+
});
|
|
182
|
+
Handlebars.registerHelper("not", function (a) {
|
|
183
|
+
var out = !a;
|
|
184
|
+
return out;
|
|
185
|
+
});
|
|
186
|
+
Handlebars.registerHelper("count", function (map) {
|
|
187
|
+
return map.length;
|
|
188
|
+
});
|
|
189
|
+
Handlebars.registerHelper("gt", function (a, b) {
|
|
190
|
+
var out = a > b;
|
|
191
|
+
return out;
|
|
192
|
+
});
|
|
193
|
+
/**
|
|
194
|
+
* This class represents a single template in the viewer's template tree.
|
|
195
|
+
* An example for a template is a single canvas, an overlay (containing sub-templates) or the navigation bar.
|
|
196
|
+
* A template is injected using the template manager in the correct position.
|
|
197
|
+
* The template is rendered using Handlebars and can use Handlebars' features (such as parameter injection)
|
|
198
|
+
*
|
|
199
|
+
* For further information please refer to the documentation page, https://doc.babylonjs.com
|
|
200
|
+
*/
|
|
201
|
+
var Template = /** @class */ (function () {
|
|
202
|
+
function Template(name, _configuration) {
|
|
203
|
+
var _this = this;
|
|
204
|
+
this.name = name;
|
|
205
|
+
this._configuration = _configuration;
|
|
206
|
+
this.onLoaded = new Observable();
|
|
207
|
+
this.onAppended = new Observable();
|
|
208
|
+
this.onStateChange = new Observable();
|
|
209
|
+
this.onEventTriggered = new Observable();
|
|
210
|
+
this.onParamsUpdated = new Observable();
|
|
211
|
+
this.onHTMLRendered = new Observable();
|
|
212
|
+
this._loadRequests = [];
|
|
213
|
+
this.isLoaded = false;
|
|
214
|
+
this.isShown = false;
|
|
215
|
+
this.isInHtmlTree = false;
|
|
216
|
+
var htmlContentPromise = this._getTemplateAsHtml(_configuration);
|
|
217
|
+
this.initPromise = htmlContentPromise.then(function (htmlTemplate) {
|
|
218
|
+
if (htmlTemplate) {
|
|
219
|
+
_this._htmlTemplate = htmlTemplate;
|
|
220
|
+
var compiledTemplate = Handlebars.compile(htmlTemplate, { noEscape: _this._configuration.params && !!_this._configuration.params.noEscape });
|
|
221
|
+
var config = _this._configuration.params || {};
|
|
222
|
+
_this._rawHtml = compiledTemplate(config);
|
|
223
|
+
try {
|
|
224
|
+
_this._fragment = document.createRange().createContextualFragment(_this._rawHtml);
|
|
225
|
+
}
|
|
226
|
+
catch (e) {
|
|
227
|
+
var test_1 = document.createElement(_this.name);
|
|
228
|
+
test_1.innerHTML = _this._rawHtml;
|
|
229
|
+
_this._fragment = test_1;
|
|
230
|
+
}
|
|
231
|
+
_this.isLoaded = true;
|
|
232
|
+
_this.isShown = true;
|
|
233
|
+
_this.onLoaded.notifyObservers(_this);
|
|
234
|
+
}
|
|
235
|
+
return _this;
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Some templates have parameters (like background color for example).
|
|
240
|
+
* The parameters are provided to Handlebars which in turn generates the template.
|
|
241
|
+
* This function will update the template with the new parameters
|
|
242
|
+
*
|
|
243
|
+
* Note that when updating parameters the events will be registered again (after being cleared).
|
|
244
|
+
*
|
|
245
|
+
* @param params the new template parameters
|
|
246
|
+
* @param append
|
|
247
|
+
*/
|
|
248
|
+
Template.prototype.updateParams = function (params, append) {
|
|
249
|
+
if (append === void 0) { append = true; }
|
|
250
|
+
if (append) {
|
|
251
|
+
this._configuration.params = deepmerge(this._configuration.params, params);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
this._configuration.params = params;
|
|
255
|
+
}
|
|
256
|
+
// update the template
|
|
257
|
+
if (this.isLoaded) {
|
|
258
|
+
// this.dispose();
|
|
259
|
+
}
|
|
260
|
+
var compiledTemplate = Handlebars.compile(this._htmlTemplate);
|
|
261
|
+
var config = this._configuration.params || {};
|
|
262
|
+
this._rawHtml = compiledTemplate(config);
|
|
263
|
+
try {
|
|
264
|
+
this._fragment = document.createRange().createContextualFragment(this._rawHtml);
|
|
265
|
+
}
|
|
266
|
+
catch (e) {
|
|
267
|
+
var test_2 = document.createElement(this.name);
|
|
268
|
+
test_2.innerHTML = this._rawHtml;
|
|
269
|
+
this._fragment = test_2;
|
|
270
|
+
}
|
|
271
|
+
if (this.parent) {
|
|
272
|
+
this.appendTo(this.parent, true);
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
Template.prototype.redraw = function () {
|
|
276
|
+
this.updateParams({});
|
|
277
|
+
};
|
|
278
|
+
Object.defineProperty(Template.prototype, "configuration", {
|
|
279
|
+
/**
|
|
280
|
+
* Get the template'S configuration
|
|
281
|
+
*/
|
|
282
|
+
get: function () {
|
|
283
|
+
return this._configuration;
|
|
284
|
+
},
|
|
285
|
+
enumerable: false,
|
|
286
|
+
configurable: true
|
|
287
|
+
});
|
|
288
|
+
/**
|
|
289
|
+
* A template can be a parent element for other templates or HTML elements.
|
|
290
|
+
* This function will deliver all child HTML elements of this template.
|
|
291
|
+
*/
|
|
292
|
+
Template.prototype.getChildElements = function () {
|
|
293
|
+
var childrenArray = [];
|
|
294
|
+
//Edge and IE don't support frage,ent.children
|
|
295
|
+
var children = this._fragment && this._fragment.children;
|
|
296
|
+
if (!this._fragment) {
|
|
297
|
+
var fragment = this.parent.querySelector(this.name);
|
|
298
|
+
if (fragment) {
|
|
299
|
+
children = fragment.querySelectorAll("*");
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (!children) {
|
|
303
|
+
// casting to HTMLCollection, as both NodeListOf and HTMLCollection have 'item()' and 'length'.
|
|
304
|
+
children = this._fragment.querySelectorAll("*");
|
|
305
|
+
}
|
|
306
|
+
for (var i = 0; i < children.length; ++i) {
|
|
307
|
+
var child = children.item(i);
|
|
308
|
+
if (child) {
|
|
309
|
+
childrenArray.push(kebabToCamel(child.nodeName.toLowerCase()));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return childrenArray;
|
|
313
|
+
};
|
|
314
|
+
/**
|
|
315
|
+
* Appending the template to a parent HTML element.
|
|
316
|
+
* If a parent is already set and you wish to replace the old HTML with new one, forceRemove should be true.
|
|
317
|
+
* @param parent the parent to which the template is added
|
|
318
|
+
* @param forceRemove if the parent already exists, shoud the template be removed from it?
|
|
319
|
+
*/
|
|
320
|
+
Template.prototype.appendTo = function (parent, forceRemove) {
|
|
321
|
+
var _this = this;
|
|
322
|
+
if (this.parent) {
|
|
323
|
+
if (forceRemove && this._addedFragment) {
|
|
324
|
+
/*let fragement = this.parent.querySelector(this.name)
|
|
325
|
+
if (fragement)
|
|
326
|
+
this.parent.removeChild(fragement);*/
|
|
327
|
+
this.parent.innerHTML = "";
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
this.parent = parent;
|
|
334
|
+
if (this._configuration.id) {
|
|
335
|
+
this.parent.id = this._configuration.id;
|
|
336
|
+
}
|
|
337
|
+
if (this._fragment) {
|
|
338
|
+
this.parent.appendChild(this._fragment);
|
|
339
|
+
this._addedFragment = this._fragment;
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
this.parent.insertAdjacentHTML("beforeend", this._rawHtml);
|
|
343
|
+
}
|
|
344
|
+
this.onHTMLRendered.notifyObservers(this);
|
|
345
|
+
// appended only one frame after.
|
|
346
|
+
setTimeout(function () {
|
|
347
|
+
_this._registerEvents();
|
|
348
|
+
_this.onAppended.notifyObservers(_this);
|
|
349
|
+
});
|
|
350
|
+
};
|
|
351
|
+
/**
|
|
352
|
+
* Show the template using the provided visibilityFunction, or natively using display: flex.
|
|
353
|
+
* The provided function returns a promise that should be fulfilled when the element is shown.
|
|
354
|
+
* Since it is a promise async operations are more than possible.
|
|
355
|
+
* See the default viewer for an opacity example.
|
|
356
|
+
* @param visibilityFunction The function to execute to show the template.
|
|
357
|
+
*/
|
|
358
|
+
Template.prototype.show = function (visibilityFunction) {
|
|
359
|
+
var _this = this;
|
|
360
|
+
if (this._isHiding) {
|
|
361
|
+
return Promise.resolve(this);
|
|
362
|
+
}
|
|
363
|
+
return Promise.resolve()
|
|
364
|
+
.then(function () {
|
|
365
|
+
_this._isShowing = true;
|
|
366
|
+
if (visibilityFunction) {
|
|
367
|
+
return visibilityFunction(_this);
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
// flex? box? should this be configurable easier than the visibilityFunction?
|
|
371
|
+
_this.parent.style.display = "flex";
|
|
372
|
+
// support old browsers with no flex:
|
|
373
|
+
if (_this.parent.style.display !== "flex") {
|
|
374
|
+
_this.parent.style.display = "";
|
|
375
|
+
}
|
|
376
|
+
return _this;
|
|
377
|
+
}
|
|
378
|
+
})
|
|
379
|
+
.then(function () {
|
|
380
|
+
_this.isShown = true;
|
|
381
|
+
_this._isShowing = false;
|
|
382
|
+
_this.onStateChange.notifyObservers(_this);
|
|
383
|
+
return _this;
|
|
384
|
+
});
|
|
385
|
+
};
|
|
386
|
+
/**
|
|
387
|
+
* Hide the template using the provided visibilityFunction, or natively using display: none.
|
|
388
|
+
* The provided function returns a promise that should be fulfilled when the element is hidden.
|
|
389
|
+
* Since it is a promise async operations are more than possible.
|
|
390
|
+
* See the default viewer for an opacity example.
|
|
391
|
+
* @param visibilityFunction The function to execute to show the template.
|
|
392
|
+
*/
|
|
393
|
+
Template.prototype.hide = function (visibilityFunction) {
|
|
394
|
+
var _this = this;
|
|
395
|
+
if (this._isShowing) {
|
|
396
|
+
return Promise.resolve(this);
|
|
397
|
+
}
|
|
398
|
+
return Promise.resolve()
|
|
399
|
+
.then(function () {
|
|
400
|
+
_this._isHiding = true;
|
|
401
|
+
if (visibilityFunction) {
|
|
402
|
+
return visibilityFunction(_this);
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
// flex? box? should this be configurable easier than the visibilityFunction?
|
|
406
|
+
_this.parent.style.display = "none";
|
|
407
|
+
return _this;
|
|
408
|
+
}
|
|
409
|
+
})
|
|
410
|
+
.then(function () {
|
|
411
|
+
_this.isShown = false;
|
|
412
|
+
_this._isHiding = false;
|
|
413
|
+
_this.onStateChange.notifyObservers(_this);
|
|
414
|
+
return _this;
|
|
415
|
+
});
|
|
416
|
+
};
|
|
417
|
+
/**
|
|
418
|
+
* Dispose this template
|
|
419
|
+
*/
|
|
420
|
+
Template.prototype.dispose = function () {
|
|
421
|
+
this.onAppended.clear();
|
|
422
|
+
this.onEventTriggered.clear();
|
|
423
|
+
this.onLoaded.clear();
|
|
424
|
+
this.onStateChange.clear();
|
|
425
|
+
this.isLoaded = false;
|
|
426
|
+
// remove from parent
|
|
427
|
+
try {
|
|
428
|
+
this.parent.removeChild(this._fragment);
|
|
429
|
+
}
|
|
430
|
+
catch (e) {
|
|
431
|
+
//noop
|
|
432
|
+
}
|
|
433
|
+
this._loadRequests.forEach(function (request) {
|
|
434
|
+
request.abort();
|
|
435
|
+
});
|
|
436
|
+
if (this._registeredEvents) {
|
|
437
|
+
this._registeredEvents.forEach(function (evt) {
|
|
438
|
+
evt.htmlElement.removeEventListener(evt.eventName, evt.function);
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
Template.prototype._getTemplateAsHtml = function (templateConfig) {
|
|
443
|
+
var _this = this;
|
|
444
|
+
if (!templateConfig) {
|
|
445
|
+
return Promise.reject("No templateConfig provided");
|
|
446
|
+
}
|
|
447
|
+
else if (templateConfig.html && !templateConfig.location) {
|
|
448
|
+
return Promise.resolve(templateConfig.html);
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
var location_1 = this._getTemplateLocation(templateConfig);
|
|
452
|
+
if (isUrl(location_1)) {
|
|
453
|
+
return new Promise(function (resolve, reject) {
|
|
454
|
+
var fileRequest = Tools.LoadFile(location_1, function (data) {
|
|
455
|
+
resolve(data);
|
|
456
|
+
}, undefined, undefined, false, function (request, error) {
|
|
457
|
+
reject(error);
|
|
458
|
+
});
|
|
459
|
+
_this._loadRequests.push(fileRequest);
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
location_1 = location_1.replace("#", "");
|
|
464
|
+
var element = document.getElementById(location_1);
|
|
465
|
+
if (element) {
|
|
466
|
+
return Promise.resolve(element.innerHTML);
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
return Promise.reject("Template ID not found");
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
Template.prototype._registerEvents = function () {
|
|
475
|
+
var _this = this;
|
|
476
|
+
this._registeredEvents = this._registeredEvents || [];
|
|
477
|
+
if (this._registeredEvents.length) {
|
|
478
|
+
// first remove the registered events
|
|
479
|
+
this._registeredEvents.forEach(function (evt) {
|
|
480
|
+
evt.htmlElement.removeEventListener(evt.eventName, evt.function);
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
if (this._configuration.events) {
|
|
484
|
+
var _loop_1 = function (eventName) {
|
|
485
|
+
if (this_1._configuration.events && this_1._configuration.events[eventName]) {
|
|
486
|
+
var functionToFire_1 = function (selector, event) {
|
|
487
|
+
_this.onEventTriggered.notifyObservers({ event: event, template: _this, selector: selector });
|
|
488
|
+
};
|
|
489
|
+
// if boolean, set the parent as the event listener
|
|
490
|
+
if (typeof this_1._configuration.events[eventName] === "boolean") {
|
|
491
|
+
var selector = this_1.parent.id;
|
|
492
|
+
if (selector) {
|
|
493
|
+
selector = "#" + selector;
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
selector = this_1.parent.tagName;
|
|
497
|
+
}
|
|
498
|
+
var binding = functionToFire_1.bind(this_1, selector);
|
|
499
|
+
this_1.parent.addEventListener(eventName, binding, false);
|
|
500
|
+
this_1._registeredEvents.push({
|
|
501
|
+
htmlElement: this_1.parent,
|
|
502
|
+
eventName: eventName,
|
|
503
|
+
function: binding,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
else if (typeof this_1._configuration.events[eventName] === "object") {
|
|
507
|
+
var selectorsArray = Object.keys(this_1._configuration.events[eventName] || {});
|
|
508
|
+
// strict null check is working incorrectly, must override:
|
|
509
|
+
var event_1 = this_1._configuration.events[eventName] || {};
|
|
510
|
+
selectorsArray
|
|
511
|
+
.filter(function (selector) { return typeof event_1 !== "boolean" && event_1[selector]; })
|
|
512
|
+
.forEach(function (selector) {
|
|
513
|
+
var htmlElement = _this.parent.querySelector(selector);
|
|
514
|
+
if (!htmlElement) {
|
|
515
|
+
// backcompat, fallback to id
|
|
516
|
+
if (selector && selector.indexOf("#") !== 0) {
|
|
517
|
+
selector = "#" + selector;
|
|
518
|
+
}
|
|
519
|
+
try {
|
|
520
|
+
htmlElement = _this.parent.querySelector(selector);
|
|
521
|
+
}
|
|
522
|
+
catch (e) { }
|
|
523
|
+
}
|
|
524
|
+
if (htmlElement) {
|
|
525
|
+
var binding = functionToFire_1.bind(_this, selector);
|
|
526
|
+
htmlElement.addEventListener(eventName, binding, false);
|
|
527
|
+
_this._registeredEvents.push({
|
|
528
|
+
htmlElement: htmlElement,
|
|
529
|
+
eventName: eventName,
|
|
530
|
+
function: binding,
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
var this_1 = this;
|
|
538
|
+
for (var eventName in this._configuration.events) {
|
|
539
|
+
_loop_1(eventName);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
Template.prototype._getTemplateLocation = function (templateConfig) {
|
|
544
|
+
if (!templateConfig || typeof templateConfig === "string") {
|
|
545
|
+
return templateConfig;
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
return templateConfig.location;
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
return Template;
|
|
552
|
+
}());
|
|
553
|
+
export { Template };
|
|
554
554
|
//# sourceMappingURL=templateManager.js.map
|