@jinntec/fore 1.10.3 → 2.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.
- 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/index.js +3 -0
- package/package.json +1 -1
- package/src/actions/abstract-action.js +101 -67
- package/src/actions/fx-confirm.js +3 -3
- package/src/actions/fx-construct-done.js +28 -0
- package/src/actions/fx-insert.js +53 -51
- package/src/actions/fx-load.js +3 -35
- package/src/actions/fx-refresh.js +3 -0
- package/src/actions/fx-setattribute.js +68 -0
- package/src/actions/fx-toggle.js +1 -1
- package/src/fore.js +79 -2
- package/src/fx-bind.js +1 -0
- package/src/fx-fore.js +116 -66
- package/src/fx-instance.js +1 -0
- package/src/fx-model.js +36 -11
- package/src/fx-submission.js +25 -5
- package/src/getInScopeContext.js +11 -5
- package/src/json-util.js +27 -0
- package/src/relevance.js +18 -0
- package/src/ui/abstract-control.js +2 -0
- package/src/ui/fx-case.js +5 -2
- package/src/ui/fx-container.js +22 -0
- package/src/ui/fx-control.js +25 -31
- package/src/ui/fx-droptarget.js +9 -0
- package/src/ui/fx-inspector.js +16 -12
- package/src/ui/fx-repeat-attributes.js +4 -2
- package/src/ui/fx-repeat.js +366 -355
- package/src/ui/fx-repeatitem.js +78 -86
- package/src/ui/fx-switch.js +7 -2
- package/src/ui/fx-trigger.js +0 -1
- package/src/withDraggability.js +218 -0
- package/src/xpath-evaluation.js +137 -0
package/src/getInScopeContext.js
CHANGED
|
@@ -61,18 +61,24 @@ export default function getInScopeContext(node, ref) {
|
|
|
61
61
|
const parentElement = _getElement(node);
|
|
62
62
|
// console.log('getInScopeContext parent', parentElement);
|
|
63
63
|
|
|
64
|
-
if(parentElement.closest('fx-fore').mergePartial){
|
|
65
|
-
console.log('mergePartial mode')
|
|
66
|
-
}
|
|
67
|
-
|
|
68
64
|
if(parentElement.nodeName === 'FX-FORE'){
|
|
69
|
-
|
|
65
|
+
const context = parentElement.getModel().getDefaultInstance()?.getDefaultContext();
|
|
66
|
+
if (!context) {
|
|
67
|
+
// Edge-case, we are in an inner fore. Use the outer fore's default context
|
|
68
|
+
return getInScopeContext(parentElement.parentNode, ref);
|
|
69
|
+
}
|
|
70
|
+
return context;
|
|
70
71
|
}
|
|
71
72
|
const parentBind = XPathUtil.getClosest('[ref]', parentElement.parentNode);
|
|
72
73
|
if (parentBind && (parentBind.nodeName === 'FX-GROUP' || parentBind.nodeName === 'FX-CONTROL')) {
|
|
73
74
|
return parentBind.nodeset;
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
const parentActionWithIterateExpr = parentElement.matches('[iterate]') ? parentElement : XPathUtil.getClosest('[iterate]', parentElement.parentNode);
|
|
78
|
+
if (parentActionWithIterateExpr && parentActionWithIterateExpr.currentContext) {
|
|
79
|
+
return parentActionWithIterateExpr.currentContext;
|
|
80
|
+
}
|
|
81
|
+
|
|
76
82
|
const repeatItem = XPathUtil.getClosest('fx-repeatitem', parentElement);
|
|
77
83
|
if (repeatItem) {
|
|
78
84
|
if (node.nodeName === 'context') {
|
package/src/json-util.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const jsonToXml = (json) => {
|
|
2
|
+
const convert = (obj) => {
|
|
3
|
+
let xml = '';
|
|
4
|
+
for (const key in obj) {
|
|
5
|
+
if (obj.hasOwnProperty(key)) {
|
|
6
|
+
xml += `<${key}`;
|
|
7
|
+
if (typeof obj[key] === 'object') {
|
|
8
|
+
if (Array.isArray(obj[key])) {
|
|
9
|
+
xml += ' type="array">';
|
|
10
|
+
obj[key].forEach((item) => {
|
|
11
|
+
xml += `<_>${convert(item)}</_>`;
|
|
12
|
+
});
|
|
13
|
+
} else {
|
|
14
|
+
xml += ' type="object">';
|
|
15
|
+
xml += convert(obj[key]);
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
xml += ` type="${typeof obj[key]}">${obj[key]}</${key}>`;
|
|
19
|
+
}
|
|
20
|
+
xml += `</${key}>`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return xml;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return `<json>${convert(json)}</json>`;
|
|
27
|
+
};
|
package/src/relevance.js
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
|
+
import {Fore} from "./fore.js";
|
|
2
|
+
|
|
1
3
|
export class Relevance {
|
|
4
|
+
|
|
5
|
+
static handleRelevance(boundElement){
|
|
6
|
+
const modelItem = boundElement.getModelItem();
|
|
7
|
+
|
|
8
|
+
if (modelItem && modelItem.relevant) {
|
|
9
|
+
boundElement.removeAttribute('nonrelevant');
|
|
10
|
+
boundElement.setAttribute('relevant','');
|
|
11
|
+
Fore.dispatch(this,'relevant',{});
|
|
12
|
+
|
|
13
|
+
} else {
|
|
14
|
+
boundElement.removeAttribute('relevant');
|
|
15
|
+
boundElement.setAttribute('nonrelevant','');
|
|
16
|
+
Fore.dispatch(this,'nonrelevant',{});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
2
20
|
static selectRelevant(element, type) {
|
|
3
21
|
// console.log('selectRelevant', type);
|
|
4
22
|
switch (type) {
|
|
@@ -5,6 +5,7 @@ import { Fore } from '../fore.js';
|
|
|
5
5
|
import { XPathUtil } from '../xpath-util.js';
|
|
6
6
|
import getInScopeContext from '../getInScopeContext.js';
|
|
7
7
|
import { evaluateXPathToFirstNode} from '../xpath-evaluation.js';
|
|
8
|
+
import {Relevance} from "../relevance.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* `AbstractControl` -
|
|
@@ -172,6 +173,7 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
172
173
|
this.handleValid();
|
|
173
174
|
}
|
|
174
175
|
this.handleRelevant();
|
|
176
|
+
// Relevance.handleRelevance(this);
|
|
175
177
|
// todo: handleType()
|
|
176
178
|
}
|
|
177
179
|
|
package/src/ui/fx-case.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// import { foreElementMixin } from '../ForeElementMixin';
|
|
2
2
|
|
|
3
|
+
import {FxContainer} from "./fx-container.js";
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* `fx-case`
|
|
5
7
|
* a container allowing to switch between fx-case elements
|
|
@@ -7,11 +9,12 @@
|
|
|
7
9
|
* * todo: implement
|
|
8
10
|
* @customElement
|
|
9
11
|
*/
|
|
10
|
-
class FxCase extends
|
|
12
|
+
class FxCase extends FxContainer {
|
|
13
|
+
/*
|
|
11
14
|
constructor() {
|
|
12
15
|
super();
|
|
13
|
-
this.attachShadow({ mode: 'open' });
|
|
14
16
|
}
|
|
17
|
+
*/
|
|
15
18
|
|
|
16
19
|
connectedCallback() {
|
|
17
20
|
if (this.hasAttribute('label')) {
|
package/src/ui/fx-container.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '../fx-model.js';
|
|
2
2
|
import { foreElementMixin } from '../ForeElementMixin.js';
|
|
3
|
+
import {Fore} from "../fore.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* `fx-container` -
|
|
@@ -7,12 +8,23 @@ import { foreElementMixin } from '../ForeElementMixin.js';
|
|
|
7
8
|
*
|
|
8
9
|
*/
|
|
9
10
|
export class FxContainer extends foreElementMixin(HTMLElement) {
|
|
11
|
+
static get properties() {
|
|
12
|
+
return {
|
|
13
|
+
...super.properties,
|
|
14
|
+
/*
|
|
15
|
+
src: {
|
|
16
|
+
type: String,
|
|
17
|
+
},
|
|
18
|
+
*/
|
|
19
|
+
};
|
|
20
|
+
}
|
|
10
21
|
constructor() {
|
|
11
22
|
super();
|
|
12
23
|
this.attachShadow({ mode: 'open' });
|
|
13
24
|
}
|
|
14
25
|
|
|
15
26
|
connectedCallback() {
|
|
27
|
+
this.src = this.hasAttribute('src') ? this.getAttribute('src'):null;
|
|
16
28
|
const style = `
|
|
17
29
|
:host {
|
|
18
30
|
display: block;
|
|
@@ -51,6 +63,16 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
|
|
|
51
63
|
if (!force && this.hasAttribute('refresh-on-view')) return;
|
|
52
64
|
// console.log('### FxContainer.refresh on : ', this);
|
|
53
65
|
|
|
66
|
+
// if loading from 'src' needs to be done do it now
|
|
67
|
+
/*
|
|
68
|
+
if(this.src){
|
|
69
|
+
await Fore.loadForeFromSrc(this,this.src,'fx-group')
|
|
70
|
+
.then(foreElement =>{
|
|
71
|
+
this.getOwnerForm().registerLazyElement(foreElement);
|
|
72
|
+
foreElement.refresh();
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
*/
|
|
54
76
|
if (this.isBound()) {
|
|
55
77
|
this.evalInContext();
|
|
56
78
|
this.modelItem = this.getModelItem();
|
package/src/ui/fx-control.js
CHANGED
|
@@ -48,6 +48,9 @@ export default class FxControl extends XfAbstractControl {
|
|
|
48
48
|
},
|
|
49
49
|
initial: {
|
|
50
50
|
type: Boolean
|
|
51
|
+
},
|
|
52
|
+
src:{
|
|
53
|
+
type: String
|
|
51
54
|
}
|
|
52
55
|
};
|
|
53
56
|
}
|
|
@@ -62,7 +65,7 @@ export default class FxControl extends XfAbstractControl {
|
|
|
62
65
|
|
|
63
66
|
connectedCallback() {
|
|
64
67
|
this.initial = this.hasAttribute('initial') ? this.getAttribute('initial') : null;
|
|
65
|
-
this.
|
|
68
|
+
this.src = this.hasAttribute('src') ? this.getAttribute('src') : null;
|
|
66
69
|
this.loaded = false;
|
|
67
70
|
this.initialNode = null;
|
|
68
71
|
this.debounceDelay = this.hasAttribute('debounce') ? this.getAttribute('debounce') : null;
|
|
@@ -263,7 +266,7 @@ export default class FxControl extends XfAbstractControl {
|
|
|
263
266
|
} else (
|
|
264
267
|
Fore.dispatch(this, "warn", {'message': 'trying to replace a node that is neither an Attribute, Elemment or Text node'})
|
|
265
268
|
)
|
|
266
|
-
this.getOwnerForm().refresh();
|
|
269
|
+
// this.getOwnerForm().refresh();
|
|
267
270
|
}
|
|
268
271
|
|
|
269
272
|
renderHTML(ref) {
|
|
@@ -374,8 +377,8 @@ export default class FxControl extends XfAbstractControl {
|
|
|
374
377
|
return;
|
|
375
378
|
}
|
|
376
379
|
|
|
377
|
-
// ### when there's a
|
|
378
|
-
if (this.
|
|
380
|
+
// ### when there's a src Fore is used as widget and will be loaded from external file
|
|
381
|
+
if (this.src && !this.loaded && this.modelItem.relevant) {
|
|
379
382
|
// ### evaluate initial data if necessary
|
|
380
383
|
|
|
381
384
|
if (this.initial) {
|
|
@@ -383,8 +386,8 @@ export default class FxControl extends XfAbstractControl {
|
|
|
383
386
|
// console.log('initialNodes', this.initialNode);
|
|
384
387
|
}
|
|
385
388
|
|
|
386
|
-
// ### load the markup from
|
|
387
|
-
await this.
|
|
389
|
+
// ### load the markup from src
|
|
390
|
+
await this._loadForeFromSrc();
|
|
388
391
|
this.loaded = true;
|
|
389
392
|
|
|
390
393
|
// ### replace default instance of embedded Fore with initial nodes
|
|
@@ -393,20 +396,13 @@ export default class FxControl extends XfAbstractControl {
|
|
|
393
396
|
return;
|
|
394
397
|
}
|
|
395
398
|
|
|
396
|
-
/*
|
|
397
|
-
if(this.url && !this.loaded){
|
|
398
|
-
this._loadForeFromUrl();
|
|
399
|
-
this.loaded=true;
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
*/
|
|
403
399
|
if (widget.value !== this.value) {
|
|
404
400
|
widget.value = this.value;
|
|
405
401
|
}
|
|
406
402
|
}
|
|
407
403
|
|
|
408
404
|
/**
|
|
409
|
-
* loads an external Fore from an HTML file given by `
|
|
405
|
+
* loads an external Fore from an HTML file given by `src` attribute and embed it as child of this control.
|
|
410
406
|
*
|
|
411
407
|
* Will look for the `<fx-fore>` element within the returned HTML file and return that element.
|
|
412
408
|
*
|
|
@@ -415,13 +411,13 @@ export default class FxControl extends XfAbstractControl {
|
|
|
415
411
|
* todo: dispatch link error
|
|
416
412
|
* @private
|
|
417
413
|
*/
|
|
418
|
-
async
|
|
414
|
+
async _loadForeFromSrc() {
|
|
419
415
|
console.info(
|
|
420
|
-
`%
|
|
416
|
+
`%cControl ref="${this.ref}" is loading ${this.src}`,
|
|
421
417
|
"background:#64b5f6; color:white; padding:0.5rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;width:100%;",
|
|
422
418
|
);
|
|
423
419
|
try {
|
|
424
|
-
const response = await fetch(this.
|
|
420
|
+
const response = await fetch(this.src, {
|
|
425
421
|
method: 'GET',
|
|
426
422
|
credentials: this.credentials,
|
|
427
423
|
mode: 'cors',
|
|
@@ -457,10 +453,12 @@ export default class FxControl extends XfAbstractControl {
|
|
|
457
453
|
this.initialNode = evaluateXPathToFirstNode(this.initial, this.nodeset, this);
|
|
458
454
|
|
|
459
455
|
doc.firstElementChild.appendChild(this.initialNode.cloneNode(true));
|
|
460
|
-
|
|
456
|
+
defaultInst.instanceData = doc;
|
|
461
457
|
}
|
|
462
|
-
|
|
463
|
-
|
|
458
|
+
imported.model = imported.querySelector('fx-model');
|
|
459
|
+
imported.model.updateModel();
|
|
460
|
+
|
|
461
|
+
imported.refresh(true);
|
|
464
462
|
},
|
|
465
463
|
{once: true},
|
|
466
464
|
);
|
|
@@ -477,23 +475,19 @@ export default class FxControl extends XfAbstractControl {
|
|
|
477
475
|
dummy.replaceWith(imported);
|
|
478
476
|
}
|
|
479
477
|
|
|
480
|
-
|
|
481
478
|
if (!theFore) {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}),
|
|
488
|
-
);
|
|
479
|
+
Fore.dispatch('error', {
|
|
480
|
+
detail: {
|
|
481
|
+
message: `Fore element not found in '${this.src}'. Maybe wrapped within 'template' element?`,
|
|
482
|
+
}
|
|
483
|
+
});
|
|
489
484
|
}
|
|
490
|
-
|
|
485
|
+
Fore.dispatch('loaded', {detail: {fore: theFore}});
|
|
491
486
|
} catch (error) {
|
|
492
487
|
// console.log('error', error);
|
|
493
488
|
Fore.dispatch(this, 'error', {
|
|
494
489
|
origin: this,
|
|
495
|
-
message: `control couldn't be loaded from
|
|
496
|
-
expr:xpath,
|
|
490
|
+
message: `control couldn't be loaded from src '${this.src}'`,
|
|
497
491
|
level:'Error'
|
|
498
492
|
});
|
|
499
493
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { foreElementMixin } from '../ForeElementMixin.js';
|
|
2
|
+
import { withDraggability } from '../withDraggability.js';
|
|
3
|
+
|
|
4
|
+
class FxDroptarget extends withDraggability(foreElementMixin(HTMLElement)) {
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
if (!customElements.get('fx-droptarget')) {
|
|
8
|
+
window.customElements.define('fx-droptarget', FxDroptarget);
|
|
9
|
+
}
|
package/src/ui/fx-inspector.js
CHANGED
|
@@ -86,19 +86,23 @@ export class FxInspector extends HTMLElement {
|
|
|
86
86
|
|
|
87
87
|
update() {
|
|
88
88
|
// console.log('update');
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
try{
|
|
90
|
+
const pre = this.shadowRoot.querySelectorAll('pre');
|
|
91
|
+
// console.log('pre', pre);
|
|
92
|
+
const fore = this.closest('fx-fore');
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
Array.from(pre).forEach(element => {
|
|
95
|
+
const inst = fore.getModel().getInstance(element.getAttribute('id'));
|
|
96
|
+
if (inst.getAttribute('type') === 'xml') {
|
|
97
|
+
element.innerText = this.serializeDOM(inst.instanceData);
|
|
98
|
+
}
|
|
99
|
+
if (inst.getAttribute('type') === 'json') {
|
|
100
|
+
element.innerText = JSON.stringify(inst.instanceData, undefined, 2);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}catch (e){
|
|
104
|
+
console.warn('caught problem in inspector', e.message);
|
|
105
|
+
}
|
|
102
106
|
}
|
|
103
107
|
|
|
104
108
|
render(style) {
|
|
@@ -3,6 +3,7 @@ import { evaluateXPath } from '../xpath-evaluation.js';
|
|
|
3
3
|
import getInScopeContext from '../getInScopeContext.js';
|
|
4
4
|
import { XPathUtil } from '../xpath-util.js';
|
|
5
5
|
import {foreElementMixin} from "../ForeElementMixin.js";
|
|
6
|
+
import {withDraggability} from "../withDraggability.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* `fx-repeat`
|
|
@@ -19,7 +20,7 @@ import {foreElementMixin} from "../ForeElementMixin.js";
|
|
|
19
20
|
*
|
|
20
21
|
* todo: it should be seriously be considered to extend FxContainer instead but needs refactoring first.
|
|
21
22
|
*/
|
|
22
|
-
export class FxRepeatAttributes extends foreElementMixin(HTMLElement) {
|
|
23
|
+
export class FxRepeatAttributes extends withDraggability(foreElementMixin(HTMLElement), false) {
|
|
23
24
|
static get properties() {
|
|
24
25
|
return {
|
|
25
26
|
...super.properties,
|
|
@@ -51,6 +52,7 @@ export class FxRepeatAttributes extends foreElementMixin(HTMLElement) {
|
|
|
51
52
|
super();
|
|
52
53
|
this.ref = '';
|
|
53
54
|
this.dataTemplate = [];
|
|
55
|
+
this.isDraggable=null;
|
|
54
56
|
this.focusOnCreate = '';
|
|
55
57
|
this.initDone = false;
|
|
56
58
|
this.repeatIndex = 1;
|
|
@@ -87,7 +89,7 @@ export class FxRepeatAttributes extends foreElementMixin(HTMLElement) {
|
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
get index() {
|
|
90
|
-
|
|
92
|
+
return parseInt(this.getAttribute('index'), 10);
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
set index(idx) {
|