@jinntec/fore 1.0.0-4 → 1.1.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 (66) hide show
  1. package/README.md +26 -38
  2. package/dist/fore-dev.js +43 -0
  3. package/dist/fore-dev.js.map +1 -0
  4. package/dist/fore.js +37 -0
  5. package/dist/fore.js.map +1 -0
  6. package/index.js +4 -0
  7. package/package.json +42 -42
  8. package/resources/fore.css +186 -0
  9. package/resources/toastify.css +87 -0
  10. package/resources/{fore-styles.css → vars.css} +0 -292
  11. package/src/DependencyNotifyingDomFacade.js +10 -16
  12. package/src/ForeElementMixin.js +26 -19
  13. package/src/actions/abstract-action.js +30 -9
  14. package/src/actions/fx-action.js +6 -4
  15. package/src/actions/fx-append.js +8 -17
  16. package/src/actions/fx-confirm.js +5 -3
  17. package/src/actions/fx-delete.js +6 -3
  18. package/src/actions/fx-dispatch.js +9 -8
  19. package/src/actions/fx-hide.js +10 -6
  20. package/src/actions/fx-insert.js +49 -39
  21. package/src/actions/fx-message.js +3 -1
  22. package/src/actions/fx-refresh.js +15 -1
  23. package/src/actions/fx-replace.js +73 -0
  24. package/src/actions/fx-return.js +42 -0
  25. package/src/actions/fx-send.js +3 -1
  26. package/src/actions/fx-setfocus.js +37 -0
  27. package/src/actions/fx-setvalue.js +58 -51
  28. package/src/actions/fx-show.js +12 -4
  29. package/src/actions/fx-toggle.js +15 -10
  30. package/src/actions/fx-update.js +3 -1
  31. package/src/dep_graph.js +4 -2
  32. package/src/drawdown.js +67 -82
  33. package/src/fore.js +158 -12
  34. package/src/functions/fx-function.js +17 -3
  35. package/src/fx-bind.js +42 -202
  36. package/src/fx-fore.js +599 -567
  37. package/src/fx-header.js +3 -1
  38. package/src/fx-instance.js +9 -1
  39. package/src/fx-model.js +59 -23
  40. package/src/fx-submission.js +106 -48
  41. package/src/fx-var.js +7 -4
  42. package/src/getInScopeContext.js +37 -11
  43. package/src/modelitem.js +4 -4
  44. package/src/relevance.js +64 -0
  45. package/src/ui/abstract-control.js +64 -37
  46. package/src/ui/fx-alert.js +7 -1
  47. package/src/ui/fx-case.js +4 -3
  48. package/src/ui/fx-container.js +7 -1
  49. package/src/ui/fx-control.js +309 -34
  50. package/src/ui/fx-dialog.js +54 -40
  51. package/src/ui/fx-group.js +3 -1
  52. package/src/ui/fx-hint.js +4 -1
  53. package/src/ui/fx-inspector.js +120 -17
  54. package/src/ui/fx-items.js +8 -8
  55. package/src/ui/fx-output.js +16 -5
  56. package/src/ui/fx-repeat.js +33 -41
  57. package/src/ui/fx-repeatitem.js +10 -4
  58. package/src/ui/fx-switch.js +5 -3
  59. package/src/ui/fx-trigger.js +3 -1
  60. package/src/xpath-evaluation.js +621 -576
  61. package/src/xpath-util.js +15 -8
  62. package/dist/fore-all.js +0 -140
  63. package/dist/fore-debug.js +0 -140
  64. package/src/.DS_Store +0 -0
  65. package/src/actions/.DS_Store +0 -0
  66. package/src/ui/.DS_Store +0 -0
package/src/fore.js CHANGED
@@ -127,7 +127,12 @@ export class Fore {
127
127
  const { children } = startElement;
128
128
  if (children) {
129
129
  Array.from(children).forEach(element => {
130
+ if (element.nodeName.toUpperCase() === 'FX-FORE') {
131
+ resolve('done');
132
+ }
130
133
  if (Fore.isUiElement(element.nodeName) && typeof element.refresh === 'function') {
134
+ // console.log('refreshing', element, element?.ref);
135
+ // console.log('refreshing ',element);
131
136
  element.refresh();
132
137
  } else if (element.nodeName.toUpperCase() !== 'FX-MODEL') {
133
138
  Fore.refreshChildren(element, force);
@@ -140,14 +145,21 @@ export class Fore {
140
145
  return refreshed;
141
146
  }
142
147
 
143
- static isRepeated(element) {
144
- return element.closest('fx-repeatitem') !== null;
145
- }
146
-
147
- static getRepeatTarget(element, id) {
148
- const repeatContextItem = element.closest('fx-repeatitem');
149
- const target = repeatContextItem.querySelector(`#${id}`);
150
- return target;
148
+ /**
149
+ * Alternative to `closest` that respects subcontrol boundaries
150
+ */
151
+ static getClosest(querySelector, start) {
152
+ while (!start.matches(querySelector)) {
153
+ if (start.matches('fx-fore')) {
154
+ // Subform reached. Bail out
155
+ return null;
156
+ }
157
+ start = start.parentNode;
158
+ if (!start) {
159
+ return null;
160
+ }
161
+ }
162
+ return start;
151
163
  }
152
164
 
153
165
  /**
@@ -190,8 +202,8 @@ export class Fore {
190
202
  return fadeIn();
191
203
  }
192
204
 
193
- static fadeOutElement(element) {
194
- const duration = 2600;
205
+ static fadeOutElement(element, duration) {
206
+ // const duration = duration;
195
207
  let fadeOut = () => {
196
208
  // Stop all current animations
197
209
  if (element.getAnimations) {
@@ -212,14 +224,148 @@ export class Fore {
212
224
 
213
225
  static dispatch(target, eventName, detail) {
214
226
  const event = new CustomEvent(eventName, {
215
- composed: true,
227
+ composed: false,
216
228
  bubbles: true,
217
229
  detail,
218
230
  });
219
- console.log('firing', event);
231
+ console.log('dispatching', event);
220
232
  target.dispatchEvent(event);
221
233
  }
222
234
 
235
+ static prettifyXml(source) {
236
+ const xmlDoc = new DOMParser().parseFromString(source, 'application/xml');
237
+ const xsltDoc = new DOMParser().parseFromString(
238
+ [
239
+ // describes how we want to modify the XML - indent everything
240
+ '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">',
241
+ ' <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>',
242
+ ' <xsl:strip-space elements="*"/>',
243
+ ' <xsl:template match="text()">', // change to just text() to strip space in text nodes
244
+ ' <xsl:value-of select="normalize-space(.)"/>',
245
+ ' </xsl:template>',
246
+ ' <xsl:template match="node()|@*">',
247
+ ' <xsl:copy>',
248
+ ' <xsl:apply-templates select="node()|@*"/>',
249
+ ' </xsl:copy>',
250
+ ' </xsl:template>',
251
+ '</xsl:stylesheet>',
252
+ ].join('\n'),
253
+ 'application/xml',
254
+ );
255
+
256
+
257
+ const xsltProcessor = new XSLTProcessor();
258
+ xsltProcessor.importStylesheet(xsltDoc);
259
+ const resultDoc = xsltProcessor.transformToDocument(xmlDoc);
260
+ const resultXml = new XMLSerializer().serializeToString(resultDoc);
261
+ return resultXml;
262
+ }
263
+
264
+ static formatXml (xml) {
265
+ var reg = /(>)(<)(\/*)/g;
266
+ var wsexp = / *(.*) +\n/g;
267
+ var contexp = /(<.+>)(.+\n)/g;
268
+ xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2');
269
+ var pad = 0;
270
+ var formatted = '';
271
+ var lines = xml.split('\n');
272
+ var indent = 0;
273
+ var lastType = 'other';
274
+ // 4 types of tags - single, closing, opening, other (text, doctype, comment) - 4*4 = 16 transitions
275
+ var transitions = {
276
+ 'single->single': 0,
277
+ 'single->closing': -1,
278
+ 'single->opening': 0,
279
+ 'single->other': 0,
280
+ 'closing->single': 0,
281
+ 'closing->closing': -1,
282
+ 'closing->opening': 0,
283
+ 'closing->other': 0,
284
+ 'opening->single': 1,
285
+ 'opening->closing': 0,
286
+ 'opening->opening': 1,
287
+ 'opening->other': 1,
288
+ 'other->single': 0,
289
+ 'other->closing': -1,
290
+ 'other->opening': 0,
291
+ 'other->other': 0
292
+ };
293
+
294
+ for (var i = 0; i < lines.length; i++) {
295
+ var ln = lines[i];
296
+ var single = Boolean(ln.match(/<.+\/>/)); // is this line a single tag? ex. <br />
297
+ var closing = Boolean(ln.match(/<\/.+>/)); // is this a closing tag? ex. </a>
298
+ var opening = Boolean(ln.match(/<[^!].*>/)); // is this even a tag (that's not <!something>)
299
+ var type = single ? 'single' : closing ? 'closing' : opening ? 'opening' : 'other';
300
+ var fromTo = lastType + '->' + type;
301
+ lastType = type;
302
+ var padding = '';
303
+
304
+ indent += transitions[fromTo];
305
+ for (var j = 0; j < indent; j++) {
306
+ padding += ' ';
307
+ }
308
+
309
+ formatted += padding + ln + '\n';
310
+ }
311
+ }
312
+
313
+ static async loadForeFromUrl(hostElement, url) {
314
+ console.log('########## loading Fore from ', this.src, '##########');
315
+ await fetch(url, {
316
+ method: 'GET',
317
+ mode: 'cors',
318
+ credentials: 'include',
319
+ headers: {
320
+ 'Content-Type': 'text/html',
321
+ },
322
+ })
323
+ .then(response => {
324
+ const responseContentType = response.headers.get('content-type').toLowerCase();
325
+ console.log('********** responseContentType *********', responseContentType);
326
+ if (responseContentType.startsWith('text/html')) {
327
+ return response.text().then(result =>
328
+ // console.log('xml ********', result);
329
+ new DOMParser().parseFromString(result, 'text/html'),
330
+ );
331
+ }
332
+ return 'done';
333
+ })
334
+ .then(data => {
335
+ // const theFore = fxEvaluateXPathToFirstNode('//fx-fore', data.firstElementChild);
336
+ const theFore = data.querySelector('fx-fore');
337
+ // console.log('thefore', theFore)
338
+ if (!theFore) {
339
+ hostElement.dispatchEvent(
340
+ new CustomEvent('error', {
341
+ composed: false,
342
+ bubbles: true,
343
+ detail: {
344
+ message: 'cyclic graph',
345
+ },
346
+ }),
347
+ );
348
+ }
349
+ hostElement.appendChild(theFore);
350
+ theFore.classList.add('widget');
351
+ // return theFore;
352
+ // theFore.setAttribute('from-src', this.src);
353
+ // this.replaceWith(theFore);
354
+ })
355
+ .catch(error => {
356
+ hostElement.dispatchEvent(
357
+ new CustomEvent('error', {
358
+ composed: false,
359
+ bubbles: true,
360
+ detail: {
361
+ error: error,
362
+ message: `'${url}' not found or does not contain Fore element.`,
363
+ },
364
+ }),
365
+ );
366
+ });
367
+ }
368
+
223
369
  /**
224
370
  * clear all text nodes and attribute values to get a 'clean' template.
225
371
  * @param n
@@ -1,6 +1,6 @@
1
1
  import { registerCustomXPathFunction } from 'fontoxpath';
2
2
  import { foreElementMixin } from '../ForeElementMixin.js';
3
- import { evaluateXPath } from '../xpath-evaluation.js';
3
+ import { evaluateXPath, globallyDeclaredFunctionLocalNames } from '../xpath-evaluation.js';
4
4
 
5
5
  /**
6
6
  * Allows to extend a form with local custom functions.
@@ -41,10 +41,16 @@ export class FxFunction extends foreElementMixin(HTMLElement) {
41
41
 
42
42
  // TODO: lookup prefix
43
43
  const functionIdentifier =
44
- prefix === 'local'
44
+ prefix === 'local' || !prefix
45
45
  ? { namespaceURI: 'http://www.w3.org/2005/xquery-local-functions', localName }
46
46
  : `${prefix}:${localName}`;
47
47
 
48
+ // Make the function available globally w/o a prefix. See the functionNameResolver for for how
49
+ // this is picked up
50
+ if (!prefix) {
51
+ globallyDeclaredFunctionLocalNames.push(localName);
52
+ }
53
+
48
54
  const paramParts = params
49
55
  ? params.split(',').map(param => {
50
56
  const match = param.match(/(?<variableName>\$[^\s]+)(?:\sas\s(?<varType>.+))/);
@@ -77,7 +83,12 @@ export class FxFunction extends foreElementMixin(HTMLElement) {
77
83
  break;
78
84
  }
79
85
 
86
+ case 'text/xquf':
87
+ case 'text/xquery':
80
88
  case 'text/xpath': {
89
+ const language = type === 'text/xpath' ?
90
+ 'XPath3.1' : type === 'text/xquery' ?
91
+ 'XQuery3.1' : 'XQueryUpdate3.1';
81
92
  const fun = (domFacade, ...args) =>
82
93
  evaluateXPath(
83
94
  this.functionBody,
@@ -87,6 +98,7 @@ export class FxFunction extends foreElementMixin(HTMLElement) {
87
98
  variablesByName[paramPart.variableName.replace('$', '')] = args[i];
88
99
  return variablesByName;
89
100
  }, {}),
101
+ {language}
90
102
  );
91
103
  registerCustomXPathFunction(
92
104
  functionIdentifier,
@@ -102,4 +114,6 @@ export class FxFunction extends foreElementMixin(HTMLElement) {
102
114
  }
103
115
  }
104
116
  }
105
- customElements.define('fx-function', FxFunction);
117
+ if (!customElements.get('fx-function')) {
118
+ customElements.define('fx-function', FxFunction);
119
+ }
package/src/fx-bind.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { DependencyNotifyingDomFacade } from './DependencyNotifyingDomFacade.js';
2
2
  import { foreElementMixin } from './ForeElementMixin.js';
3
+ import { Fore } from './fore.js';
3
4
  import { ModelItem } from './modelitem.js';
4
5
  import {
5
6
  evaluateXPathToBoolean,
@@ -32,98 +33,8 @@ export class FxBind extends foreElementMixin(HTMLElement) {
32
33
 
33
34
  static TYPE_DEFAULT = 'xs:string';
34
35
 
35
- /*
36
- static get styles() {
37
- return css`
38
- :host {
39
- display: none;
40
- }
41
- `;
42
- }
43
- */
44
-
45
- /*
46
- static get properties() {
47
- return {
48
- ...super.properties,
49
-
50
- /!**
51
- * allows to calculate a value. This value will become readonly.
52
- *!/
53
- calculate: {
54
- type: String
55
- },
56
- contextNode:{
57
- type:Object
58
- },
59
- /!**
60
- * arbitrary XPath resolving to xs:boolean - defaults to 'true()'
61
- *!/
62
- constraint: {
63
- type: String
64
- },
65
- /!**
66
- * id of this bind
67
- *!/
68
- id:{
69
- type:String
70
- },
71
- /!**
72
- * the nodeset the bind is referring to by it's binding expression (ref attribute)
73
- *!/
74
- nodeset: {
75
- type: Array
76
- },
77
- /!**
78
- * the owning model of this bind
79
- *!/
80
- model:{
81
- type:Object
82
- },
83
- /!**
84
- * XPath statement resolving to xs:boolean to switch between readonly and readwrite mode - defaults to 'false()'
85
- *!/
86
- readonly: {
87
- type: String
88
- },
89
- /!**
90
- * the XPath binding expression of this bind
91
- *!/
92
- ref: {
93
- type: String
94
- },
95
- /!**
96
- * XPath statement resolving to xs:boolean to switch between relevant and non-relevant mode - defaults to 'true()'
97
- *!/
98
- relevant: {
99
- type: String
100
- },
101
- /!**
102
- * XPath statement resolving to xs:boolean to switch between required and optional - defaults to 'false'.
103
- *!/
104
- required: {
105
- type: String
106
- },
107
- /!**
108
- * XPath statement
109
- *!/
110
- type: {
111
- type: String
112
- }
113
- };
114
- }
115
- */
116
-
117
36
  constructor() {
118
37
  super();
119
- // this.id='';
120
- // this.ref = '';
121
- // this.readonly = 'false()';
122
- // this.required = 'false()';
123
- // this.relevant = 'true()';
124
- // this.constraint = 'true()';
125
- // this.type = 'xs:string';
126
- // this.calculate = '';
127
38
  this.nodeset = [];
128
39
  this.model = {};
129
40
  this.contextNode = {};
@@ -165,26 +76,23 @@ export class FxBind extends foreElementMixin(HTMLElement) {
165
76
  this._processChildren(model);
166
77
  }
167
78
 
168
- /*
169
- //todo: certainly not ideal to rely on duplicating instance id on instance document - better way later ;)
170
- static getPath(node){
171
- let path = fx.evaluateXPath('path()',node);
172
- const instanceId = node.ownerDocument.firstElementChild.getAttribute('id');
173
- if(instanceId !== 'default'){
174
- return '#' + instanceId + FxBind.shortenPath(path);
175
- }else {
176
- return FxBind.shortenPath(path);
177
- }
178
-
179
- }
180
- */
181
-
182
79
  _buildBindGraph() {
183
80
  if (this.bindType === 'xml') {
184
81
  this.nodeset.forEach(node => {
185
82
  const path = XPathUtil.getPath(node);
186
83
  this.model.mainGraph.addNode(path, node);
187
84
 
85
+ /* ### catching references in the 'ref' itself...
86
+ todo: investigate cases where 'ref' attributes use predicates pointing to other nodes. These would not be handled
87
+ in current implementation.
88
+
89
+ General question: are there valid use-cases for using a 'filter' expression to narrow the nodeset
90
+ where to apply constraints? Guess yes and if it's 'just' for reducing the amount of necessary modelItem objects.
91
+
92
+
93
+ */
94
+ // const foreignRefs = this.getReferences(this.ref);
95
+
188
96
  if (this.calculate) {
189
97
  this.model.mainGraph.addNode(`${path}:calculate`, node);
190
98
  // Calculated values are a dependency of the model item.
@@ -251,7 +159,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
251
159
  // console.log('otherPath', otherPath)
252
160
 
253
161
  // todo: nasty hack to prevent duplicate pathes like 'a[1]' and 'a[1]/text()[1]' to end up as separate nodes in the graph
254
- if(!otherPath.endsWith('text()[1]')){
162
+ if (!otherPath.endsWith('text()[1]')) {
255
163
  if (!this.model.mainGraph.hasNode(otherPath)) {
256
164
  this.model.mainGraph.addNode(otherPath, ref);
257
165
  }
@@ -271,14 +179,6 @@ export class FxBind extends foreElementMixin(HTMLElement) {
271
179
  });
272
180
  }
273
181
 
274
- /*
275
- render() {
276
- return html`
277
- <slot></slot>
278
- `;
279
- }
280
- */
281
-
282
182
  getAlert() {
283
183
  if (this.hasAttribute('alert')) {
284
184
  return this.getAttribute('alert');
@@ -290,33 +190,6 @@ export class FxBind extends foreElementMixin(HTMLElement) {
290
190
  return null;
291
191
  }
292
192
 
293
- /*
294
- firstUpdated(_changedProperties) {
295
- super.firstUpdated(_changedProperties);
296
- }
297
- */
298
-
299
- /*
300
- namespaceResolver(prefix) {
301
- // TODO: Do proper namespace resolving. Look at the ancestry / namespacesInScope of the declaration
302
-
303
- /!**
304
- * for (let ancestor = this; ancestor; ancestor = ancestor.parentNode) {
305
- * if (ancestor.getAttribute(`xmlns:${prefix}`)) {
306
- * // Return value
307
- * }
308
- * }
309
- *!/
310
-
311
- // console.log('namespaceResolver prefix', prefix);
312
- const ns = {
313
- xhtml: 'http://www.w3.org/1999/xhtml',
314
- // '' : Fore.XFORMS_NAMESPACE_URI
315
- };
316
- return ns[prefix] || null;
317
- }
318
- */
319
-
320
193
  /**
321
194
  * overwrites
322
195
  */
@@ -335,7 +208,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
335
208
  } else {
336
209
  // eslint-disable-next-line no-lonely-if
337
210
  if (this.ref) {
338
- const localResult = evaluateXPathToNodes(this.ref, n, this.getOwnerForm());
211
+ const localResult = evaluateXPathToNodes(this.ref, n, this);
339
212
  localResult.forEach(item => {
340
213
  this.nodeset.push(item);
341
214
  });
@@ -351,7 +224,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
351
224
  } else {
352
225
  const inst = this.getModel().getInstance(this.instanceId);
353
226
  if (inst.type === 'xml') {
354
- this.nodeset = evaluateXPathToNodes(this.ref, inscopeContext, this.getOwnerForm());
227
+ this.nodeset = evaluateXPathToNodes(this.ref, inscopeContext, this);
355
228
  } else {
356
229
  this.nodeset = this.ref;
357
230
  }
@@ -361,11 +234,6 @@ export class FxBind extends foreElementMixin(HTMLElement) {
361
234
  _createModelItems() {
362
235
  // console.log('#### ', thi+s.nodeset);
363
236
 
364
- /*
365
- if(XPathUtil.isSelfReference(this.ref)){
366
- return;
367
- }
368
- */
369
237
  if (Array.isArray(this.nodeset)) {
370
238
  // todo - iterate and create
371
239
  // console.log('################################################ ', this.nodeset);
@@ -380,54 +248,6 @@ export class FxBind extends foreElementMixin(HTMLElement) {
380
248
  }
381
249
  }
382
250
 
383
- static lazyCreateModelitems(model, ref, nodeset) {
384
- if (Array.isArray(nodeset)) {
385
- Array.from(nodeset).forEach(n => {
386
- FxBind.lazyCreateModelItem(model, ref, n);
387
- });
388
- } else {
389
- FxBind.lazyCreateModelItem(model, ref, nodeset);
390
- }
391
- }
392
-
393
- /*
394
- static lazyCreateModelItem(model,ref,node){
395
- console.log('lazyCreateModelItem ', node);
396
-
397
- let mItem = {};
398
- let targetNode = {};
399
- if(node === null) return null;
400
- if(node.nodeType === node.TEXT_NODE){
401
- // const parent = node.parentNode;
402
- // console.log('PARENT ', parent);
403
- targetNode = node.parentNode;
404
- }else {
405
- targetNode = node;
406
- }
407
-
408
- // const path = fx.evaluateXPath('path()',node);
409
- const path = FxBind.getPath(node);
410
-
411
- // const path = Fore.evaluateXPath ('path()', node, this, Fore.namespaceResolver) ;
412
-
413
- // ### intializing ModelItem with default values (as there is no <fx-bind> matching for given ref)
414
- const mi = new ModelItem(path,
415
- ref,
416
- FxBind.READONLY_DEFAULT,
417
- FxBind.RELEVANT_DEFAULT,
418
- FxBind.REQUIRED_DEFAULT,
419
- FxBind.CONSTRAINT_DEFAULT,
420
- FxBind.TYPE_DEFAULT,
421
- targetNode,
422
- this);
423
-
424
-
425
- // console.log('new ModelItem is instanceof ModelItem ', mi instanceof ModelItem);
426
- model.registerModelItem(mi);
427
- return mi;
428
- }
429
- */
430
-
431
251
  /**
432
252
  * creates a ModelItem for given instance node.
433
253
  *
@@ -452,7 +272,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
452
272
  if bind is the dot expression we use the modelitem of the parent
453
273
  */
454
274
  if (XPathUtil.isSelfReference(this.ref)) {
455
- const parentBoundElement = this.parentElement.closest('fx-bind[ref]');
275
+ const parentBoundElement = Fore.getClosest('fx-bind[ref]', this.parentElement);
456
276
  console.log('parent bound element ', parentBoundElement);
457
277
 
458
278
  if (parentBoundElement) {
@@ -514,16 +334,34 @@ export class FxBind extends foreElementMixin(HTMLElement) {
514
334
  */
515
335
  _getReferencesForProperty(propertyExpr) {
516
336
  if (propertyExpr) {
517
- const touchedNodes = new Set();
518
- const domFacade = new DependencyNotifyingDomFacade(otherNode => touchedNodes.add(otherNode));
519
- this.nodeset.forEach(node => {
520
- evaluateXPathToString(propertyExpr, node, this.getOwnerForm(), domFacade);
521
- });
337
+ return this.getReferences(propertyExpr);
338
+ }
339
+ return [];
340
+ }
341
+
342
+ getReferences(propertyExpr) {
343
+ const touchedNodes = new Set();
344
+ const domFacade = new DependencyNotifyingDomFacade(otherNode => touchedNodes.add(otherNode));
345
+ this.nodeset.forEach(node => {
346
+ evaluateXPathToString(propertyExpr, node, this, domFacade);
347
+ });
348
+ return Array.from(touchedNodes.values());
349
+ }
350
+
351
+ /*
352
+ static getReferencesForRef(ref,nodeset){
353
+ if (ref && nodeset) {
354
+ const touchedNodes = new Set();
355
+ const domFacade = new DependencyNotifyingDomFacade(otherNode => touchedNodes.add(otherNode));
356
+ nodeset.forEach(node => {
357
+ evaluateXPathToString(ref, node, this, domFacade);
358
+ });
522
359
 
523
360
  return Array.from(touchedNodes.values());
524
361
  }
525
362
  return [];
526
363
  }
364
+ */
527
365
 
528
366
  _initBooleanModelItemProperty(property, node) {
529
367
  // evaluate expression to boolean
@@ -562,4 +400,6 @@ export class FxBind extends foreElementMixin(HTMLElement) {
562
400
  return 'default';
563
401
  }
564
402
  }
565
- customElements.define('fx-bind', FxBind);
403
+ if (!customElements.get('fx-bind')) {
404
+ customElements.define('fx-bind', FxBind);
405
+ }