@jinntec/fore 1.8.0 → 1.10.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.
- package/README.md +17 -0
- package/dist/fore-dev.js +2 -2
- package/dist/fore-dev.js.map +1 -1
- package/dist/fore.js +2 -2
- package/dist/fore.js.map +1 -1
- package/package.json +7 -2
- package/resources/fore.css +4 -0
- package/src/DependencyNotifyingDomFacade.js +2 -2
- package/src/actions/abstract-action.js +24 -11
- package/src/actions/fx-insert.js +13 -6
- package/src/actions/fx-setfocus.js +1 -1
- package/src/fore.js +238 -1
- package/src/fx-bind.js +12 -6
- package/src/fx-fore.js +86 -9
- package/src/fx-instance.js +9 -3
- package/src/fx-model.js +3 -1
- package/src/fx-submission.js +46 -157
- package/src/tools/adi.js +16 -7
- package/src/tools/fx-action-log.js +1 -1
- package/src/ui/abstract-control.js +8 -7
- package/src/ui/fx-control.js +18 -7
- package/src/ui/fx-dialog.js +2 -0
- package/src/ui/fx-group.js +4 -1
- package/src/ui/fx-repeat-attributes.js +4 -1
- package/src/ui/fx-repeat.js +11 -2
- package/src/ui/fx-repeatitem.js +5 -3
- package/src/ui/fx-trigger.js +3 -1
- package/src/xpath-evaluation.js +101 -4
- package/src/xpath-util.js +9 -12
package/src/ui/fx-control.js
CHANGED
|
@@ -2,7 +2,7 @@ import XfAbstractControl from './abstract-control.js';
|
|
|
2
2
|
import {
|
|
3
3
|
evaluateXPath,
|
|
4
4
|
evaluateXPathToString,
|
|
5
|
-
evaluateXPathToFirstNode,
|
|
5
|
+
evaluateXPathToFirstNode,
|
|
6
6
|
} from '../xpath-evaluation.js';
|
|
7
7
|
import getInScopeContext from '../getInScopeContext.js';
|
|
8
8
|
import {Fore} from '../fore.js';
|
|
@@ -43,6 +43,9 @@ export default class FxControl extends XfAbstractControl {
|
|
|
43
43
|
static get properties() {
|
|
44
44
|
return {
|
|
45
45
|
...XfAbstractControl.properties,
|
|
46
|
+
credentials:{
|
|
47
|
+
type: String
|
|
48
|
+
},
|
|
46
49
|
initial: {
|
|
47
50
|
type: Boolean
|
|
48
51
|
}
|
|
@@ -74,6 +77,13 @@ export default class FxControl extends XfAbstractControl {
|
|
|
74
77
|
}
|
|
75
78
|
`;
|
|
76
79
|
|
|
80
|
+
this.credentials = this.hasAttribute('credentials')
|
|
81
|
+
? this.getAttribute('credentials')
|
|
82
|
+
: 'same-origin';
|
|
83
|
+
if (!['same-origin', 'include', 'omit'].includes(this.credentials)) {
|
|
84
|
+
console.error(`fx-submission: the value of credentials is not valid. Expected 'same-origin', 'include' or 'omit' but got '${this.credentials}'`, this);
|
|
85
|
+
}
|
|
86
|
+
|
|
77
87
|
this.shadowRoot.innerHTML = `
|
|
78
88
|
<style>
|
|
79
89
|
${style}
|
|
@@ -369,7 +379,7 @@ export default class FxControl extends XfAbstractControl {
|
|
|
369
379
|
}
|
|
370
380
|
|
|
371
381
|
// ### when there's a url Fore is used as widget and will be loaded from external file
|
|
372
|
-
if (this.url && !this.loaded) {
|
|
382
|
+
if (this.url && !this.loaded && this.modelItem.relevant) {
|
|
373
383
|
// ### evaluate initial data if necessary
|
|
374
384
|
|
|
375
385
|
if (this.initial) {
|
|
@@ -417,10 +427,8 @@ export default class FxControl extends XfAbstractControl {
|
|
|
417
427
|
try {
|
|
418
428
|
const response = await fetch(this.url, {
|
|
419
429
|
method: 'GET',
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
credentials: 'include',
|
|
423
|
-
*/
|
|
430
|
+
credentials: this.credentials,
|
|
431
|
+
mode: 'cors',
|
|
424
432
|
headers: {
|
|
425
433
|
'Content-Type': 'text/html',
|
|
426
434
|
},
|
|
@@ -446,9 +454,12 @@ export default class FxControl extends XfAbstractControl {
|
|
|
446
454
|
'model-construct-done',
|
|
447
455
|
e => {
|
|
448
456
|
const defaultInst = imported.querySelector('fx-instance');
|
|
449
|
-
if (this.
|
|
457
|
+
if (this.initial) {
|
|
450
458
|
const doc = new DOMParser().parseFromString('<data></data>', 'application/xml');
|
|
451
459
|
// Note: Clone the input to prevent the inner fore from editing the outer node
|
|
460
|
+
// Also update the `initialNode` to make sure we have an up-to-date version
|
|
461
|
+
this.initialNode = evaluateXPathToFirstNode(this.initial, this.nodeset, this);
|
|
462
|
+
|
|
452
463
|
doc.firstElementChild.appendChild(this.initialNode.cloneNode(true));
|
|
453
464
|
defaultInst.setInstanceData(doc);
|
|
454
465
|
}
|
package/src/ui/fx-dialog.js
CHANGED
package/src/ui/fx-group.js
CHANGED
|
@@ -98,6 +98,7 @@ export class FxRepeatAttributes extends foreElementMixin(HTMLElement) {
|
|
|
98
98
|
const refd = this.querySelector('[data-ref]');
|
|
99
99
|
return refd.children;
|
|
100
100
|
}
|
|
101
|
+
|
|
101
102
|
async connectedCallback() {
|
|
102
103
|
// console.log('connectedCallback',this);
|
|
103
104
|
// this.display = window.getComputedStyle(this, null).getPropertyValue("display");
|
|
@@ -134,7 +135,9 @@ export class FxRepeatAttributes extends foreElementMixin(HTMLElement) {
|
|
|
134
135
|
if (mutations[0].type === 'childList') {
|
|
135
136
|
const added = mutations[0].addedNodes[0];
|
|
136
137
|
if (added) {
|
|
137
|
-
const
|
|
138
|
+
const instance = XPathUtil.resolveInstance(this);
|
|
139
|
+
|
|
140
|
+
const path = XPathUtil.getPath(added, instance);
|
|
138
141
|
// this.dispatch('path-mutated',{'path':path,'nodeset':this.nodeset,'index': this.index});
|
|
139
142
|
// this.index = index;
|
|
140
143
|
// const prev = mutations[0].previousSibling.previousElementSibling;
|
package/src/ui/fx-repeat.js
CHANGED
|
@@ -5,6 +5,7 @@ import { foreElementMixin } from '../ForeElementMixin.js';
|
|
|
5
5
|
import { evaluateXPath } from '../xpath-evaluation.js';
|
|
6
6
|
import getInScopeContext from '../getInScopeContext.js';
|
|
7
7
|
import { XPathUtil } from '../xpath-util.js';
|
|
8
|
+
import {DependencyNotifyingDomFacade} from '../DependencyNotifyingDomFacade';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* `fx-repeat`
|
|
@@ -131,7 +132,8 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
|
|
|
131
132
|
if (mutations[0].type === 'childList') {
|
|
132
133
|
const added = mutations[0].addedNodes[0];
|
|
133
134
|
if (added) {
|
|
134
|
-
|
|
135
|
+
const instance = XPathUtil.resolveInstance(this, this.ref);
|
|
136
|
+
const path = XPathUtil.getPath(added, instance);
|
|
135
137
|
// console.log('path mutated', path);
|
|
136
138
|
// this.dispatch('path-mutated',{'path':path,'nodeset':this.nodeset,'index': this.index});
|
|
137
139
|
// this.index = index;
|
|
@@ -205,7 +207,13 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
|
|
|
205
207
|
});
|
|
206
208
|
}
|
|
207
209
|
|
|
208
|
-
|
|
210
|
+
this.touchedPaths = new Set();
|
|
211
|
+
const instance = XPathUtil.resolveInstance(this, this.ref);
|
|
212
|
+
const depTrackDomfacade = new DependencyNotifyingDomFacade((node) => {
|
|
213
|
+
this.touchedPaths.add(XPathUtil.getPath(node, instance));
|
|
214
|
+
});
|
|
215
|
+
const rawNodeset = evaluateXPath(this.ref, inscope, this, {}, {}, depTrackDomfacade );
|
|
216
|
+
console.log('Touched!', this.ref, [...this.touchedPaths].join(', '));
|
|
209
217
|
if (rawNodeset.length === 1 && Array.isArray(rawNodeset[0])) {
|
|
210
218
|
// This XPath likely returned an XPath array. Just collapse to that array
|
|
211
219
|
this.nodeset = rawNodeset[0];
|
|
@@ -220,6 +228,7 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
|
|
|
220
228
|
if (!this.inited) this.init();
|
|
221
229
|
// console.time('repeat-refresh', this);
|
|
222
230
|
this._evalNodeset();
|
|
231
|
+
|
|
223
232
|
// console.log('repeat refresh nodeset ', this.nodeset);
|
|
224
233
|
// console.log('repeatCount', this.repeatCount);
|
|
225
234
|
|
package/src/ui/fx-repeatitem.js
CHANGED
|
@@ -58,7 +58,9 @@ export class FxRepeatitem extends foreElementMixin(HTMLElement) {
|
|
|
58
58
|
this.shadowRoot.innerHTML = `
|
|
59
59
|
${html}
|
|
60
60
|
`;
|
|
61
|
-
|
|
61
|
+
this.getOwnerForm().registerLazyElement(this);
|
|
62
|
+
|
|
63
|
+
this.ref = `${this.parentNode.ref}`;
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
disconnectedCallback() {
|
|
@@ -91,13 +93,13 @@ export class FxRepeatitem extends foreElementMixin(HTMLElement) {
|
|
|
91
93
|
if (this.modelItem && !this.modelItem.relevant) {
|
|
92
94
|
// await Fore.fadeOutElement(this)
|
|
93
95
|
// this.style.display = 'none';
|
|
94
|
-
|
|
96
|
+
this.style.display = 'none';
|
|
95
97
|
} else {
|
|
96
98
|
// if(this.hasAttribute('repeat-index')){
|
|
97
99
|
// Fore.fadeInElement(this);
|
|
98
100
|
// }
|
|
99
101
|
// this.style.display = this.display;
|
|
100
|
-
|
|
102
|
+
this.style.display = 'block';
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
/*
|
package/src/ui/fx-trigger.js
CHANGED
|
@@ -25,7 +25,9 @@ export class FxTrigger extends XfAbstractControl {
|
|
|
25
25
|
slot.addEventListener('slotchange', () => {
|
|
26
26
|
const elements = slot.assignedElements({ flatten: true });
|
|
27
27
|
elements[0].setAttribute('tabindex', '0');
|
|
28
|
-
elements[0].
|
|
28
|
+
if(elements[0].nodeName !== 'BUTTON'){
|
|
29
|
+
elements[0].setAttribute('role', 'button');
|
|
30
|
+
}
|
|
29
31
|
|
|
30
32
|
const element = elements[0];
|
|
31
33
|
|
package/src/xpath-evaluation.js
CHANGED
|
@@ -341,7 +341,18 @@ function functionNameResolver({prefix, localName}, _arity) {
|
|
|
341
341
|
case 'instance':
|
|
342
342
|
case 'log':
|
|
343
343
|
case 'parse':
|
|
344
|
+
case 'local-date':
|
|
345
|
+
case 'local-dateTime':
|
|
344
346
|
case 'logtree':
|
|
347
|
+
case 'uri':
|
|
348
|
+
case 'uri-fragment':
|
|
349
|
+
case 'uri-host':
|
|
350
|
+
case 'uri-param':
|
|
351
|
+
case 'uri-path':
|
|
352
|
+
case 'uri-port':
|
|
353
|
+
case 'uri-query':
|
|
354
|
+
case 'uri-scheme':
|
|
355
|
+
case 'uri-scheme-specific-part':
|
|
345
356
|
return {namespaceURI: XFORMS_NAMESPACE_URI, localName};
|
|
346
357
|
default:
|
|
347
358
|
if (prefix === '' && globallyDeclaredFunctionLocalNames.includes(localName)) {
|
|
@@ -407,14 +418,14 @@ function getVariablesInScope(formElement) {
|
|
|
407
418
|
* @param {Node} contextNode The start of the XPath
|
|
408
419
|
* @param {{parentNode}|ForeElementMixin} formElement The form element associated to the XPath
|
|
409
420
|
*/
|
|
410
|
-
export function evaluateXPath(xpath, contextNode, formElement, variables = {}, options={}) {
|
|
421
|
+
export function evaluateXPath(xpath, contextNode, formElement, variables = {}, options={}, domFacade = null) {
|
|
411
422
|
const namespaceResolver = createNamespaceResolverForNode(xpath, contextNode, formElement);
|
|
412
423
|
const variablesInScope = getVariablesInScope(formElement);
|
|
413
424
|
|
|
414
425
|
return fxEvaluateXPath(
|
|
415
426
|
xpath,
|
|
416
427
|
contextNode,
|
|
417
|
-
|
|
428
|
+
domFacade,
|
|
418
429
|
{...variablesInScope, ...variables},
|
|
419
430
|
fxEvaluateXPath.ALL_RESULTS_TYPE,
|
|
420
431
|
{
|
|
@@ -834,8 +845,8 @@ const instance = (dynamicContext, string) => {
|
|
|
834
845
|
);
|
|
835
846
|
|
|
836
847
|
const inst = string
|
|
837
|
-
|
|
838
|
-
|
|
848
|
+
? formElement.getModel().getInstance(string)
|
|
849
|
+
: formElement.getModel().getDefaultInstance();
|
|
839
850
|
|
|
840
851
|
/*
|
|
841
852
|
const inst = string
|
|
@@ -980,3 +991,89 @@ registerCustomXPathFunction(
|
|
|
980
991
|
'xs:string?',
|
|
981
992
|
(dynamicContext, string) => btoa(string),
|
|
982
993
|
);
|
|
994
|
+
|
|
995
|
+
registerCustomXPathFunction(
|
|
996
|
+
{namespaceURI: XFORMS_NAMESPACE_URI, localName: 'local-date'},
|
|
997
|
+
[],
|
|
998
|
+
'xs:string?',
|
|
999
|
+
(dynamicContext, string) => new Date().toLocaleDateString(),
|
|
1000
|
+
);
|
|
1001
|
+
registerCustomXPathFunction(
|
|
1002
|
+
{namespaceURI: XFORMS_NAMESPACE_URI, localName: 'local-dateTime'},
|
|
1003
|
+
[],
|
|
1004
|
+
'xs:string?',
|
|
1005
|
+
(dynamicContext, string) => {
|
|
1006
|
+
return new Date().toLocaleString();
|
|
1007
|
+
},
|
|
1008
|
+
);
|
|
1009
|
+
registerCustomXPathFunction(
|
|
1010
|
+
{namespaceURI: XFORMS_NAMESPACE_URI, localName: 'uri'},
|
|
1011
|
+
[],
|
|
1012
|
+
'xs:string?',
|
|
1013
|
+
(dynamicContext, string) => window.location.href,
|
|
1014
|
+
);
|
|
1015
|
+
registerCustomXPathFunction(
|
|
1016
|
+
{namespaceURI: XFORMS_NAMESPACE_URI, localName: 'uri-fragment'},
|
|
1017
|
+
[],
|
|
1018
|
+
'xs:string?',
|
|
1019
|
+
(dynamicContext, arg) => window.location.hash,
|
|
1020
|
+
);
|
|
1021
|
+
registerCustomXPathFunction(
|
|
1022
|
+
{namespaceURI: XFORMS_NAMESPACE_URI, localName: 'uri-host'},
|
|
1023
|
+
[],
|
|
1024
|
+
'xs:string?',
|
|
1025
|
+
(dynamicContext, arg) => window.location.host,
|
|
1026
|
+
);
|
|
1027
|
+
registerCustomXPathFunction(
|
|
1028
|
+
{namespaceURI: XFORMS_NAMESPACE_URI, localName: 'uri-query'},
|
|
1029
|
+
[],
|
|
1030
|
+
'xs:string?',
|
|
1031
|
+
(dynamicContext, arg) => window.location.search,
|
|
1032
|
+
);
|
|
1033
|
+
registerCustomXPathFunction(
|
|
1034
|
+
{namespaceURI: XFORMS_NAMESPACE_URI, localName: 'uri-path'},
|
|
1035
|
+
[],
|
|
1036
|
+
'xs:string?',
|
|
1037
|
+
(dynamicContext, arg) => {
|
|
1038
|
+
return new URL(window.location.href).pathname;
|
|
1039
|
+
},
|
|
1040
|
+
);
|
|
1041
|
+
registerCustomXPathFunction(
|
|
1042
|
+
{namespaceURI: XFORMS_NAMESPACE_URI, localName: 'uri-port'},
|
|
1043
|
+
[],
|
|
1044
|
+
'xs:string?',
|
|
1045
|
+
(dynamicContext, arg) => {
|
|
1046
|
+
return window.location.port;
|
|
1047
|
+
},
|
|
1048
|
+
);
|
|
1049
|
+
registerCustomXPathFunction(
|
|
1050
|
+
{namespaceURI: XFORMS_NAMESPACE_URI, localName: 'uri-param'},
|
|
1051
|
+
['xs:string?'],
|
|
1052
|
+
'xs:string?',
|
|
1053
|
+
(dynamicContext, arg) => {
|
|
1054
|
+
if (!arg) return null;
|
|
1055
|
+
|
|
1056
|
+
const search = window.location.search;
|
|
1057
|
+
const urlparams = new URLSearchParams(search);
|
|
1058
|
+
const param = urlparams.get(arg);
|
|
1059
|
+
return param ? param : '';
|
|
1060
|
+
|
|
1061
|
+
},
|
|
1062
|
+
);
|
|
1063
|
+
registerCustomXPathFunction(
|
|
1064
|
+
{namespaceURI: XFORMS_NAMESPACE_URI, localName: 'uri-scheme'},
|
|
1065
|
+
[],
|
|
1066
|
+
'xs:string?',
|
|
1067
|
+
(dynamicContext, arg) => {
|
|
1068
|
+
return new URL(window.location.href).protocol;
|
|
1069
|
+
},
|
|
1070
|
+
);
|
|
1071
|
+
registerCustomXPathFunction(
|
|
1072
|
+
{namespaceURI: XFORMS_NAMESPACE_URI, localName: 'uri-scheme-specific-part'},
|
|
1073
|
+
[],
|
|
1074
|
+
'xs:string?',
|
|
1075
|
+
(dynamicContext, arg) => {
|
|
1076
|
+
const uri = window.location.href;
|
|
1077
|
+
return uri.substring(uri.indexOf(':') + 1, uri.length);
|
|
1078
|
+
},
|
|
1079
|
+
);
|
package/src/xpath-util.js
CHANGED
|
@@ -115,29 +115,26 @@ export class XPathUtil {
|
|
|
115
115
|
return null;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
static resolveInstance(boundElement, path){
|
|
119
|
+
let instanceId = XPathUtil.getInstanceId(path);
|
|
120
|
+
if (!instanceId) {
|
|
121
|
+
instanceId = XPathUtil.getInstanceId(boundElement.getAttribute('ref'));
|
|
122
|
+
}
|
|
120
123
|
if(instanceId !== null){
|
|
121
124
|
return instanceId;
|
|
122
125
|
}
|
|
123
126
|
|
|
124
127
|
const parentBinding = XPathUtil.getParentBindingElement(boundElement);
|
|
125
128
|
if(parentBinding){
|
|
126
|
-
|
|
129
|
+
return this.resolveInstance(parentBinding, path);
|
|
127
130
|
}
|
|
128
131
|
return 'default';
|
|
129
132
|
}
|
|
130
133
|
|
|
131
|
-
|
|
132
|
-
static getPath(node) {
|
|
134
|
+
static getPath(node, instanceId) {
|
|
133
135
|
const path = fx.evaluateXPathToString('path()', node);
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (instanceId !== null && instanceId !== 'default') {
|
|
137
|
-
return `#${instanceId}${XPathUtil.shortenPath(path)}`;
|
|
138
|
-
}
|
|
139
|
-
*/
|
|
140
|
-
return XPathUtil.shortenPath(path);
|
|
136
|
+
// Path is like `$default/x/y`
|
|
137
|
+
return `$${instanceId}${XPathUtil.shortenPath(path)}`;
|
|
141
138
|
}
|
|
142
139
|
|
|
143
140
|
static shortenPath(path) {
|