@jinntec/fore 1.10.0 → 1.10.1

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.
@@ -418,6 +418,7 @@ function getVariablesInScope(formElement) {
418
418
  * @param {Node} contextNode The start of the XPath
419
419
  * @param {{parentNode}|ForeElementMixin} formElement The form element associated to the XPath
420
420
  */
421
+ /*
421
422
  export function evaluateXPath(xpath, contextNode, formElement, variables = {}, options={}, domFacade = null) {
422
423
  const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
423
424
  const variablesInScope = getVariablesInScope(formElement);
@@ -440,7 +441,59 @@ export function evaluateXPath(xpath, contextNode, formElement, variables = {}, o
440
441
  },
441
442
  );
442
443
  }
444
+ */
445
+ export function evaluateXPath(xpath, contextNode, formElement, variables = {}, options={}) {
446
+ try{
447
+ console.log('evaluateXPath',xpath);
448
+ const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
449
+ const variablesInScope = getVariablesInScope(formElement);
450
+
451
+ return fxEvaluateXPath(
452
+ xpath,
453
+ contextNode,
454
+ null,
455
+ {...variablesInScope, ...variables},
456
+ fxEvaluateXPath.ALL_RESULTS_TYPE,
457
+ {
458
+ debug: true,
459
+ currentContext: {formElement, variables},
460
+ moduleImports: {
461
+ xf: XFORMS_NAMESPACE_URI,
462
+ },
463
+ functionNameResolver,
464
+ namespaceResolver,
465
+ language: options.language || evaluateXPath.XPATH_3_1
466
+ },
467
+ );
468
+ }catch (e){
469
+ formElement.dispatchEvent(new CustomEvent('error', {
470
+ composed: false,
471
+ bubbles: true,
472
+ detail: {
473
+ origin: formElement,
474
+ message: `Expression '${xpath}' failed`,
475
+ expr:xpath,
476
+ level:'Error'
477
+ },
478
+ }));
443
479
 
480
+ /*
481
+ formElement.dispatchEvent(
482
+ new CustomEvent('error', {
483
+ composed: false,
484
+ bubbles: true,
485
+ cancelable:true,
486
+ detail: {
487
+ origin: formElement,
488
+ message: `Expression '${xpath}' failed`,
489
+ expr:xpath,
490
+ level:'Error'},
491
+ }),
492
+ );
493
+ */
494
+ return false;
495
+ }
496
+ }
444
497
  /**
445
498
  * Evaluate an XPath to the first Node
446
499
  *
@@ -450,17 +503,30 @@ export function evaluateXPath(xpath, contextNode, formElement, variables = {}, o
450
503
  * @return {Node} The first node found by the XPath
451
504
  */
452
505
  export function evaluateXPathToFirstNode(xpath, contextNode, formElement) {
453
- const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
454
- const variablesInScope = getVariablesInScope(formElement);
455
- return fxEvaluateXPathToFirstNode(xpath, contextNode, null, variablesInScope, {
456
- defaultFunctionNamespaceURI: XFORMS_NAMESPACE_URI,
457
- moduleImports: {
458
- xf: XFORMS_NAMESPACE_URI,
459
- },
460
- currentContext: {formElement},
461
- functionNameResolver,
462
- namespaceResolver,
463
- });
506
+ try{
507
+ const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
508
+ const variablesInScope = getVariablesInScope(formElement);
509
+ return fxEvaluateXPathToFirstNode(xpath, contextNode, null, variablesInScope, {
510
+ defaultFunctionNamespaceURI: XFORMS_NAMESPACE_URI,
511
+ moduleImports: {
512
+ xf: XFORMS_NAMESPACE_URI,
513
+ },
514
+ currentContext: {formElement},
515
+ functionNameResolver,
516
+ namespaceResolver,
517
+ });
518
+ } catch (e){
519
+ formElement.dispatchEvent(new CustomEvent('error', {
520
+ composed: false,
521
+ bubbles: true,
522
+ detail: {
523
+ origin: formElement,
524
+ message: `Expression '${xpath}' failed`,
525
+ expr:xpath,
526
+ level:'Error'
527
+ },
528
+ }));
529
+ }
464
530
  }
465
531
 
466
532
  /**
@@ -472,17 +538,30 @@ export function evaluateXPathToFirstNode(xpath, contextNode, formElement) {
472
538
  * @return {Node[]} All nodes
473
539
  */
474
540
  export function evaluateXPathToNodes(xpath, contextNode, formElement) {
475
- const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
476
- const variablesInScope = getVariablesInScope(formElement);
541
+ try{
542
+ const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
543
+ const variablesInScope = getVariablesInScope(formElement);
477
544
 
478
- return fxEvaluateXPathToNodes(xpath, contextNode, null, variablesInScope, {
479
- currentContext: {formElement},
480
- functionNameResolver,
481
- moduleImports: {
482
- xf: XFORMS_NAMESPACE_URI,
483
- },
484
- namespaceResolver,
485
- });
545
+ return fxEvaluateXPathToNodes(xpath, contextNode, null, variablesInScope, {
546
+ currentContext: {formElement},
547
+ functionNameResolver,
548
+ moduleImports: {
549
+ xf: XFORMS_NAMESPACE_URI,
550
+ },
551
+ namespaceResolver,
552
+ });
553
+ }catch (e){
554
+ formElement.dispatchEvent(new CustomEvent('error', {
555
+ composed: false,
556
+ bubbles: true,
557
+ detail: {
558
+ origin: formElement,
559
+ message: `Expression '${xpath}' failed`,
560
+ expr:xpath,
561
+ level:'Error'
562
+ },
563
+ }));
564
+ }
486
565
  }
487
566
 
488
567
  /**
@@ -494,17 +573,30 @@ export function evaluateXPathToNodes(xpath, contextNode, formElement) {
494
573
  * @return {boolean}
495
574
  */
496
575
  export function evaluateXPathToBoolean(xpath, contextNode, formElement) {
497
- const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
498
- const variablesInScope = getVariablesInScope(formElement);
576
+ try{
577
+ const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
578
+ const variablesInScope = getVariablesInScope(formElement);
499
579
 
500
- return fxEvaluateXPathToBoolean(xpath, contextNode, null, variablesInScope, {
501
- currentContext: {formElement},
502
- functionNameResolver,
503
- moduleImports: {
504
- xf: XFORMS_NAMESPACE_URI,
505
- },
506
- namespaceResolver,
507
- });
580
+ return fxEvaluateXPathToBoolean(xpath, contextNode, null, variablesInScope, {
581
+ currentContext: {formElement},
582
+ functionNameResolver,
583
+ moduleImports: {
584
+ xf: XFORMS_NAMESPACE_URI,
585
+ },
586
+ namespaceResolver,
587
+ });
588
+ }catch (e){
589
+ formElement.dispatchEvent(new CustomEvent('error', {
590
+ composed: false,
591
+ bubbles: true,
592
+ detail: {
593
+ origin: formElement,
594
+ message: `Expression '${xpath}' failed`,
595
+ expr:xpath,
596
+ level:'Error'
597
+ },
598
+ }));
599
+ }
508
600
  }
509
601
 
510
602
  /**
@@ -525,17 +617,30 @@ export function evaluateXPathToString(
525
617
  domFacade = null,
526
618
  namespaceReferenceNode = formElement,
527
619
  ) {
528
- const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
529
- const variablesInScope = getVariablesInScope(formElement);
620
+ try{
621
+ const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
622
+ const variablesInScope = getVariablesInScope(formElement);
530
623
 
531
- return fxEvaluateXPathToString(xpath, contextNode, domFacade, variablesInScope, {
532
- currentContext: {formElement},
533
- functionNameResolver,
534
- moduleImports: {
535
- xf: XFORMS_NAMESPACE_URI,
536
- },
537
- namespaceResolver,
538
- });
624
+ return fxEvaluateXPathToString(xpath, contextNode, domFacade, variablesInScope, {
625
+ currentContext: {formElement},
626
+ functionNameResolver,
627
+ moduleImports: {
628
+ xf: XFORMS_NAMESPACE_URI,
629
+ },
630
+ namespaceResolver,
631
+ });
632
+ }catch (e) {
633
+ formElement.dispatchEvent(new CustomEvent('error', {
634
+ composed: false,
635
+ bubbles: true,
636
+ detail: {
637
+ origin: formElement,
638
+ message: `Expression '${xpath}' failed`,
639
+ expr:xpath,
640
+ level:'Error'
641
+ },
642
+ }));
643
+ }
539
644
  }
540
645
 
541
646
  /**
@@ -556,22 +661,31 @@ export function evaluateXPathToStrings(
556
661
  domFacade = null,
557
662
  namespaceReferenceNode = formElement,
558
663
  ) {
559
- const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
560
- return fxEvaluateXPathToStrings(
561
- xpath,
562
- contextNode,
563
- domFacade,
564
- {},
565
-
566
- {
567
- currentContext: {formElement},
568
- functionNameResolver,
569
- moduleImports: {
570
- xf: XFORMS_NAMESPACE_URI,
664
+ try{
665
+ const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
666
+ return fxEvaluateXPathToStrings( xpath, contextNode, domFacade,
667
+ {},
668
+ {
669
+ currentContext: {formElement},
670
+ functionNameResolver,
671
+ moduleImports: {
672
+ xf: XFORMS_NAMESPACE_URI,
673
+ },
674
+ namespaceResolver,
571
675
  },
572
- namespaceResolver,
573
- },
574
- );
676
+ );
677
+ } catch (e){
678
+ formElement.dispatchEvent(new CustomEvent('error', {
679
+ composed: false,
680
+ bubbles: true,
681
+ detail: {
682
+ origin: formElement,
683
+ message: `Expression '${xpath}' failed`,
684
+ expr:xpath,
685
+ level:'Error'
686
+ },
687
+ }));
688
+ }
575
689
  }
576
690
 
577
691
  /**
@@ -592,17 +706,30 @@ export function evaluateXPathToNumber(
592
706
  domFacade = null,
593
707
  namespaceReferenceNode = formElement,
594
708
  ) {
595
- const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
596
- const variablesInScope = getVariablesInScope(formElement);
709
+ try{
710
+ const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
711
+ const variablesInScope = getVariablesInScope(formElement);
597
712
 
598
- return fxEvaluateXPathToNumber(xpath, contextNode, domFacade, variablesInScope, {
599
- currentContext: {formElement},
600
- functionNameResolver,
601
- moduleImports: {
602
- xf: XFORMS_NAMESPACE_URI,
603
- },
604
- namespaceResolver,
605
- });
713
+ return fxEvaluateXPathToNumber(xpath, contextNode, domFacade, variablesInScope, {
714
+ currentContext: {formElement},
715
+ functionNameResolver,
716
+ moduleImports: {
717
+ xf: XFORMS_NAMESPACE_URI,
718
+ },
719
+ namespaceResolver,
720
+ });
721
+ }catch (e) {
722
+ formElement.dispatchEvent(new CustomEvent('error', {
723
+ composed: false,
724
+ bubbles: true,
725
+ detail: {
726
+ origin: formElement,
727
+ message: `Expression '${xpath}' failed`,
728
+ expr:xpath,
729
+ level:'Error'
730
+ },
731
+ }));
732
+ }
606
733
  }
607
734
 
608
735
  const contextFunction = (dynamicContext, string) => {
@@ -844,18 +971,44 @@ const instance = (dynamicContext, string) => {
844
971
  {namespaceResolver: xhtmlNamespaceResolver},
845
972
  );
846
973
 
974
+ let lookup = null;
975
+ if(string === null || string === 'default'){
976
+ lookup = formElement.getModel().getDefaultInstance();
977
+ }else{
978
+ lookup = formElement.getModel().getInstance(string);
979
+ if(!lookup){
980
+ document.querySelector('fx-fore').dispatchEvent(new CustomEvent('error', {
981
+ composed: true,
982
+ bubbles: true,
983
+ detail: {
984
+ origin: 'functions',
985
+ message: `Function not found '${localName}'`,
986
+ level:'Error'
987
+ },
988
+ }));
989
+ }
990
+ }
991
+
992
+ const context = lookup.getDefaultContext();
993
+ if (!context) {
994
+ debugger;
995
+ return null;
996
+ }
997
+ return context;
998
+
999
+ /*
847
1000
  const inst = string
848
1001
  ? formElement.getModel().getInstance(string)
849
1002
  : formElement.getModel().getDefaultInstance();
1003
+ */
850
1004
 
851
1005
  /*
852
1006
  const inst = string
853
1007
  ? resolveId(string, formElement, 'fx-instance')
854
1008
  : formElement.querySelector(`fx-instance`);
855
- */
856
1009
 
857
- if (inst) {
858
- const context = inst.getDefaultContext();
1010
+ if (lookup) {
1011
+ const context = lookup.getDefaultContext();
859
1012
  if (!context) {
860
1013
  debugger;
861
1014
  return null;
@@ -863,6 +1016,7 @@ const instance = (dynamicContext, string) => {
863
1016
  return context;
864
1017
  }
865
1018
  return null;
1019
+ */
866
1020
  };
867
1021
 
868
1022
  registerCustomXPathFunction(
package/src/xpath-util.js CHANGED
@@ -2,151 +2,159 @@ import * as fx from 'fontoxpath';
2
2
 
3
3
  export class XPathUtil {
4
4
 
5
- /**
6
- * Alternative to `contains` that respects shadowroots
7
- */
8
- static contains(ancestor, descendant) {
9
- while (descendant) {
10
- if (descendant === ancestor) {
11
- return true;
12
- }
5
+ /**
6
+ * Alternative to `contains` that respects shadowroots
7
+ */
8
+ static contains(ancestor, descendant) {
9
+ while (descendant) {
10
+ if (descendant === ancestor) {
11
+ return true;
12
+ }
13
13
 
14
- if (descendant.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
15
- // We are passing a shadow root boundary
16
- descendant = descendant.host;
17
- } else {
18
- descendant = descendant.parentNode;
19
- }
20
- }
21
- return false;
22
- }
23
-
24
- /**
25
- * Alternative to `closest` that respects subcontrol boundaries
26
- */
27
- static getClosest(querySelector, start) {
28
- while (start && !start.matches || !start.matches(querySelector)) {
29
- if (start.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
30
- // We are passing a shadow root boundary
31
- start = start.host;
32
- continue;
33
- }
34
- if (start.nodeType === Node.ATTRIBUTE_NODE) {
35
- // We are passing an attribute
36
- start = start.ownerElement;
37
- continue;
38
- }
39
- if (start.nodeType === Node.TEXT_NODE) {
40
- start = start.parentNode;
41
- }
42
- if (start.matches('fx-fore')) {
43
- // Subform reached. Bail out
44
- return null;
45
- }
46
- start = start.parentNode;
47
- if (!start) {
48
- return null;
49
- }
14
+ if (descendant.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
15
+ // We are passing a shadow root boundary
16
+ descendant = descendant.host;
17
+ } else {
18
+ descendant = descendant.parentNode;
19
+ }
20
+ }
21
+ return false;
50
22
  }
51
- return start;
52
- }
53
-
54
- /**
55
- * returns next bound element upwards in tree
56
- * @param start where to start the search
57
- * @returns {*|null}
58
- */
59
- static getParentBindingElement(start) {
60
- /* if (start.parentNode.host) {
61
- const { host } = start.parentNode;
62
- if (host.hasAttribute('ref')) {
63
- return host;
64
- }
65
- } else */
66
- if (start.parentNode &&
67
- (start.parentNode.nodeType !== Node.DOCUMENT_NODE || start.parentNode.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) ) {
68
- /*
69
- if (start.parentNode.hasAttribute('ref')) {
70
- return start.parentNode;
71
- }
72
- return XPathUtil.getParentBindingElement(start.parentNode);
73
- */
74
23
 
75
- return start.parentNode.closest('[ref]');
24
+ /**
25
+ * Alternative to `closest` that respects subcontrol boundaries
26
+ */
27
+ static getClosest(querySelector, start) {
28
+ while (start && !start.matches || !start.matches(querySelector)) {
29
+ if (start.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
30
+ // We are passing a shadow root boundary
31
+ start = start.host;
32
+ continue;
33
+ }
34
+ if (start.nodeType === Node.ATTRIBUTE_NODE) {
35
+ // We are passing an attribute
36
+ start = start.ownerElement;
37
+ continue;
38
+ }
39
+ if (start.nodeType === Node.TEXT_NODE) {
40
+ start = start.parentNode;
41
+ }
42
+ if (start.matches('fx-fore')) {
43
+ // Subform reached. Bail out
44
+ return null;
45
+ }
46
+ start = start.parentNode;
47
+ if (!start) {
48
+ return null;
49
+ }
50
+ }
51
+ return start;
76
52
  }
77
- return null;
78
- }
79
53
 
80
- /**
81
- * Checks whether the specified path expression is an absolute path.
82
- *
83
- * @param path the path expression.
84
- * @return <code>true</code> if specified path expression is an absolute
85
- * path, otherwise <code>false</code>.
86
- */
87
- static isAbsolutePath(path) {
88
- return path != null && (path.startsWith('/') || path.startsWith('instance('));
89
- }
54
+ /**
55
+ * returns next bound element upwards in tree
56
+ * @param start where to start the search
57
+ * @returns {*|null}
58
+ */
59
+ static getParentBindingElement(start) {
60
+ /* if (start.parentNode.host) {
61
+ const { host } = start.parentNode;
62
+ if (host.hasAttribute('ref')) {
63
+ return host;
64
+ }
65
+ } else */
66
+ if (start.parentNode &&
67
+ (start.parentNode.nodeType !== Node.DOCUMENT_NODE || start.parentNode.nodeType !== Node.DOCUMENT_FRAGMENT_NODE)) {
68
+ /*
69
+ if (start.parentNode.hasAttribute('ref')) {
70
+ return start.parentNode;
71
+ }
72
+ return XPathUtil.getParentBindingElement(start.parentNode);
73
+ */
90
74
 
91
- static isSelfReference(ref) {
92
- return ref === '.' || ref === './text()' || ref === 'text()' || ref === '' || ref === null;
93
- }
75
+ return start.parentNode.closest('[ref]');
76
+ }
77
+ return null;
78
+ }
94
79
 
95
- /**
96
- * returns the instance id from a complete XPath using `instance()` function.
97
- *
98
- * Will return 'default' in case no ref is given at all or the `instance()` function is called without arg.
99
- *
100
- * Otherwise instance id is extracted from function and returned. If all fails null is returned.
101
- * @param ref
102
- * @returns {string}
103
- */
104
- static getInstanceId(ref) {
105
- if (!ref) {
106
- return 'default';
80
+ /**
81
+ * Checks whether the specified path expression is an absolute path.
82
+ *
83
+ * @param path the path expression.
84
+ * @return <code>true</code> if specified path expression is an absolute
85
+ * path, otherwise <code>false</code>.
86
+ */
87
+ static isAbsolutePath(path) {
88
+ return path != null && (path.startsWith('/') || path.startsWith('instance('));
107
89
  }
108
- if (ref.startsWith('instance()')) {
109
- return 'default';
90
+
91
+ static isSelfReference(ref) {
92
+ return ref === '.' || ref === './text()' || ref === 'text()' || ref === '' || ref === null;
110
93
  }
111
- if (ref.startsWith('instance(')) {
112
- const result = ref.substring(ref.indexOf('(') + 1);
113
- return result.substring(1, result.indexOf(')') - 1);
94
+
95
+ /**
96
+ * returns the instance id from a complete XPath using `instance()` function.
97
+ *
98
+ * Will return 'default' in case no ref is given at all or the `instance()` function is called without arg.
99
+ *
100
+ * Otherwise instance id is extracted from function and returned. If all fails null is returned.
101
+ * @param ref
102
+ * @returns {string}
103
+ */
104
+ static getInstanceId(ref) {
105
+ if (!ref) {
106
+ return 'default';
107
+ }
108
+ if (ref.startsWith('instance()')) {
109
+ return 'default';
110
+ }
111
+ if (ref.startsWith('instance(')) {
112
+ const result = ref.substring(ref.indexOf('(') + 1);
113
+ return result.substring(1, result.indexOf(')') - 1);
114
+ }
115
+ return null;
114
116
  }
115
- return null;
116
- }
117
117
 
118
- static resolveInstance(boundElement, path){
119
- let instanceId = XPathUtil.getInstanceId(path);
120
- if (!instanceId) {
121
- instanceId = XPathUtil.getInstanceId(boundElement.getAttribute('ref'));
122
- }
123
- if(instanceId !== null){
124
- return instanceId;
118
+ static resolveInstance(boundElement, path) {
119
+ let instanceId = XPathUtil.getInstanceId(path);
120
+ if (!instanceId) {
121
+ instanceId = XPathUtil.getInstanceId(boundElement.getAttribute('ref'));
122
+ }
123
+ if (instanceId !== null) {
124
+ return instanceId;
125
+ }
126
+
127
+ const parentBinding = XPathUtil.getParentBindingElement(boundElement);
128
+ if (parentBinding) {
129
+ return this.resolveInstance(parentBinding, path);
130
+ }
131
+ return 'default';
125
132
  }
126
133
 
127
- const parentBinding = XPathUtil.getParentBindingElement(boundElement);
128
- if(parentBinding){
129
- return this.resolveInstance(parentBinding, path);
134
+ static getDocPath(node) {
135
+ const path = fx.evaluateXPathToString('path()', node);
136
+ // Path is like `$default/x[1]/y[1]`
137
+ const shortened = XPathUtil.shortenPath(path);
138
+ return shortened.startsWith('/') ? `${shortened}` : `/${shortened}`;
130
139
  }
131
- return 'default';
132
- }
133
140
 
134
- static getPath(node, instanceId) {
135
- const path = fx.evaluateXPathToString('path()', node);
136
- // Path is like `$default/x/y`
137
- return `$${instanceId}${XPathUtil.shortenPath(path)}`;
138
- }
141
+ static getPath(node, instanceId) {
142
+ const path = fx.evaluateXPathToString('path()', node);
143
+ // Path is like `$default/x[1]/y[1]`
144
+ const shortened = XPathUtil.shortenPath(path);
145
+ return shortened.startsWith('/') ? `$${instanceId}${shortened}` : `$${instanceId}/${shortened}`;
146
+ }
139
147
 
140
- static shortenPath(path) {
141
- const tmp = path.replaceAll(/(Q{(.*?)\})/g, '');
142
- // cut off leading slash
143
- const tmp1 = tmp.substring(1, tmp.length);
144
- // ### cut-off root node ref
145
- return tmp1.substring(tmp1.indexOf('/'), tmp.length);
146
- }
148
+ static shortenPath(path) {
149
+ const tmp = path.replaceAll(/(Q{(.*?)\})/g, '');
150
+ // cut off leading slash
151
+ const tmp1 = tmp.substring(1, tmp.length);
152
+ // ### cut-off root node ref
153
+ return tmp1.substring(tmp1.indexOf('/'), tmp.length);
154
+ }
147
155
 
148
- static getBasePath(dep) {
149
- const split = dep.split(':');
150
- return split[0];
151
- }
156
+ static getBasePath(dep) {
157
+ const split = dep.split(':');
158
+ return split[0];
159
+ }
152
160
  }