@jinntec/fore 1.5.0 → 1.6.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 (71) hide show
  1. package/dist/fore-dev.js +2 -36
  2. package/dist/fore-dev.js.map +1 -1
  3. package/dist/fore.js +2 -30
  4. package/dist/fore.js.map +1 -1
  5. package/index.js +12 -0
  6. package/package.json +9 -5
  7. package/resources/fore.css +178 -92
  8. package/src/DependencyNotifyingDomFacade.js +1 -2
  9. package/src/ForeElementMixin.js +31 -5
  10. package/src/actions/abstract-action.js +379 -297
  11. package/src/actions/fx-action.js +0 -1
  12. package/src/actions/fx-append.js +1 -2
  13. package/src/actions/fx-confirm.js +12 -0
  14. package/src/actions/fx-copy.js +0 -1
  15. package/src/actions/fx-delete.js +31 -9
  16. package/src/actions/fx-dispatch.js +19 -5
  17. package/src/actions/fx-hide.js +19 -0
  18. package/src/actions/fx-insert.js +72 -8
  19. package/src/actions/fx-load.js +253 -0
  20. package/src/actions/fx-message.js +22 -7
  21. package/src/actions/fx-refresh.js +11 -1
  22. package/src/actions/fx-reload.js +12 -2
  23. package/src/actions/fx-replace.js +5 -4
  24. package/src/actions/fx-reset.js +48 -0
  25. package/src/actions/fx-return.js +0 -1
  26. package/src/actions/fx-send.js +40 -2
  27. package/src/actions/fx-setfocus.js +25 -7
  28. package/src/actions/fx-setvalue.js +32 -4
  29. package/src/actions/fx-show.js +14 -2
  30. package/src/actions/fx-toggle.js +0 -1
  31. package/src/actions/fx-update.js +9 -0
  32. package/src/events.js +0 -1
  33. package/src/fore.js +118 -63
  34. package/src/functions/common-function.js +28 -0
  35. package/src/fx-bind.js +7 -7
  36. package/src/fx-fore.js +152 -55
  37. package/src/fx-instance.js +55 -17
  38. package/src/fx-model.js +31 -33
  39. package/src/fx-submission.js +50 -47
  40. package/src/getInScopeContext.js +8 -10
  41. package/src/lab/fore-component.js +90 -0
  42. package/src/lab/instance-inspector.js +56 -0
  43. package/src/lab/template.html +16 -0
  44. package/src/relevance.js +27 -1
  45. package/src/tools/adi.js +1056 -0
  46. package/src/tools/fx-action-log.js +662 -0
  47. package/src/tools/fx-devtools.js +444 -0
  48. package/src/tools/fx-dom-inspector.js +609 -0
  49. package/src/tools/fx-json-instance.js +435 -0
  50. package/src/tools/fx-log-item.js +133 -0
  51. package/src/tools/fx-log-settings.js +474 -0
  52. package/src/tools/fx-minimap.js +194 -0
  53. package/src/tools/helpers.js +132 -0
  54. package/src/ui/abstract-control.js +41 -3
  55. package/src/ui/fx-action-log.js +358 -0
  56. package/src/ui/fx-alert.js +0 -1
  57. package/src/ui/fx-container.js +14 -3
  58. package/src/ui/fx-control.js +553 -474
  59. package/src/ui/fx-dialog.js +2 -0
  60. package/src/ui/fx-dom-inspector.js +1255 -0
  61. package/src/ui/fx-group.js +3 -4
  62. package/src/ui/fx-hint.js +2 -4
  63. package/src/ui/fx-inspector.js +5 -6
  64. package/src/ui/fx-items.js +55 -14
  65. package/src/ui/fx-output.js +36 -17
  66. package/src/ui/fx-repeat-attributes.js +10 -43
  67. package/src/ui/fx-repeat.js +5 -7
  68. package/src/ui/fx-switch.js +14 -3
  69. package/src/ui/fx-trigger.js +13 -1
  70. package/src/xpath-evaluation.js +109 -26
  71. package/src/xpath-util.js +55 -1
@@ -37,7 +37,6 @@ export class FxAction extends AbstractAction {
37
37
 
38
38
  if (this.src) {
39
39
  this.innerHTML = ''; // reset
40
- console.log('### fx-script.perform ');
41
40
  const script = document.createElement('script');
42
41
  script.src = this.src;
43
42
  this.appendChild(script);
@@ -15,6 +15,7 @@ import { resolveId } from '../xpath-evaluation.js';
15
15
  class FxAppend extends AbstractAction {
16
16
  static get properties() {
17
17
  return {
18
+ ...AbstractAction.properties,
18
19
  ref: {
19
20
  type: String,
20
21
  },
@@ -37,7 +38,6 @@ class FxAppend extends AbstractAction {
37
38
 
38
39
  connectedCallback() {
39
40
  super.connectedCallback();
40
- console.log('connectedCallback ', this);
41
41
  this.ref = this.getAttribute('ref');
42
42
  this.repeat = this.getAttribute('repeat');
43
43
  // this.repeated = this.closest('fx-repeatitem');
@@ -120,7 +120,6 @@ class FxAppend extends AbstractAction {
120
120
  */
121
121
  _dispatch() {
122
122
  const targetRepeat = resolveId(this.repeat, this);
123
- console.log('dispatching index change ', targetRepeat.nodeset.length);
124
123
  Fore.dispatch(targetRepeat, 'index-changed', { index: targetRepeat.nodeset.length });
125
124
  }
126
125
 
@@ -8,7 +8,19 @@ import {FxAction} from "./fx-action.js";
8
8
  * @demo demo/project.html
9
9
  */
10
10
  export class FxConfirm extends FxAction {
11
+ static get properties () {
12
+ return {
13
+ ...FxAction.properties,
14
+ message: {
15
+ type:String
16
+ }
17
+ };
18
+ }
19
+
11
20
  connectedCallback() {
21
+ if(super.connectedCallback){
22
+ super.connectedCallback();
23
+ }
12
24
  this.message = this.hasAttribute('message') ? this.getAttribute('message') : null;
13
25
  }
14
26
 
@@ -39,7 +39,6 @@ export default class FxCopy extends AbstractAction {
39
39
  }
40
40
 
41
41
  perform() {
42
- console.log('copying to clipboard')
43
42
  super.perform();
44
43
 
45
44
  if(this.nodeset.nodeType === Node.ATTRIBUTE_NODE){
@@ -1,7 +1,8 @@
1
+ import * as fx from "fontoxpath";
1
2
  import {AbstractAction} from './abstract-action.js';
2
3
  import {Fore} from '../fore.js';
3
- import {evaluateXPathToNodes} from "../xpath-evaluation.js";
4
- import {XPathUtil} from "../xpath-util";
4
+ import {evaluateXPathToNodes, evaluateXPathToString} from "../xpath-evaluation.js";
5
+ import {XPathUtil} from "../xpath-util.js";
5
6
  import getInScopeContext from '../getInScopeContext.js';
6
7
 
7
8
  /**
@@ -13,8 +14,13 @@ import getInScopeContext from '../getInScopeContext.js';
13
14
  * @demo demo/todo.html
14
15
  */
15
16
  class FxDelete extends AbstractAction {
16
- constructor() {
17
- super();
17
+ static get properties() {
18
+ return {
19
+ ...super.properties,
20
+ ref: {
21
+ type: String,
22
+ },
23
+ };
18
24
  }
19
25
 
20
26
  /**
@@ -23,13 +29,30 @@ class FxDelete extends AbstractAction {
23
29
  * Will NOT perform delete if nodeset is pointing to document node, document fragment, root node or being readonly.
24
30
  */
25
31
  async perform() {
26
- console.log('##### fx-delete executing...');
32
+
27
33
  const inscopeContext = getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
28
34
  this.nodeset = evaluateXPathToNodes(this.ref, inscopeContext, this);
29
35
 
30
- console.log('delete nodeset ', this.nodeset);
36
+ // console.log('delete nodeset ', this.nodeset);
37
+
38
+ const instanceId = XPathUtil.resolveInstance(this);
39
+ const instance = this.getModel().getInstance(instanceId);
40
+
41
+ // const path = instance && this.nodeset.length !== 0 ? evaluateXPathToString('path()', this.nodeset[0], instance) : '';
42
+
43
+ const path = Fore.getDomNodeIndexString(this.nodeset);
31
44
 
32
45
  const nodesToDelete = this.nodeset;
46
+
47
+ this.dispatchEvent(
48
+ new CustomEvent('execute-action', {
49
+ composed: true,
50
+ bubbles: true,
51
+ cancelable:true,
52
+ detail: { action: this, event:this.event, path:path},
53
+ }),
54
+ );
55
+
33
56
  let parent;
34
57
  if (Array.isArray(nodesToDelete)) {
35
58
  if(nodesToDelete.length === 0) return;
@@ -42,9 +65,8 @@ class FxDelete extends AbstractAction {
42
65
  this._deleteNode(parent, nodesToDelete);
43
66
  }
44
67
 
45
- const instanceId = XPathUtil.resolveInstance(this);
46
- const instance = this.getModel().getInstance(instanceId);
47
- Fore.dispatch(instance, 'deleted', {deletedNodes:nodesToDelete});
68
+
69
+ await Fore.dispatch(instance, 'deleted', {ref:path,deletedNodes:nodesToDelete});
48
70
  this.needsUpdate = true;
49
71
  }
50
72
 
@@ -10,6 +10,21 @@ import { evaluateXPath, resolveId } from '../xpath-evaluation.js';
10
10
  * can be accessed in usual JavaScript way.
11
11
  */
12
12
  export class FxDispatch extends AbstractAction {
13
+ static get properties() {
14
+ return {
15
+ ...super.properties,
16
+ name: {
17
+ type: String,
18
+ },
19
+ targetid: {
20
+ type: String,
21
+ },
22
+ details: {
23
+ type: String,
24
+ },
25
+ };
26
+ }
27
+
13
28
  constructor() {
14
29
  super();
15
30
  this.name = null;
@@ -53,12 +68,12 @@ export class FxDispatch extends AbstractAction {
53
68
  */
54
69
 
55
70
  async perform() {
56
- console.log('### fx-dispatch.perform ', this);
71
+ super.perform();
57
72
 
58
73
  const properties = this.querySelectorAll('fx-property');
59
74
  const details = {};
60
75
  Array.from(properties).forEach(prop => {
61
- console.log('prop ', prop);
76
+ // console.log('prop ', prop);
62
77
  const name = prop.getAttribute('name');
63
78
  const value = prop.getAttribute('value');
64
79
  const expr = prop.getAttribute('expr');
@@ -67,7 +82,7 @@ export class FxDispatch extends AbstractAction {
67
82
  if (value) {
68
83
  throw new Error('if "expr" is given there must not be a "value" attribute');
69
84
  }
70
- const [result] = evaluateXPath(expr, this.getInScopeContext(), this.getOwnerForm());
85
+ const [result] = evaluateXPath(expr, this.getInScopeContext(), this);
71
86
 
72
87
  let serialized = null;
73
88
  if (result.nodeName) {
@@ -86,7 +101,7 @@ export class FxDispatch extends AbstractAction {
86
101
  }
87
102
  });
88
103
 
89
- console.log('details ', details);
104
+ // console.log('details ', details);
90
105
 
91
106
  // ### when targetid is given dispatch to that if present (throw an error if not) - otherwise dispatch to document
92
107
  if (this.targetid) {
@@ -96,7 +111,6 @@ export class FxDispatch extends AbstractAction {
96
111
  // However, it may be that our target is elsewhere. Do a global search for that case
97
112
  target = document.getElementById(this.targetid);
98
113
  }
99
- console.log('target', target);
100
114
  if (!target) {
101
115
  throw new Error(`targetid ${this.targetid} does not exist in document`);
102
116
  }
@@ -10,7 +10,17 @@ import { resolveId } from '../xpath-evaluation.js';
10
10
  * @demo demo/project.html
11
11
  */
12
12
  export class FxHide extends AbstractAction {
13
+ static get properties() {
14
+ return {
15
+ ...super.properties,
16
+ dialog: {
17
+ type: String,
18
+ },
19
+ };
20
+ }
21
+
13
22
  connectedCallback() {
23
+ super.connectedCallback();
14
24
  this.dialog = this.getAttribute('dialog');
15
25
  if (!this.dialog) {
16
26
  Fore.dispatch(this, 'error', { message: 'dialog does not exist' });
@@ -18,6 +28,15 @@ export class FxHide extends AbstractAction {
18
28
  }
19
29
 
20
30
  async perform() {
31
+ this.dispatchEvent(
32
+ new CustomEvent('execute-action', {
33
+ composed: true,
34
+ bubbles: true,
35
+ cancelable:true,
36
+ detail: { action: this, event:this.event},
37
+ }),
38
+ );
39
+
21
40
  const dialog = resolveId(this.dialog, this);
22
41
  dialog.hide();
23
42
  Fore.dispatch(dialog,'dialog-hidden',{})
@@ -5,6 +5,8 @@ import {
5
5
  evaluateXPathToFirstNode,
6
6
  evaluateXPathToNumber,
7
7
  } from '../xpath-evaluation.js';
8
+ import {XPathUtil} from "../xpath-util";
9
+ import {Fore} from '../fore.js';
8
10
 
9
11
  /**
10
12
  * `fx-insert`
@@ -13,6 +15,24 @@ import {
13
15
  * @customElement
14
16
  */
15
17
  export class FxInsert extends AbstractAction {
18
+ static get properties() {
19
+ return {
20
+ ...super.properties,
21
+ at: {
22
+ type: Number,
23
+ },
24
+ position: {
25
+ type: Number,
26
+ },
27
+ origin: {
28
+ type: Object,
29
+ },
30
+ keepValues: {
31
+ type: Boolean,
32
+ },
33
+ };
34
+ }
35
+
16
36
  constructor() {
17
37
  super();
18
38
  this.attachShadow({ mode: 'open' });
@@ -40,6 +60,31 @@ export class FxInsert extends AbstractAction {
40
60
  this.keepValues = !!this.hasAttribute('keep-values');
41
61
  }
42
62
 
63
+ _getOriginSequence(inscope, targetSequence){
64
+ let originSequence;
65
+ if (this.origin) {
66
+ // ### if there's an origin attribute use it
67
+ let originTarget;
68
+ try {
69
+ originTarget = evaluateXPathToFirstNode(this.origin, inscope, this);
70
+ if (Array.isArray(originTarget) && originTarget.length === 0) {
71
+ console.warn('invalid origin for this insert action - ignoring...', this);
72
+ originSequence = null;
73
+ }
74
+ originSequence = originTarget;
75
+ } catch (error) {
76
+ console.warn('invalid origin for this insert action - ignoring...', this);
77
+ }
78
+ } else if (targetSequence) {
79
+ // ### use last item of targetSequence
80
+ originSequence = targetSequence;
81
+ if (originSequence && !this.keepValues) {
82
+ this._clear(originSequence);
83
+ }
84
+ }
85
+ return originSequence;
86
+ }
87
+
43
88
  _cloneOriginSequence(inscope, targetSequence) {
44
89
  let originSequenceClone;
45
90
  if (this.origin) {
@@ -52,7 +97,7 @@ export class FxInsert extends AbstractAction {
52
97
  // this.setInScopeVariables(this.detail);
53
98
 
54
99
  // originTarget = evaluateXPathToFirstNode(this.origin, inscope, this);
55
- originTarget = evaluateXPathToFirstNode(this.origin, inscope, this.getOwnerForm());
100
+ originTarget = evaluateXPathToFirstNode(this.origin, inscope, this);
56
101
  if (Array.isArray(originTarget) && originTarget.length === 0) {
57
102
  console.warn('invalid origin for this insert action - ignoring...', this);
58
103
  originSequenceClone = null;
@@ -76,13 +121,15 @@ export class FxInsert extends AbstractAction {
76
121
  return null;
77
122
  }
78
123
  if (this.hasAttribute('at')) {
79
- return evaluateXPathToNumber(this.getAttribute('at'), inscope, this.getOwnerForm());
124
+ return evaluateXPathToNumber(this.getAttribute('at'), inscope, this);
80
125
  }
81
126
  return targetSequence.length;
82
127
  }
83
128
 
84
129
  async perform() {
85
130
  // super.perform();
131
+ // as we're overwriting the superclass we need to dispatch the execute-action ourselves
132
+
86
133
 
87
134
  /*
88
135
  todo: !!! calling super here does not correctly give the nodeset - it's likely still a bug in ForeElementMixin !!!
@@ -104,10 +151,10 @@ export class FxInsert extends AbstractAction {
104
151
 
105
152
  if (this.hasAttribute('ref')) {
106
153
  if (inscope) {
107
- targetSequence = evaluateXPathToNodes(this.ref, inscope, this.getOwnerForm());
154
+ targetSequence = evaluateXPathToNodes(this.ref, inscope, this);
108
155
  } else {
109
156
  inscope = getInScopeContext(this.getAttributeNode('ref'), this.ref);
110
- targetSequence = evaluateXPathToNodes(this.ref, inscope, this.getOwnerForm());
157
+ targetSequence = evaluateXPathToNodes(this.ref, inscope, this);
111
158
  }
112
159
  }
113
160
  const originSequenceClone = this._cloneOriginSequence(inscope, targetSequence);
@@ -124,7 +171,6 @@ export class FxInsert extends AbstractAction {
124
171
  insertLocationNode = inscope;
125
172
  inscope.appendChild(originSequenceClone);
126
173
  index = 1;
127
- console.log('appended', inscope);
128
174
  } else {
129
175
  /* ### insert at position given by 'at' or use the last item in the targetSequence ### */
130
176
  if (this.hasAttribute('at')) {
@@ -132,7 +178,7 @@ export class FxInsert extends AbstractAction {
132
178
  // index = this.at;
133
179
  // insertLocationNode = targetSequence[this.at - 1];
134
180
 
135
- index = evaluateXPathToNumber(this.getAttribute('at'), inscope, this.getOwnerForm());
181
+ index = evaluateXPathToNumber(this.getAttribute('at'), inscope, this);
136
182
  insertLocationNode = targetSequence[index - 1];
137
183
  } else {
138
184
  // this.at = targetSequence.length;
@@ -179,9 +225,27 @@ export class FxInsert extends AbstractAction {
179
225
  // console.log('insert context item ', insertLocationNode);
180
226
  // console.log('parent ', insertLocationNode.parentNode);
181
227
  // console.log('instance ', this.getModel().getDefaultContext());
228
+ // Fore.dispatch()
229
+
230
+ const inst = this.getModel().getInstance(XPathUtil.resolveInstance(this));
231
+ // console.log('<<<<<<< resolved instance', inst);
232
+
233
+ const path = Fore.getDomNodeIndexString(originSequenceClone);
234
+ this.dispatchEvent(
235
+ new CustomEvent('execute-action', {
236
+ composed: true,
237
+ bubbles: true,
238
+ cancelable:true,
239
+ detail: { action: this, event:this.event, path },
240
+ }),
241
+ );
242
+
243
+ Fore.dispatch(inst,'insert',{
244
+ 'inserted-nodes': originSequenceClone,
245
+ 'insert-location-node': insertLocationNode,
246
+ 'position': this.position
247
+ });
182
248
 
183
- console.log('<<<<<<< at', this.at);
184
- console.log('<<<<<<< index', index);
185
249
  // todo: this actually should dispatch to respective instance
186
250
  document.dispatchEvent(
187
251
  // new CustomEvent('insert', {
@@ -0,0 +1,253 @@
1
+ import {AbstractAction} from './abstract-action.js';
2
+ import {evaluateXPathToString, resolveId} from "../xpath-evaluation.js";
3
+ import getInScopeContext from '../getInScopeContext.js';
4
+ import {XPathUtil} from "../xpath-util.js";
5
+ import {Fore} from "../fore.js";
6
+
7
+ /**
8
+ * `fx-message`
9
+ *
10
+ * Action to display messages to the user.
11
+ *
12
+ *
13
+ */
14
+ class FxLoad extends AbstractAction {
15
+
16
+ static get properties() {
17
+ return {
18
+ ...super.properties,
19
+ attachTo: {
20
+ type: String
21
+ },
22
+ url: {
23
+ type: String
24
+ }
25
+ }
26
+ }
27
+
28
+ constructor() {
29
+ super();
30
+ this.attachShadow({mode: 'open'});
31
+ this.url='';
32
+ }
33
+
34
+ connectedCallback() {
35
+ super.connectedCallback();
36
+ this.attachTo = this.hasAttribute('attach-to') ? this.getAttribute('attach-to') : '_self';
37
+
38
+ // Add a 'doneEvent' to block the action chain untill the event fired on the element we're
39
+ // loading something into.
40
+ this.awaitEvent = this.hasAttribute('await') ? this.getAttribute('await') : '';
41
+ this.url = this.hasAttribute('url') ? this.getAttribute('url') : '';
42
+ const style = `
43
+ :host{
44
+ display:none;
45
+ }
46
+ `;
47
+ this.shadowRoot.innerHTML = `
48
+ <style>
49
+ ${style}
50
+ </style>
51
+ ${this.renderHTML()}`;
52
+ }
53
+
54
+ disconnectedCallback() {
55
+ // super.disconnectedCallback();
56
+ this.targetElement.removeEventListener(this.event, e => this.execute(e));
57
+ }
58
+
59
+ // eslint-disable-next-line class-methods-use-this
60
+ renderHTML() {
61
+ return `
62
+ <slot></slot>
63
+ `;
64
+ }
65
+
66
+ async perform() {
67
+ await super.perform();
68
+
69
+ // this.getOwnerForm().evaluateTemplateExpression(this.urlContent, this);
70
+
71
+ const template = this.querySelector('template');
72
+ if(template){
73
+ const clone = template.content.cloneNode(true);
74
+ const content = document.importNode(clone, true);
75
+ // this._attachToElement(content);
76
+ if (this.attachTo.startsWith('#')) {
77
+ const targetId = this.attachTo.substring(1);
78
+ const resolved = resolveId(targetId, this);
79
+ // remove all children
80
+ while (resolved.firstChild) {
81
+ resolved.removeChild(resolved.firstChild);
82
+ }
83
+ if (this.awaitEvent) {
84
+ let resolveEvent;
85
+ const waitForEvent = new Promise((resolve) => {
86
+ resolveEvent = resolve;
87
+ });
88
+ const eventListener = () => {
89
+ resolveEvent();
90
+ resolved.removeEventListener(this.awaitEvent, eventListener);
91
+ };
92
+
93
+ resolved.appendChild(content);
94
+ resolved.addEventListener(this.awaitEvent, eventListener);
95
+
96
+ await waitForEvent;
97
+
98
+ this.needsUpdate = true;
99
+
100
+ Fore.dispatch(this, 'loaded', {attachPoint:this.attachTo, content});
101
+ return;
102
+ }
103
+
104
+ resolved.appendChild(content);
105
+
106
+ this.needsUpdate = true;
107
+ }
108
+ Fore.dispatch(this, 'loaded', {});
109
+ return;
110
+ }
111
+
112
+ if(!this.url){
113
+ // for authoring errors we log errors directly to DOM
114
+
115
+ this.dispatchEvent(
116
+ new CustomEvent('log', {
117
+ composed: false,
118
+ bubbles: true,
119
+ cancelable:true,
120
+ detail: { id:this.id, message: `neiter template element nor Url was specified.`, level:'Error'},
121
+ }),
122
+ );
123
+ return;
124
+ }
125
+ this.url = this.evaluateAttributeTemplateExpression(this.url,this);
126
+ if (this.attachTo === '_blank') {
127
+ window.open(this.url);
128
+ }
129
+
130
+ if (this.attachTo === '_self') {
131
+ window.location.href = this.url;
132
+ }
133
+
134
+ try {
135
+ const response = await fetch(this.url, {
136
+ method: 'GET',
137
+ mode: 'cors',
138
+ credentials: 'same-origin',
139
+ headers: {
140
+ 'Content-Type': "text/html",
141
+ },
142
+ });
143
+ const data = await response.text();
144
+ // console.log('data loaded: ', data);
145
+
146
+ // todo: if data contain '<template' element as first child instanciate and insert it
147
+ if (!this.attachTo) {
148
+ this.innerHtml = data;
149
+ }
150
+ /*
151
+ if (this.attachTo.startsWith('#')) {
152
+ const targetId = this.attachTo.substring(1);
153
+ const resolved = resolveId(targetId, this);
154
+ resolved.innerHTML = '';
155
+ resolved.innerHTML = data;
156
+ }
157
+ */
158
+ this._attachToElement(data);
159
+
160
+
161
+ Fore.dispatch(this, 'loaded', {url: this.url})
162
+
163
+ } catch (error) {
164
+ throw new Error(`failed loading data ${error}`);
165
+ }
166
+ }
167
+
168
+ _attachToElement(content){
169
+ let effectiveContent;
170
+ if(content.nodeType){
171
+ effectiveContent = content
172
+ }else{
173
+ try{
174
+ effectiveContent = new DOMParser().parseFromString(content, 'text/html').firstElementChild;
175
+ }catch (e) {
176
+ Fore.dispatch(this,'error',{message:'parsing of content as HTML failed'})
177
+ }
178
+ }
179
+
180
+ if(!(this.attachTo.startsWith('_')||this.attachTo.startsWith('#'))){
181
+ Fore.dispatch(this,'error',{message:'valid values for "attach-to" start with "_" or "#"'});
182
+ }
183
+
184
+ if (this.attachTo.startsWith('#')) {
185
+ const targetId = this.attachTo.substring(1);
186
+ const resolved = resolveId(targetId, this);
187
+ resolved.innerHTML = '';
188
+ // resolved.innerHTML = effectiveContent;
189
+ if(effectiveContent.querySelector('fx-fore')){
190
+ resolved.append(effectiveContent.querySelector('fx-fore').cloneNode(true));
191
+ return;
192
+ }
193
+ const body = effectiveContent.querySelector('body').cloneNode(true);
194
+ resolved.appendChild( body.firstElementChild);
195
+ }
196
+ }
197
+
198
+ _evaluateUrlExpression() {
199
+ const url = this.getAttribute('url');
200
+ if (!url) {
201
+ throw new Error('url not specified');
202
+ }
203
+
204
+ const replaced = url.replace(/{[^}]*}/g, match => {
205
+ if (match === '{}') return match;
206
+ const naked = match.substring(1, match.length - 1);
207
+ const inscope = getInScopeContext(this, naked);
208
+ if (!inscope) {
209
+ console.warn('no inscope context for ', this);
210
+ return match;
211
+ }
212
+ // Templates are special: they use the namespace configuration from the place where they are
213
+ // being defined
214
+ const instanceId = XPathUtil.getInstanceId(naked);
215
+
216
+ // If there is an instance referred
217
+ const inst = instanceId ? this.getModel().getInstance(instanceId) : this.getModel().getDefaultInstance();
218
+ try {
219
+ return evaluateXPathToString(naked, inscope, this, null, inst);
220
+ } catch (error) {
221
+ console.warn('ignoring unparseable url', error);
222
+ return match;
223
+ }
224
+ });
225
+ return replaced;
226
+ }
227
+
228
+
229
+ /*
230
+ _getValue() {
231
+ if (this.hasAttribute('value')) {
232
+ const valAttr = this.getAttribute('value');
233
+ try {
234
+ const inscopeContext = getInScopeContext(this, valAttr);
235
+ return evaluateXPathToString(valAttr, inscopeContext, this);
236
+ } catch (error) {
237
+ console.error(error);
238
+ Fore.dispatch(this, 'error', {message: error});
239
+ }
240
+ }
241
+ if (this.textContent) {
242
+ return this.textContent;
243
+ }
244
+ return null;
245
+ }
246
+ */
247
+
248
+
249
+ }
250
+
251
+ if (!customElements.get('fx-load')) {
252
+ window.customElements.define('fx-load', FxLoad);
253
+ }