@jinntec/fore 0.25.0 → 1.0.0-2

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 (41) hide show
  1. package/README.md +75 -22
  2. package/dist/fore-all.js +11 -11
  3. package/dist/fore.js +1 -1
  4. package/index.js +5 -1
  5. package/package.json +17 -6
  6. package/resources/fore.css +121 -4
  7. package/resources/toastify.css +3 -1
  8. package/src/DependencyNotifyingDomFacade.js +9 -1
  9. package/src/ForeElementMixin.js +83 -12
  10. package/src/actions/abstract-action.js +101 -27
  11. package/src/actions/fx-action.js +4 -2
  12. package/src/actions/fx-append.js +21 -18
  13. package/src/actions/fx-confirm.js +22 -0
  14. package/src/actions/fx-dispatch.js +10 -2
  15. package/src/actions/fx-insert.js +35 -30
  16. package/src/actions/fx-message.js +7 -1
  17. package/src/actions/fx-send.js +1 -1
  18. package/src/actions/fx-setvalue.js +2 -9
  19. package/src/dep_graph.js +9 -0
  20. package/src/drawdown.js +172 -0
  21. package/src/fore.js +126 -18
  22. package/src/functions/fx-function.js +2 -2
  23. package/src/fx-bind.js +11 -7
  24. package/src/fx-fore.js +283 -67
  25. package/src/fx-header.js +20 -0
  26. package/src/fx-instance.js +54 -10
  27. package/src/fx-model.js +175 -38
  28. package/src/fx-submission.js +235 -53
  29. package/src/getInScopeContext.js +2 -3
  30. package/src/ui/abstract-control.js +23 -44
  31. package/src/ui/fx-alert.js +20 -19
  32. package/src/ui/fx-container.js +9 -4
  33. package/src/ui/fx-control.js +92 -37
  34. package/src/ui/fx-inspector.js +44 -0
  35. package/src/ui/fx-items.js +104 -20
  36. package/src/ui/fx-output.js +92 -3
  37. package/src/ui/fx-repeat.js +87 -80
  38. package/src/ui/fx-repeatitem.js +38 -48
  39. package/src/ui/fx-trigger.js +49 -27
  40. package/src/xpath-evaluation.js +533 -235
  41. package/src/xpath-util.js +50 -12
package/src/fx-fore.js CHANGED
@@ -2,21 +2,36 @@ import { Fore } from './fore.js';
2
2
  import './fx-instance.js';
3
3
  import './fx-model.js';
4
4
  import '@jinntec/jinn-toast';
5
- import { evaluateXPathToNodes, evaluateTemplateExpression } from './xpath-evaluation.js';
5
+ import { evaluateXPathToNodes, evaluateXPathToString } from './xpath-evaluation.js';
6
+ import getInScopeContext from './getInScopeContext.js';
7
+ import { XPathUtil } from './xpath-util.js';
6
8
 
7
9
  /**
8
- * Root element for forms. Kicks off initialization and displays messages.
10
+ * Main class for Fore.Outermost container element for each Fore application.
11
+ *
12
+ * Root element for Fore. Kicks off initialization and displays messages.
9
13
  *
10
14
  * fx-fore is the outermost container for each form. A form can have exactly one model
11
15
  * with arbitrary number of instances.
12
16
  *
13
- * Main responsiblities are initialization of model, update of UI (refresh) and global messaging
17
+ * Main responsiblities are initialization and updating of model and instances, update of UI (refresh) and global messaging.
18
+ *
19
+ *
14
20
  *
15
21
  * @ts-check
16
22
  */
17
23
  export class FxFore extends HTMLElement {
18
24
  static get properties() {
19
25
  return {
26
+ /**
27
+ * Setting this marker attribute will refresh the UI in a lazy fashion just updating elements being
28
+ * in viewport.
29
+ *
30
+ * this feature is still experimental and should be used with caution and extra testing
31
+ */
32
+ lazyRefresh: {
33
+ type: Boolean,
34
+ },
20
35
  model: {
21
36
  type: Object,
22
37
  },
@@ -26,6 +41,14 @@ export class FxFore extends HTMLElement {
26
41
  };
27
42
  }
28
43
 
44
+ /**
45
+ * attaches handlers for
46
+ *
47
+ * - `model-construct-done` to trigger the processing of the UI
48
+ * - `message` - to display a message triggered by an fx-message action
49
+ * - `error` - to display an error message
50
+ * - 'compute-exception` - warn about circular dependencies in graph
51
+ */
29
52
  constructor() {
30
53
  super();
31
54
  this.model = {};
@@ -37,10 +60,11 @@ export class FxFore extends HTMLElement {
37
60
  });
38
61
 
39
62
  this.ready = false;
63
+ this.storedTemplateExpressionByNode = new Map();
40
64
 
41
65
  const style = `
42
66
  :host {
43
- display: block;
67
+ display: none;
44
68
  height:auto;
45
69
  padding:var(--model-element-padding);
46
70
  font-family:Roboto, sans-serif;
@@ -49,6 +73,11 @@ export class FxFore extends HTMLElement {
49
73
  :host ::slotted(fx-model){
50
74
  display:none;
51
75
  }
76
+ :host(.fx-ready){
77
+ animation: fadein .4s forwards;
78
+ display:block;
79
+ }
80
+
52
81
  #modalMessage .dialogActions{
53
82
  text-align:center;
54
83
  }
@@ -111,12 +140,19 @@ export class FxFore extends HTMLElement {
111
140
  #messageContent{
112
141
  margin-top:40px;
113
142
  }
114
-
115
-
143
+ @keyframes fadein {
144
+ 0% {
145
+ opacity:0;
146
+ }
147
+ 100% {
148
+ opacity:1;
149
+ }
150
+ }
116
151
  `;
117
152
 
118
153
  const html = `
119
154
  <jinn-toast id="message" gravity="bottom" position="left"></jinn-toast>
155
+ <jinn-toast id="error" text="error" duration="-1" data-class="error" close="true" position="left" gravity="bottom"></jinn-toast>
120
156
  <slot></slot>
121
157
  <div id="modalMessage" class="overlay">
122
158
  <div class="popup">
@@ -137,6 +173,16 @@ export class FxFore extends HTMLElement {
137
173
  }
138
174
 
139
175
  connectedCallback() {
176
+ this.lazyRefresh = this.hasAttribute('refresh-on-view');
177
+ if (this.lazyRefresh) {
178
+ const options = {
179
+ root: null,
180
+ rootMargin: '0px',
181
+ threshold: 0.3,
182
+ };
183
+ this.intersectionObserver = new IntersectionObserver(this.handleIntersect, options);
184
+ }
185
+
140
186
  const slot = this.shadowRoot.querySelector('slot');
141
187
  slot.addEventListener('slotchange', event => {
142
188
  const children = event.target.assignedElements();
@@ -149,18 +195,62 @@ export class FxFore extends HTMLElement {
149
195
  modelElement = generatedModel;
150
196
  }
151
197
  if (!modelElement.inited) {
152
- console.log('########## FORE: kick off processing... ##########');
198
+ console.log(
199
+ `########## FORE: kick off processing for ... ${window.location.href} ##########`,
200
+ );
153
201
  modelElement.modelConstruct();
154
202
  }
155
203
  this.model = modelElement;
156
204
  });
157
205
  }
158
206
 
207
+ /**
208
+ * refreshes the UI by using IntersectionObserver API. This is the handler being called
209
+ * by the observer whenever elements come into / move out of viewport.
210
+ * @param entries
211
+ * @param observer
212
+ */
213
+ handleIntersect(entries, observer) {
214
+ console.time('refreshLazy');
215
+ entries.forEach(entry => {
216
+ const { target } = entry;
217
+
218
+ if (entry.isIntersecting) {
219
+ console.log('in view', entry);
220
+ // console.log('repeat in view entry', entry.target);
221
+ // const target = entry.target;
222
+ // if(target.hasAttribute('refresh-on-view')){
223
+ target.classList.add('loaded');
224
+ // }
225
+
226
+ // todo: too restrictive here? what if target is a usual html element? shouldn't it refresh downwards?
227
+ if (typeof target.refresh === 'function') {
228
+ console.log('refreshing target', target);
229
+ target.refresh(target, true);
230
+ } else {
231
+ console.log('refreshing children', target);
232
+ Fore.refreshChildren(target, true);
233
+ }
234
+ }
235
+ });
236
+ entries[0].target.getOwnerForm().dispatchEvent(new CustomEvent('refresh-done'));
237
+
238
+ console.timeEnd('refreshLazy');
239
+ }
240
+
159
241
  evaluateToNodes(xpath, context) {
160
242
  return evaluateXPathToNodes(xpath, context, this);
161
243
  }
162
244
 
163
- disconnectedCallback() {}
245
+ disconnectedCallback() {
246
+ /*
247
+ this.removeEventListener('model-construct-done', this._handleModelConstructDone);
248
+ this.removeEventListener('message', this._displayMessage);
249
+ this.removeEventListener('error', this._displayError);
250
+ this.storedTemplateExpressionByNode=null;
251
+ this.shadowRoot = undefined;
252
+ */
253
+ }
164
254
 
165
255
  /**
166
256
  * refreshes the whole UI by visiting each bound element (having a 'ref' attribute) and applying the state of
@@ -170,16 +260,39 @@ export class FxFore extends HTMLElement {
170
260
  * AVT:
171
261
  *
172
262
  */
173
- async refresh() {
263
+ async refresh(force) {
174
264
  // refresh () {
175
265
  console.group('### refresh');
176
- // await this.updateComplete;
177
266
 
178
- Fore.refreshChildren(this);
179
- // this.dispatchEvent(new CustomEvent('refresh-done', {detail:'foo'}));
267
+ console.time('refresh');
268
+
269
+ /*
270
+ const changedModelItems = this.getModel().changed;
271
+ const graph = this.getModel().mainGraph;
272
+ let doRefresh = true;
273
+ changedModelItems.forEach(item => {
274
+ if(graph.hasNode(item.path)) {
275
+ const deps = graph.dependentsOf(item.path, false);
276
+ if (deps.length === 0) {
277
+ doRefresh=false;
278
+ }
279
+ }
280
+ });
281
+ this.getModel().changed = [];
282
+
283
+ if (!doRefresh) {
284
+ this.dispatchEvent(new CustomEvent('refresh-done'));
285
+ return ;
286
+ }
287
+ */
288
+ // ### refresh Fore UI elements
289
+ console.time('refreshChildren');
290
+ Fore.refreshChildren(this, true);
291
+ console.timeEnd('refreshChildren');
180
292
 
181
293
  // ### refresh template expressions
182
294
  this._updateTemplateExpressions();
295
+ console.timeEnd('refresh');
183
296
 
184
297
  console.groupEnd();
185
298
  console.log('### <<<<< dispatching refresh-done - end of UI update cycle >>>>>');
@@ -189,7 +302,7 @@ export class FxFore extends HTMLElement {
189
302
  /**
190
303
  * entry point for processing of template expression enclosed in '{}' brackets.
191
304
  *
192
- * Expressions are found with an XPath search. For each node an entry is added to storedTemplateExpressions array.
305
+ * Expressions are found with an XPath search. For each node an entry is added to the storedTemplateExpressionByNode map.
193
306
  *
194
307
  *
195
308
  * @private
@@ -197,9 +310,9 @@ export class FxFore extends HTMLElement {
197
310
  _updateTemplateExpressions() {
198
311
  // Note the fact we're going over HTML here: therefore the `html` prefix.
199
312
  const search =
200
- "(descendant-or-self::*/(text(), @*))[matches(.,'\\{.*\\}')] except descendant-or-self::xhtml:fx-model/descendant-or-self::node()/(., @*)";
313
+ "(descendant-or-self::*/(text(), @*))[matches(.,'\\{.*\\}')] except descendant-or-self::fx-model/descendant-or-self::node()/(., @*)";
201
314
 
202
- const tmplExpressions = evaluateXPathToNodes(search, this, null);
315
+ const tmplExpressions = evaluateXPathToNodes(search, this, this);
203
316
  console.log('template expressions found ', tmplExpressions);
204
317
 
205
318
  if (!this.storedTemplateExpressions) {
@@ -210,28 +323,93 @@ export class FxFore extends HTMLElement {
210
323
  storing expressions and their nodes for re-evaluation
211
324
  */
212
325
  Array.from(tmplExpressions).forEach(node => {
326
+ if (this.storedTemplateExpressionByNode.has(node)) {
327
+ // If the node is already known, do not process it twice
328
+ return;
329
+ }
213
330
  const expr = this._getTemplateExpression(node);
214
- this.storedTemplateExpressions.push({
215
- expr,
216
- node,
217
- });
218
- });
219
331
 
220
- this.storedTemplateExpressions.forEach(tmpl => {
221
- this._processTemplateExpression(tmpl);
332
+ this.storedTemplateExpressionByNode.set(node, expr);
222
333
  });
223
334
 
224
- console.log('stored template expressions ', this.storedTemplateExpressions);
335
+ // TODO: Should we clean up nodes that existed but are now gone?
336
+ for (const node of this.storedTemplateExpressionByNode.keys()) {
337
+ this._processTemplateExpression({
338
+ node,
339
+ expr: this.storedTemplateExpressionByNode.get(node),
340
+ });
341
+ }
342
+
343
+ console.log('stored template expressions ', this.storedTemplateExpressionByNode);
225
344
  }
226
345
 
227
346
  // eslint-disable-next-line class-methods-use-this
228
347
  _processTemplateExpression(exprObj) {
229
- console.log('processing template expression ', exprObj);
348
+ // console.log('processing template expression ', exprObj);
230
349
 
231
350
  const { expr } = exprObj;
232
351
  const { node } = exprObj;
233
352
  // console.log('expr ', expr);
234
- evaluateTemplateExpression(expr, node, this);
353
+ this.evaluateTemplateExpression(expr, node, this);
354
+ }
355
+
356
+ /**
357
+ * evaluate a template expression (some expression in {} brackets) on a node (either text- or attribute node.
358
+ * @param expr the XPath to evaluate
359
+ * @param node the node which will get updated with evaluation result
360
+ * @param form the form element
361
+ */
362
+ evaluateTemplateExpression(expr, node) {
363
+ if (expr === '{}') return;
364
+ const matches = expr.match(/{[^}]*}/g);
365
+ const namespaceContextNode =
366
+ node.nodeType === node.TEXT_NODE ? node.parentNode : node.ownerElement;
367
+ if (matches) {
368
+ matches.forEach(match => {
369
+ // console.log('match ', match);
370
+ let naked = match.substring(1, match.length - 1);
371
+ const inscope = getInScopeContext(node, naked);
372
+ if (!inscope) {
373
+ const errNode =
374
+ node.nodeType === Node.TEXT_NODE || node.nodeType === Node.ATTRIBUTE_NODE
375
+ ? node.parentNode
376
+ : node;
377
+ console.warn('no inscope context for ', errNode);
378
+ return;
379
+ }
380
+ // Templates are special: they use the namespace configuration from the place where they are
381
+ // being defined
382
+ const instanceId = XPathUtil.getInstanceId(naked);
383
+ // console.log('target instance ', instanceId);
384
+ const inst = this.getModel().getInstance(instanceId);
385
+ try {
386
+ const result = evaluateXPathToString(naked, inscope, node, null, inst);
387
+
388
+ // console.log('result of eval ', result);
389
+ const replaced = expr.replaceAll(match, result);
390
+ // console.log('result of replacing ', replaced);
391
+
392
+ if (node.nodeType === Node.ATTRIBUTE_NODE) {
393
+ const parent = node.ownerElement;
394
+
395
+ // parent.setAttribute(name, replaced);
396
+ parent.setAttribute(node.nodeName, replaced);
397
+ } else if (node.nodeType === Node.TEXT_NODE) {
398
+ node.textContent = replaced;
399
+ }
400
+
401
+ if (replaced.includes('{')) {
402
+ // console.log('need to go next round');
403
+
404
+ // todo: duplicated code here - see above
405
+ naked = replaced.substring(1, replaced.length);
406
+ this.evaluateTemplateExpression(replaced, node);
407
+ }
408
+ } catch (error) {
409
+ this.dispatchEvent(new CustomEvent('error', { detail: error }));
410
+ }
411
+ });
412
+ }
235
413
  }
236
414
 
237
415
  // eslint-disable-next-line class-methods-use-this
@@ -240,25 +418,28 @@ export class FxFore extends HTMLElement {
240
418
  return node.value;
241
419
  }
242
420
  if (node.nodeType === Node.TEXT_NODE) {
243
- return node.textContent;
421
+ return node.textContent.trim();
244
422
  }
245
423
  return null;
246
424
  }
247
425
 
248
- _refreshChildren() {
249
- const uiElements = this.querySelectorAll('*');
250
-
251
- uiElements.forEach(element => {
252
- if (Fore.isUiElement(element.nodeName) && typeof element.refresh === 'function') {
253
- element.refresh();
254
- }
255
- });
256
- }
257
-
426
+ /**
427
+ * called when `model-construct-done` event is received to
428
+ * start initing of the UI.
429
+ *
430
+ * @private
431
+ */
258
432
  _handleModelConstructDone() {
259
433
  this._initUI();
260
434
  }
261
435
 
436
+ /**
437
+ * If there's no instance element found in a fx-model during init it will construct
438
+ * an instance from UI bindings.
439
+ *
440
+ * @returns {Promise<void>}
441
+ * @private
442
+ */
262
443
  async _lazyCreateInstance() {
263
444
  const model = this.querySelector('fx-model');
264
445
  if (model.instances.length === 0) {
@@ -318,50 +499,70 @@ export class FxFore extends HTMLElement {
318
499
  }
319
500
 
320
501
  /*
321
- _createStep(){
502
+ _createStep(){
322
503
 
323
- }
324
- */
504
+ }
505
+ */
325
506
 
326
507
  /*
327
- _generateInstance(start, parent) {
328
- if (start.hasAttribute('ref')) {
329
- const ref = start.getAttribute('ref');
508
+ _generateInstance(start, parent) {
509
+ if (start.hasAttribute('ref')) {
510
+ const ref = start.getAttribute('ref');
330
511
 
331
- if(ref.includes('/')){
332
- console.log('complex path to create ', ref);
333
- const steps = ref.split('/');
334
- steps.forEach(step => {
335
- console.log('step ', step);
512
+ if(ref.includes('/')){
513
+ console.log('complex path to create ', ref);
514
+ const steps = ref.split('/');
515
+ steps.forEach(step => {
516
+ console.log('step ', step);
336
517
 
337
518
 
338
- });
339
- }
340
-
341
- // const generated = document.createElement(ref);
342
- const generated = parent.ownerDocument.createElement(ref);
343
- if (start.children.length === 0) {
344
- generated.textContent = start.textContent;
345
- }
346
- parent.appendChild(generated);
347
- parent = generated;
348
- }
519
+ });
520
+ }
349
521
 
350
- if (start.hasChildNodes()) {
351
- const list = start.children;
352
- for (let i = 0; i < list.length; i += 1) {
353
- this._generateInstance(list[i], parent);
522
+ // const generated = document.createElement(ref);
523
+ const generated = parent.ownerDocument.createElement(ref);
524
+ if (start.children.length === 0) {
525
+ generated.textContent = start.textContent;
526
+ }
527
+ parent.appendChild(generated);
528
+ parent = generated;
529
+ }
530
+
531
+ if (start.hasChildNodes()) {
532
+ const list = start.children;
533
+ for (let i = 0; i < list.length; i += 1) {
534
+ this._generateInstance(list[i], parent);
535
+ }
536
+ }
537
+ return parent;
354
538
  }
355
- }
356
- return parent;
357
- }
358
- */
539
+ */
359
540
 
541
+ /**
542
+ * Start the initialization of the UI by
543
+ *
544
+ * 1. checking if a instance needs to be generated
545
+ * 2. attaching lazy loading intersection observers if `refresh-on-view` attributes are found
546
+ * 3. doing a full refresh of the UI
547
+ *
548
+ * @returns {Promise<void>}
549
+ * @private
550
+ */
360
551
  async _initUI() {
361
552
  console.log('### _initUI()');
362
553
 
363
554
  await this._lazyCreateInstance();
555
+
556
+ const options = {
557
+ root: null,
558
+ rootMargin: '0px',
559
+ threshold: 0.3,
560
+ };
561
+
364
562
  await this.refresh();
563
+ // this.style.display='block'
564
+ this.classList.add('fx-ready');
565
+
365
566
  this.ready = true;
366
567
  console.log('### <<<<< dispatching ready >>>>>');
367
568
  console.log('########## modelItems: ', this.getModel().modelItems);
@@ -369,6 +570,19 @@ export class FxFore extends HTMLElement {
369
570
  this.dispatchEvent(new CustomEvent('ready', {}));
370
571
  }
371
572
 
573
+ registerLazyElement(element) {
574
+ if (this.intersectionObserver) {
575
+ // console.log('registerLazyElement',element);
576
+ this.intersectionObserver.observe(element);
577
+ }
578
+ }
579
+
580
+ unRegisterLazyElement(element) {
581
+ if (this.intersectionObserver) {
582
+ this.intersectionObserver.unobserve(element);
583
+ }
584
+ }
585
+
372
586
  /**
373
587
  *
374
588
  * @returns {FxModel}
@@ -386,7 +600,9 @@ export class FxFore extends HTMLElement {
386
600
  _displayError(e) {
387
601
  // const { error } = e.detail;
388
602
  const msg = e.detail.message;
389
- this._showMessage('modal', msg);
603
+ // this._showMessage('modal', msg);
604
+ const toast = this.shadowRoot.querySelector('#error');
605
+ toast.showToast(msg);
390
606
  }
391
607
 
392
608
  _showMessage(level, msg) {
@@ -0,0 +1,20 @@
1
+ import { foreElementMixin } from './ForeElementMixin.js';
2
+
3
+ export class FxHeader extends foreElementMixin(HTMLElement) {
4
+ constructor() {
5
+ super();
6
+ this.style.display = 'none';
7
+ this.attachShadow({ mode: 'open' });
8
+ this.shadowRoot.innerHTML = ``;
9
+
10
+ if (!this.hasAttribute('name')) {
11
+ throw new Error('required attribute "name" missing');
12
+ }
13
+ this.name = this.getAttribute('name');
14
+ }
15
+
16
+ connectedCallback() {
17
+ this.shadowRoot.innerHTML = ``;
18
+ }
19
+ }
20
+ customElements.define('fx-header', FxHeader);
@@ -1,3 +1,4 @@
1
+ import { Fore } from './fore.js';
1
2
  import { evaluateXPathToFirstNode } from './xpath-evaluation.js';
2
3
 
3
4
  /**
@@ -82,9 +83,20 @@ export class FxInstance extends HTMLElement {
82
83
  * @returns {Document | T | any}
83
84
  */
84
85
  getInstanceData() {
86
+ if (!this.instanceData) {
87
+ this._createInstanceData();
88
+ }
85
89
  return this.instanceData;
86
90
  }
87
91
 
92
+ setInstanceData(data) {
93
+ if (!data) {
94
+ this._createInstanceData();
95
+ return;
96
+ }
97
+ this.instanceData = data;
98
+ }
99
+
88
100
  /**
89
101
  * return the default context (root node of respective instance) for XPath evalution.
90
102
  *
@@ -121,7 +133,7 @@ export class FxInstance extends HTMLElement {
121
133
  root.appendChild(newNode);
122
134
  }
123
135
  this.instanceData = doc;
124
- this.instanceData.firstElementChild.setAttribute('id', this.id);
136
+ // this.instanceData.firstElementChild.setAttribute('id', this.id);
125
137
  // resolve('done');
126
138
  } else if (this.src) {
127
139
  await this._loadData();
@@ -130,13 +142,25 @@ export class FxInstance extends HTMLElement {
130
142
  }
131
143
  }
132
144
 
145
+ _createInstanceData() {
146
+ if (this.type === 'xml') {
147
+ // const doc = new DOMParser().parseFromString('<data data-id="default"></data>', 'application/xml');
148
+ const doc = new DOMParser().parseFromString('<data></data>', 'application/xml');
149
+ this.instanceData = doc;
150
+ }
151
+ if (this.type === 'json') {
152
+ this.instanceData = {};
153
+ }
154
+ }
155
+
133
156
  async _loadData() {
134
157
  const url = `${this.src}`;
135
- const contentType = this._getContentType();
158
+ const contentType = Fore.getContentType(this, 'get');
159
+
136
160
  await fetch(url, {
137
161
  method: 'GET',
138
162
  mode: 'cors',
139
- credentials: 'same-origin',
163
+ credentials: 'include',
140
164
  headers: {
141
165
  'Content-Type': contentType,
142
166
  },
@@ -144,7 +168,19 @@ export class FxInstance extends HTMLElement {
144
168
  .then(response => {
145
169
  const responseContentType = response.headers.get('content-type').toLowerCase();
146
170
  console.log('********** responseContentType *********', responseContentType);
147
- if (responseContentType.startsWith('text/plain')) {
171
+ if (responseContentType.startsWith('text/html')) {
172
+ // const htmlResponse = response.text();
173
+ // return new DOMParser().parseFromString(htmlResponse, 'text/html');
174
+ // return response.text();
175
+ return response.text().then(result =>
176
+ // console.log('xml ********', result);
177
+ new DOMParser().parseFromString(result, 'text/html'),
178
+ );
179
+ }
180
+ if (
181
+ responseContentType.startsWith('text/plain') ||
182
+ responseContentType.startsWith('text/markdown')
183
+ ) {
148
184
  // console.log("********** inside res plain *********");
149
185
  return response.text();
150
186
  }
@@ -153,16 +189,20 @@ export class FxInstance extends HTMLElement {
153
189
  return response.json();
154
190
  }
155
191
  if (responseContentType.startsWith('application/xml')) {
156
- return response.text().then(result => {
157
- console.log('xml ********', result);
158
- return new DOMParser().parseFromString(result, 'application/xml');
159
- });
192
+ return response.text().then(result =>
193
+ // console.log('xml ********', result);
194
+ new DOMParser().parseFromString(result, 'application/xml'),
195
+ );
160
196
  }
161
197
  return 'done';
162
198
  })
163
199
  .then(data => {
200
+ if (data.nodeType) {
201
+ this.instanceData = data;
202
+ console.log('instanceData loaded: ', this.instanceData);
203
+ return;
204
+ }
164
205
  this.instanceData = data;
165
- console.log('instanceData loaded: ', this.instanceData);
166
206
  })
167
207
  .catch(error => {
168
208
  throw new Error(`failed loading data ${error}`);
@@ -191,10 +231,14 @@ export class FxInstance extends HTMLElement {
191
231
  // console.log('instanceData ', this.instanceData.firstElementChild);
192
232
 
193
233
  console.log('fx-instance data: ', this.instanceData);
194
- this.instanceData.firstElementChild.setAttribute('id', this.id);
234
+ // this.instanceData.firstElementChild.setAttribute('id', this.id);
195
235
  // todo: move innerHTML out to shadowDOM (for later reset)
196
236
  } else if (this.type === 'json') {
197
237
  this.instanceData = JSON.parse(this.textContent);
238
+ } else if (this.type === 'html') {
239
+ this.instanceData = this.firstElementChild.children;
240
+ } else if (this.type === 'text') {
241
+ this.instanceData = this.textContent;
198
242
  } else {
199
243
  console.warn('unknow type for data ', this.type);
200
244
  }