@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,2342 @@
1
+ /*! Componyx.UI | (c) E.H. Daanen / Componyx | BUSL-1.1 | componyx.com/license */
2
+ import '../Base/Base.js';
3
+ import '../Base/Library.js';
4
+ import '../DataPager/DataPager.js';
5
+ import '../Box/Box.js';
6
+ import '../Button/Button.js';
7
+
8
+ (function (window)
9
+ {
10
+ /**
11
+ * ComboBox class.
12
+ * @class
13
+ * @memberof componyx.UI
14
+ * @augments componyx.UI.base.Component
15
+ * @mixes componyx.UI.base.methods
16
+ * @param {String} id The id of the component.
17
+ * @param {Object|HTMLElement} properties The properties used to initialize the component or the container element.
18
+ * @property {componyx.UI.base.AjaxMethod} ajax.load - AJAX method used to load items on demand.
19
+ * @returns {Object} An instance of the component.
20
+ */
21
+ componyx.UI.ComboBox = function ComboBox(id, properties)
22
+ {
23
+ // define private properties
24
+ var _instance = this,
25
+ _elements = {},
26
+ _tags = {},
27
+ _input = null,
28
+ _selectAllId = 'SelectAll',
29
+ _loading = false,
30
+ _loadTimerId = null,
31
+ _lastQuery = null,
32
+ _keyCode = null,
33
+ _sizer = null,
34
+ _expandButton = null,
35
+ _clearButton = null,
36
+ _clearButtonClicked = false,
37
+ _listBox = null,
38
+ _pager = null,
39
+ _hidden = null,
40
+ _ajax = null,
41
+ _onDemand = false,
42
+ _multiTemplateActive = false,
43
+ _initialValue = false,
44
+ _focusedItemId = null,
45
+ _selectedItemId = null,
46
+ _selectedItems = {},
47
+ _selectedCount = 0,
48
+ _columnRegEx = null,
49
+ _forceSelect = false,
50
+ _charValue = '',
51
+ _allowHide = true,
52
+ _pendingCustomValue = null;
53
+ $base.static.ThemeOption;
54
+ var _filterOption = componyx.UI.ComboBox.FilterOption,
55
+ _classOption =
56
+ {
57
+ GROW: 'grow',
58
+ SIZER: 'sizer',
59
+ MULTISELECT: 'multi',
60
+ ALLOWINPUT: 'allow-input',
61
+ TAGGING: 'tagging',
62
+ TAG: 'button tag',
63
+ DISABLED: 'disabled',
64
+ EXPANDBUTTON: 'button expand down',
65
+ EXPANDSPLIT: 'split',
66
+ EXPANDICON: 'expand-icon',
67
+ CLEARBUTTON: 'button clear',
68
+ BOX: 'box',
69
+ DATAPAGER: 'data-pager',
70
+ BOXHEADER: 'header header-label',
71
+ BOXFOOTER: 'footer',
72
+ LIST: 'list',
73
+ ITEM: 'item',
74
+ ITEMICON: 'icon',
75
+ ITEMCHECKBOX: 'checkbox',
76
+ ITEMSELECTALL: 'item select-all',
77
+ PRELOADER: 'preloader',
78
+ NORESULT: 'no-result'
79
+ };
80
+
81
+ // define public properties
82
+ /**
83
+ * Gets or sets the css class of the expand button component.
84
+ * @type {String}
85
+ */
86
+ this.cssClassExpandButton = '';
87
+
88
+ /**
89
+ * Gets or sets the css class of the expand icon.
90
+ * @type {String}
91
+ */
92
+ this.cssClassExpandIcon = '';
93
+
94
+ /**
95
+ * Gets or sets the css class of the clear button component.
96
+ * @type {String}
97
+ */
98
+ this.cssClassClearButton = '';
99
+
100
+ /**
101
+ * Gets or sets the css class of the datapager component.
102
+ * @type {String}
103
+ */
104
+ this.cssClassDataPager = '';
105
+
106
+ /**
107
+ * Gets or sets the css class of the list box component.
108
+ * @type {String}
109
+ */
110
+ this.cssClassListBox = '';
111
+
112
+ /**
113
+ * Gets or sets the css class of the unordered list.
114
+ * @type {String}
115
+ */
116
+ this.cssClassList = '';
117
+
118
+ /**
119
+ * Gets or sets the default css class of an item.
120
+ * @type {String}
121
+ */
122
+ this.cssClassItem = '';
123
+
124
+ /**
125
+ * Gets or sets the css class of an item icon.
126
+ * @type {String}
127
+ */
128
+ this.cssClassItemIcon = '';
129
+
130
+ /**
131
+ * Gets or sets the css class of an item checkbox.
132
+ * @type {String}
133
+ */
134
+ this.cssClassItemCheckBox = '';
135
+
136
+ /**
137
+ * Gets or sets the css class of the 'select all' checkbox item.
138
+ * @type {String}
139
+ */
140
+ this.cssClassItemSelectAll = '';
141
+
142
+ /**
143
+ * Gets or sets the css class of the preloader container.
144
+ * @type {String}
145
+ */
146
+ this.cssClassPreloader = '';
147
+
148
+ /**
149
+ * Gets or sets the css class of the noresult container.
150
+ * @type {String}
151
+ */
152
+ this.cssClassNoResult = '';
153
+
154
+ /**
155
+ * Gets or sets the identifying css class of a column.
156
+ * @type {String}
157
+ */
158
+ this.columnIdentifyingCssClass = '';
159
+
160
+ /**
161
+ * Gets or sets the default template id of an item.
162
+ * @type {String|null}
163
+ */
164
+ this.itemTemplateId = null;
165
+
166
+ /**
167
+ * Gets or sets a value indicating whether textual input is allowed.
168
+ * @type {Boolean}
169
+ */
170
+ this.allowInput = true;
171
+
172
+ /**
173
+ * Gets or sets a value indicating whether users can enter values not in the option list.
174
+ * @type {Boolean}
175
+ */
176
+ this.allowCustomValue = false;
177
+
178
+ /**
179
+ * Gets or sets a value indicating whether the combo box uses a split button.
180
+ * @type {Boolean}
181
+ */
182
+ this.splitButton = false;
183
+
184
+ /**
185
+ * Gets or sets a value indicating whether multiple items can be selected through checkboxes.
186
+ * @type {Boolean}
187
+ */
188
+ this.multiSelect = false;
189
+
190
+ /**
191
+ * Gets or sets a value indicating whether selected items are displayed as tags.
192
+ * @type {Boolean}
193
+ */
194
+ this.multiSelectTagging = false;
195
+
196
+ /**
197
+ * Gets or sets a value indicating if the input box will increase width automatically based on the size of the text.
198
+ * @type {Boolean}
199
+ */
200
+ this.autoGrow = false;
201
+
202
+ /**
203
+ * Gets or sets a value indicating whether keyboard navigation is allowed.
204
+ * @type {Boolean}
205
+ */
206
+ this.keyboardNavigation = true;
207
+
208
+ /**
209
+ * Gets or sets a value indicating whether the list box is collapsed on an item select.
210
+ * @type {Boolean}
211
+ */
212
+ this.collapseOnItemSelect = true;
213
+
214
+ /**
215
+ * Gets or sets a value indicating whether the data is loaded when the component is rendering.
216
+ * @type {Boolean}
217
+ */
218
+ this.loadOnRender = false;
219
+
220
+ /**
221
+ * Gets or sets a value indicating whether the data is loaded when the text input is changed or the list box is expanded.
222
+ * @type {Boolean}
223
+ */
224
+ this.loadOnDemand = false;
225
+
226
+ /**
227
+ * Gets or sets a value indicating whether the data is reloaded when the list box is expanded.
228
+ * @type {Boolean}
229
+ */
230
+ this.reloadOnExpand = false;
231
+
232
+ /**
233
+ * Gets or sets the amount of characters required before a load on demand is performed.
234
+ * @type {Number}
235
+ */
236
+ this.loadOnDemandCharStart = 0;
237
+
238
+ /**
239
+ * Gets or sets the delay in milliseconds on a keydown event before a load on demand is performed.
240
+ * @type {Number}
241
+ */
242
+ this.loadOnDemandDelay = 250;
243
+
244
+ /**
245
+ * Gets or sets a value indicating whether the clear button is disabled.
246
+ * @type {Boolean}
247
+ */
248
+ this.disableClearButton = false;
249
+
250
+ /**
251
+ * Gets or sets a value indicating whether the datapager is enabled.
252
+ * @type {Boolean}
253
+ */
254
+ this.enableDataPager = false;
255
+
256
+ /**
257
+ * Gets or sets a value indicating whether the combobox is disabled.
258
+ * @type {Boolean}
259
+ */
260
+ this.disabled = false;
261
+
262
+ /**
263
+ * Gets or sets a value indicating whether the current selection must be kept when reloading data.
264
+ * @type {Boolean}
265
+ */
266
+ this.keepSelectionOnReload = true;
267
+
268
+ /**
269
+ * Gets or sets a value indicating whether the list box can only be expanded by typing, not by clicking the expand button.
270
+ * @type {Boolean}
271
+ */
272
+ this.disableExpandOnClick = false;
273
+
274
+ /**
275
+ * Gets or sets the placeholder which is visible when the input box has no value.
276
+ * @type {String}
277
+ */
278
+ this.placeholder = '';
279
+
280
+ /**
281
+ * Gets or sets the input width in the specified unit.
282
+ * @type {String}
283
+ */
284
+ this.width = '';
285
+
286
+ /**
287
+ * Gets or sets the name of the hidden input field which contains the selected value(s).
288
+ * @type {String}
289
+ */
290
+ this.name = '';
291
+
292
+ /**
293
+ * Gets or sets the initial selected value.
294
+ * @type {String}
295
+ */
296
+ this.value = '';
297
+
298
+ /**
299
+ * Gets or sets the list of items.
300
+ * @type {componyx.UI.ComboBox.Item[]|null}
301
+ */
302
+ this.itemList = null;
303
+
304
+ /**
305
+ * Gets or sets the tooltip manager used to display tooltips.
306
+ * @type {String|null}
307
+ */
308
+ this.tooltipManagerId = null;
309
+
310
+ /**
311
+ * Gets or sets the id of the tooltip to show.
312
+ * @type {String|null}
313
+ */
314
+ this.tooltipId = null;
315
+
316
+ /**
317
+ * Gets or sets the id of the expand button from which the settings are cloned.
318
+ * @type {String|null}
319
+ */
320
+ this.expandButtonId = null;
321
+
322
+ /**
323
+ * Gets or sets the id of the clear button from which the settings are cloned.
324
+ * @type {String|null}
325
+ */
326
+ this.clearButtonId = null;
327
+
328
+ /**
329
+ * Gets or sets the id of the tag button from which the settings are cloned.
330
+ * @type {String|null}
331
+ */
332
+ this.tagButtonId = null;
333
+
334
+ /**
335
+ * Gets or sets the id of the list box from which the settings are cloned.
336
+ * @type {String|null}
337
+ */
338
+ this.listBoxId = null;
339
+
340
+ /**
341
+ * Gets or sets the id of the list datapager from which the settings are cloned.
342
+ * @type {String|null}
343
+ */
344
+ this.dataPagerId = null;
345
+
346
+ /**
347
+ * Gets or sets or sets the id of the HTML hidden input.
348
+ * @type {String|null}
349
+ */
350
+ this.hiddenInputId = null;
351
+
352
+
353
+ /**
354
+ * @class
355
+ * @augments componyx.UI.base.Events
356
+ * @memberof componyx.UI.ComboBox
357
+ * @property {componyx.UI.base.Event} onFocus - Event which fires when the combobox is focused. @see {@link componyx.UI.base.EventArgs}
358
+ * @property {componyx.UI.base.Event} onBlur - Event which fires when the combobox is blurred. @see {@link componyx.UI.base.EventArgs}
359
+ * @property {componyx.UI.base.Event} onInputFocus - Event which fires on the focus event of the input textbox. @see {@link componyx.UI.ComboBox.ComboBoxItemEventArgs}
360
+ * @property {componyx.UI.base.Event} onInputBlur - Event which fires on the blur event of the input textbox. @see {@link componyx.UI.ComboBox.ComboBoxItemEventArgs}
361
+ * @property {componyx.UI.base.Event} onItemClick - Event which fires on an item click. @see {@link componyx.UI.ComboBox.ComboBoxItemEventArgs}
362
+ * @property {componyx.UI.base.Event} onItemSelect - Event which fires on an item select. @see {@link componyx.UI.ComboBox.ComboBoxItemEventArgs}
363
+ * @property {componyx.UI.base.Event} onItemDeselect - Event which fires on an item deselect. @see {@link componyx.UI.ComboBox.ComboBoxItemEventArgs}
364
+ * @property {componyx.UI.base.Event} onClear - Event which fires when the clear button is clicked. @see {@link componyx.UI.ComboBox.ComboBoxEventArgs}
365
+ * @property {componyx.UI.base.Event} onPreLoadItemList - Event which fires before the item-list data is loaded. @see {@link componyx.UI.ComboBox.ComboBoxQueryEventArgs}
366
+ * @property {componyx.UI.base.Event} onPostLoadItemList - Event which fires when the item-list data is loaded. @see {@link componyx.UI.ComboBox.ComboBoxEventArgs}
367
+ * @property {componyx.UI.base.Event} onPostRenderItemList - Event which fires when the item-list is rendered. @see {@link componyx.UI.ComboBox.ComboBoxEventArgs}
368
+ * @property {componyx.UI.base.Event} onPreRenderItem - Event which fires when an item is rendered. @see {@link componyx.UI.ComboBox.ComboBoxItemEventArgs}
369
+ * @property {componyx.UI.base.Event} onPostRenderItem - Event which fires when an item is rendered. @see {@link componyx.UI.ComboBox.ComboBoxItemEventArgs}
370
+ * @see {@link componyx.UI.base.Events}
371
+ */
372
+ function ComboBoxEvents(events)
373
+ {
374
+ Object.assign(this, events);
375
+
376
+ this.onFocus = $base.static.createEvent('onFocus');
377
+ this.onBlur = $base.static.createEvent('onBlur');
378
+ this.onInputFocus = $base.static.createEvent('onInputFocus');
379
+ this.onInputBlur = $base.static.createEvent('onInputBlur');
380
+ this.onItemClick = $base.static.createEvent('onItemClick');
381
+ this.onItemSelect = $base.static.createEvent('onItemSelect');
382
+ this.onItemDeselect = $base.static.createEvent('onItemDeselect');
383
+ this.onClear = $base.static.createEvent('onClear');
384
+ this.onPreLoadItemList = $base.static.createEvent('onPreLoadItemList');
385
+ this.onPostLoadItemList = $base.static.createEvent('onPostLoadItemList');
386
+ this.onPostRenderItemList = $base.static.createEvent('onPostRenderItemList');
387
+ this.onPreRenderItem = $base.static.createEvent('onPreRenderItem');
388
+ this.onPostRenderItem = $base.static.createEvent('onPostRenderItem');
389
+ }
390
+ /**
391
+ * ComboBox events
392
+ * @type {componyx.UI.ComboBox.ComboBoxEvents}
393
+ */
394
+ this.events = new ComboBoxEvents(this.events);
395
+
396
+
397
+ /**
398
+ * @typedef {Object} componyx.UI.ComboBox.ComboBoxEventArgs
399
+ * @property {componyx.UI.ComboBox} ComboBox - The ComboBox instance.
400
+ * @property {null} eventArgs - Not used, always null.
401
+ */
402
+
403
+ /**
404
+ * @typedef {Object} componyx.UI.ComboBox.ComboBoxItemEventArgs
405
+ * @property {componyx.UI.ComboBox} ComboBox - The ComboBox instance.
406
+ * @property {Object} eventArgs - The event object containing more detailed information about the event.
407
+ * @property {componyx.UI.ComboBox.Item|null} eventArgs.item - The combobox item, null for the input focus/blur events.
408
+ * @property {Event} eventArgs.event - The original event object.
409
+ */
410
+
411
+ /**
412
+ * @typedef {Object} componyx.UI.ComboBox.ComboBoxQueryEventArgs
413
+ * @property {componyx.UI.ComboBox} ComboBox - The ComboBox instance.
414
+ * @property {Object} eventArgs - The load query.
415
+ * @property {string} eventArgs.text - The search text.
416
+ * @property {number} eventArgs.pageIndex - The page index (1-based).
417
+ */
418
+
419
+ // inherit base instance members
420
+ $base.Component.apply(this, [id, properties]);
421
+
422
+ /**
423
+ * Sets the header template.
424
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content HTML string or element node as content. Pass null or empty string to remove the existing template.
425
+ * @see {@link componyx.UI.base.addTemplate}
426
+ */
427
+ this.setHeaderTemplate = function (content)
428
+ {
429
+ _instance.addTemplate('Header', content, false);
430
+ };
431
+
432
+ /**
433
+ * Sets the footer template.
434
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content HTML string or element node as content. Pass null or empty string to remove the existing template.
435
+ * @see {@link componyx.UI.base.addTemplate}
436
+ */
437
+ this.setFooterTemplate = function (content)
438
+ {
439
+ _instance.addTemplate('Footer', content, false);
440
+ };
441
+
442
+ /**
443
+ * Sets the select all checkbox template. The template supports the below listed interpolations.
444
+ * - {checkBox} This value will be replaced with the checkbox element to select all items.
445
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content HTML string or element node as content. Pass null or empty string to remove the existing template.
446
+ * @see {@link componyx.UI.base.addTemplate}
447
+ */
448
+ this.setSelectAllTemplate = function (content)
449
+ {
450
+ _instance.addTemplate('SelectAll', content, true);
451
+ };
452
+
453
+ /**
454
+ * Sets the multiselect input template. The template supports the below listed interpolations. Default value: {count} items selected
455
+ * - {count} This value will be replaced with the selected item count.
456
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content HTML string or element node as content. Pass null or empty string to remove the existing template.
457
+ * @see {@link componyx.UI.base.addTemplate}
458
+ */
459
+ this.setMultiSelectInputTemplate = function (content)
460
+ {
461
+ _instance.addTemplate('MultiSelectInput', content, true);
462
+ };
463
+
464
+ /**
465
+ * Sets the preloader template.
466
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content HTML string or element node as content. Pass null or empty string to remove the existing template.
467
+ * @see {@link componyx.UI.base.addTemplate}
468
+ */
469
+ this.setPreloaderTemplate = function (content)
470
+ {
471
+ _instance.addTemplate('Preloader', content, true);
472
+ };
473
+
474
+ /**
475
+ * Sets the no result template.
476
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content Text string. Pass null or empty string to remove the existing template.
477
+ * @see {@link componyx.UI.base.addTemplate}
478
+ */
479
+ this.setNoResultTemplate = function (content)
480
+ {
481
+ _instance.addTemplate('NoResult', content, true);
482
+ };
483
+
484
+ /**
485
+ * Sets the multi-select item tag template. The template supports all data-item interpolations (view Base method comment). Default value: {text}.
486
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content HTML string or element node as content. Pass null or empty string to remove the existing template.
487
+ * @see {@link componyx.UI.base.addTemplate}
488
+ */
489
+ this.setItemTagTemplate = function (content)
490
+ {
491
+ _instance.addTemplate('ItemTag', content, true);
492
+ };
493
+
494
+ /**
495
+ * Adds (or removes) an item template. The template supports the below listed interpolations and all data-item interpolations (view Base method comment). Default value: {checkBox}{icon}{text}
496
+ * - {checkBox} This value will be replaced with the checkbox element to select the item when multiSelect is enabled.
497
+ * - {icon} This value will be replaced with the icon of the item when item.hasIcon is set to true.
498
+ * @see {@link componyx.UI.base.methods#addTemplate}
499
+ * @function
500
+ */
501
+
502
+ /**
503
+ * Sets the placeholder text.
504
+ * @param {String} text The placeholder text.
505
+ */
506
+ this.setPlaceholder = function (text)
507
+ {
508
+ _input.placeholder = text;
509
+ _instance.placeholder = text;
510
+ };
511
+
512
+ /**
513
+ * Selects/deselects the item with the specified id.
514
+ * @param {String} id The item identifier.
515
+ */
516
+ this.toggleSelectItem = function (id)
517
+ {
518
+ _forceSelect = true;
519
+ toggleSelectItem(id);
520
+ };
521
+
522
+ /**
523
+ * Selects the items with the specified id.
524
+ * @param {Array} ids The list of item ids.
525
+ */
526
+ this.selectItems = function (ids)
527
+ {
528
+ for (var index = 0; index < ids.length; ++index)
529
+ {
530
+ _instance.selectItem(ids[index]);
531
+ }
532
+ };
533
+
534
+ /**
535
+ * Deselects the items with the specified id.
536
+ * @param {Array} ids The list of item ids.
537
+ */
538
+ this.deselectItems = function (ids)
539
+ {
540
+ if ($lib.isEmpty(ids))
541
+ return;
542
+
543
+ for (var index = 0; index < ids.length; ++index)
544
+ {
545
+ deselectItem(ids[index]);
546
+ }
547
+ };
548
+
549
+ /**
550
+ * Selects the item with the specified id.
551
+ * @param {String} id The item identifier.
552
+ */
553
+ this.selectItem = function (id)
554
+ {
555
+ _forceSelect = true;
556
+ selectItem(id);
557
+ };
558
+
559
+ /**
560
+ * Deselects the item with the specified id.
561
+ * @param {String} id The item identifier.
562
+ */
563
+ this.deselectItem = function (id)
564
+ {
565
+ deselectItem(id);
566
+ };
567
+
568
+ /**
569
+ * Enables the item with the specified id.
570
+ * @param {String} id The item identifier.
571
+ */
572
+ this.enableItem = function (id)
573
+ {
574
+ enableItem(id);
575
+ };
576
+
577
+ /**
578
+ * Disables the item with the specified id.
579
+ * @param {String} id The item identifier.
580
+ */
581
+ this.disableItem = function (id)
582
+ {
583
+ disableItem(id);
584
+ };
585
+
586
+ /**
587
+ * Gets the list-item element for the specified item id.
588
+ * @param {String} id The item identifier.
589
+ * @returns {HTMLElement} The list item element.
590
+ */
591
+ this.getItemElement = function (id)
592
+ {
593
+ return _elements[id];
594
+ };
595
+
596
+ /**
597
+ * Gets the box component which serves as item list container.
598
+ * @returns {Box} The Box component.
599
+ */
600
+ this.getListBox = function ()
601
+ {
602
+ return _listBox;
603
+ };
604
+
605
+ /**
606
+ * Shows the listbox.
607
+ */
608
+ this.showListBox = function ()
609
+ {
610
+ _listBox.show();
611
+ };
612
+
613
+ /**
614
+ * Hides the listbox.
615
+ */
616
+ this.hideListBox = function ()
617
+ {
618
+ _listBox.hide();
619
+ };
620
+
621
+ /**
622
+ * Gets the selected item.
623
+ * @returns {Item} The selected item.
624
+ */
625
+ this.getSelectedItem = function ()
626
+ {
627
+ for (const id in _selectedItems)
628
+ {
629
+ return _selectedItems[id];
630
+ }
631
+ return null;
632
+ };
633
+
634
+ /**
635
+ * Gets the selected items in a multiselect combobox.
636
+ * @returns {Item[]} The selected items.
637
+ */
638
+ this.getSelectedItems = function ()
639
+ {
640
+ if (!_instance.multiSelect)
641
+ return this.getSelectedItem();
642
+
643
+ var items = [];
644
+
645
+ for (var id in _selectedItems)
646
+ {
647
+ items.push(_selectedItems[id]);
648
+ }
649
+
650
+ return items;
651
+ };
652
+
653
+ /**
654
+ * Gets the selected value.
655
+ * @returns {String} The selected value;
656
+ */
657
+ this.getValue = function ()
658
+ {
659
+ if (!_instance.multiSelect && _instance.allowCustomValue && _input.value !== _hidden.value)
660
+ commitInputValue(); // make sure we commit when there is a pending custom value
661
+
662
+ return _hidden.value;
663
+ };
664
+
665
+ /**
666
+ * Clears the input value and the selected item(s).
667
+ */
668
+ this.clear = function ()
669
+ {
670
+ clear();
671
+ };
672
+
673
+ /**
674
+ * Clears the selected item(s).
675
+ */
676
+ this.clearSelection = function ()
677
+ {
678
+ clearSelection();
679
+ };
680
+
681
+ /**
682
+ * Clears the input.
683
+ */
684
+ this.clearInput = function ()
685
+ {
686
+ clearInput();
687
+ };
688
+
689
+ /**
690
+ * Clears the item list.
691
+ */
692
+ this.clearList = function ()
693
+ {
694
+ clearList();
695
+ };
696
+
697
+ /**
698
+ * Gets the input element.
699
+ * @returns {HTMLElement} The input element.
700
+ */
701
+ this.getInput = function ()
702
+ {
703
+ return _input;
704
+ };
705
+
706
+ /**
707
+ * Disables the combo-box
708
+ */
709
+ this.disable = function ()
710
+ {
711
+ _instance.disabled = true;
712
+
713
+ if (_instance.renderState < $base.static.RenderState.RENDERED)
714
+ return;
715
+
716
+ _input.disabled = true;
717
+ $lib.addClass(_instance.element, _classOption.DISABLED);
718
+ _listBox.hide(true);
719
+ _expandButton.disable();
720
+
721
+ if (_clearButton)
722
+ _clearButton.disable();
723
+ };
724
+
725
+ /**
726
+ * Enables the combo-box
727
+ */
728
+ this.enable = function ()
729
+ {
730
+ _instance.disabled = false;
731
+
732
+ if (_instance.renderState < $base.static.RenderState.RENDERED)
733
+ return;
734
+
735
+ _input.disabled = false;
736
+ $lib.removeClass(_instance.element, _classOption.DISABLED);
737
+ _expandButton.enable();
738
+
739
+ if (_clearButton)
740
+ _clearButton.enable();
741
+ };
742
+
743
+ /**
744
+ * Sets the input to the specified value. With multi-select enabled, a comma separated list of item values can be specified.
745
+ * @param {String|String[]} value The value(s) to set.
746
+ * @param {Boolean} [focus] A value indicating if the input should get focus.
747
+ */
748
+ this.setValue = function (value, focus)
749
+ {
750
+ if (!_instance.itemList)
751
+ {
752
+ _instance.value = value;
753
+ _initialValue = true;
754
+ return;
755
+ }
756
+
757
+ var selectedItems = _instance.getSelectedItems();
758
+
759
+ if (!$lib.isEmpty(selectedItems))
760
+ {
761
+ if (!$.isArray(selectedItems))
762
+ selectedItems = [selectedItems];
763
+
764
+ var result = [];
765
+ $lib.each(selectedItems, function (item) { result.push(item.id); });
766
+ _instance.deselectItems(result);
767
+ }
768
+
769
+ if (!$lib.isEmpty(value))
770
+ {
771
+ var values = value.split(',');
772
+
773
+ $lib.each(values, function (value)
774
+ {
775
+ var item = _instance.itemList.getByValue(value);
776
+
777
+ if (item)
778
+ _instance.selectItem(item.id);
779
+ });
780
+ }
781
+
782
+ if (focus)
783
+ setFocus();
784
+ };
785
+
786
+ /**
787
+ * Sets the focus on the input element.
788
+ */
789
+ this.focus = function ()
790
+ {
791
+ setFocus();
792
+ };
793
+
794
+ /**
795
+ * Triggers a data load.
796
+ * @param {Boolean} [clear] Defines if the current selection and input value should be cleared.
797
+ * @param {Number} [pageIndex] Defines which page index to load.
798
+ * @param {Boolean} [showListBox=true] Defines if the list box is shown.
799
+ */
800
+ this.load = function (clear, pageIndex, showListBox)
801
+ {
802
+ if (clear)
803
+ {
804
+ clearSelection();
805
+ clearInput();
806
+ clearList();
807
+ }
808
+
809
+ _lastQuery = null;
810
+ load(pageIndex, showListBox, false);
811
+ };
812
+
813
+ /**
814
+ * Renders the component.
815
+ */
816
+ this.render = function ()
817
+ {
818
+ if (_instance.renderState != $base.static.RenderState.RENDERING)
819
+ {
820
+ // call base render and return
821
+ $base.methods.render.call(_instance, preRender, 'combo-box');
822
+ return;
823
+ }
824
+
825
+ // render logic after loading resources
826
+ // create default templates
827
+ if (!_instance.hasTemplate('Default'))
828
+ _instance.addTemplate('Default', '{checkBox}{icon}{text}', true);
829
+
830
+ if (!_instance.hasTemplate('MultiSelectInput'))
831
+ _instance.addTemplate('MultiSelectInput', '{count} items selected', true);
832
+
833
+ draw();
834
+ };
835
+
836
+ /**
837
+ * Executes the post render procedure.
838
+ */
839
+ this.postRender = function ()
840
+ {
841
+ if (_instance.renderState == $base.static.RenderState.RENDERED)
842
+ return;
843
+
844
+ // disable focusable command button because the text input should get focus instead
845
+ _expandButton.getCommandButton().removeAttribute('tabindex');
846
+
847
+ if (_expandButton.split)
848
+ _expandButton.getExpandButton().removeAttribute('tabindex');
849
+
850
+ toggleClearButton();
851
+ bindInputEvents();
852
+ autoGrow();
853
+
854
+ if (!$base.methods.postRender.call(_instance)) // component got destroyed on postrender event
855
+ return;
856
+
857
+ if (_instance.itemList)
858
+ dataLoaded();
859
+ else if (_instance.loadOnRender)
860
+ load(null, false, true);
861
+ };
862
+
863
+ /**
864
+ * Destroys the component.
865
+ * @see {@link componyx.UI.base.methods#destroy}
866
+ */
867
+ this.destroy = function (...args)
868
+ {
869
+ dispose();
870
+ $base.methods.destroy.call(this, ...args);
871
+ };
872
+
873
+ function preRender()
874
+ {
875
+ // initialize script and css
876
+ var script = ['Box', 'Button'];
877
+
878
+ if (_instance.enableDataPager)
879
+ script.push('DataPager');
880
+
881
+ return ['ComboBox', script];
882
+ }
883
+
884
+ function setListBoxMinWidth()
885
+ {
886
+ var el = _listBox.element,
887
+ devSize = $lib.borderAndPadding(el),
888
+ r = /min-width:[^;]*(;|$)/gi,
889
+ pos = el.style.position,
890
+ important = el.style.getPropertyPriority('position');
891
+
892
+ if (pos && important == 'important')
893
+ pos += ' !' + important;
894
+
895
+ el.style.position = "";
896
+ var width = _expandButton.element.offsetWidth - devSize.width;
897
+ el.style.position = pos;
898
+
899
+ if (_listBox.style.match(r))
900
+ _listBox.style = _listBox.style.replace(r, $lib.format('min-width:{0}px;', (width > 0) ? width : 0));
901
+ else
902
+ {
903
+ if (_listBox.style && !$lib.endsWith(_listBox.style, ';'))
904
+ _listBox.style += ';';
905
+
906
+ _listBox.style += $lib.format('min-width:{0}px;', (width > 0) ? width : 0);
907
+ }
908
+ }
909
+
910
+ function bindInputEvents()
911
+ {
912
+ var input = _input;
913
+
914
+ $lib.on(input, 'focus', inputFocus, input);
915
+ $lib.on(input, 'focus', _instance.onFocus, _instance);
916
+ $lib.on(input, 'blur', inputBlur, input);
917
+ $lib.on(input, 'blur', _instance.onBlur, _instance);
918
+ $lib.on(input, 'keydown', inputKeyDown, input);
919
+ $lib.on(input, 'input', inputChanged, input);
920
+
921
+ if (_instance.tooltipManagerId && _instance.tooltipId)
922
+ {
923
+ $UI.store[_instance.tooltipManagerId].addTrigger(input, _instance.tooltipId);
924
+ }
925
+ }
926
+
927
+ function load(pageIndex, showListBox, initialLoad, onDemand)
928
+ {
929
+ var input = _input,
930
+ value = input.value || _charValue || '',
931
+ charStart, query = null;
932
+
933
+ showListBox = (showListBox === false) ? false : true;
934
+
935
+ query =
936
+ {
937
+ text: (!pageIndex) ? value : (_lastQuery) ? _lastQuery.text : '',
938
+ pageIndex: pageIndex || 1
939
+ };
940
+
941
+ _instance.events.onPreLoadItemList.fire(_instance, query);
942
+ charStart = _instance.loadOnDemandCharStart;
943
+
944
+ if (!initialLoad && (!pageIndex && ((onDemand && charStart > 0 && value.length < charStart) || (_lastQuery && _lastQuery.text == value))))
945
+ return;
946
+
947
+ clearTimeout(_loadTimerId);
948
+ _loadTimerId = null;
949
+ _selectedItemId = _focusedItemId = null;
950
+ _lastQuery = query;
951
+ _loading = true;
952
+ _charValue = '';
953
+
954
+ if (_pager)
955
+ _pager.hide();
956
+
957
+ if (!_instance.keepSelectionOnReload)
958
+ clearSelection();
959
+
960
+ if (_instance.ajax.load && _instance.ajax.load.isDefined())
961
+ {
962
+ if (_ajax)
963
+ _ajax.abort();
964
+
965
+ showPreloader();
966
+ _ajax = _instance.ajaxCall('load', window.JSON.stringify(query), { onSuccess: function (args) { dataLoaded(pageIndex || -1, args, showListBox, onDemand); } });
967
+ }
968
+ else
969
+ dataLoaded(null, null, showListBox, onDemand);
970
+ }
971
+
972
+ function dataLoaded(pageIndex, ajaxArgs, showListBox, onDemand)
973
+ {
974
+ var ajaxResult = null;
975
+
976
+ _loading = false;
977
+ _onDemand = onDemand || false;
978
+
979
+ if (ajaxArgs)
980
+ {
981
+ _instance.itemList = [];
982
+
983
+ if (ajaxArgs.data)
984
+ {
985
+ ajaxResult = (typeof ajaxArgs.data === 'string') ? window.JSON.parse(ajaxArgs.data) : ajaxArgs.data;
986
+ _instance.itemList = (ajaxResult) ? ajaxResult.itemList || [] : [];
987
+ }
988
+ }
989
+ else if (_instance.itemList)
990
+ _instance.itemList = (typeof _instance.itemList === 'string') ? window.JSON.parse(_instance.itemList) : _instance.itemList || [];
991
+
992
+ setupItemList();
993
+ setupPager(ajaxResult, pageIndex);
994
+ _instance.events.onPostLoadItemList.fire(_instance, null);
995
+
996
+ if (_instance.itemList.length > 0)
997
+ {
998
+ drawItemList(ajaxResult, onDemand);
999
+
1000
+ if (!_instance.loadOnDemand && _keyCode)
1001
+ navigate();
1002
+ }
1003
+ else
1004
+ showNoResult();
1005
+
1006
+ if (!onDemand)
1007
+ setMultiSelectValue();
1008
+
1009
+ _onDemand = false;
1010
+ _initialValue = false;
1011
+
1012
+ if (!_instance.itemList.length && !getList()?.childNodes.length)
1013
+ _listBox.hide(); // no point in showing empty list
1014
+ else
1015
+ _listBox.update(null, showListBox);
1016
+
1017
+ if (_pendingCustomValue)
1018
+ {
1019
+ let value = _pendingCustomValue;
1020
+ _pendingCustomValue = null;
1021
+ addCustomValue(value);
1022
+ }
1023
+
1024
+ _instance.events.onPostRenderItemList.fire(_instance, null);
1025
+ }
1026
+
1027
+ function setupItemList()
1028
+ {
1029
+ if (!_instance.itemList)
1030
+ _instance.itemList = [];
1031
+
1032
+ if (!_instance.itemList.getByValue)
1033
+ $base.static.ItemList.call(_instance.itemList);
1034
+ }
1035
+
1036
+ function setupPager(ajaxResult, pageIndex)
1037
+ {
1038
+ if (_pager && ajaxResult && ajaxResult.totalItemCount && ajaxResult.totalItemCount > ajaxResult.itemList.length)
1039
+ {
1040
+ _pager.itemCount = ajaxResult.totalItemCount;
1041
+
1042
+ if (pageIndex == -1)
1043
+ _pager.setPageIndex(1);
1044
+ else
1045
+ _pager.setPageIndex(pageIndex);
1046
+
1047
+ _pager.show();
1048
+ }
1049
+ else if (_pager)
1050
+ _pager.hide();
1051
+ }
1052
+
1053
+ function draw()
1054
+ {
1055
+ if (_instance.itemList && _instance.itemList.length == 0)
1056
+ _instance.itemList = null;
1057
+
1058
+ if (_instance.multiSelect)
1059
+ $lib.addClass(_instance.element, _classOption.MULTISELECT);
1060
+
1061
+ if (_instance.allowInput)
1062
+ $lib.addClass(_instance.element, _classOption.ALLOWINPUT);
1063
+
1064
+ if (tagging())
1065
+ $lib.addClass(_instance.element, _classOption.TAGGING);
1066
+
1067
+ if (_instance.autoGrow)
1068
+ $lib.addClass(_instance.element, _classOption.GROW);
1069
+
1070
+ if (_instance.disabled)
1071
+ $lib.addClass(_instance.element, _classOption.DISABLED);
1072
+
1073
+ if (!$lib.isEmpty(_instance.width))
1074
+ _instance.element.style.width = $lib.unit(_instance.width);
1075
+
1076
+ createExpandButton();
1077
+ createListBox();
1078
+ _hidden = _instance.createSyncedInput(_instance.hiddenInputId, function ()
1079
+ {
1080
+ _instance.setValue(this.value);
1081
+ });
1082
+
1083
+ _sizer = $lib.element(_instance.element);
1084
+ _sizer.className = _classOption.SIZER;
1085
+ _sizer.style.display = 'none';
1086
+
1087
+ _instance.value = _instance.value || _hidden.value;
1088
+
1089
+ if (!$lib.isEmpty(_instance.value))
1090
+ {
1091
+ _initialValue = true;
1092
+ _hidden.__setValue(_instance.value);
1093
+ }
1094
+
1095
+ _instance.renderChildren();
1096
+ }
1097
+
1098
+ function createExpandButton()
1099
+ {
1100
+ var id = _instance.id + '_Expand';
1101
+ _expandButton = $UI.createComponent(componyx.UI.Button, { id: id, containerElement: _instance.element });
1102
+
1103
+ _expandButton.transparentBorder = _expandButton.primary = false;
1104
+ _expandButton.clone($UI.store[_instance.expandButtonId], _instance);
1105
+
1106
+ _expandButton.showing = true;
1107
+ _expandButton.textSelection = true;
1108
+ _expandButton.split = _instance.splitButton;
1109
+ _expandButton.cssClass = _expandButton.cssClass || _instance.cssClassExpandButton || _classOption.EXPANDBUTTON;
1110
+ _expandButton.boxId = (_expandButton.split) ? _instance.id + '_Box' : null;
1111
+ _expandButton.setContentTemplate(createContent());
1112
+ _expandButton.events.onPostRender.priorityAdd(() => { _instance.isReady.apply(_instance); }, null);
1113
+ _expandButton.disabled = _instance.disabled;
1114
+ _expandButton.delegateFocusEvents(_instance);
1115
+
1116
+ if (!_expandButton.split)
1117
+ {
1118
+ _expandButton.events.onPointerDown.priorityAdd(function () { _allowHide = false; });
1119
+
1120
+ _expandButton.command = function ()
1121
+ {
1122
+ _allowHide = true;
1123
+
1124
+ if (_clearButtonClicked)
1125
+ {
1126
+ _clearButtonClicked = false;
1127
+ _expandButton.deselect();
1128
+ return;
1129
+ }
1130
+
1131
+ if (_instance.disableExpandOnClick)
1132
+ {
1133
+ _expandButton.deselect();
1134
+ return;
1135
+ }
1136
+
1137
+ if ($lib.event.type != 'keydown' || $lib.event.key != ' ')
1138
+ _listBox.toggle();
1139
+ };
1140
+ }
1141
+ else
1142
+ {
1143
+ _expandButton.events.onCommandPointerDown.priorityAdd(function () { if (_listBox.showing) { _allowHide = false; } });
1144
+ }
1145
+ }
1146
+
1147
+ function createContent()
1148
+ {
1149
+ var arrContent = [], spanIcon, div;
1150
+
1151
+ if (_instance.splitButton)
1152
+ {
1153
+ arrContent.push(createInput());
1154
+ }
1155
+ else
1156
+ {
1157
+ spanIcon = document.createElement('span');
1158
+ spanIcon.className = _instance.cssClassExpandIcon || _classOption.EXPANDICON;
1159
+ arrContent.push(createInput());
1160
+ arrContent.push(spanIcon);
1161
+ }
1162
+
1163
+ if (!_instance.disableClearButton)
1164
+ {
1165
+ div = _instance.element.appendChild(document.createElement('div'));
1166
+ createClearButton(div);
1167
+ arrContent.push(_clearButton.containerElement);
1168
+ }
1169
+
1170
+ return arrContent;
1171
+ }
1172
+
1173
+ function createClearButton(container)
1174
+ {
1175
+ var id = _instance.id + '_Clear';
1176
+ _clearButton = $UI.createComponent(componyx.UI.Button, { id: id, containerElement: container });
1177
+
1178
+ _clearButton.clone($UI.store[_instance.clearButtonId], _instance);
1179
+ _clearButton.hasIcon = true;
1180
+ _clearButton.transparent = true;
1181
+ _clearButton.cssClass = _clearButton.cssClass || _instance.cssClassClearButton || _classOption.CLEARBUTTON;
1182
+ _clearButton.command = clearCommand;
1183
+ _clearButton.disabled = _instance.disabled;
1184
+ _clearButton.delegateFocusEvents(_instance);
1185
+ _clearButton.events.onPostRender.priorityAdd(() => { _instance.isReady.apply(_instance); }, null);
1186
+ _clearButton.events.onPostRender.priorityAdd(() => { _instance.isReady.apply(_instance); }, null);
1187
+ _clearButton.showing = true;
1188
+ }
1189
+
1190
+ function createInput()
1191
+ {
1192
+ _input = document.createElement('input');
1193
+
1194
+ _input.className = _input.style.cssText = '';
1195
+ _input.type = 'text';
1196
+ _input.autoComplete = 'off';
1197
+ _input.spellcheck = false;
1198
+ _input.setAttribute('autocomplete', 'off');
1199
+ _input.setAttribute('spellcheck', 'false');
1200
+ _input.placeholder = _instance.placeholder;
1201
+
1202
+ if (_instance.disabled)
1203
+ _input.disabled = true;
1204
+
1205
+ if (!_instance.allowInput)
1206
+ _input.readOnly = true;
1207
+
1208
+ if (_instance.value)
1209
+ _input.value = _instance.value;
1210
+
1211
+ return _input;
1212
+ }
1213
+
1214
+ function createListBox()
1215
+ {
1216
+ var id = _instance.id + '_Box',
1217
+ box = $UI.createComponent(componyx.UI.Box, { id: id, containerElement: _instance.element }),
1218
+ divContainer = document.createElement('div'),
1219
+ divHeader = document.createElement('div'),
1220
+ divFooter = document.createElement('div'),
1221
+ ul = document.createElement('ul');
1222
+
1223
+ _listBox = box;
1224
+ box.clone($UI.store[_instance.listBoxId], _instance);
1225
+ ul.className = _instance.cssClassList || _classOption.LIST;
1226
+
1227
+ if (_instance.hasTemplate('Header') || _instance.hasTemplate('Footer') || _instance.enableDataPager)
1228
+ {
1229
+ if (_instance.hasTemplate('Header'))
1230
+ {
1231
+ _instance.applyTemplate(divHeader, 'Header');
1232
+ divHeader.className = _instance.cssClassHeader || _classOption.BOXHEADER;
1233
+ divContainer.appendChild(divHeader);
1234
+ }
1235
+
1236
+ divContainer.appendChild(ul);
1237
+
1238
+ if (_instance.enableDataPager)
1239
+ createDataPager(divContainer);
1240
+
1241
+ if (_instance.hasTemplate('Footer'))
1242
+ {
1243
+ _instance.applyTemplate(divFooter, 'Footer');
1244
+ divFooter.className = _instance.cssClassFooter || _classOption.BOXFOOTER;
1245
+ divContainer.appendChild(divFooter);
1246
+ }
1247
+
1248
+ box.setContentTemplate(divContainer);
1249
+ }
1250
+ else
1251
+ box.setContentTemplate(ul);
1252
+
1253
+
1254
+ box.theme = $base.static.ThemeOption.NONE;
1255
+ box.cssClass = box.cssClass || _instance.cssClassListBox || _classOption.BOX;
1256
+ box.showing = false;
1257
+ box.hideOnOutsideClick = box.autoResizeFit = box.autoInvertFit = true;
1258
+ box.resizeToMaxHeight = false;
1259
+ box.expander = _expandButton.id;
1260
+ box.expandDirection = componyx.UI.Box.ExpandDirectionOption.DOWN;
1261
+ box.autoPosition = componyx.UI.Box.AutoPositionOption.EXPAND;
1262
+ box.events.onPostRender.priorityAdd(() => { _instance.isReady.apply(_instance); }, null);
1263
+ box.events.onPrePosition.priorityAdd(function (box)
1264
+ {
1265
+ $lib.removeClass(box.element, 'resized');
1266
+ getList().style.maxHeight = '';
1267
+ });
1268
+
1269
+ box.events.onAutoFit.priorityAdd(function (box, args)
1270
+ {
1271
+ if (!args.resizedY)
1272
+ return;
1273
+
1274
+ var ul = getList(), height = 0, el = ul.parentNode.firstChild;
1275
+
1276
+ $lib.addClass(box.element, 'resized');
1277
+
1278
+ while (el)
1279
+ {
1280
+ if (el != ul)
1281
+ height += el.offsetHeight;
1282
+
1283
+ el = el.nextSibling;
1284
+ }
1285
+
1286
+ el = ul;
1287
+ while (el != box.element.parentNode)
1288
+ {
1289
+ height += $lib.borderAndPadding(el).height;
1290
+ el = el.parentNode;
1291
+ }
1292
+
1293
+ height = (box.element.offsetHeight - height);
1294
+ ul.style.maxHeight = (height > 0) ? $lib.unit(height) : $lib.unit(0);
1295
+ }, null);
1296
+
1297
+ box.events.onHide.priorityAdd(function (box, args)
1298
+ {
1299
+ args.cancel = !_allowHide;
1300
+ _allowHide = true;
1301
+
1302
+ if (!_expandButton.split)
1303
+ _expandButton.deselect();
1304
+ });
1305
+
1306
+ box.events.onHideComplete.priorityAdd(function ()
1307
+ {
1308
+ if (_instance.element && _instance.element.parentNode)
1309
+ {
1310
+ if (!$lib.isEmpty(_focusedItemId))
1311
+ {
1312
+ $lib.removeClass(_elements[_focusedItemId], 'focus');
1313
+
1314
+ if (!$lib.isEmpty(_selectedItemId))
1315
+ $lib.addClass(_elements[_selectedItemId], 'selected');
1316
+ }
1317
+ }
1318
+
1319
+ commitInputValue();
1320
+ _focusedItemId = null;
1321
+ _keyCode = null;
1322
+ });
1323
+
1324
+ box.events.onShow.priorityAdd(function ()
1325
+ {
1326
+ setListBoxMinWidth();
1327
+ }, null);
1328
+
1329
+ box.events.onShowComplete.priorityAdd(function ()
1330
+ {
1331
+ if (!_instance.element)
1332
+ return;
1333
+
1334
+ setFocus();
1335
+
1336
+ if (_instance.loadOnDemand && (_instance.reloadOnExpand || $lib.isEmpty(_instance.itemList)))
1337
+ {
1338
+ if (_instance.reloadOnExpand)
1339
+ _lastQuery = null;
1340
+
1341
+ loadOnDemand(0);
1342
+ }
1343
+ else if (_keyCode)
1344
+ navigate();
1345
+ else if (!$lib.isEmpty(_selectedItemId) && !$.isEmpty(_elements))
1346
+ scrollToItem(_elements[_selectedItemId]);
1347
+ });
1348
+ }
1349
+
1350
+ function createDataPager(divContainer)
1351
+ {
1352
+ var id = _instance.id + '_Pager';
1353
+ _pager = $UI.createComponent(componyx.UI.DataPager, { id: id, containerElement: divContainer });
1354
+
1355
+ _pager.visiblePages = 0;
1356
+ _pager.pageSize = 25;
1357
+
1358
+ _pager.clone($UI.store[_instance.dataPagerId], _instance);
1359
+ _pager.cssClass = _pager.cssClass || _instance.cssClassDataPager || _classOption.DATAPAGER;
1360
+
1361
+ _pager.delegateFocusEvents(_instance);
1362
+ _pager.events.onPostRender.priorityAdd(() => { _instance.isReady.apply(_instance); }, null);
1363
+ _pager.events.onIndexChange.priorityAdd(pageIndexChange, null);
1364
+
1365
+ }
1366
+
1367
+ function pageIndexChange(pager, args)
1368
+ {
1369
+ load(args.pageIndex);
1370
+ }
1371
+
1372
+ function inputFocus(input, e)
1373
+ {
1374
+ $lib.addClass(_instance.element, 'focus');
1375
+
1376
+ if (_multiTemplateActive)
1377
+ input.value = '';
1378
+
1379
+ if (input.value && _instance.allowInput)
1380
+ input.select();
1381
+
1382
+ _instance.events.onInputFocus.fire(_instance, eventArgs(null));
1383
+ }
1384
+
1385
+ function inputBlur(input)
1386
+ {
1387
+ $lib.removeClass(_instance.element, 'focus');
1388
+
1389
+ if (!_listBox.showing)
1390
+ {
1391
+ commitInputValue();
1392
+ }
1393
+
1394
+ _instance.events.onInputBlur.fire(_instance, eventArgs(null));
1395
+ }
1396
+
1397
+ function commitInputValue()
1398
+ {
1399
+ const input = _input,
1400
+ selectedItem = _instance.getSelectedItem();
1401
+
1402
+ if (_instance.multiSelect)
1403
+ {
1404
+ setMultiSelectValue();
1405
+ }
1406
+ else if (selectedItem && input.value !== selectedItem.text)
1407
+ {
1408
+ if (_instance.allowCustomValue)
1409
+ {
1410
+ const value = input.value.trim();
1411
+ clearSelection();
1412
+ setInputValue(value);
1413
+ _hidden.__setValue(value); // Set custom input value as selected value
1414
+ }
1415
+ else
1416
+ input.value = selectedItem.text; // reset textual input to selected item text (is current selected value)
1417
+ }
1418
+ else if (!selectedItem)
1419
+ {
1420
+ if (_instance.allowCustomValue)
1421
+ _hidden.__setValue(input.value); // Set custom input value as selected value
1422
+ else
1423
+ $lib.fireEvent(_hidden, 'change'); // Fake change event otherwise there is no way to detect an invalid value was typed (validation, data-binding etc.)
1424
+ }
1425
+ }
1426
+
1427
+ function inputKeyDown(input, e)
1428
+ {
1429
+ var key = e.key;
1430
+
1431
+ autoGrow();
1432
+
1433
+ if (e.ctrlKey)
1434
+ return;
1435
+
1436
+ keyDownAction(key, e);
1437
+ toggleClearButton();
1438
+ }
1439
+
1440
+ function keyDownAction(key, e)
1441
+ {
1442
+ var updateKeys = ' Backspace Delete ',
1443
+ isNavigate = (key == 'ArrowUp' || key == 'ArrowDown'),
1444
+ hasItems = _instance.itemList && _instance.itemList.length > 0,
1445
+ isChar = false, char;
1446
+
1447
+ _keyCode = null;
1448
+
1449
+ if (!_instance.loadOnDemand)
1450
+ updateKeys = updateKeys.replace(' Backspace Delete', '');
1451
+
1452
+ if (key == 'Tab')
1453
+ {
1454
+ _allowHide = true;
1455
+ _listBox.hide();
1456
+ return;
1457
+ }
1458
+
1459
+ isChar = key.match(/\s|\w|[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/) != null || updateKeys.indexOf(key) > -1;
1460
+
1461
+ if (isChar && updateKeys.indexOf(' ' + key + ' ') == -1)
1462
+ char = key;
1463
+
1464
+ if (key == 'Enter' || (key == ' ' && !_instance.allowInput))
1465
+ {
1466
+ if (!$lib.isEmpty(_focusedItemId))
1467
+ {
1468
+ (_focusedItemId == _selectAllId) ? selectAll() : toggleSelectItem(_focusedItemId);
1469
+ }
1470
+ else if (_instance.allowInput && _instance.allowCustomValue && _instance.multiSelect)
1471
+ {
1472
+ const value = _input.value.trim();
1473
+ if (!$lib.isEmpty(value))
1474
+ {
1475
+ if (_loading || _loadTimerId)
1476
+ _pendingCustomValue = value; // itemList is stale mid-request, decide once fresh results arrive
1477
+ else
1478
+ addCustomValue(value);
1479
+ }
1480
+ }
1481
+
1482
+ if (!_instance.multiSelect)
1483
+ _listBox.hide();
1484
+
1485
+ e.preventDefault();
1486
+ return;
1487
+ }
1488
+
1489
+ if (isNavigate || (!_instance.loadOnDemand && isChar))
1490
+ {
1491
+ if (isNavigate)
1492
+ e.preventDefault();
1493
+
1494
+ if (_listBox.showing && hasItems)
1495
+ {
1496
+ if (navigate(key) === false)
1497
+ {
1498
+ e.preventDefault();
1499
+ return;
1500
+ }
1501
+ }
1502
+ else
1503
+ {
1504
+ _keyCode = key;
1505
+
1506
+ if (hasItems)
1507
+ _listBox.show();
1508
+ }
1509
+ }
1510
+ else if (_instance.loadOnDemand && isChar)
1511
+ {
1512
+ _charValue = '';
1513
+
1514
+ if (updateKeys.indexOf(' ' + key + ' ') == -1)
1515
+ _charValue = char;
1516
+
1517
+ loadOnDemand();
1518
+ }
1519
+
1520
+ autoGrow();
1521
+ }
1522
+ function inputChanged(input)
1523
+ {
1524
+ autoGrow();
1525
+ toggleClearButton();
1526
+
1527
+ if ($lib.isEmpty(input.value))
1528
+ {
1529
+ if (_selectedItemId)
1530
+ {
1531
+ deselectItem(_selectedItemId);
1532
+ }
1533
+ return;
1534
+ }
1535
+
1536
+ if (_instance.loadOnDemand)
1537
+ {
1538
+ loadOnDemand();
1539
+ }
1540
+ }
1541
+
1542
+ function autoGrow()
1543
+ {
1544
+ if (!_instance.autoGrow)
1545
+ return;
1546
+
1547
+ var value = ($lib.isEmpty(_input.value)) ? _instance.placeholder : _input.value;
1548
+
1549
+ _sizer.textContent = value.replace(/\s/g, '\xa0') + '\xa0\xa0\xa0\xa0';
1550
+ _sizer.style.display = 'inline-block';
1551
+ _input.style.width = $lib.unit(_sizer.offsetWidth);
1552
+ _sizer.style.display = 'none';
1553
+ }
1554
+
1555
+ function loadOnDemand(delay = null)
1556
+ {
1557
+ clearTimeout(_loadTimerId);
1558
+
1559
+ if (_loading)
1560
+ return;
1561
+
1562
+ _loadTimerId = setTimeout(function () { load(null, null, null, true); }, (!$.isEmpty(delay)) ? delay : _instance.loadOnDemandDelay);
1563
+ }
1564
+
1565
+ function navigate(keyCode)
1566
+ {
1567
+ if (!_instance.keyboardNavigation)
1568
+ return;
1569
+
1570
+ var input = _input, value,
1571
+ itemList = _instance.itemList,
1572
+ itemId = _focusedItemId || _selectedItemId,
1573
+ id = '', item = null, selectRange = false,
1574
+ selectAll = (_instance.multiSelect && _instance.hasTemplate('SelectAll'));
1575
+
1576
+ keyCode = (keyCode == undefined) ? _keyCode : keyCode; // active or cached keyCode
1577
+
1578
+ if (_instance.allowInput)
1579
+ {
1580
+ if (_keyCode == null)
1581
+ {
1582
+ const start = input.selectionStart, end = input.selectionEnd;
1583
+ const hasSelection = start !== end;
1584
+ if (hasSelection)
1585
+ value = input.value.substring(0, start) + keyCode + input.value.substring(end);
1586
+ else
1587
+ value = ((start > 0) ? input.value.substr(0, start) : input.value) + keyCode;
1588
+ }
1589
+ else
1590
+ value = input.value;
1591
+ }
1592
+ else
1593
+ value = keyCode;
1594
+
1595
+ _keyCode = null;
1596
+
1597
+ switch (keyCode)
1598
+ {
1599
+ case 'ArrowUp':
1600
+
1601
+ if (itemId == _selectAllId)
1602
+ id = itemList[itemList.length - 1].id;
1603
+ else if (!itemId || !(item = itemList.previous(itemId)))
1604
+ id = (selectAll) ? _selectAllId : itemList[itemList.length - 1].id;
1605
+ else
1606
+ id = item.id;
1607
+
1608
+ if (id == _selectAllId)
1609
+ {
1610
+ focusSelectAll();
1611
+ return;
1612
+ }
1613
+
1614
+ break;
1615
+
1616
+ case 'ArrowDown':
1617
+
1618
+ if (itemId == _selectAllId)
1619
+ id = itemList[0].id;
1620
+ else if (!itemId || !(item = itemList.next(itemId)))
1621
+ id = (selectAll) ? _selectAllId : itemList[0].id;
1622
+ else
1623
+ id = item.id;
1624
+
1625
+ if (id == _selectAllId)
1626
+ {
1627
+ focusSelectAll();
1628
+ return;
1629
+ }
1630
+
1631
+ break;
1632
+
1633
+ default:
1634
+
1635
+ itemId = (itemId != _selectAllId) ? itemId : '';
1636
+ item = _instance.itemList.find(value, (!_instance.allowInput) ? itemId : null);
1637
+
1638
+ if (item)
1639
+ {
1640
+ id = item.id;
1641
+
1642
+ if (_instance.allowInput)
1643
+ selectRange = true;
1644
+ }
1645
+
1646
+ break;
1647
+ }
1648
+
1649
+ if (!$lib.isEmpty(id))
1650
+ (_instance.multiSelect) ? focusItem(id, true) : selectItem(id, true);
1651
+ else if (!_instance.multiSelect && !$lib.isEmpty(_selectedItemId) && !_instance.allowCustomValue)
1652
+ deselectItem(_selectedItemId, false);
1653
+
1654
+ if (selectRange)
1655
+ $lib.selectTextRange(input, value.length);
1656
+
1657
+ return ($lib.isEmpty(id) || (_instance.multiSelect == true)); // do not accept key when item was selected
1658
+ }
1659
+
1660
+ function drawItemList(ajaxResult, onDemand)
1661
+ {
1662
+ var li = null, ul = getList(),
1663
+ value = ',' + _instance.value + ',',
1664
+ filter = (_instance.allowInput && ajaxResult && ajaxResult.filteredColumns && !$lib.isEmpty(_lastQuery) && !$lib.isEmpty(_lastQuery.text)) ? true : false,
1665
+ item = null, select = false;
1666
+
1667
+ _elements = {};
1668
+ ul.innerHTML = '';
1669
+
1670
+ if (_instance.multiSelect && _instance.hasTemplate('SelectAll'))
1671
+ {
1672
+ var values = {},
1673
+ checkBoxClass = _instance.cssClassItemCheckBox || _classOption.ITEMCHECKBOX;
1674
+
1675
+ values['checkBox'] = $lib.format('<span class="{0}"></span>', checkBoxClass);
1676
+ ul.appendChild(li = document.createElement('li'));
1677
+
1678
+ li.className = _instance.cssClassItemSelectAll || _classOption.ITEMSELECTALL;
1679
+ _instance.applyTemplate(li, _selectAllId, values);
1680
+
1681
+ $lib.on(li, 'click', selectAll);
1682
+ $lib.on(li, 'pointerenter', focusSelectAll);
1683
+
1684
+ _elements[_selectAllId] = li;
1685
+ }
1686
+
1687
+ if (ajaxResult && ajaxResult.filteredColumns)
1688
+ _columnRegEx = {};
1689
+
1690
+ for (var index = 0; index < _instance.itemList.length; ++index)
1691
+ {
1692
+ var itemOrg = _instance.itemList[index];
1693
+
1694
+ if ($lib.isEmpty(itemOrg.id))
1695
+ itemOrg.id = itemOrg.text.replace(/\s/g, '_');
1696
+
1697
+ itemOrg.value = ($lib.isEmpty(itemOrg.value)) ? itemOrg.id : itemOrg.value;
1698
+
1699
+ item = $lib.clone({}, itemOrg, true);
1700
+ item.text = $lib.encodeHTML(item.text);
1701
+
1702
+ if (filter)
1703
+ highlightMatch(item, ajaxResult);
1704
+
1705
+ li = drawItem(item, index);
1706
+
1707
+ if (item.selected || _selectedItems[item.id] || (_initialValue && value.indexOf(',' + item.value + ',') > -1))
1708
+ {
1709
+ _forceSelect = select = true;
1710
+ selectItem(item.id, true);
1711
+ }
1712
+ }
1713
+
1714
+ if (!_instance.multiSelect && select && !onDemand)
1715
+ _listBox.hide();
1716
+ }
1717
+
1718
+ function drawItem(item, index)
1719
+ {
1720
+ let ul = getList(),
1721
+ values = [],
1722
+ checkBoxClass, iconClass,
1723
+ li = document.createElement('li'), iconEl;
1724
+
1725
+ if (_elements[item.id])
1726
+ ul.replaceChild(li, _elements[item.id]);
1727
+ else
1728
+ ul.appendChild(li);
1729
+
1730
+ _elements[item.id] = li;
1731
+
1732
+ _instance.events.onPreRenderItem.fire(_instance, eventArgs(item));
1733
+ checkBoxClass = item.cssClassCheckBox || _instance.cssClassItemCheckBox || _classOption.ITEMCHECKBOX,
1734
+ iconClass = item.cssClassIcon || _instance.cssClassItemIcon || _classOption.ITEMICON,
1735
+ values[0] = {};
1736
+
1737
+ li.className = item.cssClass || _instance.cssClassItem || _classOption.ITEM;
1738
+
1739
+ if ((index != undefined && index % 2 != 0) || (index == undefined && $lib.indexOf(ul.childNodes, li) % 2 != 0))
1740
+ $lib.addClass(li, 'odd');
1741
+
1742
+ if (_instance.multiSelect)
1743
+ values[0]['checkBox'] = $lib.format('<span class="{0}"></span>', checkBoxClass);
1744
+
1745
+ if (item.hasIcon)
1746
+ values[0]['icon'] = $lib.format('<i class="{0}"></i>', iconClass);
1747
+
1748
+ values[1] = item;
1749
+
1750
+ if (item.templateId || _instance.itemTemplateId)
1751
+ _instance.applyTemplate(li, item.templateId || _instance.itemTemplateId, values);
1752
+ else
1753
+ _instance.applyTemplate(li, 'Default', values);
1754
+
1755
+ if ((iconEl = $lib(iconClass, li)[0]) && item.iconURL)
1756
+ iconEl.style.backgroundImage = 'url(' + item.iconURL + ')';
1757
+
1758
+ if (item.disabled)
1759
+ disableItem(item.id);
1760
+ else if (_instance.tooltipManagerId && item.tooltip)
1761
+ addTooltip(li, item);
1762
+
1763
+ bindItemEvents(li, item);
1764
+
1765
+ _instance.events.onPostRenderItem.fire(_instance, eventArgs(item));
1766
+ return li;
1767
+ }
1768
+
1769
+ function addTooltip(li, item)
1770
+ {
1771
+ const tooltipManager = $UI.store[_instance.tooltipManagerId],
1772
+ id = `${_instance.id}_${item.id}`;
1773
+
1774
+ tooltipManager.addTooltip(id, tooltip);
1775
+ tooltipManager.addTrigger(li, id);
1776
+ }
1777
+
1778
+ function bindItemEvents(li, item)
1779
+ {
1780
+ $lib.on(li, 'pointerenter', focusItem, [item.id, false]);
1781
+ $lib.on(li, 'click', function (itemId)
1782
+ {
1783
+ if (_instance.multiSelect)
1784
+ toggleSelectItem(itemId);
1785
+ else
1786
+ selectItem(itemId);
1787
+
1788
+ _instance.events.onItemClick.fire(_instance, eventArgs(_instance.itemList.get(itemId)));
1789
+ }, item.id, _instance);
1790
+ }
1791
+
1792
+ function highlightMatch(item, ajaxResult)
1793
+ {
1794
+ var match = '<b class="match">$1</b>';
1795
+
1796
+ $lib.each(ajaxResult.filteredColumns, function (column, key)
1797
+ {
1798
+ if (!_columnRegEx[key])
1799
+ _columnRegEx[key] = createRegEx(column.filter, column.value || _input.value);
1800
+
1801
+ if (item[key])
1802
+ item[key] = item[key].toString().replace(_columnRegEx[key], match);
1803
+ else if (item.attributes && item.attributes[key])
1804
+ item.attributes[key] = item.attributes[key].toString().replace(_columnRegEx[key], match);
1805
+ });
1806
+
1807
+ function createRegEx(filter, value)
1808
+ {
1809
+ value = $lib.escapeRegExp(value);
1810
+
1811
+ switch (filter)
1812
+ {
1813
+ case (_filterOption.STARTSWITH):
1814
+ return new RegExp('^(' + value + ')', 'gi');
1815
+ case (_filterOption.CONTAINS):
1816
+ return new RegExp('(' + value + ')', 'gi');
1817
+ case (_filterOption.EQUALS):
1818
+ return new RegExp('^(' + value + ')$', 'gi');
1819
+ case (_filterOption.ENDSWITH):
1820
+ return new RegExp('(' + value + ')$', 'gi');
1821
+ }
1822
+ }
1823
+ }
1824
+
1825
+ function showPreloader()
1826
+ {
1827
+ if (_instance.hasTemplate('Preloader'))
1828
+ {
1829
+ var li = document.createElement('li'),
1830
+ ul = getList();
1831
+ ul.innerHTML = '';
1832
+ ul.appendChild(li);
1833
+ li.className = _instance.cssClassPreloader || _classOption.PRELOADER;
1834
+ _instance.applyTemplate(li, 'Preloader');
1835
+ }
1836
+ }
1837
+
1838
+ function showNoResult()
1839
+ {
1840
+ var ul = getList();
1841
+ ul.innerHTML = '';
1842
+
1843
+ if (_instance.hasTemplate('NoResult'))
1844
+ {
1845
+ var li = document.createElement('li');
1846
+ ul.appendChild(li);
1847
+ li.className = _instance.cssClassNoResult || _classOption.NORESULT;
1848
+ _instance.applyTemplate(li, 'NoResult');
1849
+ }
1850
+ }
1851
+
1852
+ function eventArgs(item, e)
1853
+ {
1854
+ return { item: item, event: $lib.event }
1855
+ }
1856
+
1857
+ function selectAll(id)
1858
+ {
1859
+ var id = _selectAllId,
1860
+ li = _elements[id],
1861
+ selected = $lib.hasClass(li, 'selected');
1862
+
1863
+ $lib.toggleClass(li, 'selected');
1864
+
1865
+ $lib.each(_instance.itemList, function (item)
1866
+ {
1867
+ if (selected)
1868
+ deselectItem(item.id);
1869
+ else
1870
+ selectItem(item.id);
1871
+ });
1872
+
1873
+ if (selected)
1874
+ clearInput();
1875
+ }
1876
+
1877
+ function focusSelectAll()
1878
+ {
1879
+ var id = _selectAllId;
1880
+
1881
+ if (_focusedItemId)
1882
+ $lib.removeClass(_elements[_focusedItemId], 'focus');
1883
+
1884
+ $lib.addClass(_elements[id], 'focus');
1885
+ _focusedItemId = id;
1886
+ }
1887
+
1888
+ function focusItem(id, scroll, e)
1889
+ {
1890
+ _instance.itemList.get(id);
1891
+
1892
+ if (!_listBox.showing || id == _focusedItemId)
1893
+ return;
1894
+
1895
+ if (_focusedItemId)
1896
+ $lib.removeClass(_elements[_focusedItemId], 'focus');
1897
+
1898
+ $lib.addClass(_elements[id], 'focus');
1899
+ _focusedItemId = id;
1900
+
1901
+ if (!$lib.isEmpty(_selectedItemId) && _selectedItemId != id)
1902
+ {
1903
+ $lib.removeClass(_elements[_selectedItemId], 'selected');
1904
+ }
1905
+
1906
+ if (scroll)
1907
+ scrollToItem(_elements[id]);
1908
+ }
1909
+
1910
+ function toggleSelectItem(id)
1911
+ {
1912
+ _instance.itemList.get(id);
1913
+
1914
+ if (_selectedItems[id])
1915
+ deselectItem(id);
1916
+ else
1917
+ selectItem(id);
1918
+
1919
+ _forceSelect = false;
1920
+ }
1921
+
1922
+ function selectItem(id, forceShow = false)
1923
+ {
1924
+ var item = _instance.itemList.get(id),
1925
+ li = _elements[id];
1926
+
1927
+ if (item.disabled)
1928
+ return;
1929
+
1930
+ if (!_forceSelect && item.selected)
1931
+ {
1932
+ if (!forceShow && _instance.collapseOnItemSelect)
1933
+ _listBox.hide();
1934
+
1935
+ return;
1936
+ }
1937
+
1938
+ const selectionRestored = !!_selectedItems[id];
1939
+
1940
+ item.selected = true;
1941
+ $lib.addClass(li, 'selected');
1942
+
1943
+ if (_instance.multiSelect)
1944
+ {
1945
+ _selectedItems[id] = item;
1946
+ storeSelected();
1947
+
1948
+ if (_instance.multiSelectTagging)
1949
+ createTag(item);
1950
+ }
1951
+ else
1952
+ {
1953
+ clearSelection();
1954
+ _selectedItems[id] = item;
1955
+
1956
+ if (!$lib.isEmpty(_focusedItemId))
1957
+ $lib.removeClass(_elements[_focusedItemId], 'focus');
1958
+
1959
+ _focusedItemId = null;
1960
+ _selectedItemId = id;
1961
+ _hidden.__setValue(item.value);
1962
+
1963
+ if (_hidden.value === _instance.value)
1964
+ _initialValue = false;
1965
+
1966
+ if (!forceShow && _instance.collapseOnItemSelect)
1967
+ _listBox.hide();
1968
+ else
1969
+ scrollToItem(li);
1970
+ }
1971
+
1972
+ if (!selectionRestored || !_instance.allowInput)
1973
+ {
1974
+ if (!tagging())
1975
+ setInputValue(item.text, _instance.__focus);
1976
+ else
1977
+ clearInput();
1978
+ }
1979
+
1980
+ $lib.addClass(_instance.element, 'selected');
1981
+ toggleClearButton();
1982
+ _forceSelect = false;
1983
+
1984
+ if (!selectionRestored)
1985
+ _instance.events.onItemSelect.fire(_instance, eventArgs(item));
1986
+ }
1987
+
1988
+ function deselectItem(id, clearValue)
1989
+ {
1990
+ var item = _instance.itemList.get(id),
1991
+ li = _elements[id];
1992
+
1993
+ if (item)
1994
+ {
1995
+ item.selected = false;
1996
+ _selectedItemId = null;
1997
+ $lib.removeClass(li, 'selected');
1998
+ }
1999
+ else // item was selected on previously loaded item-list
2000
+ {
2001
+ item = {};
2002
+ item.id = id; // for event arguments
2003
+ }
2004
+
2005
+ delete _selectedItems[id];
2006
+
2007
+ if (_instance.multiSelect)
2008
+ {
2009
+ storeSelected();
2010
+
2011
+ if (_instance.multiSelectTagging)
2012
+ removeTag(id);
2013
+
2014
+ if (!_selectedCount)
2015
+ $lib.removeClass(_instance.element, 'selected');
2016
+ }
2017
+ else
2018
+ {
2019
+ _hidden.__setValue('');
2020
+ $lib.removeClass(_instance.element, 'selected');
2021
+ }
2022
+
2023
+ if (item.value === _instance.value)
2024
+ _initialValue = false;
2025
+
2026
+ if (clearValue !== false && !tagging())
2027
+ setInputValue('', _instance.__focus);
2028
+
2029
+ toggleClearButton();
2030
+ _instance.events.onItemDeselect.fire(_instance, eventArgs(item));
2031
+ }
2032
+
2033
+ function disableItem(id)
2034
+ {
2035
+ var item = getItem(id);
2036
+
2037
+ item.disabled = true;
2038
+ $lib.addClass(_elements[id], 'disabled');
2039
+ }
2040
+
2041
+ function enableItem(id)
2042
+ {
2043
+ var item = getItem(id);
2044
+
2045
+ item.disabled = false;
2046
+ $lib.removeClass(_elements[id], 'disabled');
2047
+ }
2048
+
2049
+ function addCustomValue(value)
2050
+ {
2051
+ if (_selectedItems[value])
2052
+ return;
2053
+
2054
+ setupItemList();
2055
+
2056
+ let existingItem = _instance.itemList.getByText(value, true);
2057
+
2058
+ if (existingItem && !existingItem.disabled)
2059
+ {
2060
+ selectItem(existingItem.id);
2061
+ clearInput();
2062
+ return;
2063
+ }
2064
+
2065
+ let item = { id: value, value: value, text: value, selected: true, disabled: false };
2066
+
2067
+ _selectedItems[value] = item;
2068
+
2069
+ if (_instance.multiSelectTagging)
2070
+ createTag(item);
2071
+
2072
+ storeSelected();
2073
+ clearInput();
2074
+ toggleClearButton();
2075
+ $lib.addClass(_instance.element, 'selected');
2076
+ _instance.events.onItemSelect.fire(_instance, eventArgs(item));
2077
+ }
2078
+
2079
+ function createTag(item)
2080
+ {
2081
+ if (_tags[item.id])
2082
+ return;
2083
+
2084
+ var button = $UI.createComponent(componyx.UI.Button, { id: getItemId(item.id), beforeElement: _input });
2085
+
2086
+ _tags[item.id] = button;
2087
+ button.clone($UI.store[_instance.tagButtonId], _instance);
2088
+ button.primary = !_instance.allowInput;
2089
+ button.iconAlign = 2;
2090
+ button.hasIcon = true;
2091
+ button.transparentBorder = true;
2092
+ button.cssClass = _classOption.TAG;
2093
+ button.command = function (itemId)
2094
+ {
2095
+ $lib.event.stopPropagation();
2096
+ deselectItem(itemId);
2097
+ }.bind(_instance, item.id);
2098
+ button.delegateFocusEvents(_instance);
2099
+
2100
+ if (_instance.hasTemplate('ItemTag'))
2101
+ {
2102
+ var content = $lib.element();
2103
+ _instance.applyTemplate(content, 'ItemTag', item);
2104
+ button.text = content.innerHTML;
2105
+ }
2106
+ else
2107
+ button.text = item.text;
2108
+
2109
+ button.show();
2110
+ }
2111
+
2112
+ function removeTag(id)
2113
+ {
2114
+ if (_tags[id])
2115
+ {
2116
+ _tags[id].destroy();
2117
+ delete _tags[id];
2118
+ }
2119
+ }
2120
+
2121
+ function scrollToItem(li)
2122
+ {
2123
+ var ul = getList();
2124
+ ul.scrollTop = li.offsetTop - ul.offsetTop;
2125
+ }
2126
+
2127
+ function getList()
2128
+ {
2129
+ return $lib(_instance.cssClassList || _classOption.LIST, _listBox.element, 'ul')[0];
2130
+ }
2131
+
2132
+ function hasInputValue()
2133
+ {
2134
+ var input = _input;
2135
+
2136
+ return (!$lib.isEmpty(input.value));
2137
+ }
2138
+
2139
+ function setInputValue(text, focus)
2140
+ {
2141
+ var input = _input;
2142
+
2143
+ if (!_instance.multiSelect || !_onDemand)
2144
+ {
2145
+ input.value = text;
2146
+ _multiTemplateActive = false;
2147
+ autoGrow();
2148
+ }
2149
+
2150
+ if (focus)
2151
+ setFocus(input);
2152
+ }
2153
+
2154
+ function setMultiSelectValue()
2155
+ {
2156
+ var input = _input;
2157
+
2158
+ if (!input || tagging())
2159
+ return; // expand button containing input could be destoyed before the box (onHideComplete event) when the comboBox is destroyed
2160
+
2161
+ if (_selectedCount > 1)
2162
+ {
2163
+ _instance.applyTemplate(input, 'MultiSelectInput', { 'count': _selectedCount });
2164
+ _multiTemplateActive = true;
2165
+ }
2166
+ else if (_selectedCount == 1)
2167
+ input.value = _instance.getSelectedItems()[0].text;
2168
+
2169
+ autoGrow();
2170
+ }
2171
+
2172
+ function setFocus(input)
2173
+ {
2174
+ input = input || _input;
2175
+
2176
+ if ($lib.visible(input) && !input.hasFocus)
2177
+ input.focus();
2178
+ }
2179
+
2180
+ function toggleClearButton()
2181
+ {
2182
+ if (_instance.disableClearButton)
2183
+ return;
2184
+
2185
+ var show = (!$lib.isEmpty(_selectedItems) || hasInputValue());
2186
+
2187
+ if (show)
2188
+ _clearButton.element.style.visibility = '';
2189
+ else
2190
+ _clearButton.element.style.visibility = 'hidden';
2191
+ }
2192
+
2193
+ function storeSelected()
2194
+ {
2195
+ var sel = [];
2196
+ $lib.each(_selectedItems, function (item, key)
2197
+ {
2198
+ sel.push(item.value);
2199
+ });
2200
+
2201
+ _selectedCount = sel.length;
2202
+ _hidden.__setValue((sel.length > 0) ? sel.join(',') : '');
2203
+ }
2204
+
2205
+ function tagging()
2206
+ {
2207
+ return (_instance.multiSelect && _instance.multiSelectTagging);
2208
+ }
2209
+
2210
+ function getItemId(id)
2211
+ {
2212
+ return $lib.format('{0}_{1}', _instance.id, id);
2213
+ }
2214
+
2215
+ function getItem(itemId)
2216
+ {
2217
+ return (typeof (itemId) == 'string') ? _instance.itemList.get(itemId) : itemId;
2218
+ }
2219
+
2220
+ function clearCommand()
2221
+ {
2222
+ _clearButtonClicked = true;
2223
+ _instance.events.onClear.fire(_instance, null);
2224
+
2225
+ if (_instance.loadOnDemand)
2226
+ clearList();
2227
+
2228
+ clear();
2229
+
2230
+ _clearButton.element.style.visibility = 'hidden';
2231
+ }
2232
+
2233
+ function clear()
2234
+ {
2235
+ clearSelection();
2236
+ clearInput();
2237
+ }
2238
+
2239
+ function clearSelection()
2240
+ {
2241
+ const hasSelectedItems = Object.keys(_selectedItems).length > 0;
2242
+
2243
+ if (hasSelectedItems)
2244
+ {
2245
+ for (const id in _selectedItems)
2246
+ {
2247
+ deselectItem(id);
2248
+ }
2249
+ }
2250
+ else
2251
+ {
2252
+ _hidden.__setValue(''); // trigger change event
2253
+ }
2254
+
2255
+ _selectedCount = 0;
2256
+ }
2257
+
2258
+ function clearInput()
2259
+ {
2260
+ var input = _input;
2261
+ input.value = '';
2262
+ _lastQuery = null;
2263
+
2264
+ if (_instance.loadOnDemand && _instance.loadOnRender)
2265
+ load(null, _listBox.showing, null, false);
2266
+ }
2267
+
2268
+ function clearList()
2269
+ {
2270
+ _lastQuery = null;
2271
+ var ul = getList();
2272
+ ul.innerHTML = '';
2273
+
2274
+ if (_instance.itemList)
2275
+ _instance.itemList.length = 0;
2276
+
2277
+ if (_pager)
2278
+ _pager.hide();
2279
+ }
2280
+
2281
+ function dispose()
2282
+ {
2283
+ if (_listBox)
2284
+ _listBox.hide(true);
2285
+
2286
+ _pendingCustomValue = null;
2287
+ _listBox = null;
2288
+ _elements = {};
2289
+ _tags = {};
2290
+ _pager = _focusedItemId = _selectedItemId = _lastQuery = _expandButton = _clearButton = null;
2291
+ _selectedItems = {};
2292
+ _selectedCount = 0;
2293
+ _initialValue = _clearButtonClicked = false;
2294
+ }
2295
+ };
2296
+
2297
+ /**
2298
+ * @see {@link componyx.UI.base.methods}
2299
+ */
2300
+ componyx.UI.ComboBox.prototype = Object.create($base.methods);
2301
+ componyx.UI.ComboBox.prototype.constructor = componyx.UI.ComboBox;
2302
+
2303
+ /**
2304
+ * FilterOption
2305
+ * @readonly
2306
+ * @enum {number}
2307
+ */
2308
+ componyx.UI.ComboBox.FilterOption =
2309
+ {
2310
+ STARTSWITH: 0,
2311
+ CONTAINS: 1,
2312
+ EQUALS: 2,
2313
+ ENDSWITH: 3
2314
+ };
2315
+
2316
+ /**
2317
+ * Creates an instance of the ComboBox item.
2318
+ * @class
2319
+ * @param {Object} properties The properties used to initialize the object.
2320
+ * @param {Boolean} properties.hasIcon Gets or sets a value indicating if the icon is displayed.
2321
+ * @param {String} properties.cssClassIcon Gets or sets the css class of the icon.
2322
+ * @param {String} properties.cssClassCheckBox Gets or sets the css class of the checkbox.
2323
+ * @param {String} properties.iconURL Gets or sets the icon URL.
2324
+ * @param {String} properties.tooltip Gets or sets the tooltip.
2325
+ * @augments componyx.UI.base.Item
2326
+ * @see {@link componyx.UI.base.Item}
2327
+ */
2328
+ componyx.UI.ComboBox.Item = function (properties)
2329
+ {
2330
+ this.hasIcon = false;
2331
+ this.cssClassIcon = null;
2332
+ this.cssClassCheckBox = null;
2333
+ this.iconURL = '';
2334
+ this.tooltip = '';
2335
+
2336
+ $base.static.Item.call(this, properties);
2337
+ };
2338
+ })(window);
2339
+
2340
+ const ComboBox = componyx.UI.ComboBox;
2341
+
2342
+ export { ComboBox };