@qtoggle/qui 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.json +492 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  5. package/.github/ISSUE_TEMPLATE/improvement_proposal.md +20 -0
  6. package/.github/workflows/main.yml +74 -0
  7. package/.pre-commit-config.yaml +8 -0
  8. package/LICENSE.txt +177 -0
  9. package/README.md +4 -0
  10. package/font/dejavusans-bold.woff +0 -0
  11. package/font/dejavusans-bolditalic.woff +0 -0
  12. package/font/dejavusans-italic.woff +0 -0
  13. package/font/dejavusans-regular.woff +0 -0
  14. package/img/qui-icons.svg +1937 -0
  15. package/js/base/base.js +47 -0
  16. package/js/base/condition-variable.js +92 -0
  17. package/js/base/errors.js +36 -0
  18. package/js/base/i18n.js +20 -0
  19. package/js/base/mixwith.js +135 -0
  20. package/js/base/require-js-compat.js +78 -0
  21. package/js/base/signal.js +91 -0
  22. package/js/base/singleton.js +66 -0
  23. package/js/base/timer.js +126 -0
  24. package/js/config.js +184 -0
  25. package/js/forms/common-fields/check-field.js +42 -0
  26. package/js/forms/common-fields/choice-buttons-field.js +30 -0
  27. package/js/forms/common-fields/color-combo-field.js +37 -0
  28. package/js/forms/common-fields/combo-field.js +108 -0
  29. package/js/forms/common-fields/common-fields.js +23 -0
  30. package/js/forms/common-fields/composite-field.js +132 -0
  31. package/js/forms/common-fields/custom-html-field.js +51 -0
  32. package/js/forms/common-fields/email-field.js +30 -0
  33. package/js/forms/common-fields/file-picker-field.js +46 -0
  34. package/js/forms/common-fields/jquery-ui-field.js +111 -0
  35. package/js/forms/common-fields/labels-field.js +69 -0
  36. package/js/forms/common-fields/numeric-field.js +39 -0
  37. package/js/forms/common-fields/password-field.js +28 -0
  38. package/js/forms/common-fields/phone-field.js +26 -0
  39. package/js/forms/common-fields/progress-disk-field.js +69 -0
  40. package/js/forms/common-fields/push-button-field.js +138 -0
  41. package/js/forms/common-fields/slider-field.js +51 -0
  42. package/js/forms/common-fields/text-area-field.js +34 -0
  43. package/js/forms/common-fields/text-field.js +89 -0
  44. package/js/forms/common-fields/up-down-field.js +85 -0
  45. package/js/forms/common-forms/common-forms.js +16 -0
  46. package/js/forms/common-forms/options-form.js +77 -0
  47. package/js/forms/common-forms/page-form.js +115 -0
  48. package/js/forms/form-button.js +202 -0
  49. package/js/forms/form-field.js +1183 -0
  50. package/js/forms/form.js +1181 -0
  51. package/js/forms/forms.js +68 -0
  52. package/js/global-glass.js +100 -0
  53. package/js/icons/default-stock.js +173 -0
  54. package/js/icons/icon.js +64 -0
  55. package/js/icons/icons.js +16 -0
  56. package/js/icons/multi-state-sprites-icon.js +362 -0
  57. package/js/icons/stock-icon.js +219 -0
  58. package/js/icons/stock.js +98 -0
  59. package/js/icons/stocks.js +57 -0
  60. package/js/index.js +232 -0
  61. package/js/lib/jquery.longpress.js +79 -0
  62. package/js/lib/jquery.module.js +4 -0
  63. package/js/lib/logger.module.js +4 -0
  64. package/js/lib/pep.module.js +4 -0
  65. package/js/lists/common-items/common-items.js +5 -0
  66. package/js/lists/common-items/icon-label-list-item.js +86 -0
  67. package/js/lists/common-lists/common-lists.js +5 -0
  68. package/js/lists/common-lists/page-list.js +53 -0
  69. package/js/lists/list-item.js +147 -0
  70. package/js/lists/list.js +636 -0
  71. package/js/lists/lists.js +26 -0
  72. package/js/main-ui/main-ui.js +64 -0
  73. package/js/main-ui/menu-bar.js +144 -0
  74. package/js/main-ui/options-bar.js +181 -0
  75. package/js/main-ui/status.js +185 -0
  76. package/js/main-ui/top-bar.js +59 -0
  77. package/js/messages/common-message-forms/common-message-forms.js +7 -0
  78. package/js/messages/common-message-forms/confirm-message-form.js +81 -0
  79. package/js/messages/common-message-forms/simple-message-form.js +67 -0
  80. package/js/messages/common-message-forms/sticky-simple-message-form.js +27 -0
  81. package/js/messages/message-form.js +107 -0
  82. package/js/messages/messages.js +21 -0
  83. package/js/messages/sticky-modal-page.js +98 -0
  84. package/js/messages/sticky-modal-progress-message.js +27 -0
  85. package/js/messages/toast.js +164 -0
  86. package/js/navigation.js +654 -0
  87. package/js/pages/breadcrumbs.js +124 -0
  88. package/js/pages/common-pages/common-pages.js +6 -0
  89. package/js/pages/common-pages/modal-progress-page.js +83 -0
  90. package/js/pages/common-pages/structured-page.js +46 -0
  91. package/js/pages/page.js +1018 -0
  92. package/js/pages/pages-context.js +154 -0
  93. package/js/pages/pages.js +252 -0
  94. package/js/pwa.js +337 -0
  95. package/js/sections/section.js +612 -0
  96. package/js/sections/sections.js +300 -0
  97. package/js/tables/common-cells/common-cells.js +7 -0
  98. package/js/tables/common-cells/icon-label-table-cell.js +68 -0
  99. package/js/tables/common-cells/push-button-table-cell.js +133 -0
  100. package/js/tables/common-cells/simple-table-cell.js +37 -0
  101. package/js/tables/common-tables/common-tables.js +5 -0
  102. package/js/tables/common-tables/page-table.js +55 -0
  103. package/js/tables/table-cell.js +198 -0
  104. package/js/tables/table-row.js +126 -0
  105. package/js/tables/table.js +492 -0
  106. package/js/tables/tables.js +36 -0
  107. package/js/theme.js +304 -0
  108. package/js/utils/ajax.js +126 -0
  109. package/js/utils/array.js +194 -0
  110. package/js/utils/colors.js +445 -0
  111. package/js/utils/cookies.js +65 -0
  112. package/js/utils/crypto.js +439 -0
  113. package/js/utils/css.js +234 -0
  114. package/js/utils/date.js +300 -0
  115. package/js/utils/files.js +27 -0
  116. package/js/utils/gestures.js +165 -0
  117. package/js/utils/html.js +76 -0
  118. package/js/utils/misc.js +81 -0
  119. package/js/utils/object.js +324 -0
  120. package/js/utils/promise.js +49 -0
  121. package/js/utils/string.js +192 -0
  122. package/js/utils/url.js +187 -0
  123. package/js/utils/utils.js +3 -0
  124. package/js/utils/visibility-manager.js +211 -0
  125. package/js/views/common-views/common-views.js +7 -0
  126. package/js/views/common-views/icon-label-view.js +210 -0
  127. package/js/views/common-views/progress-view.js +89 -0
  128. package/js/views/common-views/structured-view.js +368 -0
  129. package/js/views/view.js +467 -0
  130. package/js/views/views.js +3 -0
  131. package/js/widgets/base-widget.js +23 -0
  132. package/js/widgets/common-widgets/check-button.js +109 -0
  133. package/js/widgets/common-widgets/choice-buttons.js +322 -0
  134. package/js/widgets/common-widgets/color-combo.js +104 -0
  135. package/js/widgets/common-widgets/combo.js +645 -0
  136. package/js/widgets/common-widgets/common-widgets.js +17 -0
  137. package/js/widgets/common-widgets/email-input.js +7 -0
  138. package/js/widgets/common-widgets/file-picker.js +133 -0
  139. package/js/widgets/common-widgets/labels.js +132 -0
  140. package/js/widgets/common-widgets/numeric-input.js +49 -0
  141. package/js/widgets/common-widgets/password-input.js +91 -0
  142. package/js/widgets/common-widgets/phone-input.js +7 -0
  143. package/js/widgets/common-widgets/progress-disk.js +174 -0
  144. package/js/widgets/common-widgets/push-button.js +155 -0
  145. package/js/widgets/common-widgets/slider.js +455 -0
  146. package/js/widgets/common-widgets/text-area.js +52 -0
  147. package/js/widgets/common-widgets/text-input.js +174 -0
  148. package/js/widgets/common-widgets/up-down.js +351 -0
  149. package/js/widgets/widgets.js +57 -0
  150. package/js/window.js +557 -0
  151. package/jsdoc.conf.json +20 -0
  152. package/less/base.less +123 -0
  153. package/less/forms/common-fields.less +101 -0
  154. package/less/forms/common-forms.less +5 -0
  155. package/less/forms/form-button.less +21 -0
  156. package/less/forms/form-field.less +266 -0
  157. package/less/forms/form.less +131 -0
  158. package/less/global-glass.less +64 -0
  159. package/less/icon-label-view.less +82 -0
  160. package/less/icons.less +144 -0
  161. package/less/lists.less +105 -0
  162. package/less/main-ui.less +328 -0
  163. package/less/messages.less +189 -0
  164. package/less/no-effects.less +24 -0
  165. package/less/pages/breadcrumbs.less +98 -0
  166. package/less/pages/common-pages.less +36 -0
  167. package/less/pages/page.less +70 -0
  168. package/less/progress-view.less +51 -0
  169. package/less/stock-icons.less +43 -0
  170. package/less/structured-view.less +245 -0
  171. package/less/tables.less +84 -0
  172. package/less/theme-dark.less +133 -0
  173. package/less/theme-light.less +132 -0
  174. package/less/theme.less +419 -0
  175. package/less/visibility-manager.less +11 -0
  176. package/less/widgets/check-button.less +96 -0
  177. package/less/widgets/choice-buttons.less +160 -0
  178. package/less/widgets/color-combo.less +33 -0
  179. package/less/widgets/combo.less +230 -0
  180. package/less/widgets/common-buttons.less +120 -0
  181. package/less/widgets/common.less +24 -0
  182. package/less/widgets/input.less +258 -0
  183. package/less/widgets/labels.less +81 -0
  184. package/less/widgets/progress-disk.less +70 -0
  185. package/less/widgets/slider.less +199 -0
  186. package/less/widgets/updown.less +115 -0
  187. package/less/widgets/various.less +36 -0
  188. package/package.json +47 -0
  189. package/pyproject.toml +45 -0
  190. package/qui/__init__.py +110 -0
  191. package/qui/constants.py +1 -0
  192. package/qui/exceptions.py +2 -0
  193. package/qui/j2template.py +71 -0
  194. package/qui/settings.py +60 -0
  195. package/qui/templates/manifest.json +25 -0
  196. package/qui/templates/qui.html +126 -0
  197. package/qui/templates/service-worker.js +188 -0
  198. package/qui/web/__init__.py +0 -0
  199. package/qui/web/tornado.py +220 -0
  200. package/scripts/postinstall.sh +10 -0
  201. package/webpack/webpack-adjust-css-urls-loader.js +36 -0
  202. package/webpack/webpack-common.js +384 -0
@@ -0,0 +1,645 @@
1
+
2
+ import $ from '$qui/lib/jquery.module.js'
3
+
4
+ import {gettext} from '$qui/base/i18n.js'
5
+ import * as Theme from '$qui/theme.js'
6
+ import {asap} from '$qui/utils/misc.js'
7
+ import * as ObjectUtils from '$qui/utils/object.js'
8
+ import * as PromiseUtils from '$qui/utils/promise.js'
9
+ import * as StringUtils from '$qui/utils/string.js'
10
+ import * as Window from '$qui/window.js'
11
+
12
+ import * as BaseWidget from '../base-widget.js' /* Needed */
13
+
14
+
15
+ const MAX_VISIBLE_ITEMS = 100
16
+
17
+
18
+ $.widget('qui.combo', $.qui.basewidget, {
19
+
20
+ options: {
21
+ makeChoices: null,
22
+ choices: [],
23
+ fastFactor: 5,
24
+ filterEnabled: false,
25
+ filterFunc: null,
26
+ readonly: false,
27
+ disabled: false
28
+ },
29
+
30
+ _create: function () {
31
+ this._buttonDiv = $('<div></div>', {class: 'qui-base-button qui-combo-button'})
32
+ this._opened = false
33
+ this._searchStr = ''
34
+ this._prevItemDiv = null
35
+ this._maxHeightSet = false
36
+
37
+ this.element.addClass('qui-combo-container')
38
+ if (this.options.readonly) {
39
+ this.element.addClass('readonly')
40
+ }
41
+ if (this.options.disabled) {
42
+ this.element.addClass('disabled')
43
+ }
44
+ if (this.options.filterEnabled) {
45
+ this.element.addClass('filter-enabled')
46
+ }
47
+
48
+ this.element.append(this._buttonDiv)
49
+
50
+ this._currentEntryDiv = $('<div></div>', {class: 'qui-combo-current-label'})
51
+ this._buttonDiv.append(this._currentEntryDiv)
52
+ this._buttonDiv.css('text-align', 'left')
53
+
54
+ this._buttonDiv.append($('<span></span>', {class: 'qui-combo-arrow-separator'}))
55
+ this._buttonDiv.append($('<span></span>', {class: 'qui-combo-arrow'}))
56
+
57
+ let searchMsg = gettext('search...')
58
+ this._filterInput = $('<input>', {type: 'text', class: 'qui-combo-filter', placeholder: searchMsg})
59
+ this._buttonDiv.after(this._filterInput)
60
+
61
+ this._itemContainer = $('<div></div>', {class: 'qui-combo-item-container'})
62
+ this._itemContainer.on('mousedown', function () {
63
+ return false
64
+ })
65
+
66
+ /* Ensure the combo element is on view port when focused (opened) */
67
+ this.element.on('focus', function () {
68
+ if (this.scrollIntoView) {
69
+ let transitionDuration = parseFloat(Theme.getVar('transition-duration')) * 1000
70
+ PromiseUtils.later(transitionDuration * 1.1).then(() => this.scrollIntoView({
71
+ behavior: 'smooth',
72
+ block: 'center',
73
+ inline: 'nearest'
74
+ }))
75
+ }
76
+ })
77
+
78
+ this.element.append(this._itemContainer)
79
+
80
+ if (!this.options.disabled) {
81
+ this.element.attr('tabIndex', 0) /* Make the container focusable */
82
+ }
83
+
84
+ let widget = this
85
+
86
+ this._cachedChoices = null
87
+
88
+ this._makeItems()
89
+ this._updateFiltered()
90
+
91
+ this._handleKeyDown = function (e) {
92
+ if (widget.options.readonly) {
93
+ return
94
+ }
95
+
96
+ let changed = false
97
+ let selectedItem
98
+
99
+ switch (e.which) {
100
+ case 13: /* Enter */
101
+ if (widget._opened) {
102
+ widget.close()
103
+ return false
104
+ }
105
+
106
+ break
107
+
108
+ case 8: /* Backspace */
109
+ if (widget._opened && !widget._filterInput.is(':focus')) {
110
+ if (widget._searchStr.length) {
111
+ widget._searchStr = widget._searchStr.substring(0, widget._searchStr.length - 1)
112
+ return false
113
+ }
114
+ }
115
+
116
+ break
117
+
118
+ case 27: /* Escape */
119
+ if (widget._opened) {
120
+ widget._selectItemDiv(widget._prevItemDiv)
121
+ widget.close()
122
+ return false
123
+ }
124
+
125
+ break
126
+
127
+ case 38: /* Up */
128
+ changed = widget._selectPrev()
129
+
130
+ if (changed) {
131
+ if (!widget._opened) {
132
+ widget._updateCurrentEntry()
133
+ selectedItem = widget._itemContainer.children('div.qui-combo-item.selected')
134
+ widget.element.trigger('change', selectedItem.index())
135
+ }
136
+
137
+ return false
138
+ }
139
+
140
+ break
141
+
142
+ case 40: /* Down */
143
+ changed = widget._selectNext()
144
+
145
+ if (changed) {
146
+ if (!widget._opened) {
147
+ widget._updateCurrentEntry()
148
+ selectedItem = widget._itemContainer.children('div.qui-combo-item.selected')
149
+ widget.element.trigger('change', selectedItem.index())
150
+ }
151
+
152
+ return false
153
+ }
154
+
155
+ break
156
+
157
+ case 32: /* Space */
158
+ if (!widget._opened && !widget._filterInput.is(':focus')) {
159
+ widget.open()
160
+ return false
161
+ }
162
+
163
+ break
164
+
165
+ case 34: /* Page-down */
166
+ for (let i = 0; i < widget.options.fastFactor; i++) {
167
+ if (widget._selectNext()) {
168
+ changed = true
169
+ }
170
+ }
171
+
172
+ if (changed) {
173
+ if (!widget._opened) {
174
+ widget._updateCurrentEntry()
175
+ selectedItem = widget._itemContainer.children('div.qui-combo-item.selected')
176
+ widget.element.trigger('change', selectedItem.index())
177
+ }
178
+
179
+ return false
180
+ }
181
+
182
+ break
183
+
184
+ case 33: /* Page-up */
185
+ for (let i = 0; i < widget.options.fastFactor; i++) {
186
+ if (widget._selectPrev()) {
187
+ changed = true
188
+ }
189
+ }
190
+
191
+ if (changed) {
192
+ if (!widget._opened) {
193
+ widget._updateCurrentEntry()
194
+ selectedItem = widget._itemContainer.children('div.qui-combo-item.selected')
195
+ widget.element.trigger('change', selectedItem.index())
196
+ }
197
+
198
+ return false
199
+ }
200
+
201
+ break
202
+
203
+ case 36: /* Home */
204
+ while (widget._selectPrev()) {
205
+ changed = true
206
+ }
207
+
208
+ if (changed) {
209
+ if (!widget._opened) {
210
+ widget._updateCurrentEntry()
211
+ selectedItem = widget._itemContainer.children('div.qui-combo-item.selected')
212
+ widget.element.trigger('change', selectedItem.index())
213
+ }
214
+
215
+ return false
216
+ }
217
+
218
+ break
219
+
220
+ case 35: /* End */
221
+ while (widget._selectNext()) {
222
+ changed = true
223
+ }
224
+
225
+ if (changed) {
226
+ if (!widget._opened) {
227
+ widget._updateCurrentEntry()
228
+ selectedItem = widget._itemContainer.children('div.qui-combo-item.selected')
229
+ widget.element.trigger('change', selectedItem.index())
230
+ }
231
+
232
+ return false
233
+ }
234
+ }
235
+ }
236
+
237
+ this._handleKeyPress = function (e) {
238
+ if (widget.options.readonly) {
239
+ return
240
+ }
241
+
242
+ if (widget._filterInput.is(':focus')) {
243
+ return
244
+ }
245
+
246
+ widget._searchStr += String.fromCharCode(e.which).toLowerCase()
247
+
248
+ widget._itemContainer.children('div.qui-combo-item').each(function () {
249
+ let itemDiv = $(this)
250
+ if (itemDiv.text().toLowerCase().startsWith(widget._searchStr)) {
251
+ if (widget._opened) {
252
+ widget._selectItemDiv(itemDiv, true)
253
+ }
254
+ else {
255
+ let selectedItem = widget._itemContainer.children('div.qui-combo-item.selected')
256
+ if (!selectedItem.is(itemDiv)) {
257
+ itemDiv.addClass('selected')
258
+ selectedItem.removeClass('selected')
259
+ widget._updateCurrentEntry()
260
+ widget.element.trigger('change', itemDiv.index())
261
+ }
262
+ }
263
+
264
+ return false
265
+ }
266
+ })
267
+ }
268
+
269
+ this._pointerDown = function (e) {
270
+ if (widget.element.parent().has(e.target).length) {
271
+ return
272
+ }
273
+
274
+ if (!widget._prevItemDiv) {
275
+ return
276
+ }
277
+
278
+ widget._selectItemDiv(widget._prevItemDiv)
279
+ widget.close()
280
+ }
281
+
282
+ this._buttonDiv.on('click', function () {
283
+ if (widget.options.readonly || widget.options.disabled) {
284
+ return
285
+ }
286
+
287
+ if (widget._opened) {
288
+ widget.close()
289
+ }
290
+ else {
291
+ widget.open()
292
+ }
293
+
294
+ return false
295
+ })
296
+
297
+ this.element.on('keydown', this._handleKeyDown)
298
+ this.element.on('keypress', this._handleKeyPress)
299
+ this.element.on('blur', function () {
300
+
301
+ asap(function () {
302
+ if (widget._filterInput.is(':focus')) {
303
+ return
304
+ }
305
+
306
+ /* Close the combo when losing focus */
307
+ if (widget._opened) {
308
+ widget._selectItemDiv(widget._prevItemDiv)
309
+ widget.close()
310
+ }
311
+ })
312
+
313
+ })
314
+
315
+ this._filterInput.on('blur', function () {
316
+
317
+ /* Close the combo when losing focus */
318
+ if (widget._opened) {
319
+ widget._selectItemDiv(widget._prevItemDiv)
320
+ widget.close()
321
+ }
322
+
323
+ })
324
+
325
+ this._filterInput.on('keydown', function () {
326
+ asap(function () {
327
+ widget._updateFiltered()
328
+ })
329
+ })
330
+ },
331
+
332
+ getValue: function () {
333
+ let value = this._itemContainer.children('div.qui-combo-item.selected').data('value')
334
+ if (value === undefined) {
335
+ value = null
336
+ }
337
+
338
+ return value
339
+ },
340
+
341
+ setValue: function (value) {
342
+ let itemDiv = this._getItemDivByValue(value)
343
+ this._selectItemDiv(itemDiv)
344
+ this._updateCurrentEntry()
345
+ },
346
+
347
+ getSelectedIndex: function () {
348
+ return this._itemContainer.children('div.qui-combo-item.selected').index()
349
+ },
350
+
351
+ setSelectedIndex: function (index) {
352
+ this._itemContainer.children('div.qui-combo-item.selected').removeClass('selected')
353
+ if (index >= 0) {
354
+ this._itemContainer.children(`div.qui-combo-item:eq(${index})`).addClass('selected')
355
+ }
356
+ this._updateCurrentEntry()
357
+ },
358
+
359
+ open: function () {
360
+ if (this._opened) {
361
+ return
362
+ }
363
+
364
+ this._opened = true
365
+ this.element.addClass('open')
366
+
367
+ Window.$body.on('pointerdown', this._pointerDown)
368
+
369
+ this._searchStr = ''
370
+ this._prevItemDiv = this._itemContainer.children('div.qui-combo-item.selected')
371
+
372
+ if (this._prevItemDiv.length) {
373
+ let scrollTop = this._prevItemDiv.offset().top - this._itemContainer.offset().top +
374
+ this._itemContainer.scrollTop()
375
+ this._itemContainer.scrollTop(scrollTop)
376
+ }
377
+
378
+ if (this.options.filterEnabled) {
379
+ this._filterInput.val('')
380
+ this._filterInput.focus()
381
+ this._updateFiltered()
382
+ }
383
+ },
384
+
385
+ close: function () {
386
+ if (!this._opened) {
387
+ return
388
+ }
389
+
390
+ this._opened = false
391
+ this.element.removeClass('open')
392
+
393
+ Window.$body.off('pointerdown', this._pointerDown)
394
+
395
+ this._searchStr = ''
396
+ this._updateCurrentEntry()
397
+
398
+ let selectedItem = this._itemContainer.children('div.qui-combo-item.selected')
399
+ if (!selectedItem.is(this._prevItemDiv)) {
400
+ this.element.trigger('change', selectedItem.index())
401
+ }
402
+
403
+ this._prevItemDiv = null
404
+
405
+ if (this.options.filterEnabled) {
406
+ this._filterInput.val('')
407
+ }
408
+ },
409
+
410
+ makeChoices: function () {
411
+ if (this.options.makeChoices) {
412
+ return this.options.makeChoices() || []
413
+ }
414
+ else {
415
+ return []
416
+ }
417
+ },
418
+
419
+ updateChoices: function () {
420
+ /* Will call makeChoices */
421
+ this._setOption('choices', [])
422
+ },
423
+
424
+ _makeItems: function () {
425
+ let widget = this
426
+ let choices = this._getChoices()
427
+
428
+ choices.forEach(function (choice, i) {
429
+ let itemDiv = $('<div></div>', {class: 'qui-combo-item'})
430
+
431
+ if (choice.label instanceof $) {
432
+ itemDiv.html(choice.label)
433
+ }
434
+ else {
435
+ itemDiv.html(`<div class="qui-combo-item-simple-label">${choice.label}</div>`)
436
+ }
437
+
438
+ if (choice.separator && i > 0) {
439
+ itemDiv.addClass('separator')
440
+ }
441
+
442
+ widget._itemContainer.append(itemDiv)
443
+
444
+ itemDiv.on('click', function () {
445
+ widget._selectItemDiv(itemDiv)
446
+ widget.close()
447
+ })
448
+ itemDiv.on('pointerover', function () {
449
+ if (!widget._opened) {
450
+ return
451
+ }
452
+
453
+ widget._selectItemDiv(itemDiv)
454
+ })
455
+
456
+ itemDiv.data('value', choice.value)
457
+ })
458
+
459
+ this._maxHeightSet = false
460
+ },
461
+
462
+ _getChoices: function () {
463
+ if (!this._cachedChoices) {
464
+ this._cachedChoices = this.makeChoices().concat(this.options.choices)
465
+ }
466
+
467
+ return this._cachedChoices
468
+ },
469
+
470
+ _getItemDivByValue: function (value) {
471
+ let itemDiv = null
472
+ this._itemContainer.children('div.qui-combo-item').each(function () {
473
+ let $this = $(this)
474
+ if (ObjectUtils.deepEquals($this.data('value'), value)) {
475
+ itemDiv = $this
476
+ return false
477
+ }
478
+ })
479
+
480
+ return itemDiv
481
+ },
482
+
483
+ _selectPrev: function () {
484
+ let visibleIndexes = this._itemContainer.children('div.qui-combo-item:NOT(.hidden)').map(function () {
485
+ return $(this).index()
486
+ }).toArray()
487
+
488
+ if (visibleIndexes.length === 0) {
489
+ return false
490
+ }
491
+
492
+ let selectedIndex = this._itemContainer.children('div.qui-combo-item.selected:NOT(.hidden)').index()
493
+ let newIndex = visibleIndexes.reverse().find(i => i < selectedIndex)
494
+
495
+ if (newIndex != null) {
496
+ this._selectItemDiv(this._itemContainer.children(`div.qui-combo-item:eq(${newIndex})`), true)
497
+ this._searchStr = ''
498
+
499
+ return true
500
+ }
501
+
502
+ return false
503
+ },
504
+
505
+ _selectNext: function () {
506
+ let visibleIndexes = this._itemContainer.children('div.qui-combo-item:NOT(.hidden)').map(function () {
507
+ return $(this).index()
508
+ }).toArray()
509
+
510
+ if (visibleIndexes.length === 0) {
511
+ return false
512
+ }
513
+
514
+ let selectedIndex = this._itemContainer.children('div.qui-combo-item.selected:NOT(.hidden)').index()
515
+ let newIndex = visibleIndexes.find(i => i > selectedIndex)
516
+
517
+ if (newIndex != null) {
518
+ this._selectItemDiv(this._itemContainer.children(`div.qui-combo-item:eq(${newIndex})`), true)
519
+ this._searchStr = ''
520
+
521
+ return true
522
+ }
523
+
524
+ return false
525
+ },
526
+
527
+ _selectItemDiv: function (itemDiv, scroll = false) {
528
+ if (itemDiv && itemDiv.hasClass('selected')) {
529
+ return /* Already selected */
530
+ }
531
+
532
+ this._itemContainer.children('div.qui-combo-item.selected').removeClass('selected')
533
+
534
+ if (itemDiv) {
535
+ itemDiv.addClass('selected')
536
+ if (scroll) {
537
+ let scrollTop = itemDiv.offset().top - this._itemContainer.offset().top +
538
+ this._itemContainer.scrollTop()
539
+ this._itemContainer.scrollTop(scrollTop)
540
+ }
541
+ }
542
+ },
543
+
544
+ _updateCurrentEntry: function () {
545
+ this._currentEntryDiv.html(this._itemContainer.children('div.qui-combo-item.selected').html() || '&nbsp;')
546
+ },
547
+
548
+ _updateFiltered: function () {
549
+ /* Assign a fixed max-height to each combo item - enables height animation when hiding filtered items */
550
+ if (this.element.is(':visible') && !this._maxHeightSet) {
551
+ this._maxHeightSet = true
552
+ this._itemContainer.children('div.qui-combo-item').each(function () {
553
+ let $this = $(this)
554
+ $this.css('max-height', $this.height())
555
+ })
556
+ }
557
+
558
+ let searchText = this._filterInput.val().trim().toLowerCase()
559
+ searchText = searchText.replace(/\s\s+/g, ' ')
560
+ let searchTextParts = searchText.split(' ')
561
+ let children = this._itemContainer.children('div.qui-combo-item')
562
+
563
+ let filterFunc = this.options.filterFunc
564
+ if (!filterFunc) {
565
+ /* Default filter function */
566
+ filterFunc = function (choice, searchText) {
567
+ let labelText = choice.label
568
+ if (labelText instanceof $) {
569
+ labelText = labelText.text()
570
+ }
571
+ else {
572
+ labelText = labelText.toString()
573
+ }
574
+
575
+ return this._textMatchesFilter(labelText, searchText)
576
+ }.bind(this)
577
+ }
578
+
579
+ let odd = true
580
+ let visibleCount = 0
581
+ this._getChoices().forEach(function (choice, i) {
582
+
583
+ let visible = !searchText || searchTextParts.every(p => filterFunc(choice, p))
584
+ if (visibleCount > MAX_VISIBLE_ITEMS && this._maxHeightSet) {
585
+ visible = false
586
+ }
587
+ if (visible) {
588
+ visibleCount++
589
+ odd = !odd
590
+ }
591
+
592
+ let classList = children[i].classList
593
+ classList.toggle('hidden', !visible)
594
+ if (visible) {
595
+ classList.toggle('odd', odd)
596
+ }
597
+
598
+ }, this)
599
+ },
600
+
601
+ _textMatchesFilter: function (text, filter) {
602
+ return StringUtils.intelliSearch(text, filter) != null
603
+ },
604
+
605
+ _setOption: function (key, value) {
606
+ this._super(key, value)
607
+
608
+ switch (key) {
609
+ case 'readonly':
610
+ this.element.toggleClass('readonly', value)
611
+ break
612
+
613
+ case 'choices': {
614
+ let selectedValue = this.getValue()
615
+ this._itemContainer.children().detach()
616
+ this._cachedChoices = null
617
+ this._makeItems()
618
+ this.setValue(selectedValue)
619
+ this._updateFiltered()
620
+ break
621
+ }
622
+
623
+ case 'disabled':
624
+ this.element.toggleClass('disabled', value)
625
+ if (value) {
626
+ this.element.removeAttr('tabIndex')
627
+ }
628
+ else {
629
+ this.element.attr('tabIndex', 0)
630
+ }
631
+ break
632
+
633
+ case 'filterEnabled':
634
+ this.element.toggleClass('filter-enabled', !!value)
635
+ this._updateFiltered()
636
+ break
637
+
638
+ case 'filterFunc':
639
+ this._updateFiltered()
640
+ break
641
+
642
+ }
643
+ }
644
+
645
+ })
@@ -0,0 +1,17 @@
1
+
2
+ import './check-button.js'
3
+ import './choice-buttons.js'
4
+ import './color-combo.js'
5
+ import './combo.js'
6
+ import './email-input.js'
7
+ import './file-picker.js'
8
+ import './labels.js'
9
+ import './numeric-input.js'
10
+ import './password-input.js'
11
+ import './phone-input.js'
12
+ import './progress-disk.js'
13
+ import './push-button.js'
14
+ import './slider.js'
15
+ import './text-area.js'
16
+ import './text-input.js'
17
+ import './up-down.js'
@@ -0,0 +1,7 @@
1
+
2
+ import $ from '$qui/lib/jquery.module.js'
3
+
4
+ import * as TextInput from './text-input.js' /* Needed */
5
+
6
+
7
+ $.widget('qui.emailinput', $.qui.textinput, {type: 'email'})