@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,155 @@
1
+
2
+ import $ from '$qui/lib/jquery.module.js'
3
+
4
+ import * as Theme from '$qui/theme.js'
5
+ import * as Colors from '$qui/utils/colors.js'
6
+
7
+ import * as BaseWidget from '../base-widget.js' /* Needed */
8
+
9
+
10
+ const STYLES = [
11
+ 'foreground',
12
+ 'interactive',
13
+ 'highlight',
14
+ 'danger',
15
+ 'colored'
16
+ ]
17
+
18
+
19
+ $.widget('qui.pushbutton', $.qui.basewidget, {
20
+
21
+ options: {
22
+ style: 'interactive',
23
+ caption: 'Button',
24
+ backgroundColor: '@interactive-color',
25
+ backgroundActiveColor: '@interactive-active-color',
26
+ foregroundColor: '@foreground-interactive-color',
27
+ icon: null,
28
+ disabled: false
29
+ },
30
+
31
+ _create: function () {
32
+ let widget = this
33
+
34
+ this.element.addClass('qui-base-button qui-push-button')
35
+ if (this.options.disabled) {
36
+ this.element.addClass('disabled')
37
+ }
38
+ else {
39
+ this.element.attr('tabIndex', 0) /* Make element focusable */
40
+ }
41
+
42
+ this._setStyle(this.options.style)
43
+ this._setIcon(this.options.icon)
44
+ this._setCaption(this.options.caption)
45
+
46
+ this.element.on('click', function (e) {
47
+ if (widget.options.disabled) {
48
+ e.stopImmediatePropagation()
49
+ }
50
+ })
51
+
52
+ /* When specifying custom colors, we have to manually update background color */
53
+ this.element.on('pressed released', () => this._updateStyle())
54
+
55
+ this.element.on('keydown', function (e) {
56
+ if (e.which === 32) {
57
+ this.element.trigger('click')
58
+ }
59
+ }.bind(this))
60
+ },
61
+
62
+ _setStyle: function (style) {
63
+
64
+ this.element.removeClass(STYLES.map(s => `qui-${s}-button`))
65
+ this.element.addClass(`qui-${style}-button`)
66
+
67
+ this._updateStyle()
68
+ },
69
+
70
+ _updateStyle: function () {
71
+ if (this.options.style === 'colored' && !this.options.disabled) {
72
+ if (this.element.hasClass('active')) {
73
+ this.element.css('background', Theme.getColor(this.options.backgroundActiveColor))
74
+ }
75
+ else {
76
+ this.element.css('background', Theme.getColor(this.options.backgroundColor))
77
+ }
78
+
79
+ this.element.css('color', Theme.getColor(this.options.foregroundColor))
80
+
81
+ /* Manually compute and supply box-shadow focus color */
82
+ let shadowColor = Colors.alpha(Theme.getColor(this.options.backgroundColor), 0.3)
83
+ this.element[0].style.setProperty('--focus-shadow-color', shadowColor)
84
+ }
85
+ else {
86
+ this.element.css('background', '')
87
+ this.element.css('color', '')
88
+ }
89
+ },
90
+
91
+ _setIcon: function (icon) {
92
+ this.element.toggleClass('has-icon', icon)
93
+ this.element.children('div.qui-push-button-icon').remove()
94
+
95
+ if (icon) {
96
+ let iconDiv = $('<div></div>', {class: 'qui-push-button-icon'})
97
+ let variant = 'foreground-interactive' /* Default */
98
+
99
+ if (this.options.disabled) {
100
+ variant = 'disabled'
101
+ }
102
+ else if ((this.options.style === 'colored') && this.options.foregroundColor.startsWith('@')) {
103
+ variant = this.options.foregroundColor.slice(1, -6)
104
+ }
105
+
106
+ icon = icon.alterDefault({variant: variant})
107
+ icon = icon.alter({scale: 0.75})
108
+ icon.applyTo(iconDiv)
109
+
110
+ this.element.prepend(iconDiv)
111
+ }
112
+ },
113
+
114
+ _setCaption: function (caption) {
115
+ this.element.children('span.qui-push-button-caption').remove()
116
+
117
+ let captionDiv = $('<span></span>', {class: 'qui-push-button-caption'})
118
+ captionDiv.html(caption)
119
+
120
+ this.element.append(captionDiv)
121
+ },
122
+
123
+ _setOption: function (key, value) {
124
+ this._super(key, value)
125
+
126
+ switch (key) {
127
+ case 'disabled':
128
+ this.element.toggleClass('disabled', value)
129
+ if (value) {
130
+ this.element.removeAttr('tabIndex')
131
+ }
132
+ else {
133
+ this.element.attr('tabIndex', 0)
134
+ }
135
+
136
+ this._updateStyle()
137
+ break
138
+
139
+ case 'caption':
140
+ this._setCaption(value)
141
+ break
142
+
143
+ case 'style':
144
+ this._setStyle(value)
145
+ /* Icon must also be updated as the foreground color might have changed */
146
+ this._setIcon(this.options.icon)
147
+ break
148
+
149
+ case 'icon':
150
+ this._setIcon(value)
151
+ break
152
+ }
153
+ }
154
+
155
+ })
@@ -0,0 +1,455 @@
1
+
2
+ import $ from '$qui/lib/jquery.module.js'
3
+
4
+ import * as Gestures from '$qui/utils/gestures.js'
5
+
6
+ import * as BaseWidget from '../base-widget.js' /* Needed */
7
+
8
+
9
+ const TEMPORARY_SHOW_VALUE_TIMEOUT = 500 /* Seconds */
10
+
11
+
12
+ $.widget('qui.slider', $.qui.basewidget, {
13
+
14
+ options: {
15
+ value: 0,
16
+ ticks: [{label: 0, value: 0}, {label: 50, value: 50}, {label: 100, value: 100}],
17
+ ticksStep: 1,
18
+ continuousChange: true,
19
+ equidistant: false,
20
+ fastFactor: 5,
21
+ caption: '%s',
22
+ readonly: false,
23
+ disabled: false
24
+ },
25
+
26
+ _create: function () {
27
+ /* Create the widget elements */
28
+
29
+ this.element.addClass('qui-slider')
30
+ if (this.options.readonly) {
31
+ this.element.addClass('readonly')
32
+ }
33
+ if (this.options.disabled) {
34
+ this.element.addClass('disabled')
35
+ }
36
+ else {
37
+ this.element.attr('tabIndex', 0) /* Make the container focusable */
38
+ }
39
+
40
+ this._labels = $('<div></div>', {class: 'qui-slider-labels'})
41
+ this.element.append(this._labels)
42
+
43
+ this._barContainer = $('<div></div>', {class: 'qui-slider-bar-container'})
44
+ this.element.append(this._barContainer)
45
+
46
+ this._bar = $('<div></div>', {class: 'qui-slider-bar'})
47
+ this._barContainer.append(this._bar)
48
+
49
+ this._cursor = $('<div></div>', {class: 'qui-slider-cursor qui-base-button'})
50
+ this._bar.append(this._cursor)
51
+
52
+ this._cursorLabel = $('<span></span>', {class: 'qui-slider-label qui-slider-cursor-label'})
53
+ this._labels.append(this._cursorLabel)
54
+
55
+ this._temporaryShowValueHandle = null
56
+ this._isDragged = false
57
+
58
+ this._maxVal = this.options.value
59
+ this._minVal = this.options.value
60
+ this._curVal = this.options.value
61
+
62
+ let widget = this
63
+
64
+ Gestures.enableDragging(
65
+ this.element,
66
+ /* onMove = */ function (elemX, elemY, deltaX, deltaY, pageX, pageY) {
67
+ if (widget.options.readonly) {
68
+ return
69
+ }
70
+
71
+ let offset = widget._bar.offset()
72
+ let pos = pageX - offset.left
73
+ pos = pos / widget._getWidth()
74
+ pos = widget._bestPos(pos)
75
+
76
+ widget._setPos(pos)
77
+
78
+ if (widget.options.continuousChange) {
79
+ widget.element.trigger('change', widget._curVal)
80
+ }
81
+ },
82
+ /* onBegin = */ function () {
83
+ if (widget.options.readonly || widget.options.disabled) {
84
+ return false
85
+ }
86
+
87
+ widget.element.focus()
88
+ widget.element.addClass('active')
89
+ widget._isDragged = true
90
+ },
91
+ /* onEnd = */ function () {
92
+ if (!widget.options.continuousChange && !widget.options.readonly) {
93
+ widget.element.trigger('change', widget._curVal)
94
+ }
95
+ widget.element.removeClass('active')
96
+ widget._isDragged = false
97
+ }
98
+ )
99
+
100
+ this.element.on('mousewheel', function (e, delta) {
101
+ if (widget.options.readonly || widget.options.disabled) {
102
+ return
103
+ }
104
+
105
+ /* Ignore scroll events on unfocused widget */
106
+ if (!widget.element.is(':focus')) {
107
+ return
108
+ }
109
+
110
+ let changed
111
+ if (delta > 0) {
112
+ changed = widget._increase()
113
+ }
114
+ else {
115
+ changed = widget._decrease()
116
+ }
117
+
118
+ if (changed) {
119
+ widget._temporarilyShowValue()
120
+ widget.element.trigger('change', widget._curVal)
121
+ return false
122
+ }
123
+ })
124
+
125
+ this.element.on('keydown', function (e) {
126
+ if (widget.options.readonly) {
127
+ return
128
+ }
129
+
130
+ let changed = false
131
+
132
+ switch (e.which) {
133
+ case 38: /* Up */
134
+ case 37: /* Left */
135
+ if (widget._decrease()) {
136
+ widget._temporarilyShowValue()
137
+ widget.element.trigger('change', widget._curVal)
138
+ return false
139
+ }
140
+
141
+ break
142
+
143
+ case 40: /* Down */
144
+ case 39: /* Right */
145
+ if (widget._increase()) {
146
+ widget._temporarilyShowValue()
147
+ widget.element.trigger('change', widget._curVal)
148
+ return false
149
+ }
150
+
151
+ break
152
+
153
+ case 33: /* Page-up */
154
+ for (let i = 0; i < widget.options.fastFactor; i++) {
155
+ if (widget._decrease()) {
156
+ changed = true
157
+ }
158
+ }
159
+ if (changed) {
160
+ widget._temporarilyShowValue()
161
+ widget.element.trigger('change', widget._curVal)
162
+ return false
163
+ }
164
+
165
+ break
166
+
167
+ case 34: /* Page-down */
168
+ for (let i = 0; i < widget.options.fastFactor; i++) {
169
+ if (widget._increase()) {
170
+ changed = true
171
+ }
172
+ }
173
+ if (changed) {
174
+ widget._temporarilyShowValue()
175
+ widget.element.trigger('change', widget._curVal)
176
+ return false
177
+ }
178
+
179
+ break
180
+
181
+ case 36: /* Home */
182
+ while (widget._decrease()) {
183
+ changed = true
184
+ }
185
+ if (changed) {
186
+ widget._temporarilyShowValue()
187
+ widget.element.trigger('change', widget._curVal)
188
+ return false
189
+ }
190
+
191
+ break
192
+
193
+ case 35: /* End */
194
+ while (widget._increase()) {
195
+ changed = true
196
+ }
197
+ if (changed) {
198
+ widget._temporarilyShowValue()
199
+ widget.element.trigger('change', widget._curVal)
200
+ return false
201
+ }
202
+
203
+ break
204
+ }
205
+ })
206
+
207
+ this._updateTicks()
208
+ },
209
+
210
+ setValue: function (val) {
211
+ val = Math.max(this._minVal, Math.min(this._maxVal, val))
212
+ this._setPos(this._valToPos(val))
213
+ },
214
+
215
+ getValue: function () {
216
+ return this._curVal
217
+ },
218
+
219
+ _updateTicks: function () {
220
+ this._maxVal = Math.max.apply(Math, this.options.ticks.map(t => t.value))
221
+ this._minVal = Math.min.apply(Math, this.options.ticks.map(t => t.value))
222
+ this._makeLabels()
223
+
224
+ /* Update the position and the current value */
225
+ this._curVal = Math.min(this._maxVal, Math.max(this._minVal, this._curVal))
226
+ this._setPos(this._valToPos(this._curVal))
227
+
228
+ this._labels.toggleClass('all-ticks-visible', this.options.ticksStep === 1)
229
+ },
230
+
231
+ _getWidth: function () {
232
+ return this._bar.width() || 100
233
+ },
234
+
235
+ _getPos: function () {
236
+ return this._cursor.position().left / this._getWidth()
237
+ },
238
+
239
+ _setPos: function (pos) {
240
+ pos = Math.max(0, Math.min(1, pos))
241
+ let val = this._posToVal(pos)
242
+
243
+ /* Find matching tick */
244
+ let tick = this.options.ticks.find(t => t.value === val)
245
+ if (!tick) {
246
+ return
247
+ }
248
+
249
+ /* Update cursor caption */
250
+ this._cursorLabel.html(tick.label)
251
+
252
+ /* Update cursor position */
253
+ this._cursor.css('left', `${(pos * 100)}%`)
254
+ this._cursorLabel.css('left', `${(pos * 100 - 15)}%`)
255
+ this._curVal = val
256
+
257
+
258
+ /* Hide overlapped tick labels */
259
+ let cursorLabelLeft = parseInt(this._cursorLabel[0].style.left) /* Percent */
260
+
261
+ /* Cursor overlaps neighbors only if not all ticks are visible */
262
+ let overlapWidth = this.options.ticksStep === 1 ? 0 : 15 /* Percent */
263
+
264
+ this._labels.children('span.qui-slider-label:NOT(.qui-slider-cursor-label)').each(function () {
265
+ let labelElement = $(this)
266
+ let labelLeft = parseInt(this.style.left) /* Percent */
267
+
268
+ let overlapped = (cursorLabelLeft <= labelLeft + overlapWidth) &&
269
+ (cursorLabelLeft + overlapWidth >= labelLeft)
270
+ let completelyOverlapped = Math.abs(cursorLabelLeft - labelLeft) / Math.abs(cursorLabelLeft) < 0.01
271
+ labelElement.toggleClass('overlapped', overlapped)
272
+ labelElement.toggleClass('completely-overlapped', completelyOverlapped)
273
+ })
274
+ },
275
+
276
+ _valToPos: function (val) {
277
+ if (this.options.equidistant) {
278
+ let index = this.options.ticks.findIndex(function (tick) {
279
+ return tick.value === val
280
+ })
281
+
282
+ if (index < 0) {
283
+ index = 0
284
+ }
285
+
286
+ return index / (this.options.ticks.length - 1)
287
+ }
288
+ else {
289
+ return (val - this._minVal) / (this._maxVal - this._minVal)
290
+ }
291
+ },
292
+
293
+ _posToVal: function (pos) {
294
+ if (this.options.equidistant) {
295
+ let index = Math.round(pos * (this.options.ticks.length - 1))
296
+
297
+ return this.options.ticks[index].value
298
+ }
299
+ else {
300
+ return this._minVal + pos * (this._maxVal - this._minVal)
301
+ }
302
+ },
303
+
304
+ _bestPos: function (pos) {
305
+ pos = Math.max(0, Math.min(1, pos))
306
+
307
+ let minDif = Infinity
308
+ let bp = null
309
+ for (let i = 0; i < this.options.ticks.length; i++) {
310
+ let tick = this.options.ticks[i]
311
+ let p = this._valToPos(tick.value)
312
+ let dif = Math.abs(p - pos)
313
+ if (dif < minDif) {
314
+ minDif = dif
315
+ bp = p
316
+ }
317
+ }
318
+
319
+ if (bp != null) {
320
+ pos = bp
321
+ }
322
+
323
+ return pos
324
+ },
325
+
326
+ _increase: function () {
327
+ let index
328
+ if (this.options.equidistant) {
329
+ index = Math.round(this._getPos() * (this.options.ticks.length - 1))
330
+ if (index < this.options.ticks.length - 1) {
331
+ index++
332
+ this._setPos(index / (this.options.ticks.length - 1))
333
+
334
+ return true
335
+ }
336
+ }
337
+ else {
338
+ index = this.options.ticks.findIndex(function (tick) {
339
+ return tick.value === this._curVal
340
+ }, this)
341
+
342
+ if (index < 0) {
343
+ index = 0
344
+ }
345
+
346
+ if (index < this.options.ticks.length - 1) {
347
+ index++
348
+ this._setPos(this._valToPos(this.options.ticks[index].value))
349
+
350
+ return true
351
+ }
352
+ }
353
+
354
+ return false
355
+ },
356
+
357
+ _decrease: function () {
358
+ let index
359
+ if (this.options.equidistant) {
360
+ index = Math.round(this._getPos() * (this.options.ticks.length - 1))
361
+ if (index > 0) {
362
+ index--
363
+ this._setPos(index / (this.options.ticks.length - 1))
364
+
365
+ return true
366
+ }
367
+ }
368
+ else {
369
+ index = this.options.ticks.findIndex(function (tick) {
370
+ return tick.value === this._curVal
371
+ }, this)
372
+
373
+ if (index < 0) {
374
+ index = 0
375
+ }
376
+
377
+ if (index > 0) {
378
+ index--
379
+ this._setPos(this._valToPos(this.options.ticks[index].value))
380
+
381
+ return true
382
+ }
383
+ }
384
+
385
+ return false
386
+ },
387
+
388
+ _makeLabels: function () {
389
+ this._labels.children('span.qui-slider-label:NOT(.qui-slider-cursor-label)').remove()
390
+
391
+ /* Ensure ticksStep is always strictly positive */
392
+ let ticksStep = this.options.ticksStep
393
+ if (ticksStep <= 0) {
394
+ ticksStep = 1
395
+ }
396
+
397
+ for (let i = 0; i < this.options.ticks.length; i += ticksStep) {
398
+ let tick = this.options.ticks[i]
399
+ let span = $('<span></span>', {class: 'qui-slider-label'})
400
+ span.text(tick.label)
401
+ this._cursorLabel.before(span)
402
+
403
+ /* Determine the position */
404
+ let pos
405
+ if (this.options.equidistant) {
406
+ pos = i / (this.options.ticks.length - 1)
407
+ }
408
+ else {
409
+ pos = this._valToPos(tick.value)
410
+ }
411
+
412
+ span.css('left', `${(pos * 100 - 15)}%`)
413
+ }
414
+ },
415
+
416
+ _temporarilyShowValue: function () {
417
+ if (this._temporaryShowValueHandle != null) {
418
+ clearTimeout(this._temporaryShowValueHandle)
419
+ }
420
+
421
+ this.element.addClass('active')
422
+
423
+ this._temporaryShowValueHandle = setTimeout(function () {
424
+ if (!this._isDragged) {
425
+ this.element.removeClass('active')
426
+ }
427
+ }.bind(this), TEMPORARY_SHOW_VALUE_TIMEOUT)
428
+ },
429
+
430
+ _setOption: function (key, value) {
431
+ this._super(key, value)
432
+
433
+ switch (key) {
434
+ case 'ticks':
435
+ case 'equidistant':
436
+ this._updateTicks()
437
+ break
438
+
439
+ case 'readonly':
440
+ this.element.toggleClass('readonly', value)
441
+ break
442
+
443
+ case 'disabled':
444
+ this.element.toggleClass('disabled', value)
445
+ if (value) {
446
+ this.element.removeAttr('tabIndex')
447
+ }
448
+ else {
449
+ this.element.attr('tabIndex', 0)
450
+ }
451
+ break
452
+ }
453
+ }
454
+
455
+ })
@@ -0,0 +1,52 @@
1
+
2
+ import $ from '$qui/lib/jquery.module.js'
3
+
4
+ import * as TextInput from './text-input.js' /* Needed */
5
+
6
+
7
+ $.widget('qui.textarea', $.qui.textinput, {
8
+
9
+ options: {
10
+ columns: null,
11
+ rows: null,
12
+ wrap: false,
13
+ resize: null
14
+ },
15
+
16
+ type: 'textarea',
17
+
18
+ _create: function () {
19
+ this._super()
20
+
21
+ this._setOption('columns', this.options.columns)
22
+ this._setOption('rows', this.options.rows)
23
+ this._setOption('wrap', this.options.wrap)
24
+ this._setOption('resize', this.options.resize)
25
+
26
+ this._input.on('keydown', function (e) {
27
+ if (e.which === 13) { /* Enter */
28
+ e.stopPropagation()
29
+ }
30
+ })
31
+ },
32
+
33
+ _setOption: function (key, value) {
34
+ this._super(key, value)
35
+
36
+ switch (key) {
37
+ case 'columns':
38
+ case 'rows':
39
+ this._input.attr(key, value || '')
40
+ break
41
+
42
+ case 'wrap':
43
+ this._input.attr('wrap', value ? 'hard' : 'off')
44
+ break
45
+
46
+ case 'resize':
47
+ this._input.css('resize', value)
48
+ break
49
+ }
50
+ }
51
+
52
+ })