@jinntec/fore 1.0.0-3 → 1.0.0

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.
Files changed (62) hide show
  1. package/README.md +25 -34
  2. package/dist/fore-dev.js +43 -0
  3. package/dist/fore-dev.js.map +1 -0
  4. package/dist/fore.js +36 -1
  5. package/dist/fore.js.map +1 -0
  6. package/index.js +3 -0
  7. package/package.json +34 -38
  8. package/resources/fore.css +35 -50
  9. package/src/DependencyNotifyingDomFacade.js +10 -16
  10. package/src/ForeElementMixin.js +25 -18
  11. package/src/actions/abstract-action.js +17 -9
  12. package/src/actions/fx-action.js +6 -4
  13. package/src/actions/fx-append.js +8 -17
  14. package/src/actions/fx-confirm.js +3 -1
  15. package/src/actions/fx-delete.js +6 -3
  16. package/src/actions/fx-dispatch.js +9 -8
  17. package/src/actions/fx-hide.js +10 -6
  18. package/src/actions/fx-insert.js +49 -39
  19. package/src/actions/fx-message.js +3 -1
  20. package/src/actions/fx-refresh.js +11 -1
  21. package/src/actions/fx-replace.js +68 -0
  22. package/src/actions/fx-return.js +42 -0
  23. package/src/actions/fx-send.js +3 -1
  24. package/src/actions/fx-setvalue.js +58 -51
  25. package/src/actions/fx-show.js +8 -4
  26. package/src/actions/fx-toggle.js +15 -10
  27. package/src/actions/fx-update.js +3 -1
  28. package/src/dep_graph.js +4 -2
  29. package/src/drawdown.js +67 -82
  30. package/src/fore.js +158 -11
  31. package/src/functions/fx-function.js +11 -3
  32. package/src/fx-bind.js +42 -202
  33. package/src/fx-fore.js +105 -70
  34. package/src/fx-header.js +3 -1
  35. package/src/fx-instance.js +9 -1
  36. package/src/fx-model.js +31 -23
  37. package/src/fx-submission.js +73 -47
  38. package/src/fx-var.js +7 -4
  39. package/src/getInScopeContext.js +37 -11
  40. package/src/modelitem.js +4 -4
  41. package/src/relevance.js +65 -0
  42. package/src/ui/abstract-control.js +55 -35
  43. package/src/ui/fx-alert.js +7 -1
  44. package/src/ui/fx-case.js +3 -1
  45. package/src/ui/fx-container.js +7 -1
  46. package/src/ui/fx-control.js +283 -33
  47. package/src/ui/fx-dialog.js +54 -40
  48. package/src/ui/fx-group.js +3 -1
  49. package/src/ui/fx-hint.js +4 -1
  50. package/src/ui/fx-inspector.js +117 -17
  51. package/src/ui/fx-items.js +8 -8
  52. package/src/ui/fx-output.js +14 -5
  53. package/src/ui/fx-repeat.js +33 -41
  54. package/src/ui/fx-repeatitem.js +10 -4
  55. package/src/ui/fx-switch.js +3 -1
  56. package/src/ui/fx-trigger.js +3 -1
  57. package/src/xpath-evaluation.js +121 -131
  58. package/src/xpath-util.js +14 -7
  59. package/dist/fore-all.js +0 -140
  60. package/src/.DS_Store +0 -0
  61. package/src/actions/.DS_Store +0 -0
  62. package/src/ui/.DS_Store +0 -0
package/src/fx-fore.js CHANGED
@@ -16,7 +16,10 @@ import { XPathUtil } from './xpath-util.js';
16
16
  *
17
17
  * Main responsiblities are initialization and updating of model and instances, update of UI (refresh) and global messaging.
18
18
  *
19
- *
19
+ * @event compute-exception - dispatched in case the dependency graph is cirular
20
+ * @event refresh-done - dispatched after a refresh() run
21
+ * @event ready - dispatched after Fore has fully been initialized
22
+ * @event error - dispatches error when template expression fails to evaluate
20
23
  *
21
24
  * @ts-check
22
25
  */
@@ -73,10 +76,10 @@ export class FxFore extends HTMLElement {
73
76
  :host ::slotted(fx-model){
74
77
  display:none;
75
78
  }
76
- :host(.fx-ready){
77
- animation: fadein .4s forwards;
78
- display:block;
79
- }
79
+ // :host(.fx-ready){
80
+ // animation: fadein .4s forwards;
81
+ // display:block;
82
+ // }
80
83
 
81
84
  #modalMessage .dialogActions{
82
85
  text-align:center;
@@ -152,6 +155,7 @@ export class FxFore extends HTMLElement {
152
155
 
153
156
  const html = `
154
157
  <jinn-toast id="message" gravity="bottom" position="left"></jinn-toast>
158
+ <jinn-toast id="sticky" gravity="bottom" position="left" duration="-1" close="true" data-class="sticky-message"></jinn-toast>
155
159
  <jinn-toast id="error" text="error" duration="-1" data-class="error" close="true" position="left" gravity="bottom"></jinn-toast>
156
160
  <slot></slot>
157
161
  <div id="modalMessage" class="overlay">
@@ -177,6 +181,25 @@ export class FxFore extends HTMLElement {
177
181
  }
178
182
 
179
183
  connectedCallback() {
184
+ /*
185
+ document.addEventListener('ready', (e) =>{
186
+ if(e.target !== this){
187
+ // e.preventDefault();
188
+ console.log('>>> e', e);
189
+ console.log('event this', this);
190
+ // console.log('event eventPhase', e.eventPhase);
191
+ // console.log('event cancelable', e.cancelable);
192
+ console.log('event target', e.target);
193
+ console.log('event composed', e.composedPath());
194
+ console.log('<<< event stopping');
195
+ e.stopPropagation();
196
+ }else{
197
+ console.log('event proceed', this);
198
+ }
199
+ // e.stopImmediatePropagation();
200
+ },true);
201
+ */
202
+
180
203
  this.lazyRefresh = this.hasAttribute('refresh-on-view');
181
204
  if (this.lazyRefresh) {
182
205
  const options = {
@@ -187,10 +210,10 @@ export class FxFore extends HTMLElement {
187
210
  this.intersectionObserver = new IntersectionObserver(this.handleIntersect, options);
188
211
  }
189
212
 
190
- this.src = this.hasAttribute('src')? this.getAttribute('src'):null;
191
- if(this.src){
213
+ this.src = this.hasAttribute('src') ? this.getAttribute('src') : null;
214
+ if (this.src) {
192
215
  this._loadFromSrc();
193
- return ;
216
+ return;
194
217
  }
195
218
 
196
219
  const slot = this.shadowRoot.querySelector('slot');
@@ -200,7 +223,7 @@ export class FxFore extends HTMLElement {
200
223
  modelElem => modelElem.nodeName.toUpperCase() === 'FX-MODEL',
201
224
  );
202
225
  if (!modelElement) {
203
- const generatedModel = document.createElement('FX-model');
226
+ const generatedModel = document.createElement('fx-model');
204
227
  this.appendChild(generatedModel);
205
228
  modelElement = generatedModel;
206
229
  }
@@ -208,23 +231,22 @@ export class FxFore extends HTMLElement {
208
231
  console.log(
209
232
  `########## FORE: kick off processing for ... ${window.location.href} ##########`,
210
233
  );
211
- if(this.src){
234
+ if (this.src) {
212
235
  console.log('########## FORE: loaded from ... ', this.src, '##########');
213
236
  }
214
237
  modelElement.modelConstruct();
215
238
  }
216
239
  this.model = modelElement;
217
240
  });
218
- this.addEventListener('path-mutated', (e) =>{
241
+ this.addEventListener('path-mutated', e => {
219
242
  console.log('path-mutated event received', e.detail.path, e.detail.index);
220
243
  this.someInstanceDataStructureChanged = true;
221
244
  });
222
245
  }
223
246
 
224
-
225
- addToRefresh(modelItem){
226
- const found = this.toRefresh.find(mi => mi.path === modelItem.path );
227
- if(!found){
247
+ addToRefresh(modelItem) {
248
+ const found = this.toRefresh.find(mi => mi.path === modelItem.path);
249
+ if (!found) {
228
250
  this.toRefresh.push(modelItem);
229
251
  }
230
252
  }
@@ -236,7 +258,7 @@ export class FxFore extends HTMLElement {
236
258
  * @private
237
259
  */
238
260
  _loadFromSrc() {
239
- console.log('########## loading Fore from ',this.src ,'##########');
261
+ console.log('########## loading Fore from ', this.src, '##########');
240
262
  fetch(this.src, {
241
263
  method: 'GET',
242
264
  mode: 'cors',
@@ -245,34 +267,40 @@ export class FxFore extends HTMLElement {
245
267
  'Content-Type': 'text/html',
246
268
  },
247
269
  })
248
- .then(response => {
249
- const responseContentType = response.headers.get('content-type').toLowerCase();
250
- console.log('********** responseContentType *********', responseContentType);
251
- if (responseContentType.startsWith('text/html')) {
252
- // const htmlResponse = response.text();
253
- // return new DOMParser().parseFromString(htmlResponse, 'text/html');
254
- // return response.text();
255
- return response.text().then(result =>
256
- // console.log('xml ********', result);
257
- new DOMParser().parseFromString(result, 'text/html'),
258
- );
259
- }
260
- return 'done';
261
- })
262
- .then(data => {
263
- // const theFore = fxEvaluateXPathToFirstNode('//fx-fore', data.firstElementChild);
264
- const theFore = data.querySelector('fx-fore');
265
-
266
- // console.log('thefore', theFore)
267
- if(!theFore){
268
- this.dispatchEvent(new CustomEvent('error',{detail:{message: `Fore element not found in '${this.src}'. Maybe wrapped within 'template' element?`}}));
269
- }
270
- theFore.setAttribute('from-src', this.src);
271
- this.replaceWith(theFore);
272
- })
273
- .catch(error => {
274
- this.dispatchEvent(new CustomEvent('error',{detail:{message: `'${this.src}' not found or does not contain Fore element.`}}));
270
+ .then(response => {
271
+ const responseContentType = response.headers.get('content-type').toLowerCase();
272
+ console.log('********** responseContentType *********', responseContentType);
273
+ if (responseContentType.startsWith('text/html')) {
274
+ // const htmlResponse = response.text();
275
+ // return new DOMParser().parseFromString(htmlResponse, 'text/html');
276
+ // return response.text();
277
+ return response.text().then(result =>
278
+ // console.log('xml ********', result);
279
+ new DOMParser().parseFromString(result, 'text/html'),
280
+ );
281
+ }
282
+ return 'done';
283
+ })
284
+ .then(data => {
285
+ // const theFore = fxEvaluateXPathToFirstNode('//fx-fore', data.firstElementChild);
286
+ const theFore = data.querySelector('fx-fore');
287
+
288
+ // console.log('thefore', theFore)
289
+ if (!theFore) {
290
+ Fore.dispatchEvent(this, 'error', {
291
+ detail: {
292
+ message: `Fore element not found in '${this.src}'. Maybe wrapped within 'template' element?`,
293
+ },
294
+ });
295
+ }
296
+ theFore.setAttribute('from-src', this.src);
297
+ this.replaceWith(theFore);
298
+ })
299
+ .catch(() => {
300
+ Fore.dispatch(this, 'error', {
301
+ message: `'${this.src}' not found or does not contain Fore element.`,
275
302
  });
303
+ });
276
304
  }
277
305
 
278
306
  /**
@@ -331,7 +359,7 @@ export class FxFore extends HTMLElement {
331
359
  * AVT:
332
360
  *
333
361
  */
334
- async refresh(force) {
362
+ async refresh() {
335
363
  // refresh () {
336
364
  console.group('### refresh');
337
365
 
@@ -339,58 +367,60 @@ export class FxFore extends HTMLElement {
339
367
 
340
368
  // ### refresh Fore UI elements
341
369
  console.time('refreshChildren');
342
- console.log('toRefresh',this.toRefresh);
370
+ console.log('toRefresh', this.toRefresh);
343
371
 
344
- if(!this.initialRun && this.toRefresh.length !== 0){
372
+ if (!this.initialRun && this.toRefresh.length !== 0) {
345
373
  let needsRefresh = false;
346
374
 
347
375
  // ### after recalculation the changed modelItems are copied to 'toRefresh' array for processing
348
376
  this.toRefresh.forEach(modelItem => {
349
377
  // check if modelItem has boundControls - if so, call refresh() for each of them
350
378
  const controlsToRefresh = modelItem.boundControls;
351
- if(controlsToRefresh){
379
+ if (controlsToRefresh) {
352
380
  controlsToRefresh.forEach(ctrl => {
353
381
  ctrl.refresh();
354
382
  });
355
383
  }
356
384
 
357
385
  // ### check if other controls depend on current modelItem
358
- const mainGraph = this.getModel().mainGraph;
359
- if(mainGraph && mainGraph.hasNode(modelItem.path)){
386
+ const { mainGraph } = this.getModel();
387
+ if (mainGraph && mainGraph.hasNode(modelItem.path)) {
360
388
  const deps = this.getModel().mainGraph.dependentsOf(modelItem.path, false);
361
389
  // ### iterate dependant modelItems and refresh all their boundControls
362
- if(deps.length !== 0){
390
+ if (deps.length !== 0) {
363
391
  deps.forEach(dep => {
364
392
  // ### if changed modelItem has a 'facet' path we use the basePath that is the locationPath without facet name
365
393
  const basePath = XPathUtil.getBasePath(dep);
366
394
  const modelItemOfDep = this.getModel().modelItems.find(mip => mip.path === basePath);
367
395
  // ### refresh all boundControls
368
- modelItemOfDep.boundControls.forEach(control =>{control.refresh()});
396
+ modelItemOfDep.boundControls.forEach(control => {
397
+ control.refresh();
398
+ });
369
399
  });
370
400
  needsRefresh = true;
371
401
  }
372
402
  }
373
403
  });
374
404
  this.toRefresh = [];
375
- if(!needsRefresh){
405
+ if (!needsRefresh) {
376
406
  console.log('skipping refresh - no dependants');
377
407
  }
378
- }else{
408
+ } else {
379
409
  Fore.refreshChildren(this, true);
380
410
  console.timeEnd('refreshChildren');
381
411
  }
382
412
 
383
413
  // ### refresh template expressions
384
- if(this.initialRun || this.someInstanceDataStructureChanged){
414
+ if (this.initialRun || this.someInstanceDataStructureChanged) {
385
415
  this._updateTemplateExpressions();
386
- this.someInstanceDataStructureChanged = false; //reset
416
+ this.someInstanceDataStructureChanged = false; // reset
387
417
  }
388
418
  this._processTemplateExpressions();
389
419
 
390
420
  console.timeEnd('refresh');
391
421
 
392
422
  console.groupEnd();
393
- console.log('### <<<<< dispatching refresh-done - end of UI update cycle >>>>>');
423
+ // console.log('### <<<<< dispatching refresh-done - end of UI update cycle >>>>>');
394
424
  this.dispatchEvent(new CustomEvent('refresh-done'));
395
425
  }
396
426
 
@@ -408,7 +438,7 @@ export class FxFore extends HTMLElement {
408
438
  "(descendant-or-self::*/(text(), @*))[matches(.,'\\{.*\\}')] except descendant-or-self::fx-model/descendant-or-self::node()/(., @*)";
409
439
 
410
440
  const tmplExpressions = evaluateXPathToNodes(search, this, this);
411
- console.log('template expressions found ', tmplExpressions);
441
+ // console.log('template expressions found ', tmplExpressions);
412
442
 
413
443
  if (!this.storedTemplateExpressions) {
414
444
  this.storedTemplateExpressions = [];
@@ -433,7 +463,6 @@ export class FxFore extends HTMLElement {
433
463
 
434
464
  // TODO: Should we clean up nodes that existed but are now gone?
435
465
  this._processTemplateExpressions();
436
-
437
466
  }
438
467
 
439
468
  _processTemplateExpressions() {
@@ -445,7 +474,7 @@ export class FxFore extends HTMLElement {
445
474
  }
446
475
  }
447
476
 
448
- // eslint-disable-next-line class-methods-use-this
477
+ // eslint-disable-next-line class-methods-use-this
449
478
  _processTemplateExpression(exprObj) {
450
479
  // console.log('processing template expression ', exprObj);
451
480
 
@@ -464,8 +493,6 @@ export class FxFore extends HTMLElement {
464
493
  evaluateTemplateExpression(expr, node) {
465
494
  if (expr === '{}') return;
466
495
  const matches = expr.match(/{[^}]*}/g);
467
- const namespaceContextNode =
468
- node.nodeType === node.TEXT_NODE ? node.parentNode : node.ownerElement;
469
496
  if (matches) {
470
497
  matches.forEach(match => {
471
498
  // console.log('match ', match);
@@ -508,6 +535,7 @@ export class FxFore extends HTMLElement {
508
535
  this.evaluateTemplateExpression(replaced, node);
509
536
  }
510
537
  } catch (error) {
538
+ // console.log(error);
511
539
  this.dispatchEvent(new CustomEvent('error', { detail: error }));
512
540
  }
513
541
  });
@@ -652,10 +680,10 @@ export class FxFore extends HTMLElement {
652
680
  */
653
681
  async _initUI() {
654
682
  console.log('### _initUI()');
655
-
683
+ if (!this.initialRun) return;
656
684
  await this._lazyCreateInstance();
657
685
 
658
- console.log('registering variables!');
686
+ // console.log('registering variables!');
659
687
  const variables = new Map();
660
688
  (function registerVariables(node) {
661
689
  for (const child of node.children) {
@@ -667,22 +695,25 @@ export class FxFore extends HTMLElement {
667
695
  })(this);
668
696
  console.log('Found variables:', variables);
669
697
 
698
+ /*
670
699
  const options = {
671
700
  root: null,
672
701
  rootMargin: '0px',
673
702
  threshold: 0.3,
674
703
  };
704
+ */
675
705
 
676
706
  await this.refresh();
677
707
  // this.style.display='block'
678
708
  this.classList.add('fx-ready');
709
+ document.body.classList.add('fx-ready');
679
710
 
680
711
  this.ready = true;
681
712
  this.initialRun = false;
682
- console.log('### <<<<< dispatching ready >>>>>');
683
- console.log('########## modelItems: ', this.getModel().modelItems);
684
- console.log('########## FORE: form fully initialized... ##########');
685
- this.dispatchEvent(new CustomEvent('ready', {}));
713
+ console.log('### >>>>> dispatching ready >>>>>', this);
714
+ console.log('modelItems: ', this.getModel().modelItems);
715
+ console.log('### <<<<< FORE: form fully initialized...', this);
716
+ Fore.dispatch(this, 'ready', {});
686
717
  }
687
718
 
688
719
  registerLazyElement(element) {
@@ -707,9 +738,11 @@ export class FxFore extends HTMLElement {
707
738
  }
708
739
 
709
740
  _displayMessage(e) {
741
+ // console.log('_displayMessage',e);
710
742
  const { level } = e.detail;
711
743
  const msg = e.detail.message;
712
744
  this._showMessage(level, msg);
745
+ e.stopPropagation();
713
746
  }
714
747
 
715
748
  _displayError(e) {
@@ -728,9 +761,9 @@ export class FxFore extends HTMLElement {
728
761
  this.shadowRoot.getElementById('messageContent').innerText = msg;
729
762
  // this.shadowRoot.getElementById('modalMessage').open();
730
763
  this.shadowRoot.getElementById('modalMessage').classList.add('show');
731
- } else if (level === 'modeless') {
764
+ } else if (level === 'sticky') {
732
765
  // const notification = this.$.modeless;
733
- this.shadowRoot.querySelector('#message').showToast(msg);
766
+ this.shadowRoot.querySelector('#sticky').showToast(msg);
734
767
  } else {
735
768
  const toast = this.shadowRoot.querySelector('#message');
736
769
  toast.showToast(msg);
@@ -738,4 +771,6 @@ export class FxFore extends HTMLElement {
738
771
  }
739
772
  }
740
773
 
741
- customElements.define('fx-fore', FxFore);
774
+ if (!customElements.get('fx-fore')) {
775
+ customElements.define('fx-fore', FxFore);
776
+ }
package/src/fx-header.js CHANGED
@@ -17,4 +17,6 @@ export class FxHeader extends foreElementMixin(HTMLElement) {
17
17
  this.shadowRoot.innerHTML = ``;
18
18
  }
19
19
  }
20
- customElements.define('fx-header', FxHeader);
20
+ if (!customElements.get('fx-header')) {
21
+ customElements.define('fx-header', FxHeader);
22
+ }
@@ -166,6 +166,12 @@ export class FxInstance extends HTMLElement {
166
166
  },
167
167
  })
168
168
  .then(response => {
169
+ const { status } = response;
170
+ if (status >= 400) {
171
+ console.log('response status', status);
172
+ alert(`response status: ${status} - failed to load data for '${this.src}' - stopping.`);
173
+ throw new Error(`failed to load data - status: ${status}`);
174
+ }
169
175
  const responseContentType = response.headers.get('content-type').toLowerCase();
170
176
  console.log('********** responseContentType *********', responseContentType);
171
177
  if (responseContentType.startsWith('text/html')) {
@@ -257,4 +263,6 @@ export class FxInstance extends HTMLElement {
257
263
  console.log('_handleResponse ', loader.lastError);
258
264
  }
259
265
  }
260
- customElements.define('fx-instance', FxInstance);
266
+ if (!customElements.get('fx-instance')) {
267
+ customElements.define('fx-instance', FxInstance);
268
+ }
package/src/fx-model.js CHANGED
@@ -35,11 +35,11 @@ export class FxModel extends HTMLElement {
35
35
  <slot></slot>
36
36
  `;
37
37
 
38
- this.addEventListener('model-construct-done', e => {
39
- this.modelConstructed = true;
40
- // console.log('model-construct-done fired ', this.modelConstructed);
41
- console.log('model-construct-done fired ', e.detail.model.instances);
42
- });
38
+ this.addEventListener('model-construct-done', () => {
39
+ this.modelConstructed = true;
40
+ // console.log('model-construct-done fired ', this.modelConstructed);
41
+ // console.log('model-construct-done fired ', e.detail.model.instances);
42
+ },{ once: true });
43
43
 
44
44
  this.skipUpdate = false;
45
45
  }
@@ -95,8 +95,15 @@ export class FxModel extends HTMLElement {
95
95
  *
96
96
  */
97
97
  modelConstruct() {
98
- console.log('### <<<<< dispatching model-construct >>>>>');
99
- this.dispatchEvent(new CustomEvent('model-construct', { detail: this }));
98
+ // console.log('### <<<<< dispatching model-construct >>>>>');
99
+ // this.dispatchEvent(new CustomEvent('model-construct', { detail: this }));
100
+ this.dispatchEvent(
101
+ new CustomEvent('model-construct', {
102
+ composed: false,
103
+ bubbles: true,
104
+ detail: { model: this },
105
+ }),
106
+ );
100
107
 
101
108
  console.time('instance-loading');
102
109
  const instances = this.querySelectorAll('fx-instance');
@@ -109,14 +116,14 @@ export class FxModel extends HTMLElement {
109
116
 
110
117
  Promise.all(promises).then(() => {
111
118
  this.instances = Array.from(instances);
112
- console.log('_modelConstruct this.instances ', this.instances);
119
+ // console.log('_modelConstruct this.instances ', this.instances);
113
120
  this.updateModel();
114
121
  this.inited = true;
115
122
 
116
- console.log('### <<<<< dispatching model-construct-done >>>>>');
123
+ // console.log('### <<<<< dispatching model-construct-done >>>>>');
117
124
  this.dispatchEvent(
118
125
  new CustomEvent('model-construct-done', {
119
- composed: true,
126
+ composed: false,
120
127
  bubbles: true,
121
128
  detail: { model: this },
122
129
  }),
@@ -127,7 +134,7 @@ export class FxModel extends HTMLElement {
127
134
  // ### if there's no instance one will created
128
135
  this.dispatchEvent(
129
136
  new CustomEvent('model-construct-done', {
130
- composed: true,
137
+ composed: false,
131
138
  bubbles: true,
132
139
  detail: { model: this },
133
140
  }),
@@ -146,32 +153,32 @@ export class FxModel extends HTMLElement {
146
153
  * update action triggering the update cycle
147
154
  */
148
155
  updateModel() {
149
- console.time('updateModel');
156
+ // console.time('updateModel');
150
157
  this.rebuild();
151
- if(this.skipUpdate) return;
158
+ if (this.skipUpdate) return;
152
159
  this.recalculate();
153
160
  this.revalidate();
154
- console.timeEnd('updateModel');
161
+ // console.timeEnd('updateModel');
155
162
  }
156
163
 
157
164
  rebuild() {
158
165
  console.group('### rebuild');
159
166
  console.time('rebuild');
160
- this.mainGraph = new DepGraph(false); //do: should be moved down below binds.length check but causes errors in tests.
167
+ this.mainGraph = new DepGraph(false); // do: should be moved down below binds.length check but causes errors in tests.
161
168
  this.modelItems = [];
162
169
 
163
170
  // trigger recursive initialization of the fx-bind elements
164
171
  const binds = this.querySelectorAll('fx-model > fx-bind');
165
- if(binds.length === 0 ) {
166
- console.log('skipped model update');
172
+ if (binds.length === 0) {
173
+ // console.log('skipped model update');
167
174
  this.skipUpdate = true;
168
- return ;
175
+ return;
169
176
  }
170
177
 
171
178
  binds.forEach(bind => {
172
179
  bind.init(this);
173
180
  });
174
- console.timeEnd('rebuild');
181
+ // console.timeEnd('rebuild');
175
182
 
176
183
  // console.log(`dependencies of a `, this.mainGraph.dependenciesOf("/Q{}data[1]/Q{}a[1]:required"));
177
184
  // console.log(`dependencies of b `, this.mainGraph.dependenciesOf("/Q{}data[1]/Q{}b[1]:required"));
@@ -208,7 +215,7 @@ export class FxModel extends HTMLElement {
208
215
  this.subgraph.addNode(modelItem.path, modelItem.node);
209
216
  // const dependents = this.mainGraph.dependantsOf(modelItem.path, false);
210
217
  // this._addSubgraphDependencies(modelItem.path);
211
- if (this.mainGraph.hasNode(modelItem.path)) {
218
+ if (this.mainGraph && this.mainGraph.hasNode(modelItem.path)) {
212
219
  // const dependents = this.mainGraph.directDependantsOf(modelItem.path)
213
220
 
214
221
  const all = this.mainGraph.dependantsOf(modelItem.path, false);
@@ -238,7 +245,7 @@ export class FxModel extends HTMLElement {
238
245
  // ### compute the subgraph
239
246
  const ordered = this.subgraph.overallOrder(false);
240
247
  ordered.forEach(path => {
241
- if (this.mainGraph.hasNode(path)) {
248
+ if (this.mainGraph && this.mainGraph.hasNode(path)) {
242
249
  const node = this.mainGraph.getNodeData(path);
243
250
  this.compute(node, path);
244
251
  }
@@ -445,5 +452,6 @@ export class FxModel extends HTMLElement {
445
452
  return result;
446
453
  }
447
454
  }
448
-
449
- customElements.define('fx-model', FxModel);
455
+ if (!customElements.get('fx-model')) {
456
+ customElements.define('fx-model', FxModel);
457
+ }