@jinntec/fore 2.0.0 → 2.1.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.
- 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 +100 -66
- 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-setattribute.js +68 -0
- package/src/fore.js +3 -1
- package/src/fx-bind.js +1 -0
- package/src/fx-fore.js +48 -1
- package/src/fx-model.js +6 -3
- package/src/fx-submission.js +24 -4
- package/src/fx-var.js +7 -2
- package/src/getInScopeContext.js +11 -1
- 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-droptarget.js +9 -0
- package/src/ui/fx-repeat-attributes.js +4 -2
- package/src/ui/fx-repeat.js +366 -356
- package/src/ui/fx-repeatitem.js +78 -86
- package/src/ui/fx-trigger.js +3 -2
- package/src/withDraggability.js +218 -0
- package/src/xpath-evaluation.js +140 -1
package/src/ui/fx-repeat.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import './fx-repeatitem.js';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import {Fore} from '../fore.js';
|
|
4
|
+
import {foreElementMixin} from '../ForeElementMixin.js';
|
|
5
|
+
import {evaluateXPath} from '../xpath-evaluation.js';
|
|
6
6
|
import getInScopeContext from '../getInScopeContext.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import {XPathUtil} from '../xpath-util.js';
|
|
8
|
+
import {FxFore} from '../fx-fore.js';
|
|
9
|
+
import {withDraggability} from '../withDraggability.js';
|
|
10
|
+
|
|
11
|
+
// import {DependencyNotifyingDomFacade} from '../DependencyNotifyingDomFacade';
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
14
|
* `fx-repeat`
|
|
@@ -22,133 +25,136 @@ import {DependencyNotifyingDomFacade} from '../DependencyNotifyingDomFacade';
|
|
|
22
25
|
*
|
|
23
26
|
* todo: it should be seriously be considered to extend FxContainer instead but needs refactoring first.
|
|
24
27
|
*/
|
|
25
|
-
export class FxRepeat extends foreElementMixin(HTMLElement) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
setIndex(index) {
|
|
73
|
-
// console.log('new repeat index ', index);
|
|
74
|
-
this.index = index;
|
|
75
|
-
const rItems = this.querySelectorAll(':scope > fx-repeatitem');
|
|
76
|
-
this.applyIndex(rItems[this.index - 1]);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
applyIndex(repeatItem) {
|
|
80
|
-
this._removeIndexMarker();
|
|
81
|
-
if (repeatItem) {
|
|
82
|
-
repeatItem.setAttribute('repeat-index', '');
|
|
28
|
+
export class FxRepeat extends withDraggability(foreElementMixin(HTMLElement), false) {
|
|
29
|
+
static get properties() {
|
|
30
|
+
return {
|
|
31
|
+
...super.properties,
|
|
32
|
+
index: {
|
|
33
|
+
type: Number,
|
|
34
|
+
},
|
|
35
|
+
template: {
|
|
36
|
+
type: Object,
|
|
37
|
+
},
|
|
38
|
+
focusOnCreate: {
|
|
39
|
+
type: String,
|
|
40
|
+
},
|
|
41
|
+
initDone: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
},
|
|
44
|
+
repeatIndex: {
|
|
45
|
+
type: Number,
|
|
46
|
+
},
|
|
47
|
+
nodeset: {
|
|
48
|
+
type: Array,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
constructor() {
|
|
54
|
+
super();
|
|
55
|
+
this.ref = '';
|
|
56
|
+
this.dataTemplate = [];
|
|
57
|
+
this.isDraggable=null;
|
|
58
|
+
this.dropTarget=null;
|
|
59
|
+
this.focusOnCreate = '';
|
|
60
|
+
this.initDone = false;
|
|
61
|
+
this.repeatIndex = 1;
|
|
62
|
+
this.nodeset = [];
|
|
63
|
+
this.inited = false;
|
|
64
|
+
this.index = 1;
|
|
65
|
+
this.repeatSize = 0;
|
|
66
|
+
this.attachShadow({mode: 'open', delegatesFocus: true});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get repeatSize() {
|
|
70
|
+
return this.querySelectorAll(':scope > fx-repeatitem').length;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
set repeatSize(size) {
|
|
74
|
+
this.size = size;
|
|
83
75
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
connectedCallback() {
|
|
99
|
-
// console.log('connectedCallback',this);
|
|
100
|
-
// this.display = window.getComputedStyle(this, null).getPropertyValue("display");
|
|
101
|
-
this.ref = this.getAttribute('ref');
|
|
102
|
-
// this.ref = this._getRef();
|
|
103
|
-
// console.log('### fx-repeat connected ', this.id);
|
|
104
|
-
this.addEventListener('item-changed', e => {
|
|
105
|
-
const { item } = e.detail;
|
|
106
|
-
const idx = Array.from(this.children).indexOf(item);
|
|
107
|
-
this.applyIndex(this.children[idx]);
|
|
108
|
-
this.index = idx + 1;
|
|
109
|
-
});
|
|
110
|
-
// todo: review - this is just used by append action - event consolidation ?
|
|
111
|
-
document.addEventListener('index-changed', e => {
|
|
112
|
-
e.stopPropagation();
|
|
113
|
-
if (!e.target === this) return;
|
|
114
|
-
// const { item } = e.detail;
|
|
115
|
-
// const idx = Array.from(this.children).indexOf(item);
|
|
116
|
-
const { index } = e.detail;
|
|
117
|
-
this.index = Number(index);
|
|
118
|
-
this.applyIndex(this.children[index - 1]);
|
|
119
|
-
});
|
|
120
|
-
/*
|
|
121
|
-
document.addEventListener('insert', e => {
|
|
122
|
-
const nodes = e.detail.insertedNodes;
|
|
123
|
-
this.index = e.detail.position;
|
|
124
|
-
console.log('insert catched', nodes, this.index);
|
|
125
|
-
});
|
|
126
|
-
*/
|
|
127
|
-
|
|
128
|
-
// if (this.getOwnerForm().lazyRefresh) {
|
|
129
|
-
this.mutationObserver = new MutationObserver(mutations => {
|
|
130
|
-
// console.log('mutations', mutations);
|
|
131
|
-
|
|
132
|
-
if (mutations[0].type === 'childList') {
|
|
133
|
-
const added = mutations[0].addedNodes[0];
|
|
134
|
-
if (added) {
|
|
135
|
-
const instance = XPathUtil.resolveInstance(this, this.ref);
|
|
136
|
-
const path = XPathUtil.getPath(added, instance);
|
|
137
|
-
// console.log('path mutated', path);
|
|
138
|
-
// this.dispatch('path-mutated',{'path':path,'nodeset':this.nodeset,'index': this.index});
|
|
139
|
-
// this.index = index;
|
|
140
|
-
// const prev = mutations[0].previousSibling.previousElementSibling;
|
|
141
|
-
// const index = prev.index();
|
|
142
|
-
// this.applyIndex(this.index -1);
|
|
143
|
-
|
|
144
|
-
Fore.dispatch(this, 'path-mutated', { path, index: this.index });
|
|
76
|
+
|
|
77
|
+
setIndex(index) {
|
|
78
|
+
// console.log('new repeat index ', index);
|
|
79
|
+
this.index = index;
|
|
80
|
+
const rItems = this.querySelectorAll(':scope > fx-repeatitem');
|
|
81
|
+
this.applyIndex(rItems[this.index - 1]);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
applyIndex(repeatItem) {
|
|
85
|
+
this._removeIndexMarker();
|
|
86
|
+
if (repeatItem) {
|
|
87
|
+
repeatItem.setAttribute('repeat-index', '');
|
|
145
88
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get index() {
|
|
92
|
+
return parseInt(this.getAttribute('index'), 10);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
set index(idx) {
|
|
96
|
+
this.setAttribute('index', idx);
|
|
97
|
+
}
|
|
150
98
|
|
|
151
|
-
|
|
99
|
+
_getRef() {
|
|
100
|
+
return this.getAttribute('ref');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
connectedCallback() {
|
|
104
|
+
super.connectedCallback();
|
|
105
|
+
// console.log('connectedCallback',this);
|
|
106
|
+
// this.display = window.getComputedStyle(this, null).getPropertyValue("display");
|
|
107
|
+
this.ref = this.getAttribute('ref');
|
|
108
|
+
// this.ref = this._getRef();
|
|
109
|
+
// console.log('### fx-repeat connected ', this.id);
|
|
110
|
+
this.addEventListener('item-changed', e => {
|
|
111
|
+
const {item} = e.detail;
|
|
112
|
+
const idx = Array.from(this.children).indexOf(item);
|
|
113
|
+
this.applyIndex(this.children[idx]);
|
|
114
|
+
this.index = idx + 1;
|
|
115
|
+
});
|
|
116
|
+
// todo: review - this is just used by append action - event consolidation ?
|
|
117
|
+
document.addEventListener('index-changed', e => {
|
|
118
|
+
e.stopPropagation();
|
|
119
|
+
if (!e.target === this) return;
|
|
120
|
+
// const { item } = e.detail;
|
|
121
|
+
// const idx = Array.from(this.children).indexOf(item);
|
|
122
|
+
const {index} = e.detail;
|
|
123
|
+
this.index = parseInt(index, 10);
|
|
124
|
+
this.applyIndex(this.children[index - 1]);
|
|
125
|
+
});
|
|
126
|
+
/*
|
|
127
|
+
document.addEventListener('insert', e => {
|
|
128
|
+
const nodes = e.detail.insertedNodes;
|
|
129
|
+
this.index = e.detail.position;
|
|
130
|
+
console.log('insert catched', nodes, this.index);
|
|
131
|
+
});
|
|
132
|
+
*/
|
|
133
|
+
|
|
134
|
+
// if (this.getOwnerForm().lazyRefresh) {
|
|
135
|
+
this.mutationObserver = new MutationObserver(mutations => {
|
|
136
|
+
// console.log('mutations', mutations);
|
|
137
|
+
|
|
138
|
+
if (mutations[0].type === 'childList') {
|
|
139
|
+
const added = mutations[0].addedNodes[0];
|
|
140
|
+
if (added) {
|
|
141
|
+
const instance = XPathUtil.resolveInstance(this, this.ref);
|
|
142
|
+
const path = XPathUtil.getPath(added, instance);
|
|
143
|
+
// console.log('path mutated', path);
|
|
144
|
+
// this.dispatch('path-mutated',{'path':path,'nodeset':this.nodeset,'index': this.index});
|
|
145
|
+
// this.index = index;
|
|
146
|
+
// const prev = mutations[0].previousSibling.previousElementSibling;
|
|
147
|
+
// const index = prev.index();
|
|
148
|
+
// this.applyIndex(this.index -1);
|
|
149
|
+
|
|
150
|
+
Fore.dispatch(this, 'path-mutated', {path, index: this.index});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
// }
|
|
155
|
+
this.getOwnerForm().registerLazyElement(this);
|
|
156
|
+
|
|
157
|
+
const style = `
|
|
152
158
|
:host{
|
|
153
159
|
}
|
|
154
160
|
.fade-out-bottom {
|
|
@@ -160,268 +166,272 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
|
|
|
160
166
|
animation: fade-out-bottom 0.7s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
|
161
167
|
}
|
|
162
168
|
`;
|
|
163
|
-
|
|
169
|
+
const html = `
|
|
164
170
|
<slot name="header"></slot>
|
|
165
171
|
<slot></slot>
|
|
166
172
|
`;
|
|
167
|
-
|
|
173
|
+
this.shadowRoot.innerHTML = `
|
|
168
174
|
<style>
|
|
169
175
|
${style}
|
|
170
176
|
</style>
|
|
171
177
|
${html}
|
|
172
178
|
`;
|
|
173
179
|
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
init() {
|
|
178
|
-
// ### there must be a single 'template' child
|
|
179
|
-
// console.log('##### repeat init ', this.id);
|
|
180
|
-
// if(!this.inited) this.init();
|
|
181
|
-
// does not use this.evalInContext as it is expecting a nodeset instead of single node
|
|
182
|
-
this._evalNodeset();
|
|
183
|
-
// console.log('##### ',this.id, this.nodeset);
|
|
184
|
-
|
|
185
|
-
this._initTemplate();
|
|
186
|
-
this._initRepeatItems();
|
|
187
|
-
|
|
188
|
-
this.setAttribute('index', this.index);
|
|
189
|
-
this.inited = true;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* repeat has no own modelItems
|
|
194
|
-
* @private
|
|
195
|
-
*/
|
|
196
|
-
_evalNodeset() {
|
|
197
|
-
// const inscope = this.getInScopeContext();
|
|
198
|
-
const inscope = getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
|
|
199
|
-
// console.log('##### inscope ', inscope);
|
|
200
|
-
// console.log('##### ref ', this.ref);
|
|
201
|
-
// now we got a nodeset and attach MutationObserver to it
|
|
202
|
-
|
|
203
|
-
if (this.mutationObserver && inscope.nodeName) {
|
|
204
|
-
this.mutationObserver.observe(inscope, {
|
|
205
|
-
childList: true,
|
|
206
|
-
subtree: true,
|
|
207
|
-
});
|
|
208
|
-
}
|
|
180
|
+
// this.init();
|
|
209
181
|
|
|
210
|
-
/*
|
|
211
|
-
this.touchedPaths = new Set();
|
|
212
|
-
const instance = XPathUtil.resolveInstance(this, this.ref);
|
|
213
|
-
const depTrackDomfacade = new DependencyNotifyingDomFacade((node) => {
|
|
214
|
-
this.touchedPaths.add(XPathUtil.getPath(node, instance));
|
|
215
|
-
});
|
|
216
|
-
const rawNodeset = evaluateXPath(this.ref, inscope, this, {}, {}, depTrackDomfacade );
|
|
217
|
-
*/
|
|
218
|
-
const rawNodeset = evaluateXPath(this.ref, inscope, this);
|
|
219
|
-
|
|
220
|
-
// console.log('Touched!', this.ref, [...this.touchedPaths].join(', '));
|
|
221
|
-
if (rawNodeset.length === 1 && Array.isArray(rawNodeset[0])) {
|
|
222
|
-
// This XPath likely returned an XPath array. Just collapse to that array
|
|
223
|
-
this.nodeset = rawNodeset[0];
|
|
224
|
-
return;
|
|
225
182
|
}
|
|
226
|
-
this.nodeset = rawNodeset;
|
|
227
|
-
}
|
|
228
183
|
|
|
229
|
-
|
|
230
|
-
|
|
184
|
+
_createNewRepeatItem() {
|
|
185
|
+
const newItem = document.createElement('fx-repeatitem');
|
|
231
186
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
187
|
+
if (this.isDraggable) {
|
|
188
|
+
newItem.setAttribute('draggable', 'true');
|
|
189
|
+
newItem.setAttribute('tabindex', 0);
|
|
190
|
+
}
|
|
191
|
+
const clone = this._clone();
|
|
192
|
+
newItem.appendChild(clone);
|
|
235
193
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const modelItem = this.getModelItem();
|
|
239
|
-
if (!modelItem.boundControls.includes(this)) {
|
|
240
|
-
modelItem.boundControls.push(this);
|
|
241
|
-
}
|
|
242
|
-
*/
|
|
243
|
-
// console.log('repeat refresh nodeset ', this.nodeset);
|
|
244
|
-
// console.log('repeatCount', this.repeatCount);
|
|
194
|
+
return newItem;
|
|
195
|
+
}
|
|
245
196
|
|
|
246
|
-
|
|
247
|
-
|
|
197
|
+
init() {
|
|
198
|
+
// ### there must be a single 'template' child
|
|
199
|
+
console.log('##### repeat init ', this.id);
|
|
200
|
+
// if(!this.inited) this.init();
|
|
201
|
+
// does not use this.evalInContext as it is expecting a nodeset instead of single node
|
|
202
|
+
this._evalNodeset();
|
|
203
|
+
// console.log('##### ',this.id, this.nodeset);
|
|
248
204
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
205
|
+
this._initTemplate();
|
|
206
|
+
this._initRepeatItems();
|
|
207
|
+
|
|
208
|
+
this.setAttribute('index', this.index);
|
|
209
|
+
this.inited = true;
|
|
252
210
|
}
|
|
253
211
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
212
|
+
/**
|
|
213
|
+
* repeat has no own modelItems
|
|
214
|
+
* @private
|
|
215
|
+
*/
|
|
216
|
+
_evalNodeset() {
|
|
217
|
+
// const inscope = this.getInScopeContext();
|
|
218
|
+
const inscope = getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
|
|
219
|
+
// console.log('##### inscope ', inscope);
|
|
220
|
+
// console.log('##### ref ', this.ref);
|
|
221
|
+
// now we got a nodeset and attach MutationObserver to it
|
|
222
|
+
|
|
223
|
+
if (this.mutationObserver && inscope.nodeName) {
|
|
224
|
+
this.mutationObserver.observe(inscope, {
|
|
225
|
+
childList: true,
|
|
226
|
+
subtree: true,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/*
|
|
231
|
+
this.touchedPaths = new Set();
|
|
232
|
+
const instance = XPathUtil.resolveInstance(this, this.ref);
|
|
233
|
+
const depTrackDomfacade = new DependencyNotifyingDomFacade((node) => {
|
|
234
|
+
this.touchedPaths.add(XPathUtil.getPath(node, instance));
|
|
235
|
+
});
|
|
236
|
+
const rawNodeset = evaluateXPath(this.ref, inscope, this, {}, {}, depTrackDomfacade );
|
|
237
|
+
*/
|
|
238
|
+
const rawNodeset = evaluateXPath(this.ref, inscope, this);
|
|
239
|
+
|
|
240
|
+
// console.log('Touched!', this.ref, [...this.touchedPaths].join(', '));
|
|
241
|
+
if (rawNodeset.length === 1 && Array.isArray(rawNodeset[0])) {
|
|
242
|
+
// This XPath likely returned an XPath array. Just collapse to that array
|
|
243
|
+
this.nodeset = rawNodeset[0];
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
this.nodeset = rawNodeset;
|
|
267
247
|
}
|
|
268
248
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
249
|
+
async refresh(force) {
|
|
250
|
+
// console.group('fx-repeat.refresh on', this.id);
|
|
251
|
+
|
|
252
|
+
if (!this.inited) this.init();
|
|
253
|
+
// console.time('repeat-refresh', this);
|
|
254
|
+
this._evalNodeset();
|
|
255
|
+
|
|
256
|
+
// ### register ourselves as boundControl
|
|
257
|
+
/*
|
|
258
|
+
const modelItem = this.getModelItem();
|
|
259
|
+
if (!modelItem.boundControls.includes(this)) {
|
|
260
|
+
modelItem.boundControls.push(this);
|
|
261
|
+
}
|
|
262
|
+
*/
|
|
263
|
+
// console.log('repeat refresh nodeset ', this.nodeset);
|
|
264
|
+
// console.log('repeatCount', this.repeatCount);
|
|
265
|
+
|
|
266
|
+
const repeatItems = this.querySelectorAll(':scope > fx-repeatitem');
|
|
267
|
+
const repeatItemCount = repeatItems.length;
|
|
268
|
+
|
|
269
|
+
let nodeCount = 1;
|
|
270
|
+
if (Array.isArray(this.nodeset)) {
|
|
271
|
+
nodeCount = this.nodeset.length;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// const contextSize = this.nodeset.length;
|
|
275
|
+
const contextSize = nodeCount;
|
|
276
|
+
// todo: review - cant the context really never be smaller than the repeat count?
|
|
277
|
+
// todo: this code can be deprecated probably but check first
|
|
278
|
+
if (contextSize < repeatItemCount) {
|
|
279
|
+
for (let position = repeatItemCount; position > contextSize; position -= 1) {
|
|
280
|
+
// remove repeatitem
|
|
281
|
+
const itemToRemove = repeatItems[position - 1];
|
|
282
|
+
itemToRemove.parentNode.removeChild(itemToRemove);
|
|
283
|
+
this.getOwnerForm().unRegisterLazyElement(itemToRemove);
|
|
284
|
+
// this._fadeOut(itemToRemove);
|
|
285
|
+
// Fore.fadeOutElement(itemToRemove)
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (contextSize > repeatItemCount) {
|
|
290
|
+
for (let position = repeatItemCount + 1; position <= contextSize; position += 1) {
|
|
291
|
+
// add new repeatitem
|
|
272
292
|
|
|
273
|
-
|
|
274
|
-
const clonedTemplate = this._clone();
|
|
275
|
-
newItem.appendChild(clonedTemplate);
|
|
276
|
-
this.appendChild(newItem);
|
|
293
|
+
const newItem = this._createNewRepeatItem();
|
|
277
294
|
|
|
278
|
-
|
|
295
|
+
this.appendChild(newItem);
|
|
296
|
+
this._initVariables(newItem);
|
|
279
297
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
298
|
+
newItem.nodeset = this.nodeset[position - 1];
|
|
299
|
+
newItem.index = position;
|
|
300
|
+
// Tell the owner form we might have new template expressions here
|
|
301
|
+
this.getOwnerForm().scanForNewTemplateExpressionsNextRefresh();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ### update nodeset of repeatitems
|
|
306
|
+
for (let position = 0; position < repeatItemCount; position += 1) {
|
|
307
|
+
const item = repeatItems[position];
|
|
308
|
+
this.getOwnerForm().registerLazyElement(item);
|
|
309
|
+
|
|
310
|
+
if (item.nodeset !== this.nodeset[position]) {
|
|
311
|
+
item.nodeset = this.nodeset[position];
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Fore.refreshChildren(clone,true);
|
|
316
|
+
const fore = this.getOwnerForm();
|
|
317
|
+
if (!fore.lazyRefresh || force) {
|
|
318
|
+
Fore.refreshChildren(this, force);
|
|
319
|
+
}
|
|
320
|
+
// this.style.display = 'block';
|
|
321
|
+
// this.style.display = this.display;
|
|
322
|
+
this.setIndex(this.index);
|
|
323
|
+
// console.timeEnd('repeat-refresh');
|
|
324
|
+
|
|
325
|
+
// this.replaceWith(clone);
|
|
326
|
+
|
|
327
|
+
// this.repeatCount = contextSize;
|
|
328
|
+
// console.log('repeatCount', this.repeatCount);
|
|
285
329
|
}
|
|
286
330
|
|
|
287
|
-
//
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
331
|
+
// eslint-disable-next-line class-methods-use-this
|
|
332
|
+
_fadeOut(el) {
|
|
333
|
+
el.style.opacity = 1;
|
|
334
|
+
|
|
335
|
+
(function fade() {
|
|
336
|
+
// eslint-disable-next-line no-cond-assign
|
|
337
|
+
if ((el.style.opacity -= 0.1) < 0) {
|
|
338
|
+
el.style.display = 'none';
|
|
339
|
+
} else {
|
|
340
|
+
requestAnimationFrame(fade);
|
|
341
|
+
}
|
|
342
|
+
})();
|
|
343
|
+
}
|
|
291
344
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
345
|
+
// eslint-disable-next-line class-methods-use-this
|
|
346
|
+
_fadeIn(el) {
|
|
347
|
+
if (!el) return;
|
|
348
|
+
|
|
349
|
+
el.style.opacity = 0;
|
|
350
|
+
el.style.display = this.display;
|
|
351
|
+
|
|
352
|
+
(function fade() {
|
|
353
|
+
// setTimeout(() => {
|
|
354
|
+
let val = parseFloat(el.style.opacity);
|
|
355
|
+
// eslint-disable-next-line no-cond-assign
|
|
356
|
+
if (!((val += 0.1) > 1)) {
|
|
357
|
+
el.style.opacity = val;
|
|
358
|
+
requestAnimationFrame(fade);
|
|
359
|
+
}
|
|
360
|
+
// }, 40);
|
|
361
|
+
})();
|
|
295
362
|
}
|
|
296
363
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
364
|
+
_initTemplate() {
|
|
365
|
+
this.template = this.querySelector('template');
|
|
366
|
+
// console.log('### init template for repeat ', this.id, this.template);
|
|
367
|
+
// todo: this.dropTarget not needed?
|
|
368
|
+
this.dropTarget = this.template.getAttribute('drop-target');
|
|
369
|
+
this.isDraggable = this.template.hasAttribute('draggable') ? this.template.getAttribute('draggable') : null;
|
|
370
|
+
|
|
371
|
+
if (this.template === null) {
|
|
372
|
+
// todo: catch this on form element
|
|
373
|
+
this.dispatchEvent(
|
|
374
|
+
new CustomEvent('no-template-error', {
|
|
375
|
+
composed: true,
|
|
376
|
+
bubbles: true,
|
|
377
|
+
detail: {message: `no template found for repeat:${this.id}`},
|
|
378
|
+
}),
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
this.shadowRoot.appendChild(this.template);
|
|
301
383
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
// eslint-disable-next-line no-cond-assign
|
|
319
|
-
if ((el.style.opacity -= 0.1) < 0) {
|
|
320
|
-
el.style.display = 'none';
|
|
321
|
-
} else {
|
|
322
|
-
requestAnimationFrame(fade);
|
|
323
|
-
}
|
|
324
|
-
})();
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// eslint-disable-next-line class-methods-use-this
|
|
328
|
-
_fadeIn(el) {
|
|
329
|
-
if (!el) return;
|
|
330
|
-
|
|
331
|
-
el.style.opacity = 0;
|
|
332
|
-
el.style.display = this.display;
|
|
333
|
-
|
|
334
|
-
(function fade() {
|
|
335
|
-
// setTimeout(() => {
|
|
336
|
-
let val = parseFloat(el.style.opacity);
|
|
337
|
-
// eslint-disable-next-line no-cond-assign
|
|
338
|
-
if (!((val += 0.1) > 1)) {
|
|
339
|
-
el.style.opacity = val;
|
|
340
|
-
requestAnimationFrame(fade);
|
|
341
|
-
}
|
|
342
|
-
// }, 40);
|
|
343
|
-
})();
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
_initTemplate() {
|
|
347
|
-
// const shadowTemplate = this.shadowRoot.querySelector('template');
|
|
348
|
-
// console.log('shadowtempl ', shadowTemplate);
|
|
349
|
-
|
|
350
|
-
// const defaultSlot = this.shadowRoot.querySelector('slot');
|
|
351
|
-
// todo: this is still weak - should handle that better maybe by an explicit slot?
|
|
352
|
-
// this.template = this.firstElementChild;
|
|
353
|
-
this.template = this.querySelector('template');
|
|
354
|
-
// console.log('### init template for repeat ', this.id, this.template);
|
|
355
|
-
|
|
356
|
-
if (this.template === null) {
|
|
357
|
-
// console.error('### no template found for this repeat:', this.id);
|
|
358
|
-
// todo: catch this on form element
|
|
359
|
-
this.dispatchEvent(
|
|
360
|
-
new CustomEvent('no-template-error', {
|
|
361
|
-
composed: true,
|
|
362
|
-
bubbles: true,
|
|
363
|
-
detail: { message: `no template found for repeat:${this.id}` },
|
|
364
|
-
}),
|
|
365
|
-
);
|
|
384
|
+
|
|
385
|
+
_initRepeatItems() {
|
|
386
|
+
this.nodeset.forEach((item, index) => {
|
|
387
|
+
const repeatItem = this._createNewRepeatItem();
|
|
388
|
+
repeatItem.nodeset = this.nodeset[index];
|
|
389
|
+
repeatItem.index = index + 1; // 1-based index
|
|
390
|
+
|
|
391
|
+
this.appendChild(repeatItem);
|
|
392
|
+
|
|
393
|
+
if (repeatItem.index === 1) {
|
|
394
|
+
this.applyIndex(repeatItem);
|
|
395
|
+
}
|
|
396
|
+
// console.log('*********repeat item created', repeatItem.nodeset)
|
|
397
|
+
Fore.dispatch(this, 'item-created', {nodeset: repeatItem.nodeset, pos: index + 1});
|
|
398
|
+
this._initVariables(repeatItem);
|
|
399
|
+
});
|
|
366
400
|
}
|
|
367
401
|
|
|
368
|
-
|
|
369
|
-
|
|
402
|
+
_initVariables(newRepeatItem) {
|
|
403
|
+
const inScopeVariables = new Map(this.inScopeVariables);
|
|
404
|
+
newRepeatItem.setInScopeVariables(inScopeVariables);
|
|
405
|
+
(function registerVariables(node) {
|
|
406
|
+
for (const child of node.children) {
|
|
407
|
+
if ('setInScopeVariables' in child) {
|
|
408
|
+
child.setInScopeVariables(inScopeVariables);
|
|
409
|
+
}
|
|
410
|
+
registerVariables(child);
|
|
411
|
+
}
|
|
412
|
+
})(newRepeatItem);
|
|
413
|
+
}
|
|
370
414
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
repeatItem.index = index + 1; // 1-based index
|
|
415
|
+
_clone() {
|
|
416
|
+
// const content = this.template.content.cloneNode(true);
|
|
417
|
+
this.template = this.shadowRoot.querySelector('template');
|
|
418
|
+
const content = this.template.content.cloneNode(true);
|
|
419
|
+
return document.importNode(content, true);
|
|
420
|
+
}
|
|
378
421
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
422
|
+
_removeIndexMarker() {
|
|
423
|
+
Array.from(this.children).forEach(item => {
|
|
424
|
+
item.removeAttribute('repeat-index');
|
|
425
|
+
});
|
|
426
|
+
}
|
|
382
427
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
this._initVariables(repeatItem);
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
_initVariables(newRepeatItem) {
|
|
393
|
-
const inScopeVariables = new Map(this.inScopeVariables);
|
|
394
|
-
newRepeatItem.setInScopeVariables(inScopeVariables);
|
|
395
|
-
(function registerVariables(node) {
|
|
396
|
-
for (const child of node.children) {
|
|
397
|
-
if ('setInScopeVariables' in child) {
|
|
398
|
-
child.setInScopeVariables(inScopeVariables);
|
|
399
|
-
}
|
|
400
|
-
registerVariables(child);
|
|
401
|
-
}
|
|
402
|
-
})(newRepeatItem);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
_clone() {
|
|
406
|
-
// const content = this.template.content.cloneNode(true);
|
|
407
|
-
this.template = this.shadowRoot.querySelector('template');
|
|
408
|
-
const content = this.template.content.cloneNode(true);
|
|
409
|
-
return document.importNode(content, true);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
_removeIndexMarker() {
|
|
413
|
-
Array.from(this.children).forEach(item => {
|
|
414
|
-
item.removeAttribute('repeat-index');
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
setInScopeVariables(inScopeVariables) {
|
|
419
|
-
// Repeats are interesting: the variables should be scoped per repeat item, they should not be
|
|
420
|
-
// able to see the variables in adjacent repeat items!
|
|
421
|
-
this.inScopeVariables = new Map(inScopeVariables);
|
|
422
|
-
}
|
|
428
|
+
setInScopeVariables(inScopeVariables) {
|
|
429
|
+
// Repeats are interesting: the variables should be scoped per repeat item, they should not be
|
|
430
|
+
// able to see the variables in adjacent repeat items!
|
|
431
|
+
this.inScopeVariables = new Map(inScopeVariables);
|
|
432
|
+
}
|
|
423
433
|
}
|
|
424
434
|
|
|
425
435
|
if (!customElements.get('fx-repeat')) {
|
|
426
|
-
|
|
436
|
+
window.customElements.define('fx-repeat', FxRepeat);
|
|
427
437
|
}
|