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