@componyx/ui 0.0.0-stage → 1.0.4
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/AppSkin/AppSkin.css +1268 -0
- package/AppSkin/AppSkin.js +2748 -0
- package/AppSkin/Themes/Default.css +241 -0
- package/Base/Base.js +3407 -0
- package/Base/ComponentIcons.css +66 -0
- package/Base/Font/ComponentIcons.woff +0 -0
- package/Base/Font/UI.woff +0 -0
- package/Base/Library.js +8432 -0
- package/Base/NavigationManager.js +462 -0
- package/Base/ResponsiveTemplates.js +371 -0
- package/Base/Sanitizer.js +288 -0
- package/Base/Themes/Default.css +255 -0
- package/Base/UI.css +618 -0
- package/Base/UIResourcePath.js +6 -0
- package/Bindary/Bindary.js +2011 -0
- package/Bindary/Modules/Connection.js +216 -0
- package/Bindary/Modules/Core.js +854 -0
- package/Bindary/Modules/DataUpdater.js +351 -0
- package/Bindary/Modules/ExpressionEngine.js +347 -0
- package/Bindary/Modules/ProxyManager.js +482 -0
- package/Bindary/Modules/Renderer.js +605 -0
- package/Bindary/Modules/Router.js +291 -0
- package/Bindary/Modules/Scroller.js +89 -0
- package/Bindary/Modules/Template.js +1273 -0
- package/BookmarkSpy/BookmarkSpy.js +430 -0
- package/Box/Box.css +36 -0
- package/Box/Box.js +1685 -0
- package/Button/Button.css +470 -0
- package/Button/Button.js +1398 -0
- package/Button/Themes/Default.css +200 -0
- package/Carousel/Carousel.css +273 -0
- package/Carousel/Carousel.js +607 -0
- package/ColorButton/ColorButton.css +39 -0
- package/ColorButton/ColorButton.js +336 -0
- package/ColorPicker/ColorPicker.css +359 -0
- package/ColorPicker/ColorPicker.js +972 -0
- package/ComboBox/ComboBox.css +357 -0
- package/ComboBox/ComboBox.js +2342 -0
- package/ComboBox/Themes/Default.css +23 -0
- package/DataPager/DataPager.css +72 -0
- package/DataPager/DataPager.js +674 -0
- package/DatePicker/DatePicker.css +227 -0
- package/DatePicker/DatePicker.js +1531 -0
- package/DatePicker/Themes/Default.css +26 -0
- package/Dialog/Dialog.css +106 -0
- package/Dialog/Dialog.js +572 -0
- package/Dialog/Themes/Default.css +10 -0
- package/Editor/Data/Emoji.json +8285 -0
- package/Editor/Data/Special.json +1042 -0
- package/Editor/Editor.css +1562 -0
- package/Editor/Editor.js +4058 -0
- package/Editor/Font/Editor.woff +0 -0
- package/Editor/Modules/ComponentFactory.js +565 -0
- package/Editor/Modules/ContentManager.js +748 -0
- package/Editor/Modules/DialogManager.js +1234 -0
- package/Editor/Modules/EventManager.js +458 -0
- package/Editor/Modules/Format.js +950 -0
- package/Editor/Modules/History.js +191 -0
- package/Editor/Modules/LayoutState.js +379 -0
- package/Editor/Modules/ListManager.js +296 -0
- package/Editor/Modules/MenuManager.js +388 -0
- package/Editor/Modules/NodeManager.js +681 -0
- package/Editor/Modules/ParagraphButtons.js +122 -0
- package/Editor/Modules/Resizer.js +176 -0
- package/Editor/Modules/SelectionRange.js +564 -0
- package/Editor/Modules/SourceViewBuilder.js +212 -0
- package/Editor/Modules/SymbolPicker.js +208 -0
- package/Editor/Modules/Table.js +2327 -0
- package/Editor/Modules/TableDialog.js +757 -0
- package/Editor/Modules/Toolbar.js +375 -0
- package/Editor/Modules/TooltipMenu.js +125 -0
- package/Editor/Modules/Utility.js +131 -0
- package/Editor/Themes/Default.css +204 -0
- package/FileUpload/FileUpload.css +156 -0
- package/FileUpload/FileUpload.js +898 -0
- package/FileUpload/Themes/Default.css +17 -0
- package/Form/Form.css +1934 -0
- package/Form/Form.js +4943 -0
- package/Form/Modules/ActionManager.js +368 -0
- package/Form/Modules/BuildPanelManager.js +319 -0
- package/Form/Modules/ComponentFactory.js +468 -0
- package/Form/Modules/ComponentPanel.js +265 -0
- package/Form/Modules/ConfigPanelManager.js +685 -0
- package/Form/Modules/DataBinder.js +602 -0
- package/Form/Modules/DataObserver.js +717 -0
- package/Form/Modules/Draggable.js +756 -0
- package/Form/Modules/OptionsPanel.js +342 -0
- package/Form/Modules/Renderer.js +1889 -0
- package/Form/Modules/RuleEngine.js +585 -0
- package/Form/Modules/RulesPanel.js +1158 -0
- package/Form/Modules/Types.js +1709 -0
- package/Form/Modules/ValidationManager.js +194 -0
- package/Form/Themes/Default.css +216 -0
- package/FormField/FormField.css +468 -0
- package/FormField/FormField.js +576 -0
- package/FormField/Themes/Default.css +99 -0
- package/Grid/Grid.css +544 -0
- package/Grid/Grid.js +3761 -0
- package/Grid/Themes/Default.css +43 -0
- package/LICENSE +126 -0
- package/MaskedTextBox/MaskedTextBox.css +28 -0
- package/MaskedTextBox/MaskedTextBox.js +642 -0
- package/MaskedTextBox/Themes/Default.css +6 -0
- package/Menu/Menu.css +328 -0
- package/Menu/Menu.js +2386 -0
- package/Menu/Themes/Default.css +24 -0
- package/NumericBox/NumericBox.css +120 -0
- package/NumericBox/NumericBox.js +984 -0
- package/PanelBar/PanelBar.css +123 -0
- package/PanelBar/PanelBar.js +505 -0
- package/PanelBar/Themes/Default.css +51 -0
- package/PieChart/PieChart.css +95 -0
- package/PieChart/PieChart.js +820 -0
- package/PieChart/Themes/Default.css +9 -0
- package/README.md +178 -3
- package/Slider/Slider.css +348 -0
- package/Slider/Slider.js +1306 -0
- package/Slider/Themes/Default.css +44 -0
- package/TabStrip/TabStrip.css +52 -0
- package/TabStrip/TabStrip.js +362 -0
- package/TabStrip/Themes/Default.css +35 -0
- package/TimePicker/Themes/Default.css +30 -0
- package/TimePicker/TimePicker.css +253 -0
- package/TimePicker/TimePicker.js +1485 -0
- package/TooltipManager/Themes/Default.css +21 -0
- package/TooltipManager/TooltipManager.css +227 -0
- package/TooltipManager/TooltipManager.js +791 -0
- package/Validator/Validator.css +54 -0
- package/Validator/Validator.js +2508 -0
- package/componyx.html-data.json +619 -0
- package/index.js +27 -0
- package/package.json +43 -4
- package/types/AppSkin.d.ts +842 -0
- package/types/Base.d.ts +1034 -0
- package/types/Bindary.d.ts +1196 -0
- package/types/BookmarkSpy.d.ts +112 -0
- package/types/Box.d.ts +374 -0
- package/types/Button.d.ts +455 -0
- package/types/Carousel.d.ts +136 -0
- package/types/ColorButton.d.ts +120 -0
- package/types/ColorPicker.d.ts +225 -0
- package/types/ComboBox.d.ts +507 -0
- package/types/DataPager.d.ts +152 -0
- package/types/DatePicker.d.ts +354 -0
- package/types/Dialog.d.ts +160 -0
- package/types/Editor.d.ts +1289 -0
- package/types/FileUpload.d.ts +206 -0
- package/types/Form.d.ts +3078 -0
- package/types/FormField.d.ts +204 -0
- package/types/Grid.d.ts +911 -0
- package/types/Library.d.ts +1899 -0
- package/types/MaskedTextBox.d.ts +91 -0
- package/types/Menu.d.ts +577 -0
- package/types/NumericBox.d.ts +310 -0
- package/types/PanelBar.d.ts +223 -0
- package/types/PieChart.d.ts +224 -0
- package/types/ResponsiveTemplates.d.ts +108 -0
- package/types/Slider.d.ts +227 -0
- package/types/TabStrip.d.ts +185 -0
- package/types/TimePicker.d.ts +265 -0
- package/types/TooltipManager.d.ts +178 -0
- package/types/UI.d.ts +29 -0
- package/types/Validator.d.ts +653 -0
- package/types/index.d.ts +59 -0
- package/ui.css +11783 -0
- package/ui.js +79477 -0
- package/ui.min.css +138 -0
- package/ui.min.js +264 -0
- package/ui.min.js.map +1 -0
|
@@ -0,0 +1,1273 @@
|
|
|
1
|
+
/*! Componyx.UI | (c) E.H. Daanen / Componyx | BUSL-1.1 | componyx.com/license */
|
|
2
|
+
await (async function ()
|
|
3
|
+
{
|
|
4
|
+
await import(`${$UI.getScriptResourcePath('Base.Bindary.Core')}`);
|
|
5
|
+
await import(`${$UI.getScriptResourcePath('Base.Bindary.DataUpdater')}`);
|
|
6
|
+
const core = componyx.bindary_modules.core;
|
|
7
|
+
const dataUpdater = componyx.bindary_modules.dataUpdater;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The base template class.
|
|
11
|
+
* @class
|
|
12
|
+
* @memberof componyx.bindary
|
|
13
|
+
*/
|
|
14
|
+
class TemplateBase
|
|
15
|
+
{
|
|
16
|
+
resolveLivePath(path)
|
|
17
|
+
{
|
|
18
|
+
let orgPath = path,
|
|
19
|
+
me = this;
|
|
20
|
+
|
|
21
|
+
if (!path) return path;
|
|
22
|
+
|
|
23
|
+
if (me.livePath[path]) return me.livePath[path];
|
|
24
|
+
|
|
25
|
+
let parent = me.parent,
|
|
26
|
+
parentRepItem = me.getParentRepeater(),
|
|
27
|
+
useItemContext = ((me.contextDataKey && path != me.contextDataKeyPath) || (me.repeatDataKeyPath && path != me.repeatDataKeyPath)),
|
|
28
|
+
contextItem = useItemContext ? me : parent,
|
|
29
|
+
livePath, contextPath;
|
|
30
|
+
|
|
31
|
+
if (path.endsWith(core.dksc + core.valueKey) || path.endsWith(core.dksc + core.key))
|
|
32
|
+
{
|
|
33
|
+
path = path.replace(new RegExp('\\' + core.dksc.split('').join('\\') + '(\\$value|\\$key)$'), '');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Adds the collection key to the live path
|
|
37
|
+
if (parentRepItem)
|
|
38
|
+
{
|
|
39
|
+
path = path.replace(parentRepItem.repeatDataKeyPath, parentRepItem.repeatDataKeyPath + core.dksc + parentRepItem.key);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (contextItem)
|
|
43
|
+
{
|
|
44
|
+
contextPath = contextItem.contextDataKeyPath;
|
|
45
|
+
livePath = contextItem.livePath ? contextItem.livePath[contextPath] : null;
|
|
46
|
+
|
|
47
|
+
if (livePath && livePath != contextPath && !path.startsWith(livePath) && path.startsWith(contextPath))
|
|
48
|
+
{
|
|
49
|
+
path = path.replace(contextPath, livePath); // Fast convert when parent's cached path is available
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (path.indexOf(core.ipc) > -1)
|
|
54
|
+
{ // Path contains pointer
|
|
55
|
+
let parts = path.split(core.dksc),
|
|
56
|
+
pointerPaths = [];
|
|
57
|
+
|
|
58
|
+
$lib.each(parts, (p, index) =>
|
|
59
|
+
{
|
|
60
|
+
if (p.indexOf(core.ipc) == 0)
|
|
61
|
+
{
|
|
62
|
+
let key = me.indexKey[p.substr(core.ipc.length)];
|
|
63
|
+
|
|
64
|
+
if (typeof key != 'number')
|
|
65
|
+
{
|
|
66
|
+
pointerPaths.push(key.join(core.dksc).substr(core.dksc.length + '$'.length)); // Add data-key to pointer path
|
|
67
|
+
key = me.getDataValue(key, contextItem); // Dynamic index/key pointer
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
parts[index] = key;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
me.pointerPaths = pointerPaths;
|
|
75
|
+
path = parts.join(core.dksc);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return (this.livePath[orgPath] = path); // Cache calculated path
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
getParentRepeater()
|
|
82
|
+
{
|
|
83
|
+
let item = this;
|
|
84
|
+
|
|
85
|
+
if (!item.inRepeat) return null;
|
|
86
|
+
|
|
87
|
+
while ((item = item.parent))
|
|
88
|
+
{
|
|
89
|
+
if (item.repeatDataKeyPath && !$lib.isEmpty(item.key))
|
|
90
|
+
{
|
|
91
|
+
return item;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
getDataChange()
|
|
99
|
+
{
|
|
100
|
+
let me = this,
|
|
101
|
+
c = core.dataChanges,
|
|
102
|
+
m = core.modelDataChanges,
|
|
103
|
+
rules = c['#' + me.updateId] || ((m.size > 0) ? m.get(me.context) || m.get(me.repeatValue) : null);
|
|
104
|
+
|
|
105
|
+
if (!rules)
|
|
106
|
+
{
|
|
107
|
+
if (me.repeatDataKey)
|
|
108
|
+
{
|
|
109
|
+
rules = c[me.livePath[me.repeatDataKeyPath]];
|
|
110
|
+
|
|
111
|
+
if (!me.rewriteArray(rules))
|
|
112
|
+
{
|
|
113
|
+
rules = me.getChangedIndexes(rules);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!rules && me.hasParentChange())
|
|
118
|
+
{
|
|
119
|
+
rules = [];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!rules)
|
|
124
|
+
{
|
|
125
|
+
let paths = me.resolveLivePaths();
|
|
126
|
+
|
|
127
|
+
if (!$lib.isEmpty(me.pointerPaths))
|
|
128
|
+
{
|
|
129
|
+
paths = paths.concat(me.pointerPaths); // Also check pointer data-keys
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
$lib.each(paths, (path) =>
|
|
133
|
+
{
|
|
134
|
+
rules = c[path] || null; // Exact match check
|
|
135
|
+
|
|
136
|
+
if (!rules && path)
|
|
137
|
+
{
|
|
138
|
+
$lib.each(c, (r, key) =>
|
|
139
|
+
{
|
|
140
|
+
if (core.dataKeyMatch(path, key))
|
|
141
|
+
{ // Partial match check
|
|
142
|
+
rules = [];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return (rules == null);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return (rules == null);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
me.dataChange = rules || null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
rewriteArray(rules)
|
|
157
|
+
{
|
|
158
|
+
let rewrite = false;
|
|
159
|
+
$lib.each(rules, (r) =>
|
|
160
|
+
{
|
|
161
|
+
rewrite = $lib.isEmpty(r); // Empty object as rules means rewrite
|
|
162
|
+
return !rewrite;
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
return rewrite;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
hasParentChange()
|
|
169
|
+
{
|
|
170
|
+
let me = this, parent = me.parent;
|
|
171
|
+
|
|
172
|
+
if (!parent || !parent.dataChange) return false;
|
|
173
|
+
|
|
174
|
+
let updateId = parent.updateId;
|
|
175
|
+
|
|
176
|
+
if (updateId && core.dataChanges['#' + updateId])
|
|
177
|
+
{ // Always update child items when change by update-id
|
|
178
|
+
me.updateId = updateId;
|
|
179
|
+
return me.updateIdFromParent = true;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (me.repeatDataKey || parent.repeatDataKey)
|
|
183
|
+
{ // Repeater can only be updated by parent through the updateId (is rerender)
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Check if item context belongs to the parent-item context
|
|
188
|
+
return (me.paths.findIndex((p) =>
|
|
189
|
+
{
|
|
190
|
+
let found = false;
|
|
191
|
+
$lib.each(parent.paths, (pp) =>
|
|
192
|
+
{
|
|
193
|
+
return !(found = p.startsWith(pp));
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
return found;
|
|
197
|
+
}) > -1);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
createDataKeyPath(key, parentKey)
|
|
201
|
+
{
|
|
202
|
+
let me = this;
|
|
203
|
+
|
|
204
|
+
if (key == null)
|
|
205
|
+
return key;
|
|
206
|
+
|
|
207
|
+
let k = key.join(core.dksc), merge = true, parent;
|
|
208
|
+
|
|
209
|
+
if (key[0] === '$')
|
|
210
|
+
{
|
|
211
|
+
k = k.substr('$'.length + core.dksc.length);
|
|
212
|
+
merge = false;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (core.isKey(key[0], core.parentKey))
|
|
216
|
+
{
|
|
217
|
+
while (core.isKey(key[0], core.parentKey)) // routine for multiple $parent navigators in data-key
|
|
218
|
+
{
|
|
219
|
+
parent = me.parent;
|
|
220
|
+
key = key.slice(1); // remove $parent from key
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
parentKey = parent.contextDataKeyPath;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (merge && parentKey)
|
|
227
|
+
return parentKey + core.dksc + k;
|
|
228
|
+
else
|
|
229
|
+
return k;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
createDataKey(dataKey, isRoot)
|
|
233
|
+
{
|
|
234
|
+
let me = this;
|
|
235
|
+
|
|
236
|
+
if (!dataKey || dataKey == 'null')
|
|
237
|
+
return dataKey;
|
|
238
|
+
|
|
239
|
+
dataKey = dataKey.replace(/\[+([\w.$]+)\]+/g, function (match, capture)
|
|
240
|
+
{
|
|
241
|
+
let number = parseInt(capture, 10);
|
|
242
|
+
|
|
243
|
+
if (isNaN(number))
|
|
244
|
+
me.indexKey.push(core.addDataContainer(capture.split(core.dksc), false)); // dynamic index/key pointer
|
|
245
|
+
else
|
|
246
|
+
me.indexKey.push(number); // static index pointer
|
|
247
|
+
|
|
248
|
+
return core.dksc + core.ipc + (me.indexKey.length - 1);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
if ($lib.startsWith(dataKey, core.dksc + core.ipc))
|
|
252
|
+
dataKey = dataKey.substr(core.dksc.length);
|
|
253
|
+
|
|
254
|
+
return core.addDataContainer(dataKey.split(core.dksc), isRoot);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
getDataValue(dataKey, dc)
|
|
258
|
+
{
|
|
259
|
+
let me = this;
|
|
260
|
+
|
|
261
|
+
if (!dataKey)
|
|
262
|
+
return null;
|
|
263
|
+
|
|
264
|
+
if (core.isKey(dataKey[0], core.valueKey))
|
|
265
|
+
return (dc || '').toString();
|
|
266
|
+
|
|
267
|
+
let index = 0, current, curItem, arrIndex, root = dc;
|
|
268
|
+
|
|
269
|
+
if (dataKey[0] === '$') // set context to root
|
|
270
|
+
{
|
|
271
|
+
dc = $bindary;
|
|
272
|
+
dataKey = dataKey.slice(1); // remove $ from key
|
|
273
|
+
|
|
274
|
+
if ($lib.indexOf(core.dataLabel, dataKey[0]) == -1)
|
|
275
|
+
dc = window;
|
|
276
|
+
}
|
|
277
|
+
else if (core.isKey(dataKey[0], core.parentKey)) // set context to parent
|
|
278
|
+
{
|
|
279
|
+
curItem = me.parent;
|
|
280
|
+
current = curItem.context;
|
|
281
|
+
|
|
282
|
+
while (core.isKey(dataKey[0], core.parentKey)) // routine for multiple $parent navigators in data-key
|
|
283
|
+
{
|
|
284
|
+
while (dc === current && curItem) // context must be different
|
|
285
|
+
{
|
|
286
|
+
curItem = curItem.parent;
|
|
287
|
+
current = (curItem) ? curItem.context : null;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
dataKey = dataKey.slice(1); // remove $parent from key
|
|
291
|
+
dc = current;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
core.escapeDataKey(dataKey);
|
|
296
|
+
|
|
297
|
+
if (core.isKey(dataKey, core.key))
|
|
298
|
+
return me.key;
|
|
299
|
+
|
|
300
|
+
while (dc && index < dataKey.length)
|
|
301
|
+
{
|
|
302
|
+
if (dataKey[index].indexOf(core.ipc) == 0) // position index within array
|
|
303
|
+
{
|
|
304
|
+
arrIndex = me.indexKey[dataKey[index].substr(core.ipc.length)];
|
|
305
|
+
|
|
306
|
+
if (typeof arrIndex != 'number')
|
|
307
|
+
arrIndex = me.getDataValue(arrIndex, root); // dynamic index/key pointer
|
|
308
|
+
|
|
309
|
+
dc = dc[arrIndex];
|
|
310
|
+
index++;
|
|
311
|
+
}
|
|
312
|
+
else
|
|
313
|
+
dc = dc[dataKey[index++]];
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return dc;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* TemplateItem class.
|
|
322
|
+
* @class
|
|
323
|
+
* @property {componyx.bindary.TemplateItem} root The root item or itself if this is the root of the item tree.
|
|
324
|
+
* @property {componyx.bindary.TemplateItem} parent The parent item.
|
|
325
|
+
* @property {TemplateItem[]} children The child items of the current item.
|
|
326
|
+
* @property {String} id The unique identifier of the item.
|
|
327
|
+
* @property {HTMLElement} placeHolder A place holder element for an item that is not rendered.
|
|
328
|
+
* @property {HTMLElement} repeatPlaceHolder A place holder element for a repeating item.
|
|
329
|
+
* @property {Boolean} trusted A value indicating if the HTML value is trusted.
|
|
330
|
+
* @property {Boolean} includable A value indicating if the item is an includable item.
|
|
331
|
+
* @property {Boolean} includableRoot A value indicating if the item is the root of the includable.
|
|
332
|
+
* @property {Boolean} included A value indicating if an includable is included.
|
|
333
|
+
* @property {String} includeFile The include file data-key or path.
|
|
334
|
+
* @property {String} include The include data-key or identifier.
|
|
335
|
+
* @property {Boolean} isComponent A value indicating if the item is a component.
|
|
336
|
+
* @property {Boolean} loaded A value indicating if the included data or component is loaded.
|
|
337
|
+
* @property {HTMLElement} element The rendered element.
|
|
338
|
+
* @property {HTMLElement} sourceElement The original collected element. This element can differ from the rendered element when it is included or within a repeater.
|
|
339
|
+
* @property {String} display The original display style of the element.
|
|
340
|
+
* @property {elementInfo} elementInfo Information about the element.
|
|
341
|
+
* @property {Object} context The object context.
|
|
342
|
+
* @property {Object} repeatValue The repeat value context.
|
|
343
|
+
* @property {Object} repeatItemIdValue The value of the repeat item id.
|
|
344
|
+
* @property {Object} itemId The item is rendered if the item id matches the value of the repeat item id.
|
|
345
|
+
* @property {Number} index The current index within the array repeater.
|
|
346
|
+
* @property {String} key The current key within the object repeater.
|
|
347
|
+
* @property {Object} value The data value.
|
|
348
|
+
* @property {Boolean} isRendered A value indicating if the element is rendered.
|
|
349
|
+
* @property {Object[]} dataChange Holds the active data change rules for the item.
|
|
350
|
+
* @property {String[]|Number[]} indexKey The index key holds the dynamic (data-key) or static index pointer.
|
|
351
|
+
* @property {HTMLElement[]} repeatElements The collection of elements within the repeater.
|
|
352
|
+
* @property {String} dataType The type of the data value.
|
|
353
|
+
* @property {String} inputBind The data bind value.
|
|
354
|
+
* @property {Boolean|Number} liveBind A value indicating if live binding is enabled (true) or disabled (false) or the debounce delay in milliseconds.
|
|
355
|
+
* @property {String} updateId The update identifier.
|
|
356
|
+
* @property {Boolean} updateIdFromParent A value indicating that the updateId was copied from the parent item in the update loop.
|
|
357
|
+
* @property {Boolean} isHTML A value indicating if the data value is HTML.
|
|
358
|
+
* @property {String} if The value of the `if` attribute, representing either a method name or an expression string used to evaluate the conditional statement.
|
|
359
|
+
* @property {function} ifExpr The expression function that evaluates the conditional statement.
|
|
360
|
+
* @property {String} elseIf The value of the `elseif` attribute, representing either a method name or an expression string used to evaluate the conditional statement.
|
|
361
|
+
* @property {function} elseIfExpr The expression function that evaluates the conditional statement.
|
|
362
|
+
* @property {Boolean} else A flag indicating that this element should be rendered when none of the preceding conditional (if/elseif) statements evaluate to true.
|
|
363
|
+
* @property {Boolean} conditionMet A value indicating the state of the conditional statement.
|
|
364
|
+
* @property {String} dataFormatter The function invoked when the value is set on the data object.
|
|
365
|
+
* @property {String} viewFormatter The function invoked when the value is set on the element.
|
|
366
|
+
* @property {String} preRender The function invoked before the element is rendered.
|
|
367
|
+
* @property {String} postRender The function invoked after the element is rendered.
|
|
368
|
+
* @property {String} load The function invoked when an includable is included.
|
|
369
|
+
* @property {String} filter The function invoked to filter a collection.
|
|
370
|
+
* @property {Object} events The element events.
|
|
371
|
+
* @property {string[]} repeatDataKey - Hierarchical data key as an array of parts (e.g. ['myObj', 'value']).
|
|
372
|
+
* @property {string[]} repeatItemIdDataKey - Hierarchical data key array for the repeat item ID.
|
|
373
|
+
* @property {string[]} contextDataKey - Hierarchical data key array for the context value.
|
|
374
|
+
* @property {string[]} hasValue - Hierarchical data key array for value existence checks.
|
|
375
|
+
* @property {string[]} dataKey - Hierarchical data key array for the main data value.
|
|
376
|
+
* @property {string} expressionValue - The raw expression value if the data-key contains expressions denoted with brackets {{}}
|
|
377
|
+
* @property {function} expression - The expression function if the data-key contains expressions.
|
|
378
|
+
* @property {Object} attributes The data bound attributes.
|
|
379
|
+
* @property {function[]} attributeExpressions Expression functions for the attributes if the attribute values contain expressions.
|
|
380
|
+
* @property {string} repeatDataKeyPath - Full path for the repeat value. (e.g. 'appData.container.myArr').
|
|
381
|
+
* @property {string} contextDataKeyPath - Path for the context value.
|
|
382
|
+
* @property {string} hasValueDataKeyPath - Full path for value existence check.
|
|
383
|
+
* @property {string} dataKeyPath - Full path for the data value (value/html/bind) if its a single data-key.
|
|
384
|
+
* @property {string} dataKeyPaths - Full paths for all value data keys when using a value expression.
|
|
385
|
+
* @property {string[]} attributeDataKeyPaths - Full paths for all attribute data keys.
|
|
386
|
+
* @property {string[]} conditionalDataKeyPaths - Full paths for all the data keys used in conditional expressions.
|
|
387
|
+
* @property {Object[]} treeState Internal. Snapshot of this item's context and its ancestors', used to restore tree state later.
|
|
388
|
+
* @property {Number} treeStatePass Internal. Tracks which render pass last captured treeState, to avoid stale ancestor data.
|
|
389
|
+
* @memberof componyx.bindary
|
|
390
|
+
*/
|
|
391
|
+
class TemplateItem extends TemplateBase
|
|
392
|
+
{
|
|
393
|
+
/**
|
|
394
|
+
* Creates an instance of TemplateItem.
|
|
395
|
+
*
|
|
396
|
+
* @param {HTMLElement} el - The DOM element associated with the template item.
|
|
397
|
+
* @param {Object} events - The events related to the template item.
|
|
398
|
+
* @param {Object} attributes - The attributes for the template item.
|
|
399
|
+
* @param {componyx.bindary.TemplateItem} parent - The parent TemplateItem if this item is a child.
|
|
400
|
+
* @param {boolean} appendToRoot - Determines whether to append to the root.
|
|
401
|
+
*/
|
|
402
|
+
constructor(el, events, attributes, parent, appendToRoot)
|
|
403
|
+
{
|
|
404
|
+
super();
|
|
405
|
+
let me = this;
|
|
406
|
+
|
|
407
|
+
me.root = (parent) ? (parent.root) : me;
|
|
408
|
+
|
|
409
|
+
if (el)
|
|
410
|
+
{
|
|
411
|
+
me.id = el.id = el.id || core.getId(); // keep original id or generate id
|
|
412
|
+
el.setAttribute(core.attr.id, me.id);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
me.parent = parent;
|
|
416
|
+
me.children = [];
|
|
417
|
+
me.repeatPlaceHolder = null;
|
|
418
|
+
me.trusted = null;
|
|
419
|
+
me.includable = null;
|
|
420
|
+
me.includableRoot = false;
|
|
421
|
+
me.included = false;
|
|
422
|
+
me.includeFile = null;
|
|
423
|
+
me.include = null;
|
|
424
|
+
me.isComponent = false;
|
|
425
|
+
me.loaded = false;
|
|
426
|
+
me.element = null;
|
|
427
|
+
me.sourceElement = null;
|
|
428
|
+
me.display = null;
|
|
429
|
+
me.elementInfo = null;
|
|
430
|
+
me.context = null;
|
|
431
|
+
me.repeatValue = null;
|
|
432
|
+
me.repeatItemIdValue = null;
|
|
433
|
+
me.itemId = null;
|
|
434
|
+
me.index = null;
|
|
435
|
+
me.key = null;
|
|
436
|
+
me.value = null;
|
|
437
|
+
me.isRendered = false;
|
|
438
|
+
me.dataChange = null;
|
|
439
|
+
me.indexKey = [];
|
|
440
|
+
me.repeatElements = {};
|
|
441
|
+
me.dataType = null;
|
|
442
|
+
me.inputBind = null;
|
|
443
|
+
me.liveBind = null;
|
|
444
|
+
me.updateId = null;
|
|
445
|
+
me.updateIdFromParent = null;
|
|
446
|
+
me.isHTML = false;
|
|
447
|
+
me.if = null;
|
|
448
|
+
me.ifExpr = null;
|
|
449
|
+
me.elseIf = null;
|
|
450
|
+
me.elseIfExpr = null;
|
|
451
|
+
me.else = null;
|
|
452
|
+
me.conditionMet = null;
|
|
453
|
+
me.dataFormatter = null;
|
|
454
|
+
me.viewFormatter = null;
|
|
455
|
+
me.preRender = null;
|
|
456
|
+
me.postRender = null;
|
|
457
|
+
me.load = null;
|
|
458
|
+
me.filter = null;
|
|
459
|
+
me.events = null;
|
|
460
|
+
me.hasValue = null;
|
|
461
|
+
me.dataKey = null;
|
|
462
|
+
me.expressionValue = null;
|
|
463
|
+
me.expression = null;
|
|
464
|
+
me.attributes = null;
|
|
465
|
+
me.attributeExpressions = null;
|
|
466
|
+
me.repeatDataKey = null;
|
|
467
|
+
me.repeatItemIdDataKey = null;
|
|
468
|
+
me.contextDataKey = null;
|
|
469
|
+
me.hasValueDataKeyPath = null;
|
|
470
|
+
me.repeatDataKeyPath = null;
|
|
471
|
+
me.contextDataKeyPath = null;
|
|
472
|
+
me.dataKeyPath = null;
|
|
473
|
+
me.dataKeyPaths = null;
|
|
474
|
+
me.attributeDataKeyPaths = null;
|
|
475
|
+
me.conditionalDataKeyPaths = null;
|
|
476
|
+
me.treeState = null;
|
|
477
|
+
me.treeStatePass = null;
|
|
478
|
+
|
|
479
|
+
if (parent)
|
|
480
|
+
parent.children.push(me);
|
|
481
|
+
else if (appendToRoot !== false)
|
|
482
|
+
core.viewTree.push(me); // root item
|
|
483
|
+
|
|
484
|
+
core.templateList.push(me);
|
|
485
|
+
|
|
486
|
+
if (el)
|
|
487
|
+
me.parseTemplateElement(el, events, attributes, parent);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
parseTemplateElement(el, events, colAttributes, parent)
|
|
491
|
+
{
|
|
492
|
+
// data-order: repeat, context, value
|
|
493
|
+
let me = this,
|
|
494
|
+
{ keep, live } = core.getTemplateFlags(el, ['keep', 'live']),
|
|
495
|
+
liveBind = live,
|
|
496
|
+
keepAttr = keep === null ? $bindary.keepAttributes : keep,
|
|
497
|
+
contextKeyPath = (parent) ? parent.contextDataKeyPath : null,
|
|
498
|
+
hasParentContext = (contextKeyPath != null),
|
|
499
|
+
hasParentInclude = (parent) ? parent.includable : false,
|
|
500
|
+
include = el.getAttribute(core.attr.include),
|
|
501
|
+
isRoot = !(el.hasAttribute(core.attr.repeat) || el.hasAttribute(core.attr.context) || hasParentContext || hasParentInclude),
|
|
502
|
+
text = el.getAttribute(core.attr.value),
|
|
503
|
+
html = el.getAttribute(core.attr.html),
|
|
504
|
+
inputBind = el.hasAttribute(core.attr.bind),
|
|
505
|
+
dataKey = el.getAttribute(core.attr.bind) || text || html || '',
|
|
506
|
+
attributes = el.getAttribute(core.attr.attributes),
|
|
507
|
+
hasValue = el.getAttribute(core.attr.hasValue),
|
|
508
|
+
updateValue = (key, value) =>
|
|
509
|
+
{
|
|
510
|
+
if (keepAttr || me[key] == undefined || !$lib.isEmpty(value))
|
|
511
|
+
me[key] = (value != 'null') ? value : null; // string value 'null' means clear previously stored value
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
if (keepAttr) // with keepAttributes enabled values are always set (removing the attribute will clear the stored value)
|
|
515
|
+
{
|
|
516
|
+
me.hasValue = null;
|
|
517
|
+
me.isHTML = false;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// these are always re-evaluated
|
|
521
|
+
me.expression = null;
|
|
522
|
+
me.ifExpr = null;
|
|
523
|
+
me.elseIfExpr = null;
|
|
524
|
+
me.dataKeyPaths = [];
|
|
525
|
+
me.conditionalDataKeyPaths = [];
|
|
526
|
+
|
|
527
|
+
if (html && $lib.startsWith(html, 'trust:'))
|
|
528
|
+
{
|
|
529
|
+
html = html.substr(6);
|
|
530
|
+
me.trusted = true;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
me.includable = hasParentInclude;
|
|
534
|
+
|
|
535
|
+
if (el.hasAttribute(core.attr.includable))
|
|
536
|
+
{
|
|
537
|
+
me.includableRoot = (el.getAttribute(core.attr.includable) != 'null');
|
|
538
|
+
me.includable = (el.getAttribute(core.attr.includable) == 'null') ? hasParentInclude : true; // includable cannot be cleared if parent has includable specified
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
me.isComponent = (parent) ? parent.isComponent : false;
|
|
542
|
+
updateValue('component', el.getAttribute(core.attr.component));
|
|
543
|
+
me.isComponent = (me.component) ? true : me.isComponent;
|
|
544
|
+
|
|
545
|
+
me.parseInclude(include, hasParentContext);
|
|
546
|
+
|
|
547
|
+
if (me.isComponent)
|
|
548
|
+
isRoot = false;
|
|
549
|
+
|
|
550
|
+
const hasContentExpr = core.hasContentExpression(el);
|
|
551
|
+
|
|
552
|
+
if (!inputBind && (hasContentExpr || dataKey.indexOf('{{') != -1))
|
|
553
|
+
{
|
|
554
|
+
me.expressionValue = (hasContentExpr) ? el.textContent : dataKey;
|
|
555
|
+
dataKey = null;
|
|
556
|
+
|
|
557
|
+
if (hasContentExpr)
|
|
558
|
+
el.textContent = '';
|
|
559
|
+
}
|
|
560
|
+
else
|
|
561
|
+
dataKey = (!$lib.isEmpty(dataKey)) ? me.createDataKey(dataKey, isRoot) : null;
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
me.isRendered = false;
|
|
565
|
+
me.display = el.style.display;
|
|
566
|
+
me.sourceElement = me.tempElement = el; // tempElement is for backwards compatibility
|
|
567
|
+
me.elementInfo = me.getElementInfo(el);
|
|
568
|
+
|
|
569
|
+
updateValue('dataType', (el.getAttribute(core.attr.type) || '').toLowerCase());
|
|
570
|
+
updateValue('dataKey', dataKey);
|
|
571
|
+
updateValue('inputBind', inputBind);
|
|
572
|
+
updateValue('liveBind', liveBind);
|
|
573
|
+
updateValue('updateId', el.getAttribute(core.attr.updateId));
|
|
574
|
+
updateValue('itemId', el.getAttribute(core.attr.itemId));
|
|
575
|
+
updateValue('attributes', (attributes && attributes != 'null') ? window.JSON.parse('{' + core.createJSON(attributes) + '}') : attributes);
|
|
576
|
+
|
|
577
|
+
if (colAttributes)
|
|
578
|
+
{
|
|
579
|
+
me.attributes = me.attributes || {};
|
|
580
|
+
$lib.each(colAttributes, (value, key) => { me.attributes[key] = value; });
|
|
581
|
+
}
|
|
582
|
+
else
|
|
583
|
+
this.collectAttributes(el);
|
|
584
|
+
|
|
585
|
+
if (!me.dataKey)
|
|
586
|
+
me.expression = null;
|
|
587
|
+
|
|
588
|
+
if (hasValue && hasValue == 'null')
|
|
589
|
+
me.hasValue = null;
|
|
590
|
+
else if (el.hasAttribute(core.attr.hasValue))
|
|
591
|
+
me.hasValue = ($lib.isEmpty(hasValue)) ? hasValue.split(core.dksc) : me.createDataKey(hasValue, isRoot);
|
|
592
|
+
|
|
593
|
+
if (dataKey)
|
|
594
|
+
me.isHTML = !$lib.isEmpty(html);
|
|
595
|
+
|
|
596
|
+
isRoot = !(hasParentContext || me.includable || me.isComponent); // defines whether repeat/context is root
|
|
597
|
+
|
|
598
|
+
if (el.hasAttribute(core.attr.repeat))
|
|
599
|
+
{
|
|
600
|
+
updateValue('repeatDataKey', me.createDataKey(el.getAttribute(core.attr.repeat), isRoot));
|
|
601
|
+
updateValue('repeatItemIdDataKey', me.createDataKey(el.getAttribute(core.attr.repeatItemId), false));
|
|
602
|
+
|
|
603
|
+
if (!me.includable)
|
|
604
|
+
{
|
|
605
|
+
updateValue('repeatDataKeyPath', me.createDataKeyPath(me.repeatDataKey, contextKeyPath));
|
|
606
|
+
contextKeyPath = me.repeatDataKeyPath || contextKeyPath;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
if (el.hasAttribute(core.attr.context))
|
|
611
|
+
{
|
|
612
|
+
updateValue('contextDataKey', me.createDataKey(el.getAttribute(core.attr.context), !el.hasAttribute(core.attr.repeat) && isRoot));
|
|
613
|
+
|
|
614
|
+
if (!me.includable)
|
|
615
|
+
{
|
|
616
|
+
|
|
617
|
+
updateValue('contextDataKeyPath', me.createDataKeyPath(me.contextDataKey, contextKeyPath));
|
|
618
|
+
contextKeyPath = me.contextDataKeyPath || contextKeyPath;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
if (el.hasAttribute(core.attr.observe))
|
|
623
|
+
{
|
|
624
|
+
|
|
625
|
+
updateValue('observeDataKeyPath', el.getAttribute(core.attr.observe));
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
if (!me.includable)
|
|
629
|
+
{
|
|
630
|
+
if (me.dataKey)
|
|
631
|
+
me.dataKeyPath = me.createDataKeyPath(me.dataKey, contextKeyPath);
|
|
632
|
+
|
|
633
|
+
if (me.hasValue && me.hasValue[0].length > 0)
|
|
634
|
+
me.hasValueDataKeyPath = me.createDataKeyPath(me.hasValue, contextKeyPath);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// store current context key-path
|
|
638
|
+
me.contextDataKeyPath = contextKeyPath;
|
|
639
|
+
|
|
640
|
+
// controller methods
|
|
641
|
+
updateValue('dataFormatter', el.getAttribute(core.attr.dataFormatter));
|
|
642
|
+
updateValue('viewFormatter', el.getAttribute(core.attr.viewFormatter));
|
|
643
|
+
updateValue('preRender', el.getAttribute(core.attr.preRender));
|
|
644
|
+
updateValue('if', el.getAttribute(core.attr.if));
|
|
645
|
+
updateValue('elseIf', el.getAttribute(core.attr.elseIf));
|
|
646
|
+
me.else = (el.hasAttribute(core.attr.else) && el.getAttribute(core.attr.else) != 'null');
|
|
647
|
+
updateValue('postRender', el.getAttribute(core.attr.postRender));
|
|
648
|
+
updateValue('load', el.getAttribute(core.attr.load));
|
|
649
|
+
updateValue('filter', el.getAttribute(core.attr.filter));
|
|
650
|
+
|
|
651
|
+
me.evaluateExpressions();
|
|
652
|
+
|
|
653
|
+
// events
|
|
654
|
+
me.events = $lib.clone(me.events || {}, events, true, true);
|
|
655
|
+
|
|
656
|
+
for (let event in me.events)
|
|
657
|
+
{
|
|
658
|
+
if (events[event] == 'null')
|
|
659
|
+
{
|
|
660
|
+
$lib.off(el, event, core.customEventHandler);
|
|
661
|
+
delete me.events[event];
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
evaluateExpressions()
|
|
667
|
+
{
|
|
668
|
+
const me = this,
|
|
669
|
+
contextKeyPath = me.contextDataKeyPath,
|
|
670
|
+
seen = {},
|
|
671
|
+
tokenHandler = function (seen, arr, token)
|
|
672
|
+
{
|
|
673
|
+
if (token.endsWith('()')) // controller method
|
|
674
|
+
return;
|
|
675
|
+
|
|
676
|
+
let dataKey = me.createDataKeyPath(me.createDataKey(token), contextKeyPath);
|
|
677
|
+
|
|
678
|
+
if (!seen[dataKey])
|
|
679
|
+
arr.push(dataKey);
|
|
680
|
+
|
|
681
|
+
seen[dataKey] = true;
|
|
682
|
+
};
|
|
683
|
+
|
|
684
|
+
me.dataKeyPaths = [];
|
|
685
|
+
me.conditionalDataKeyPaths = [];
|
|
686
|
+
|
|
687
|
+
if (me.if && me.if.indexOf('{{') != -1)
|
|
688
|
+
me.ifExpr = core.expressionEngine.evaluate(me.if, tokenHandler.bind(this, seen, me.conditionalDataKeyPaths));
|
|
689
|
+
|
|
690
|
+
if (me.elseIf && me.elseIf.indexOf('{{') != -1)
|
|
691
|
+
me.elseIfExpr = core.expressionEngine.evaluate(me.elseIf, tokenHandler.bind(this, seen, me.conditionalDataKeyPaths));
|
|
692
|
+
|
|
693
|
+
if (me.expressionValue)
|
|
694
|
+
me.expression = core.expressionEngine.evaluate(me.expressionValue, tokenHandler.bind(this, {}, me.dataKeyPaths));
|
|
695
|
+
|
|
696
|
+
me.createAttributeExpressions();
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
parseInclude(include, hasParentContext)
|
|
700
|
+
{
|
|
701
|
+
if ($lib.isEmpty(include))
|
|
702
|
+
return;
|
|
703
|
+
|
|
704
|
+
let me = this,
|
|
705
|
+
isRoot = !(hasParentContext || me.includable || me.isComponent);
|
|
706
|
+
|
|
707
|
+
me.includeFile = ($lib.startsWith(include, 'file:')) ? include.substr(5) : null;
|
|
708
|
+
|
|
709
|
+
if (me.includeFile)
|
|
710
|
+
me.includeFile = ($lib.startsWith(me.includeFile, '/')) ? me.includeFile : me.createDataKey(me.includeFile, isRoot);
|
|
711
|
+
|
|
712
|
+
if (include == 'null' || me.includeFile)
|
|
713
|
+
me.include = null;
|
|
714
|
+
else
|
|
715
|
+
me.include = ($lib.startsWith(include, '#')) ? include : me.createDataKey(include, isRoot);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
getElementInfo(el)
|
|
719
|
+
{
|
|
720
|
+
let info = {};
|
|
721
|
+
|
|
722
|
+
info.name = el.nodeName.toLowerCase();
|
|
723
|
+
info.isInput = (info.name == 'input');
|
|
724
|
+
info.isTextArea = (info.name == 'textarea');
|
|
725
|
+
info.isSelect = (info.name == 'select');
|
|
726
|
+
info.isCheck = (info.isInput && el.type == 'checkbox');
|
|
727
|
+
info.isRadio = (info.isInput && el.type == 'radio');
|
|
728
|
+
return info;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
createAttributeExpressions()
|
|
732
|
+
{
|
|
733
|
+
const me = this,
|
|
734
|
+
contextDataKeyPath = me.contextDataKeyPath,
|
|
735
|
+
seen = {},
|
|
736
|
+
addKey = (value) =>
|
|
737
|
+
{
|
|
738
|
+
if (value.endsWith('()')) // controller method
|
|
739
|
+
return;
|
|
740
|
+
|
|
741
|
+
let dataKey = me.createDataKeyPath(me.createDataKey(value), contextDataKeyPath);
|
|
742
|
+
|
|
743
|
+
if (!seen[dataKey])
|
|
744
|
+
me.attributeDataKeyPaths.push(dataKey);
|
|
745
|
+
|
|
746
|
+
seen[dataKey] = true;
|
|
747
|
+
};
|
|
748
|
+
|
|
749
|
+
me.attributeExpressions = {};
|
|
750
|
+
me.attributeDataKeyPaths = [];
|
|
751
|
+
|
|
752
|
+
$lib.each(me.attributes, (value, name) =>
|
|
753
|
+
{
|
|
754
|
+
if (value.match(core.singleWord)) // $key or $value
|
|
755
|
+
{
|
|
756
|
+
addKey(value);
|
|
757
|
+
}
|
|
758
|
+
else // simple data-key or expression
|
|
759
|
+
{
|
|
760
|
+
const exprFn = core.expressionEngine.evaluate(value, (token) => { addKey(token); });
|
|
761
|
+
me.attributeExpressions[name] = exprFn;
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
collectAttributes(el)
|
|
767
|
+
{
|
|
768
|
+
let me = this,
|
|
769
|
+
key = 'attributes',
|
|
770
|
+
attrObj = me[key] || {};
|
|
771
|
+
|
|
772
|
+
$lib.each(el.attributes, (attr) =>
|
|
773
|
+
{
|
|
774
|
+
if (attr.name.indexOf(core.prefix) != 0 && attr.value.match(core.hasBindingRegEx) != null)
|
|
775
|
+
attrObj[attr.name] = attr.value;
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
if (!$lib.isEmpty(attrObj))
|
|
779
|
+
me[key] = attrObj;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
updateKeyPaths()
|
|
783
|
+
{
|
|
784
|
+
let me = this,
|
|
785
|
+
oldDataKey = me.contextDataKeyPath,
|
|
786
|
+
contextKeyPath = me.parent.contextDataKeyPath;
|
|
787
|
+
|
|
788
|
+
if (me.repeatDataKey)
|
|
789
|
+
contextKeyPath = me.repeatDataKeyPath = me.createDataKeyPath(me.repeatDataKey, contextKeyPath);
|
|
790
|
+
|
|
791
|
+
if (me.contextDataKey)
|
|
792
|
+
contextKeyPath = me.createDataKeyPath(me.contextDataKey, contextKeyPath);
|
|
793
|
+
|
|
794
|
+
if (me.dataKey)
|
|
795
|
+
me.dataKeyPath = me.createDataKeyPath(me.dataKey, contextKeyPath);
|
|
796
|
+
|
|
797
|
+
if (me.hasValue)
|
|
798
|
+
me.hasValueDataKeyPath = me.createDataKeyPath(me.hasValue, contextKeyPath);
|
|
799
|
+
|
|
800
|
+
me.contextDataKeyPath = contextKeyPath;
|
|
801
|
+
|
|
802
|
+
const replaceContext = (value, index, obj) =>
|
|
803
|
+
{
|
|
804
|
+
if (value.startsWith(oldDataKey))
|
|
805
|
+
obj[index] = contextKeyPath + value.slice(oldDataKey.length);
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
$lib.each(me.dataKeyPaths, replaceContext);
|
|
809
|
+
$lib.each(me.attributeDataKeyPaths, replaceContext);
|
|
810
|
+
$lib.each(me.conditionalDataKeyPaths, replaceContext);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
resolveLivePaths(fromCache)
|
|
814
|
+
{
|
|
815
|
+
let me = this;
|
|
816
|
+
|
|
817
|
+
if (fromCache !== false && me.paths)
|
|
818
|
+
return me.paths;
|
|
819
|
+
|
|
820
|
+
let paths = Array.from(new Set([me.repeatDataKeyPath, me.contextDataKeyPath, me.dataKeyPath, me.hasValueDataKeyPath, me.observeDataKeyPath]
|
|
821
|
+
.concat(me.dataKeyPaths || [])
|
|
822
|
+
.concat(me.attributeDataKeyPaths || [])
|
|
823
|
+
.concat(me.conditionalDataKeyPaths || [])))
|
|
824
|
+
.filter((el) => { return el != null; });
|
|
825
|
+
|
|
826
|
+
$lib.each(paths, (path, index) =>
|
|
827
|
+
{
|
|
828
|
+
paths[index] = (path) ? me.resolveLivePath(path) : null;
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
return (me.paths = paths);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
getChangedIndexes(orgRules)
|
|
835
|
+
{
|
|
836
|
+
|
|
837
|
+
let me = this,
|
|
838
|
+
found,
|
|
839
|
+
path = me.resolveLivePath(me.repeatDataKeyPath),
|
|
840
|
+
length = path.split(core.dksc).length;
|
|
841
|
+
|
|
842
|
+
let rules = dataUpdater.initUpdateRules({}, orgRules),
|
|
843
|
+
r = rules[rules.length - 1];
|
|
844
|
+
|
|
845
|
+
r.keys = [];
|
|
846
|
+
|
|
847
|
+
$lib.each(core.dataChanges, (item, dataKey) =>
|
|
848
|
+
{
|
|
849
|
+
|
|
850
|
+
if ($lib.startsWith(dataKey, path))
|
|
851
|
+
{
|
|
852
|
+
|
|
853
|
+
let dk = dataKey.split(core.dksc),
|
|
854
|
+
key = dk[length]; // collection index or key
|
|
855
|
+
|
|
856
|
+
if (key !== undefined && r.keys.indexOf(key) == -1)
|
|
857
|
+
{
|
|
858
|
+
|
|
859
|
+
r.keys.push(key);
|
|
860
|
+
found = true;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
});
|
|
864
|
+
|
|
865
|
+
return (found) ? rules : orgRules;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
initRepeater(element, parentElement, beforeElement, remove)
|
|
869
|
+
{
|
|
870
|
+
let me = this;
|
|
871
|
+
|
|
872
|
+
if (!me.repeatElements)
|
|
873
|
+
me.repeatElements = {};
|
|
874
|
+
|
|
875
|
+
if (remove)
|
|
876
|
+
{
|
|
877
|
+
me.clearRepeater(element);
|
|
878
|
+
|
|
879
|
+
if (!beforeElement?.isConnected)
|
|
880
|
+
beforeElement = null;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
let placeHolder = me.repeatPlaceHolder,
|
|
884
|
+
exists = placeHolder?.isConnected;
|
|
885
|
+
|
|
886
|
+
if (!exists)
|
|
887
|
+
{
|
|
888
|
+
me.repeatPlaceHolder = core.createPlaceHolder(me, parentElement, beforeElement);
|
|
889
|
+
me.repeatPlaceHolder.removeAttribute('id');
|
|
890
|
+
|
|
891
|
+
if (element)
|
|
892
|
+
$lib.remove(element);
|
|
893
|
+
|
|
894
|
+
}
|
|
895
|
+
else if (beforeElement?.isConnected)
|
|
896
|
+
{
|
|
897
|
+
beforeElement.parentNode.insertBefore(placeHolder, beforeElement);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
clearRepeater(element)
|
|
902
|
+
{
|
|
903
|
+
let me = this,
|
|
904
|
+
rootKey = me.resolveLivePath(me.repeatDataKeyPath) + core.dksc;
|
|
905
|
+
|
|
906
|
+
// cleanup internal clone registry
|
|
907
|
+
$lib.each(core.repItemClones, (clone, key) =>
|
|
908
|
+
{
|
|
909
|
+
if ($lib.startsWith(key, rootKey))
|
|
910
|
+
delete core.repItemClones[key];
|
|
911
|
+
});
|
|
912
|
+
|
|
913
|
+
// remove tracked elements
|
|
914
|
+
$lib.each(me.repeatElements, (el) =>
|
|
915
|
+
{
|
|
916
|
+
$lib.remove(el);
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
// remove orphaned DOM elements
|
|
920
|
+
let parent = me.parent?.element || document;
|
|
921
|
+
let duplicates = parent.querySelectorAll(`[${core.attr.id}="${me.id}"]`);
|
|
922
|
+
|
|
923
|
+
duplicates.forEach((el) =>
|
|
924
|
+
{
|
|
925
|
+
if (el !== element && el !== me.repeatPlaceHolder)
|
|
926
|
+
{
|
|
927
|
+
el.remove();
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
me.repeatElements = {};
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
isActiveRepeatItem()
|
|
935
|
+
{
|
|
936
|
+
|
|
937
|
+
let me = this,
|
|
938
|
+
itemId = me.itemId, item = me;
|
|
939
|
+
|
|
940
|
+
if ($lib.isEmpty(itemId))
|
|
941
|
+
return true;
|
|
942
|
+
|
|
943
|
+
while (item && $lib.isEmpty(item.repeatItemIdValue))
|
|
944
|
+
{
|
|
945
|
+
|
|
946
|
+
item = item.parent;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
if (!item || item.repeatItemIdValue === itemId)
|
|
950
|
+
return true;
|
|
951
|
+
|
|
952
|
+
return false;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
getIncludeItem()
|
|
956
|
+
{
|
|
957
|
+
|
|
958
|
+
let me = this,
|
|
959
|
+
idReference = $lib.startsWith(me.include, '#'),
|
|
960
|
+
id = (idReference) ? me.include.substr(1) : me.getDataValue(me.include, (!me.component && me.parent) ? me.parent.context : me.context);
|
|
961
|
+
|
|
962
|
+
return me.getTemplateItemById(id);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
getTemplateItemById(id)
|
|
966
|
+
{
|
|
967
|
+
if ($lib.isEmpty(id))
|
|
968
|
+
return null;
|
|
969
|
+
|
|
970
|
+
let index = $lib.indexOf(core.templateList, function (item) { return (item.id == id); });
|
|
971
|
+
|
|
972
|
+
if (index > -1)
|
|
973
|
+
return core.templateList[index];
|
|
974
|
+
else
|
|
975
|
+
return null;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
dataBind(live)
|
|
979
|
+
{
|
|
980
|
+
let me = this;
|
|
981
|
+
|
|
982
|
+
if (!me)
|
|
983
|
+
return;
|
|
984
|
+
|
|
985
|
+
let el = me.element,
|
|
986
|
+
value = core.getElementValue(me),
|
|
987
|
+
info = me.elementInfo,
|
|
988
|
+
keyPath = me.dataKey.slice(0),
|
|
989
|
+
lastKey = me.dataKey[me.dataKey.length - 1],
|
|
990
|
+
isSwitch = info.isRadio || info.isCheck,
|
|
991
|
+
isPlainToggle = isSwitch && ($lib.isEmpty(value) || (info.isCheck && value == 'on')),
|
|
992
|
+
type = me.dataType,
|
|
993
|
+
obj;
|
|
994
|
+
|
|
995
|
+
keyPath.pop();
|
|
996
|
+
el._bindaryLastState = (info.isRadio || info.isCheck) ? `${el.checked}:${value}` : value;
|
|
997
|
+
|
|
998
|
+
if (me.dataFormatter)
|
|
999
|
+
value = core.call(me.dataFormatter, [me, el, value]);
|
|
1000
|
+
else if (isSwitch)
|
|
1001
|
+
{
|
|
1002
|
+
if (isPlainToggle)
|
|
1003
|
+
value = el.checked;
|
|
1004
|
+
else
|
|
1005
|
+
{
|
|
1006
|
+
value = me.castValue(value, type);
|
|
1007
|
+
|
|
1008
|
+
if (!el.checked && type == 'boolean')
|
|
1009
|
+
value = !value; // reverse
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
else if (type) // cast if explicit type is defined (e.g. for number/date inputs or select with "true" and "false" values)
|
|
1013
|
+
value = me.castValue(value, type);
|
|
1014
|
+
|
|
1015
|
+
core.observed = false; // value changes to true if object is observed
|
|
1016
|
+
|
|
1017
|
+
if (me.repeatValue)
|
|
1018
|
+
{
|
|
1019
|
+
if (core.isKey(me.dataKey, core.valueKey))
|
|
1020
|
+
{
|
|
1021
|
+
if ((obj = me.repeatValue))
|
|
1022
|
+
obj[me.key] = value;
|
|
1023
|
+
}
|
|
1024
|
+
else
|
|
1025
|
+
{
|
|
1026
|
+
if ((obj = me.getDataValue(keyPath, me.repeatValue[me.key])))
|
|
1027
|
+
obj[lastKey] = value;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
else
|
|
1031
|
+
{
|
|
1032
|
+
if (me.dataKey.length == 1)
|
|
1033
|
+
obj = me.context;
|
|
1034
|
+
else
|
|
1035
|
+
obj = me.getDataValue(keyPath, me.context);
|
|
1036
|
+
|
|
1037
|
+
if (Array.isArray(obj[lastKey]) && info.isCheck && type !== 'boolean') // handle checkboxes to array binding
|
|
1038
|
+
{
|
|
1039
|
+
const arr = obj[lastKey],
|
|
1040
|
+
val = !$lib.isEmpty(value) && value !== 'on' ? value : el.name;
|
|
1041
|
+
|
|
1042
|
+
if (el.checked)
|
|
1043
|
+
{
|
|
1044
|
+
if (!arr.includes(val))
|
|
1045
|
+
arr.push(val);
|
|
1046
|
+
}
|
|
1047
|
+
else
|
|
1048
|
+
{
|
|
1049
|
+
const index = arr.indexOf(val);
|
|
1050
|
+
if (index > -1)
|
|
1051
|
+
arr.splice(index, 1);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
else if (Array.isArray(obj[lastKey]) && typeof value === 'string') // CSV array for normal inputs
|
|
1055
|
+
{
|
|
1056
|
+
if (!$lib.isEmpty(value))
|
|
1057
|
+
{
|
|
1058
|
+
const parts = value.split(',')
|
|
1059
|
+
.map(v => v.trim())
|
|
1060
|
+
.filter(v => v.length > 0);
|
|
1061
|
+
|
|
1062
|
+
obj[lastKey] = (type) ? parts.map(v => me.castValue(v, type)) : parts;
|
|
1063
|
+
}
|
|
1064
|
+
else
|
|
1065
|
+
{
|
|
1066
|
+
obj[lastKey] = [];
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
else if (obj)
|
|
1070
|
+
{
|
|
1071
|
+
if (info.isCheck && !isPlainToggle && !el.checked && type !== 'boolean') // a checkbox with string value that is unchecked
|
|
1072
|
+
value = '';
|
|
1073
|
+
|
|
1074
|
+
obj[lastKey] = value;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
core.dataBindLive = false; // if this data-bind came from oninput event but there is no matching object, set to false
|
|
1079
|
+
|
|
1080
|
+
if (obj)
|
|
1081
|
+
{
|
|
1082
|
+
core.dataBindLive = live;
|
|
1083
|
+
$bindary.dataBindTrigger = el; // keep track of update trigger
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
const modelValue = obj
|
|
1087
|
+
? (me.repeatValue && core.isKey(me.dataKey, core.valueKey) ? obj[me.key] : obj[lastKey])
|
|
1088
|
+
: value; // fallback to raw value if obj was never resolved
|
|
1089
|
+
|
|
1090
|
+
core.fireEvent('postDataBind', [me, el, obj, modelValue]);
|
|
1091
|
+
|
|
1092
|
+
if (obj && !core.observed)
|
|
1093
|
+
{
|
|
1094
|
+
$bindary.dataChange(me.resolveLivePath(me.dataKeyPath), null, null, false); // register data-change when object is not observed
|
|
1095
|
+
$bindary.updateViewDelayed();
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
castValue(value, type)
|
|
1100
|
+
{
|
|
1101
|
+
if (!type)
|
|
1102
|
+
return value;
|
|
1103
|
+
|
|
1104
|
+
if (type == 'boolean')
|
|
1105
|
+
return core.toBoolean(value);
|
|
1106
|
+
|
|
1107
|
+
if ($lib.isEmpty(value) && (type == 'date' || type == 'datetime' || type == 'number'))
|
|
1108
|
+
return null;
|
|
1109
|
+
|
|
1110
|
+
if (type == 'date')
|
|
1111
|
+
return $lib.parseDate(value, $bindary.dateFormat.replace(core.timeRegEx, ''));
|
|
1112
|
+
|
|
1113
|
+
if (type == 'datetime')
|
|
1114
|
+
return $lib.parseDate(value, $bindary.dateFormat);
|
|
1115
|
+
|
|
1116
|
+
if (type.startsWith('number'))
|
|
1117
|
+
return parseFloat(value.replace($bindary.decimalSeparator, '.'));
|
|
1118
|
+
|
|
1119
|
+
return value;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
clone(parent)
|
|
1123
|
+
{
|
|
1124
|
+
let cloner = (item, parent) =>
|
|
1125
|
+
{
|
|
1126
|
+
let target = new componyx.bindary_modules.TemplateItem(null, null, null, null, false);
|
|
1127
|
+
|
|
1128
|
+
$lib.each(item.children, (child) =>
|
|
1129
|
+
{
|
|
1130
|
+
target.children.push(cloner(child, target));
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
$lib.each(item, (value, key) =>
|
|
1134
|
+
{
|
|
1135
|
+
if (core.omit[key] === undefined && typeof (value) !== 'function' && !$lib.isEmpty(value))
|
|
1136
|
+
target[key] = value;
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
target.evaluateExpressions();
|
|
1140
|
+
target.livePath = {};
|
|
1141
|
+
target.parent = parent;
|
|
1142
|
+
target.root = item.root;
|
|
1143
|
+
return target;
|
|
1144
|
+
};
|
|
1145
|
+
|
|
1146
|
+
return cloner(this, parent || this.parent);
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
getClone()
|
|
1150
|
+
{
|
|
1151
|
+
let me = this,
|
|
1152
|
+
key = me.resolveLivePath(me.repeatDataKeyPath),
|
|
1153
|
+
clone = core.repItemClones[key];
|
|
1154
|
+
|
|
1155
|
+
if (!clone)
|
|
1156
|
+
return (core.repItemClones[key] = me.clone());
|
|
1157
|
+
else
|
|
1158
|
+
return clone;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
defineContext(context)
|
|
1162
|
+
{
|
|
1163
|
+
let me = this,
|
|
1164
|
+
rootIndex;
|
|
1165
|
+
|
|
1166
|
+
me.context = context;
|
|
1167
|
+
|
|
1168
|
+
if (me.contextDataKey)
|
|
1169
|
+
me.context = me.getDataValue(me.contextDataKey, context); // define context/scope
|
|
1170
|
+
else if (me.dataKey && me.dataKey[0] == '$')
|
|
1171
|
+
{
|
|
1172
|
+
|
|
1173
|
+
rootIndex = $lib.indexOf(core.dataLabel, me.dataKey[1]);
|
|
1174
|
+
|
|
1175
|
+
if (rootIndex > -1)
|
|
1176
|
+
me.context = $bindary[core.dataLabel[rootIndex]];
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
setContextValue()
|
|
1181
|
+
{
|
|
1182
|
+
let me = this, context = me.context;
|
|
1183
|
+
|
|
1184
|
+
if ($lib.isEmpty(me.dataKey) && !me.expression)
|
|
1185
|
+
return;
|
|
1186
|
+
|
|
1187
|
+
if (me.expression)
|
|
1188
|
+
{
|
|
1189
|
+
let resolvedValue = me.expression(me.expressionTokenResolver.bind(me));
|
|
1190
|
+
me.value = (resolvedValue == null) ? '' : resolvedValue;
|
|
1191
|
+
}
|
|
1192
|
+
else
|
|
1193
|
+
me.value = me.getDataValue(me.dataKey, context);
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
expressionTokenResolver(token)
|
|
1197
|
+
{
|
|
1198
|
+
let me = this;
|
|
1199
|
+
|
|
1200
|
+
if (token.endsWith('()'))
|
|
1201
|
+
{
|
|
1202
|
+
const methodName = token.slice(0, -2);
|
|
1203
|
+
|
|
1204
|
+
if (me.isComponent)
|
|
1205
|
+
{
|
|
1206
|
+
let item = me;
|
|
1207
|
+
|
|
1208
|
+
while (item && !item.component)
|
|
1209
|
+
item = item.parent;
|
|
1210
|
+
|
|
1211
|
+
if (item?.context?.[methodName])
|
|
1212
|
+
return item.context[methodName](me);
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
// not a component, or the component didn't have this method: fall back to the controller
|
|
1216
|
+
return ($bindary.controller) ? $bindary.controller[methodName](me) : '';
|
|
1217
|
+
}
|
|
1218
|
+
else
|
|
1219
|
+
return me.getDataValue(token.split('.'), me.context); // data-key
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
captureTreeState()
|
|
1223
|
+
{
|
|
1224
|
+
let item = this,
|
|
1225
|
+
tree = (item.parent?.treeStatePass == core.renderPass) ? item.parent.treeState.slice() : item.parent?.captureTreeState().slice() || []; // clone always, cached or not, so no two items ever share the same treeState array reference
|
|
1226
|
+
|
|
1227
|
+
tree.push({
|
|
1228
|
+
key: item.key,
|
|
1229
|
+
index: item.index,
|
|
1230
|
+
inRepeat: item.inRepeat,
|
|
1231
|
+
repeatItemIdValue: item.repeatItemIdValue,
|
|
1232
|
+
context: item.context,
|
|
1233
|
+
value: item.value,
|
|
1234
|
+
element: item.element,
|
|
1235
|
+
livePath: $lib.clone({}, item.livePath)
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
item.treeState = tree;
|
|
1239
|
+
item.treeStatePass = core.renderPass; // valid only for this pass
|
|
1240
|
+
return tree;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
restoreContext(treeState)
|
|
1244
|
+
{
|
|
1245
|
+
let item = this, index = treeState.length, obj;
|
|
1246
|
+
|
|
1247
|
+
item.treeState = treeState;
|
|
1248
|
+
|
|
1249
|
+
while (--index > -1)
|
|
1250
|
+
{
|
|
1251
|
+
obj = treeState[index];
|
|
1252
|
+
item.key = obj.key;
|
|
1253
|
+
item.index = obj.index;
|
|
1254
|
+
item.inRepeat = obj.inRepeat;
|
|
1255
|
+
item.repeatItemIdValue = obj.repeatItemIdValue;
|
|
1256
|
+
item.context = obj.context;
|
|
1257
|
+
item.value = obj.value;
|
|
1258
|
+
item.element = obj.element;
|
|
1259
|
+
item.livePath = obj.livePath;
|
|
1260
|
+
item = item.parent;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
componyx.bindary_modules.TemplateItem = TemplateItem;
|
|
1267
|
+
})();
|
|
1268
|
+
|
|
1269
|
+
var Template = {
|
|
1270
|
+
TemplateItem: componyx.bindary_modules.TemplateItem
|
|
1271
|
+
};
|
|
1272
|
+
|
|
1273
|
+
export { Template as default };
|