@componyx/ui 0.0.0-stage → 1.0.3

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 (169) hide show
  1. package/AppSkin/AppSkin.css +1268 -0
  2. package/AppSkin/AppSkin.js +2748 -0
  3. package/AppSkin/Themes/Default.css +241 -0
  4. package/Base/Base.js +3407 -0
  5. package/Base/ComponentIcons.css +66 -0
  6. package/Base/Font/ComponentIcons.woff +0 -0
  7. package/Base/Font/UI.woff +0 -0
  8. package/Base/Library.js +8432 -0
  9. package/Base/NavigationManager.js +462 -0
  10. package/Base/ResponsiveTemplates.js +371 -0
  11. package/Base/Sanitizer.js +288 -0
  12. package/Base/Themes/Default.css +255 -0
  13. package/Base/UI.css +618 -0
  14. package/Base/UIResourcePath.js +6 -0
  15. package/Bindary/Bindary.js +2011 -0
  16. package/Bindary/Modules/Connection.js +216 -0
  17. package/Bindary/Modules/Core.js +854 -0
  18. package/Bindary/Modules/DataUpdater.js +351 -0
  19. package/Bindary/Modules/ExpressionEngine.js +347 -0
  20. package/Bindary/Modules/ProxyManager.js +482 -0
  21. package/Bindary/Modules/Renderer.js +605 -0
  22. package/Bindary/Modules/Router.js +291 -0
  23. package/Bindary/Modules/Scroller.js +89 -0
  24. package/Bindary/Modules/Template.js +1273 -0
  25. package/BookmarkSpy/BookmarkSpy.js +430 -0
  26. package/Box/Box.css +36 -0
  27. package/Box/Box.js +1685 -0
  28. package/Button/Button.css +470 -0
  29. package/Button/Button.js +1398 -0
  30. package/Button/Themes/Default.css +200 -0
  31. package/Carousel/Carousel.css +273 -0
  32. package/Carousel/Carousel.js +607 -0
  33. package/ColorButton/ColorButton.css +39 -0
  34. package/ColorButton/ColorButton.js +336 -0
  35. package/ColorPicker/ColorPicker.css +359 -0
  36. package/ColorPicker/ColorPicker.js +972 -0
  37. package/ComboBox/ComboBox.css +357 -0
  38. package/ComboBox/ComboBox.js +2342 -0
  39. package/ComboBox/Themes/Default.css +23 -0
  40. package/DataPager/DataPager.css +72 -0
  41. package/DataPager/DataPager.js +674 -0
  42. package/DatePicker/DatePicker.css +227 -0
  43. package/DatePicker/DatePicker.js +1531 -0
  44. package/DatePicker/Themes/Default.css +26 -0
  45. package/Dialog/Dialog.css +106 -0
  46. package/Dialog/Dialog.js +572 -0
  47. package/Dialog/Themes/Default.css +10 -0
  48. package/Editor/Data/Emoji.json +8285 -0
  49. package/Editor/Data/Special.json +1042 -0
  50. package/Editor/Editor.css +1562 -0
  51. package/Editor/Editor.js +4058 -0
  52. package/Editor/Font/Editor.woff +0 -0
  53. package/Editor/Modules/ComponentFactory.js +565 -0
  54. package/Editor/Modules/ContentManager.js +748 -0
  55. package/Editor/Modules/DialogManager.js +1234 -0
  56. package/Editor/Modules/EventManager.js +458 -0
  57. package/Editor/Modules/Format.js +950 -0
  58. package/Editor/Modules/History.js +191 -0
  59. package/Editor/Modules/LayoutState.js +379 -0
  60. package/Editor/Modules/ListManager.js +296 -0
  61. package/Editor/Modules/MenuManager.js +388 -0
  62. package/Editor/Modules/NodeManager.js +681 -0
  63. package/Editor/Modules/ParagraphButtons.js +122 -0
  64. package/Editor/Modules/Resizer.js +176 -0
  65. package/Editor/Modules/SelectionRange.js +564 -0
  66. package/Editor/Modules/SourceViewBuilder.js +212 -0
  67. package/Editor/Modules/SymbolPicker.js +208 -0
  68. package/Editor/Modules/Table.js +2327 -0
  69. package/Editor/Modules/TableDialog.js +757 -0
  70. package/Editor/Modules/Toolbar.js +375 -0
  71. package/Editor/Modules/TooltipMenu.js +125 -0
  72. package/Editor/Modules/Utility.js +131 -0
  73. package/Editor/Themes/Default.css +204 -0
  74. package/FileUpload/FileUpload.css +156 -0
  75. package/FileUpload/FileUpload.js +898 -0
  76. package/FileUpload/Themes/Default.css +17 -0
  77. package/Form/Form.css +1934 -0
  78. package/Form/Form.js +4943 -0
  79. package/Form/Modules/ActionManager.js +368 -0
  80. package/Form/Modules/BuildPanelManager.js +319 -0
  81. package/Form/Modules/ComponentFactory.js +468 -0
  82. package/Form/Modules/ComponentPanel.js +265 -0
  83. package/Form/Modules/ConfigPanelManager.js +685 -0
  84. package/Form/Modules/DataObserver.js +717 -0
  85. package/Form/Modules/Databinder.js +602 -0
  86. package/Form/Modules/Draggable.js +756 -0
  87. package/Form/Modules/OptionsPanel.js +342 -0
  88. package/Form/Modules/Renderer.js +1889 -0
  89. package/Form/Modules/RuleEngine.js +585 -0
  90. package/Form/Modules/RulesPanel.js +1158 -0
  91. package/Form/Modules/Types.js +1709 -0
  92. package/Form/Modules/ValidationManager.js +194 -0
  93. package/Form/Themes/Default.css +216 -0
  94. package/FormField/FormField.css +468 -0
  95. package/FormField/FormField.js +576 -0
  96. package/FormField/Themes/Default.css +99 -0
  97. package/Grid/Grid.css +544 -0
  98. package/Grid/Grid.js +3761 -0
  99. package/Grid/Themes/Default.css +43 -0
  100. package/LICENSE +126 -0
  101. package/MaskedTextBox/MaskedTextBox.css +28 -0
  102. package/MaskedTextBox/MaskedTextBox.js +642 -0
  103. package/MaskedTextBox/Themes/Default.css +6 -0
  104. package/Menu/Menu.css +328 -0
  105. package/Menu/Menu.js +2386 -0
  106. package/Menu/Themes/Default.css +24 -0
  107. package/NumericBox/NumericBox.css +120 -0
  108. package/NumericBox/NumericBox.js +984 -0
  109. package/PanelBar/PanelBar.css +123 -0
  110. package/PanelBar/PanelBar.js +505 -0
  111. package/PanelBar/Themes/Default.css +51 -0
  112. package/PieChart/PieChart.css +95 -0
  113. package/PieChart/PieChart.js +820 -0
  114. package/PieChart/Themes/Default.css +9 -0
  115. package/README.md +178 -3
  116. package/Slider/Slider.css +348 -0
  117. package/Slider/Slider.js +1306 -0
  118. package/Slider/Themes/Default.css +44 -0
  119. package/TabStrip/TabStrip.css +52 -0
  120. package/TabStrip/TabStrip.js +362 -0
  121. package/TabStrip/Themes/Default.css +35 -0
  122. package/TimePicker/Themes/Default.css +30 -0
  123. package/TimePicker/TimePicker.css +253 -0
  124. package/TimePicker/TimePicker.js +1485 -0
  125. package/TooltipManager/Themes/Default.css +21 -0
  126. package/TooltipManager/TooltipManager.css +227 -0
  127. package/TooltipManager/TooltipManager.js +791 -0
  128. package/Validator/Validator.css +54 -0
  129. package/Validator/Validator.js +2508 -0
  130. package/componyx.html-data.json +619 -0
  131. package/index.js +27 -0
  132. package/package.json +43 -4
  133. package/types/AppSkin.d.ts +842 -0
  134. package/types/Base.d.ts +1034 -0
  135. package/types/Bindary.d.ts +1196 -0
  136. package/types/BookmarkSpy.d.ts +112 -0
  137. package/types/Box.d.ts +374 -0
  138. package/types/Button.d.ts +455 -0
  139. package/types/Carousel.d.ts +136 -0
  140. package/types/ColorButton.d.ts +120 -0
  141. package/types/ColorPicker.d.ts +225 -0
  142. package/types/ComboBox.d.ts +507 -0
  143. package/types/DataPager.d.ts +152 -0
  144. package/types/DatePicker.d.ts +354 -0
  145. package/types/Dialog.d.ts +160 -0
  146. package/types/Editor.d.ts +1289 -0
  147. package/types/FileUpload.d.ts +206 -0
  148. package/types/Form.d.ts +3078 -0
  149. package/types/FormField.d.ts +204 -0
  150. package/types/Grid.d.ts +911 -0
  151. package/types/Library.d.ts +1899 -0
  152. package/types/MaskedTextBox.d.ts +91 -0
  153. package/types/Menu.d.ts +577 -0
  154. package/types/NumericBox.d.ts +310 -0
  155. package/types/PanelBar.d.ts +223 -0
  156. package/types/PieChart.d.ts +224 -0
  157. package/types/ResponsiveTemplates.d.ts +108 -0
  158. package/types/Slider.d.ts +227 -0
  159. package/types/TabStrip.d.ts +185 -0
  160. package/types/TimePicker.d.ts +265 -0
  161. package/types/TooltipManager.d.ts +178 -0
  162. package/types/UI.d.ts +29 -0
  163. package/types/Validator.d.ts +653 -0
  164. package/types/index.d.ts +59 -0
  165. package/ui.css +11783 -0
  166. package/ui.js +79477 -0
  167. package/ui.min.css +138 -0
  168. package/ui.min.js +264 -0
  169. package/ui.min.js.map +1 -0
@@ -0,0 +1,605 @@
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
+ const core = componyx.bindary_modules.core;
6
+
7
+ /**
8
+ * Represents a renderer that is responsible for rendering and managing DOM elements for items.
9
+ *
10
+ * @class
11
+ * @property {componyx.bindary.TemplateItem} item - The item being rendered.
12
+ * @property {boolean} update - A value indicating if its an update or render.
13
+ * @property {boolean} inRepeat - A value indicating if the item is part of a repeat section.
14
+ * @property {Function} next - The function to fetch the next item in the render cycle.
15
+ * @property {HTMLElement} element - The DOM element for the item.
16
+ * @property {Object|null} treeState - The tree state for the item.
17
+ * @property {Object} context - The context for the item renderer.
18
+ * @property {string|null} key - The key associated with the item.
19
+ * @property {Object|null} dataChange - Data change information for the item.
20
+ */
21
+ componyx.bindary_modules.Renderer = class
22
+ {
23
+ /**
24
+ * Creates an instance of Renderer.
25
+ *
26
+ * @param {Object} item - The item to be rendered.
27
+ * @param {HTMLElement} element - The DOM element associated with the item.
28
+ * @param {Function} update - The function responsible for updating the item renderer.
29
+ * @param {Function} next - The function to fetch the next item in the rendering process.
30
+ */
31
+ constructor(item, element, update, next)
32
+ {
33
+ this.item = item;
34
+ this.update = update;
35
+ this.inRepeat = item.inRepeat;
36
+ this.next = next;
37
+ this.element = element;
38
+ this.treeState = null;
39
+ this.context = null;
40
+ this.key = null;
41
+ this.dataChange = null;
42
+ }
43
+
44
+
45
+ render(context, key)
46
+ {
47
+ let me = this, item = me.item;
48
+
49
+ me.treeState = null;
50
+
51
+ if (item.repeatDataKey)
52
+ {
53
+
54
+ me.context = context || me.context;
55
+ me.key = (!$lib.isEmpty(key)) ? key : me.key;
56
+ me.renderRepeatItem(me.context, me.key);
57
+
58
+ }
59
+ else
60
+ {
61
+ me.renderItem();
62
+ }
63
+ }
64
+
65
+ renderRepeatItem(context, key)
66
+ {
67
+ let me = this, item = me.item;
68
+
69
+ if ($lib.isArray(item.repeatValue))
70
+ {
71
+ item.index = parseInt(key);
72
+ }
73
+
74
+ item.key = key;
75
+ item.defineContext(context);
76
+ item.setContextValue();
77
+ item.element = item.repeatElements[key] || item.repeatPlaceHolder;
78
+
79
+ if (item.repeatItemIdDataKey)
80
+ item.repeatItemIdValue = item.getDataValue(item.repeatItemIdDataKey, item.context);
81
+
82
+ me.renderElement(me.createRepeatElement);
83
+ }
84
+
85
+ renderItem()
86
+ {
87
+ let me = this, item = me.item;
88
+
89
+ item.setContextValue();
90
+ item.element = me.element;
91
+ me.renderElement(me.createElement);
92
+ }
93
+
94
+ renderElement(create)
95
+ {
96
+
97
+ let me = this, item = me.item, element = item.element;
98
+
99
+ if (me.mustRender(item, element))
100
+ {
101
+
102
+ create.bind(this)();
103
+
104
+ if (item.include)
105
+ me.includeItem();
106
+ else if (item.includeFile)
107
+ me.includeFile();
108
+ else if (item.component)
109
+ me.load();
110
+ else
111
+ me.postRender();
112
+ } else
113
+ {
114
+ me.next(); // fetch next
115
+ }
116
+ }
117
+
118
+
119
+ mustRender()
120
+ {
121
+ let me = this, item = me.item, element = item.element;
122
+
123
+ if (!item.isActiveRepeatItem(item) || (item.hasValue != null && me.isEmpty(item)) || (core.call(item.preRender, [item, me.render]) === false))
124
+ {
125
+ // element should not be visible and children should not be part of the DOM tree
126
+ core.setItemPlaceHolder(item, element);
127
+ return false;
128
+ }
129
+
130
+ return true;
131
+ }
132
+
133
+ isEmpty(item)
134
+ {
135
+ let value = (item.hasValue[0].length == 0) ? (item.dataKey) ? item.value : item.context : item.getDataValue(item.hasValue, item.context);
136
+ return $lib.isEmpty(value);
137
+ }
138
+
139
+ includeItem()
140
+ {
141
+ let me = this, item = me.item, include;
142
+
143
+ if (item.component && core.components[item.component])
144
+ item.context = core.components[item.component](item); // context is defined before include, therefore a possible includable data-key can be defined in the component's context
145
+
146
+ include = item.getIncludeItem();
147
+
148
+ if (!item.children.length && (!include && core.hasLoadingIncludes()))
149
+ { // include item not found and busy including files, add to global waiters list
150
+
151
+ me.waiting = true;
152
+ core.waiters.push(me);
153
+ return;
154
+ }
155
+
156
+ me.waiting = false;
157
+ me.load(include);
158
+ }
159
+
160
+ includeFile()
161
+ {
162
+ let me = this, item = me.item,
163
+ includeURL = $bindary.includeRootURL + (($lib.startsWith(item.includeFile, '/')) ? item.includeFile.substr(1) : item.getDataValue(item.includeFile, item.context)),
164
+ include = core.cache.include[includeURL];
165
+
166
+ if (include)
167
+ {
168
+ if (include.loading)
169
+ {
170
+
171
+ include.waiters.push(me);
172
+ return;
173
+ }
174
+
175
+ me.load(include);
176
+
177
+ }
178
+ else
179
+ {
180
+ me.createFileInclude(includeURL);
181
+
182
+ core.xhr.push($lib.load({
183
+ url: includeURL,
184
+ onSuccess: function (args)
185
+ {
186
+ let include = core.cache.include[args.settings.url];
187
+ include.dataLoaded(args);
188
+ }
189
+ }, item.element));
190
+ }
191
+ }
192
+
193
+ createFileInclude(includeURL)
194
+ {
195
+ let me = this,
196
+ include = {};
197
+
198
+ core.cache.include[includeURL] = include;
199
+
200
+ include.loading = true;
201
+ include.waiters = [];
202
+ include.waiters.push(me);
203
+ include.dataLoaded = function (args)
204
+ {
205
+ let include = core.cache.include[args.settings.url];
206
+ include.loading = false;
207
+ include.html = args.html;
208
+ include.css = args.css;
209
+ include.script = args.script;
210
+
211
+ core.renderPass++; // resuming after an async gap: nothing cached from before this point can be trusted
212
+
213
+ $lib.each(include.waiters, function (itemRenderer)
214
+ { // file includes
215
+
216
+ itemRenderer.item.restoreContext(itemRenderer.treeState);
217
+ itemRenderer.load.bind(itemRenderer)(include);
218
+ });
219
+
220
+ $lib.each(core.waiters, function (itemRenderer)
221
+ { // item includes
222
+
223
+ itemRenderer.item.restoreContext(itemRenderer.treeState);
224
+ itemRenderer.includeItem.bind(itemRenderer)();
225
+ });
226
+
227
+ delete include.waiters;
228
+ core.clearWaiters();
229
+
230
+ if (core.postRenderFlag) // post-render was called while loading data
231
+ core.postRender();
232
+ };
233
+ }
234
+
235
+ load(include)
236
+ {
237
+ let me = this, item = me.item, element = item.element;
238
+
239
+ if (include)
240
+ {
241
+ if (!element.childNodes.length)
242
+ {
243
+ item.loaded = false;
244
+
245
+ if (include.html)
246
+ { // file-include
247
+
248
+ let html = (item.children.length) ? include.cachedHtml : include.html; // the item has already been added to the view-tree before, so it's not unique and inside a repeater. Since we dont build the view-tree again, we must use the same html with set bindary identifiers.
249
+ $lib.addHTML(html, item.element);
250
+ }
251
+ else
252
+ { // item-include
253
+ element.appendChild(include.sourceElement.cloneNode(true));
254
+ }
255
+ }
256
+
257
+ if (!item.children.length)
258
+ {
259
+ if (include.html)
260
+ { // file-include
261
+
262
+ $bindary.createViewTree(element, item); // append view tree
263
+ $lib.each(item.children, (i) => { i.included = true; });
264
+ include.cachedHtml = element.innerHTML;
265
+
266
+ }
267
+ else
268
+ { // item-include
269
+
270
+ let clone = include.clone(item);
271
+ clone.included = true;
272
+ item.children.push(clone);
273
+ }
274
+ }
275
+ }
276
+ else
277
+ {
278
+ item.loaded = false;
279
+ }
280
+
281
+ if (item.loaded)
282
+ me.postRender();
283
+ else
284
+ {
285
+ item.loaded = true;
286
+
287
+ if (item.component)
288
+ {
289
+ if (!include || include.html) // context already set for item-include
290
+ item.context = core.components[item.component](item);
291
+
292
+ if (item.context?.load)
293
+ item.context.load(item); // invoke load method on component if exists
294
+ }
295
+
296
+ core.call(item.load, [item]); // invoke custom load method if exists
297
+
298
+ if (item.observeDataKeyPath)
299
+ {
300
+
301
+ let keyPath = (item.contextDataKeyPath) ? item.livePath[item.contextDataKeyPath] + core.dksc + item.observeDataKeyPath : item.observeDataKeyPath; // configure root key-path for component using current full context path
302
+ item.context[item.observeDataKeyPath] = $bindary.observe(item.context[item.observeDataKeyPath], keyPath, { viewTree: [item], reuseProxy: false }); // own proxy per component instance, so viewTree isn't silently dropped by reuse and component data will trigger view-tree update only for corresponding tree-item
303
+ }
304
+
305
+ me.postRender();
306
+ }
307
+ }
308
+
309
+ componentDataChange(event)
310
+ {
311
+
312
+ let payload = event.detail.eventPayload;
313
+
314
+ item.restoreContext(payload.treeState);
315
+ event.detail.viewTree = [item];
316
+ }
317
+
318
+ createRepeatElement()
319
+ {
320
+
321
+ let me = this,
322
+ item = me.item,
323
+ placeHolder = item.repeatPlaceHolder,
324
+ reps = item.repeatElements;
325
+
326
+ let element = reps[item.key];
327
+
328
+
329
+ if (!element || element._bindaryPlaceholder || item.dataChange?.recreate ||
330
+ ($lib.isEmpty(item.dataChange?.recreate) && $bindary.defaultRecreateRule))
331
+ {
332
+ element = item.sourceElement.cloneNode(true);
333
+ element.removeAttribute('id');
334
+ element.setAttribute(core.attr.id, item.id); // keep id as bindary attribute
335
+ element.style.display = item.display;
336
+ placeHolder.parentNode.insertBefore(element, placeHolder);
337
+ reps[item.key] = element;
338
+ }
339
+
340
+ item.element = element;
341
+ me.inRepeat = true;
342
+ return me.createElement();
343
+ }
344
+
345
+ createElement()
346
+ {
347
+ let me = this, item = me.item, context = item.context,
348
+ element = item.element,
349
+ setValue = function (name, value)
350
+ {
351
+ if (value === null || value === undefined)
352
+ {
353
+ if (element.hasAttribute(name))
354
+ element.removeAttribute(name);
355
+ }
356
+ else
357
+ {
358
+ if (typeof value === 'object')
359
+ value = JSON.stringify(value);
360
+
361
+ if (element.getAttribute(name) !== value)
362
+ element.setAttribute(name, value);
363
+ }
364
+ };
365
+
366
+ me.treeState = item.captureTreeState();
367
+ element.style.display = item.display; // element could be invisible if it was not rendered before
368
+
369
+ // set attributes
370
+ $lib.each(item.attributes, function (value, name)
371
+ {
372
+ if (item.attributeExpressions && item.attributeExpressions[name])
373
+ {
374
+ let exprFn = item.attributeExpressions[name],
375
+ resolvedValue = exprFn(item.expressionTokenResolver.bind(item));
376
+
377
+ setValue(name, resolvedValue);
378
+ }
379
+ else
380
+ {
381
+ let dataValue = (value.match(core.singleWord)) ? item.getDataValue(item.createDataKey(value, false), context) : undefined;
382
+ setValue(name, (dataValue == undefined) ? value : dataValue);
383
+ }
384
+ });
385
+
386
+ $lib.each(item.events, function (method, event)
387
+ {
388
+ if ($lib.has(element, event, core.customEventHandler))
389
+ $lib.off(element, event, core.customEventHandler);
390
+
391
+ $lib.on(element, event, core.customEventHandler, [method, item, me.treeState, null, false, core.getMethodContext(method, item)]);
392
+ });
393
+
394
+ me.clearInputEvents();
395
+ me.setElementValue();
396
+ me.bindInputEvents();
397
+
398
+ return element;
399
+ }
400
+
401
+ setElementValue()
402
+ {
403
+ let me = this, item = me.item,
404
+ el = item.element,
405
+ info = item.elementInfo,
406
+ value = item.value,
407
+ type = item.dataType;
408
+
409
+ if (el === core.dataBindTrigger && core.dataBindLive) // skip updating the element while the user is actively typing to avoid overwriting input
410
+ return;
411
+
412
+ if ((!item.dataKey && !item.expression) || info.isSelect) // select type is handled in item postrender
413
+ return;
414
+
415
+ if (item.viewFormatter)
416
+ value = core.call(item.viewFormatter, [item, el, value]);
417
+
418
+ value = me.formatValue(value);
419
+
420
+ if (info.isRadio || info.isCheck)
421
+ {
422
+ if (Array.isArray(value)) // check if this checkbox/radio value exists in the array
423
+ {
424
+ const elValue = ($lib.isEmpty(el.value) || el.value === 'on') ? el.name : el.value;
425
+ el.checked = value.includes(elValue);
426
+ }
427
+ else if (typeof value == 'boolean')
428
+ el.checked = ($lib.isEmpty(el.value) || type != 'boolean') ? value : (core.toBoolean(el.value) == value); // checkbox with value="false" is checked when value == false (e.g. checkbox with label 'enabled' and data property 'disabled')
429
+ else
430
+ el.checked = value == el.value;
431
+
432
+ el._bindaryLastState = `${el.checked}:${el.value}`;
433
+
434
+ return;
435
+ }
436
+
437
+ if (Array.isArray(value)) // convert array
438
+ value = value.map(v => { return me.formatValue(v); }).join(',');
439
+
440
+ value = ($lib.isEmpty(value, false)) ? '' : value.toString();
441
+
442
+ const isHTML = item.isHTML || el.contentEditable === 'true';
443
+ value = isHTML
444
+ ? ($bindary.trustHTML || item.trusted) ? value : ($bindary.sanitizer ? $bindary.sanitizer(value) : core.sanitizer.sanitize(value))
445
+ : value;
446
+
447
+ core.setElementValue(item, value, isHTML);
448
+ el._bindaryLastState = isHTML ? el.innerHTML : el.value;
449
+ }
450
+
451
+ formatValue(value)
452
+ {
453
+ let me = this,
454
+ item = me.item,
455
+ info = item.elementInfo,
456
+ type = item.dataType,
457
+ el = item.element,
458
+ isoDate = null;
459
+
460
+ if (typeof value == 'string' && (/^\d{4}-\d{2}-\d{2}/.test(value))) // iso string date
461
+ {
462
+ isoDate = new Date(value);
463
+ if ($lib.isDate(isoDate) && !isNaN(isoDate.getTime()))
464
+ value = isoDate;
465
+ }
466
+
467
+ if ($lib.isDate(value))
468
+ {
469
+ let format,
470
+ date = isoDate || value;
471
+
472
+ if (isNaN(date.getTime()))
473
+ return '';
474
+
475
+ if (info.isInput && el.type == 'date')
476
+ format = 'YYYY-MM-DD'; // use default date format yyyy-mm-dd
477
+ else if (type == 'date')
478
+ format = $bindary.dateFormat.replace(core.timeRegEx, ''); // remove time portion from date-format
479
+
480
+ return core.formatDate(date, format);
481
+ }
482
+ else if (typeof value == 'number' && type?.startsWith('number'))
483
+ {
484
+ const match = type.match(/^number(?:\((\d+)\))?$/),
485
+ precision = match?.[1] != null ? parseInt(match[1]) : $bindary.decimalPrecision;
486
+
487
+ return $lib.formatNumber(value, false, true, precision, null, $bindary.decimalSeparator);
488
+ }
489
+
490
+ return value;
491
+ }
492
+
493
+ clearInputEvents()
494
+ {
495
+ let me = this, item = me.item,
496
+ element = item.element;
497
+
498
+ if ($lib.has(element, 'blur', core.eventHandler))
499
+ $lib.off(element, 'blur', core.eventHandler);
500
+
501
+ if ($lib.has(element, 'change', core.eventHandler))
502
+ $lib.off(element, 'change', core.eventHandler);
503
+
504
+ if ($lib.has(element, 'input', me.deferDataBind))
505
+ $lib.off(element, 'input', me.deferDataBind);
506
+ }
507
+
508
+ bindInputEvents()
509
+ {
510
+ let me = this, item = me.item,
511
+ element = item.element;
512
+
513
+ if (!item.inputBind)
514
+ return;
515
+
516
+ let tree = me.treeState;
517
+
518
+ // Attach listeners in next event cycle to avoid infinite event call loop when the update came from dataBind().
519
+ // The library event handler uses forEach, which will always retrieve a new value because of the remove/add action
520
+ $lib.defer(function (element, tree)
521
+ {
522
+ let me = this, item = me.item;
523
+
524
+ if (element.isContentEditable)
525
+ $lib.on(element, 'blur', core.eventHandler, [me.dataBind.bind(me, false), item, tree, [], true, null], me, true);
526
+ else
527
+ $lib.on(element, 'change', core.eventHandler, [me.dataBind.bind(me, false), item, tree, [], true, null], me, true);
528
+
529
+ if ((($bindary.liveBind && item.liveBind !== false) || item.liveBind) && element.type != 'hidden')
530
+ $lib.on(element, 'input', me.deferDataBind, [tree], me, true);
531
+
532
+ }.bind(me, element, tree));
533
+ }
534
+
535
+ deferDataBind(tree, e)
536
+ {
537
+ const me = this,
538
+ element = me.item.element,
539
+ itemDelay = Number(me.item.liveBind),
540
+ delay = (!isNaN(itemDelay) && itemDelay >= 0) ? itemDelay : ($bindary.liveBindDelay || 0),
541
+ updateFn = function (tree)
542
+ {
543
+ core.eventHandler(this.dataBind.bind(this, true), this.item, tree, [], true, null);
544
+ }.bind(me, tree);
545
+
546
+ if (core.liveBindTimers.has(element))
547
+ clearTimeout(core.liveBindTimers.get(element));
548
+
549
+ const timerId = setTimeout(updateFn, delay);
550
+ core.liveBindTimers.set(element, timerId);
551
+ }
552
+
553
+ dataBind(live)
554
+ {
555
+ let me = this, item = me.item,
556
+ info = item.elementInfo,
557
+ el = item.element,
558
+ value = core.getElementValue(item),
559
+ state = info.isCheck || info.isRadio ? `${el.checked}:${value}` : value;
560
+
561
+ if (state === el._bindaryLastState)
562
+ return;
563
+
564
+ if (core.fireEvent('preDataBind', [item, el, function () { item.dataBind(live); }]) !== false)
565
+ item.dataBind(live);
566
+ }
567
+
568
+ postRender()
569
+ {
570
+ let me = this, item = me.item;
571
+
572
+ if (item.children && item.children.length)
573
+ $bindary.renderView(me.update, item.children);
574
+
575
+ if (item.elementInfo && item.elementInfo.isSelect && item.dataKey)
576
+ me.setSelectValue(); // set select value when all options are rendered
577
+
578
+ if (me.inRepeat)
579
+ core.rendered.push(item); // set rendered state after all repeat-elements are rendered
580
+ else
581
+ item.isRendered = true;
582
+
583
+ if (item.component && item.context?.postRender)
584
+ item.context.postRender(item); // invoke postRender method on component if exists
585
+
586
+ if (core.call(item.postRender, [item]) === false)
587
+ item.element.style.display = 'none';
588
+
589
+ item.key = item.index = item.value = null; // clear
590
+ me.next(); // fetch next
591
+ }
592
+
593
+ setSelectValue()
594
+ {
595
+
596
+ let me = this, item = me.item;
597
+ let dataKey = item.dataKey;
598
+ $lib('#' + item.id).value = item.getDataValue(dataKey, item.context);
599
+ }
600
+ };
601
+ })();
602
+
603
+ var Renderer = componyx.bindary_modules.Renderer;
604
+
605
+ export { Renderer as default };