@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.
- package/.eslintignore +2 -0
- package/.eslintrc.json +492 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
- package/.github/ISSUE_TEMPLATE/improvement_proposal.md +20 -0
- package/.github/workflows/main.yml +74 -0
- package/.pre-commit-config.yaml +8 -0
- package/LICENSE.txt +177 -0
- package/README.md +4 -0
- package/font/dejavusans-bold.woff +0 -0
- package/font/dejavusans-bolditalic.woff +0 -0
- package/font/dejavusans-italic.woff +0 -0
- package/font/dejavusans-regular.woff +0 -0
- package/img/qui-icons.svg +1937 -0
- package/js/base/base.js +47 -0
- package/js/base/condition-variable.js +92 -0
- package/js/base/errors.js +36 -0
- package/js/base/i18n.js +20 -0
- package/js/base/mixwith.js +135 -0
- package/js/base/require-js-compat.js +78 -0
- package/js/base/signal.js +91 -0
- package/js/base/singleton.js +66 -0
- package/js/base/timer.js +126 -0
- package/js/config.js +184 -0
- package/js/forms/common-fields/check-field.js +42 -0
- package/js/forms/common-fields/choice-buttons-field.js +30 -0
- package/js/forms/common-fields/color-combo-field.js +37 -0
- package/js/forms/common-fields/combo-field.js +108 -0
- package/js/forms/common-fields/common-fields.js +23 -0
- package/js/forms/common-fields/composite-field.js +132 -0
- package/js/forms/common-fields/custom-html-field.js +51 -0
- package/js/forms/common-fields/email-field.js +30 -0
- package/js/forms/common-fields/file-picker-field.js +46 -0
- package/js/forms/common-fields/jquery-ui-field.js +111 -0
- package/js/forms/common-fields/labels-field.js +69 -0
- package/js/forms/common-fields/numeric-field.js +39 -0
- package/js/forms/common-fields/password-field.js +28 -0
- package/js/forms/common-fields/phone-field.js +26 -0
- package/js/forms/common-fields/progress-disk-field.js +69 -0
- package/js/forms/common-fields/push-button-field.js +138 -0
- package/js/forms/common-fields/slider-field.js +51 -0
- package/js/forms/common-fields/text-area-field.js +34 -0
- package/js/forms/common-fields/text-field.js +89 -0
- package/js/forms/common-fields/up-down-field.js +85 -0
- package/js/forms/common-forms/common-forms.js +16 -0
- package/js/forms/common-forms/options-form.js +77 -0
- package/js/forms/common-forms/page-form.js +115 -0
- package/js/forms/form-button.js +202 -0
- package/js/forms/form-field.js +1183 -0
- package/js/forms/form.js +1181 -0
- package/js/forms/forms.js +68 -0
- package/js/global-glass.js +100 -0
- package/js/icons/default-stock.js +173 -0
- package/js/icons/icon.js +64 -0
- package/js/icons/icons.js +16 -0
- package/js/icons/multi-state-sprites-icon.js +362 -0
- package/js/icons/stock-icon.js +219 -0
- package/js/icons/stock.js +98 -0
- package/js/icons/stocks.js +57 -0
- package/js/index.js +232 -0
- package/js/lib/jquery.longpress.js +79 -0
- package/js/lib/jquery.module.js +4 -0
- package/js/lib/logger.module.js +4 -0
- package/js/lib/pep.module.js +4 -0
- package/js/lists/common-items/common-items.js +5 -0
- package/js/lists/common-items/icon-label-list-item.js +86 -0
- package/js/lists/common-lists/common-lists.js +5 -0
- package/js/lists/common-lists/page-list.js +53 -0
- package/js/lists/list-item.js +147 -0
- package/js/lists/list.js +636 -0
- package/js/lists/lists.js +26 -0
- package/js/main-ui/main-ui.js +64 -0
- package/js/main-ui/menu-bar.js +144 -0
- package/js/main-ui/options-bar.js +181 -0
- package/js/main-ui/status.js +185 -0
- package/js/main-ui/top-bar.js +59 -0
- package/js/messages/common-message-forms/common-message-forms.js +7 -0
- package/js/messages/common-message-forms/confirm-message-form.js +81 -0
- package/js/messages/common-message-forms/simple-message-form.js +67 -0
- package/js/messages/common-message-forms/sticky-simple-message-form.js +27 -0
- package/js/messages/message-form.js +107 -0
- package/js/messages/messages.js +21 -0
- package/js/messages/sticky-modal-page.js +98 -0
- package/js/messages/sticky-modal-progress-message.js +27 -0
- package/js/messages/toast.js +164 -0
- package/js/navigation.js +654 -0
- package/js/pages/breadcrumbs.js +124 -0
- package/js/pages/common-pages/common-pages.js +6 -0
- package/js/pages/common-pages/modal-progress-page.js +83 -0
- package/js/pages/common-pages/structured-page.js +46 -0
- package/js/pages/page.js +1018 -0
- package/js/pages/pages-context.js +154 -0
- package/js/pages/pages.js +252 -0
- package/js/pwa.js +337 -0
- package/js/sections/section.js +612 -0
- package/js/sections/sections.js +300 -0
- package/js/tables/common-cells/common-cells.js +7 -0
- package/js/tables/common-cells/icon-label-table-cell.js +68 -0
- package/js/tables/common-cells/push-button-table-cell.js +133 -0
- package/js/tables/common-cells/simple-table-cell.js +37 -0
- package/js/tables/common-tables/common-tables.js +5 -0
- package/js/tables/common-tables/page-table.js +55 -0
- package/js/tables/table-cell.js +198 -0
- package/js/tables/table-row.js +126 -0
- package/js/tables/table.js +492 -0
- package/js/tables/tables.js +36 -0
- package/js/theme.js +304 -0
- package/js/utils/ajax.js +126 -0
- package/js/utils/array.js +194 -0
- package/js/utils/colors.js +445 -0
- package/js/utils/cookies.js +65 -0
- package/js/utils/crypto.js +439 -0
- package/js/utils/css.js +234 -0
- package/js/utils/date.js +300 -0
- package/js/utils/files.js +27 -0
- package/js/utils/gestures.js +165 -0
- package/js/utils/html.js +76 -0
- package/js/utils/misc.js +81 -0
- package/js/utils/object.js +324 -0
- package/js/utils/promise.js +49 -0
- package/js/utils/string.js +192 -0
- package/js/utils/url.js +187 -0
- package/js/utils/utils.js +3 -0
- package/js/utils/visibility-manager.js +211 -0
- package/js/views/common-views/common-views.js +7 -0
- package/js/views/common-views/icon-label-view.js +210 -0
- package/js/views/common-views/progress-view.js +89 -0
- package/js/views/common-views/structured-view.js +368 -0
- package/js/views/view.js +467 -0
- package/js/views/views.js +3 -0
- package/js/widgets/base-widget.js +23 -0
- package/js/widgets/common-widgets/check-button.js +109 -0
- package/js/widgets/common-widgets/choice-buttons.js +322 -0
- package/js/widgets/common-widgets/color-combo.js +104 -0
- package/js/widgets/common-widgets/combo.js +645 -0
- package/js/widgets/common-widgets/common-widgets.js +17 -0
- package/js/widgets/common-widgets/email-input.js +7 -0
- package/js/widgets/common-widgets/file-picker.js +133 -0
- package/js/widgets/common-widgets/labels.js +132 -0
- package/js/widgets/common-widgets/numeric-input.js +49 -0
- package/js/widgets/common-widgets/password-input.js +91 -0
- package/js/widgets/common-widgets/phone-input.js +7 -0
- package/js/widgets/common-widgets/progress-disk.js +174 -0
- package/js/widgets/common-widgets/push-button.js +155 -0
- package/js/widgets/common-widgets/slider.js +455 -0
- package/js/widgets/common-widgets/text-area.js +52 -0
- package/js/widgets/common-widgets/text-input.js +174 -0
- package/js/widgets/common-widgets/up-down.js +351 -0
- package/js/widgets/widgets.js +57 -0
- package/js/window.js +557 -0
- package/jsdoc.conf.json +20 -0
- package/less/base.less +123 -0
- package/less/forms/common-fields.less +101 -0
- package/less/forms/common-forms.less +5 -0
- package/less/forms/form-button.less +21 -0
- package/less/forms/form-field.less +266 -0
- package/less/forms/form.less +131 -0
- package/less/global-glass.less +64 -0
- package/less/icon-label-view.less +82 -0
- package/less/icons.less +144 -0
- package/less/lists.less +105 -0
- package/less/main-ui.less +328 -0
- package/less/messages.less +189 -0
- package/less/no-effects.less +24 -0
- package/less/pages/breadcrumbs.less +98 -0
- package/less/pages/common-pages.less +36 -0
- package/less/pages/page.less +70 -0
- package/less/progress-view.less +51 -0
- package/less/stock-icons.less +43 -0
- package/less/structured-view.less +245 -0
- package/less/tables.less +84 -0
- package/less/theme-dark.less +133 -0
- package/less/theme-light.less +132 -0
- package/less/theme.less +419 -0
- package/less/visibility-manager.less +11 -0
- package/less/widgets/check-button.less +96 -0
- package/less/widgets/choice-buttons.less +160 -0
- package/less/widgets/color-combo.less +33 -0
- package/less/widgets/combo.less +230 -0
- package/less/widgets/common-buttons.less +120 -0
- package/less/widgets/common.less +24 -0
- package/less/widgets/input.less +258 -0
- package/less/widgets/labels.less +81 -0
- package/less/widgets/progress-disk.less +70 -0
- package/less/widgets/slider.less +199 -0
- package/less/widgets/updown.less +115 -0
- package/less/widgets/various.less +36 -0
- package/package.json +47 -0
- package/pyproject.toml +45 -0
- package/qui/__init__.py +110 -0
- package/qui/constants.py +1 -0
- package/qui/exceptions.py +2 -0
- package/qui/j2template.py +71 -0
- package/qui/settings.py +60 -0
- package/qui/templates/manifest.json +25 -0
- package/qui/templates/qui.html +126 -0
- package/qui/templates/service-worker.js +188 -0
- package/qui/web/__init__.py +0 -0
- package/qui/web/tornado.py +220 -0
- package/scripts/postinstall.sh +10 -0
- package/webpack/webpack-adjust-css-urls-loader.js +36 -0
- package/webpack/webpack-common.js +384 -0
package/js/views/view.js
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
|
|
2
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
3
|
+
|
|
4
|
+
import {AssertionError} from '$qui/base/errors.js'
|
|
5
|
+
import {Mixin} from '$qui/base/mixwith.js'
|
|
6
|
+
import * as Toast from '$qui/messages/toast.js'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @alias qui.views.STATE_NORMAL
|
|
11
|
+
*/
|
|
12
|
+
export const STATE_NORMAL = 'normal'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @alias qui.views.STATE_WARNING
|
|
16
|
+
*/
|
|
17
|
+
export const STATE_WARNING = 'warning'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @alias qui.views.STATE_ERROR
|
|
21
|
+
*/
|
|
22
|
+
export const STATE_ERROR = 'error'
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @alias qui.views.STATE_PROGRESS
|
|
26
|
+
*/
|
|
27
|
+
export const STATE_PROGRESS = 'progress'
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/** @lends qui.views.ViewMixin */
|
|
31
|
+
const ViewMixin = Mixin((superclass = Object) => {
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* A mixin to be used with classes that behave as views (have a visual HTML representation).
|
|
35
|
+
* @alias qui.views.ViewMixin
|
|
36
|
+
* @mixin
|
|
37
|
+
*/
|
|
38
|
+
class ViewMixin extends superclass {
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @constructs
|
|
42
|
+
* @param {String} [cssClass] additional CSS classes to set to the view element
|
|
43
|
+
* @param {...*} args parent class parameters
|
|
44
|
+
*/
|
|
45
|
+
constructor({cssClass = null, ...args} = {}) {
|
|
46
|
+
super(args)
|
|
47
|
+
|
|
48
|
+
/* ViewMixin is prepared to be initialized multiple times along the inheritance path;
|
|
49
|
+
* this may happen when inheriting ViewMixin more than once through mixins */
|
|
50
|
+
|
|
51
|
+
if (this._html === undefined) {
|
|
52
|
+
this._html = null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (this._state === undefined) {
|
|
56
|
+
this._state = STATE_NORMAL
|
|
57
|
+
this._warningMessage = null
|
|
58
|
+
this._errorMessage = null
|
|
59
|
+
this._progressPercent = null
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!this._cssClass) {
|
|
63
|
+
this._cssClass = cssClass
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
this._cssClass += ` ${cssClass}`
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
/* HTML */
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Create the HTML element of this view.
|
|
75
|
+
* @abstract
|
|
76
|
+
* @returns {jQuery}
|
|
77
|
+
*/
|
|
78
|
+
makeHTML() {
|
|
79
|
+
return $('<div></div>')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Override this to further initialize the HTML element of this view.
|
|
84
|
+
* @param {jQuery} html the HTML element to be initialized
|
|
85
|
+
*/
|
|
86
|
+
initHTML(html) {
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Return the HTML element of this view.
|
|
91
|
+
* @returns {jQuery}
|
|
92
|
+
*/
|
|
93
|
+
getHTML() {
|
|
94
|
+
if (this._html == null) {
|
|
95
|
+
this._html = this.makeHTML()
|
|
96
|
+
this.initHTML(this._html)
|
|
97
|
+
|
|
98
|
+
if (this._cssClass) {
|
|
99
|
+
this._html.addClass(this._cssClass)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.init()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return this._html
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Tells if the HTML element of this view has been created.
|
|
110
|
+
* @return {Boolean}
|
|
111
|
+
*/
|
|
112
|
+
hasHTML() {
|
|
113
|
+
return this._html != null
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Initialize the view. Called after the HTML has been created and initialized.
|
|
118
|
+
*/
|
|
119
|
+
init() {
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
/* State */
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Update the current state.
|
|
127
|
+
* @param {String} state the desired state
|
|
128
|
+
*/
|
|
129
|
+
setState(state) {
|
|
130
|
+
/* Make sure we have the HTML created before switching states */
|
|
131
|
+
this.getHTML()
|
|
132
|
+
|
|
133
|
+
if (this._state !== state) {
|
|
134
|
+
this.leaveState(this._state, state)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let oldState = this._state
|
|
138
|
+
this._state = state
|
|
139
|
+
|
|
140
|
+
this.enterState(oldState, state)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Return the current view state.
|
|
145
|
+
* @returns {String}
|
|
146
|
+
*/
|
|
147
|
+
getState() {
|
|
148
|
+
return this._state
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Define the behavior of the view when entering states. Entering a state usually means showing a visual element
|
|
153
|
+
* corresponding to that state.
|
|
154
|
+
* @param {String} oldState
|
|
155
|
+
* @param {String} newState
|
|
156
|
+
*/
|
|
157
|
+
enterState(oldState, newState) {
|
|
158
|
+
switch (newState) {
|
|
159
|
+
case STATE_NORMAL:
|
|
160
|
+
break
|
|
161
|
+
|
|
162
|
+
case STATE_WARNING:
|
|
163
|
+
this.showWarning(this._warningMessage)
|
|
164
|
+
break
|
|
165
|
+
|
|
166
|
+
case STATE_ERROR:
|
|
167
|
+
this.showError(this._errorMessage)
|
|
168
|
+
break
|
|
169
|
+
|
|
170
|
+
case STATE_PROGRESS:
|
|
171
|
+
this.showProgress(this._progressPercent)
|
|
172
|
+
break
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Define the behavior of the view when leaving states. Leaving a state usually means hiding a visual element
|
|
178
|
+
* corresponding to that state.
|
|
179
|
+
* @param {String} oldState
|
|
180
|
+
* @param {String} newState
|
|
181
|
+
*/
|
|
182
|
+
leaveState(oldState, newState) {
|
|
183
|
+
switch (oldState) {
|
|
184
|
+
case STATE_NORMAL:
|
|
185
|
+
break
|
|
186
|
+
|
|
187
|
+
case STATE_WARNING:
|
|
188
|
+
this._warningMessage = null
|
|
189
|
+
this.hideWarning()
|
|
190
|
+
break
|
|
191
|
+
|
|
192
|
+
case STATE_ERROR:
|
|
193
|
+
this._errorMessage = null
|
|
194
|
+
this.hideError()
|
|
195
|
+
break
|
|
196
|
+
|
|
197
|
+
case STATE_PROGRESS:
|
|
198
|
+
this._progressPercent = null
|
|
199
|
+
this.hideProgress()
|
|
200
|
+
break
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
/* Progress */
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Put the view in the progress state or updates the progress. The view state is set to
|
|
209
|
+
* {@link qui.views.STATE_PROGRESS}.
|
|
210
|
+
*
|
|
211
|
+
* It is safe to call this method multiple times, updating the progress percent.
|
|
212
|
+
*
|
|
213
|
+
* @param {?Number} [percent] optional progress percent (from `0` to `100`); `null` indicates indefinite
|
|
214
|
+
* progress
|
|
215
|
+
*/
|
|
216
|
+
setProgress(percent = null) {
|
|
217
|
+
/* No duplicate setProgress() protection, since we want to be able to update the progress */
|
|
218
|
+
|
|
219
|
+
this._progressPercent = percent
|
|
220
|
+
this.setState(STATE_PROGRESS)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Put the view in the normal state, but only if the current state is {@link qui.views.STATE_PROGRESS}.
|
|
225
|
+
*/
|
|
226
|
+
clearProgress() {
|
|
227
|
+
if (this._state === STATE_PROGRESS) {
|
|
228
|
+
this.setState(STATE_NORMAL)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Return the current progress percent.
|
|
234
|
+
*
|
|
235
|
+
* An exception will be thrown if the current view state is not {@link qui.views.STATE_PROGRESS}.
|
|
236
|
+
*
|
|
237
|
+
* @returns {?Number}
|
|
238
|
+
*/
|
|
239
|
+
getProgressPercent() {
|
|
240
|
+
if (this._state !== STATE_PROGRESS) {
|
|
241
|
+
throw new AssertionError(`getProgressPercent() called in ${this._state} state`)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return this._progressPercent
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Define how the view is displayed in progress state, disallowing any user interaction.
|
|
249
|
+
*
|
|
250
|
+
* {@link qui.views.ViewMixin#inProgress} returns `true` when called from this method.
|
|
251
|
+
*
|
|
252
|
+
* Does nothing by default. Override this method to implement your own progress display.
|
|
253
|
+
*
|
|
254
|
+
* @param {?Number} [percent] optional progress percent (from `0` to `100`); `null` indicates indefinite
|
|
255
|
+
* progress
|
|
256
|
+
*/
|
|
257
|
+
showProgress(percent) {
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Hide a previously displayed progress, re-enabling user interaction.
|
|
262
|
+
*
|
|
263
|
+
* {@link qui.views.ViewMixin#inProgress} returns `false` when called from this method.
|
|
264
|
+
*
|
|
265
|
+
* Does nothing by default. Override this method to implement your own progress hiding.
|
|
266
|
+
*/
|
|
267
|
+
hideProgress() {
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Tell if the view is currently in progress (its state is {@link qui.views.STATE_PROGRESS}).
|
|
272
|
+
* @returns {Boolean}
|
|
273
|
+
*/
|
|
274
|
+
inProgress() {
|
|
275
|
+
return this._state === STATE_PROGRESS
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
/* Warning */
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Put the view in the warning state or updates the warning message. The view state is set to
|
|
283
|
+
* {@link qui.views.STATE_WARNING}.
|
|
284
|
+
*
|
|
285
|
+
* It is safe to call this method multiple times, updating the warning message.
|
|
286
|
+
*
|
|
287
|
+
* @param {?String} [message] an optional warning message
|
|
288
|
+
*/
|
|
289
|
+
setWarning(message = null) {
|
|
290
|
+
/* No duplicate setWarning() protection, since we want to be able to update the error */
|
|
291
|
+
|
|
292
|
+
this._warningMessage = message
|
|
293
|
+
this.setState(STATE_WARNING)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Put the view in the normal state, but only if the current state is {@link qui.views.STATE_WARNING}.
|
|
298
|
+
*/
|
|
299
|
+
clearWarning() {
|
|
300
|
+
if (this._state === STATE_WARNING) {
|
|
301
|
+
this.setState(STATE_NORMAL)
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Return the warning message set with {@link qui.views.ViewMixin#setWarning} or `null` if no warning message
|
|
307
|
+
* was set.
|
|
308
|
+
*
|
|
309
|
+
* An exception will be thrown if the current view state is not {@link qui.views.STATE_WARNING}.
|
|
310
|
+
*
|
|
311
|
+
* @returns {?String}
|
|
312
|
+
*/
|
|
313
|
+
getWarningMessage() {
|
|
314
|
+
if (this._state !== STATE_WARNING) {
|
|
315
|
+
throw new AssertionError(`getWarningMessage() called in ${this._state} state`)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return this._warningMessage
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Define how the view is displayed in warning state, showing the warning message.
|
|
323
|
+
*
|
|
324
|
+
* {@link qui.views.ViewMixin#hasWarning} returns `true` when called from this method.
|
|
325
|
+
*
|
|
326
|
+
* By default displays a warning toast message. Override this method to implement your own warning display.
|
|
327
|
+
*
|
|
328
|
+
* @param {?String} message the warning message, or `null` if no warning message available
|
|
329
|
+
*/
|
|
330
|
+
showWarning(message) {
|
|
331
|
+
Toast.show({message: message, type: 'error', timeout: 0})
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Hide a previously displayed warning.
|
|
336
|
+
*
|
|
337
|
+
* {@link qui.views.ViewMixin#hasWarning} returns `false` when called from this method.
|
|
338
|
+
*
|
|
339
|
+
* By default calls {@link qui.messages.toast.hide}. Override this method to implement your own warning
|
|
340
|
+
* hiding.
|
|
341
|
+
*/
|
|
342
|
+
hideWarning() {
|
|
343
|
+
Toast.hide()
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Tell if the view is currently in the warning state (its state is {@link qui.views.STATE_WARNING}).
|
|
348
|
+
* @returns {Boolean}
|
|
349
|
+
*/
|
|
350
|
+
hasWarning() {
|
|
351
|
+
return this._state === STATE_WARNING
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
/* Error */
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Put the view in the error state or updates the error message.
|
|
359
|
+
*
|
|
360
|
+
* The view state is set to {@link qui.views.STATE_ERROR}.
|
|
361
|
+
*
|
|
362
|
+
* It is safe to call this method multiple times, updating the error message.
|
|
363
|
+
*
|
|
364
|
+
* @param {?String|Error} [message] an error message
|
|
365
|
+
*/
|
|
366
|
+
setError(message = null) {
|
|
367
|
+
/* No duplicate setError() protection, since we want to be able to update the error */
|
|
368
|
+
|
|
369
|
+
if (message instanceof Error) {
|
|
370
|
+
message = message.message
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
this._errorMessage = message
|
|
374
|
+
this.setState(STATE_ERROR)
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Put the view in the normal state, but only if the current state is {@link qui.views.STATE_ERROR}.
|
|
379
|
+
*/
|
|
380
|
+
clearError() {
|
|
381
|
+
if (this._state === STATE_ERROR) {
|
|
382
|
+
this.setState(STATE_NORMAL)
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Return the error message set with {@link qui.views.ViewMixin#setError} or `null` if no error message was set.
|
|
388
|
+
*
|
|
389
|
+
* An exception will be thrown if the current view state is not {@link qui.views.STATE_ERROR}.
|
|
390
|
+
*
|
|
391
|
+
* @returns {?String}
|
|
392
|
+
*/
|
|
393
|
+
getErrorMessage() {
|
|
394
|
+
if (this._state !== STATE_ERROR) {
|
|
395
|
+
throw new AssertionError(`getErrorMessage() called in ${this._state} state`)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return this._errorMessage
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Define how the view is displayed in error state, showing the error message.
|
|
403
|
+
*
|
|
404
|
+
* {@link qui.views.ViewMixin#hasError} returns `true` when called from this method.
|
|
405
|
+
*
|
|
406
|
+
* By default displays a error toast message. Override this method to implement your own error display.
|
|
407
|
+
*
|
|
408
|
+
* @param {?String} message the error message, or `null` if no error message available
|
|
409
|
+
*/
|
|
410
|
+
showError(message) {
|
|
411
|
+
Toast.show({message: message, type: 'error', timeout: 0})
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Hide a previously displayed error.
|
|
416
|
+
*
|
|
417
|
+
* {@link qui.views.ViewMixin#hasError} returns `false` when called from this method.
|
|
418
|
+
*
|
|
419
|
+
* By default calls {@link qui.messages.toast.hide}. Override this method to implement your own error
|
|
420
|
+
* hiding.
|
|
421
|
+
*/
|
|
422
|
+
hideError() {
|
|
423
|
+
Toast.hide()
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Tell if the view is currently in the error state (its state is {@link qui.views.STATE_ERROR}).
|
|
428
|
+
* @returns {Boolean}
|
|
429
|
+
*/
|
|
430
|
+
hasError() {
|
|
431
|
+
return this._state === STATE_ERROR
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
/* Closing */
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Tell if the view has been closed.
|
|
439
|
+
*
|
|
440
|
+
* By default returns `false`.
|
|
441
|
+
*
|
|
442
|
+
* Override this method to implement your own closed status.
|
|
443
|
+
*
|
|
444
|
+
* @returns {Boolean}
|
|
445
|
+
*/
|
|
446
|
+
isClosed() {
|
|
447
|
+
return false
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Close the view.
|
|
452
|
+
*
|
|
453
|
+
* By default does nothing.
|
|
454
|
+
*
|
|
455
|
+
* Override this method to implement your own close behavior.
|
|
456
|
+
*/
|
|
457
|
+
close() {
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return ViewMixin
|
|
463
|
+
|
|
464
|
+
})
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
export default ViewMixin
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
$.widget('qui.basewidget', {
|
|
6
|
+
|
|
7
|
+
options: {
|
|
8
|
+
warning: null,
|
|
9
|
+
error: null
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
_setOption: function (key, value) {
|
|
13
|
+
this._super(key, value)
|
|
14
|
+
|
|
15
|
+
switch (key) {
|
|
16
|
+
case 'warning':
|
|
17
|
+
case 'error':
|
|
18
|
+
this.element.toggleClass(`has-${key}`, value != null)
|
|
19
|
+
break
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
})
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
|
|
2
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
3
|
+
|
|
4
|
+
import * as BaseWidget from '../base-widget.js' /* Needed */
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
$.widget('qui.checkbutton', $.qui.basewidget, {
|
|
8
|
+
|
|
9
|
+
options: {
|
|
10
|
+
onClass: 'on',
|
|
11
|
+
readonly: false,
|
|
12
|
+
disabled: false
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
_create: function () {
|
|
16
|
+
let widget = this
|
|
17
|
+
|
|
18
|
+
this.element.addClass('qui-base-button qui-interactive-button qui-check-button')
|
|
19
|
+
if (this.options.readonly) {
|
|
20
|
+
this.element.addClass('readonly')
|
|
21
|
+
}
|
|
22
|
+
if (this.options.disabled) {
|
|
23
|
+
this.element.addClass('disabled')
|
|
24
|
+
}
|
|
25
|
+
if (!this.options.disabled) {
|
|
26
|
+
this.element.attr('tabIndex', 0) /* Make element focusable */
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.element.on('click', function () {
|
|
30
|
+
widget._toggleChange()
|
|
31
|
+
})
|
|
32
|
+
this.element.on('keydown', function (e) {
|
|
33
|
+
if (e.which === 32 /* Space */) {
|
|
34
|
+
widget._toggleChange()
|
|
35
|
+
return false
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
isOn: function () {
|
|
41
|
+
return this.element.hasClass(this.options.onClass)
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
setOn: function () {
|
|
45
|
+
this.element.addClass(this.options.onClass)
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
setOff: function () {
|
|
49
|
+
this.element.removeClass(this.options.onClass)
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
toggle: function () {
|
|
53
|
+
if (this.isOn()) {
|
|
54
|
+
this.setOff()
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.setOn()
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
getValue: function () {
|
|
62
|
+
return this.isOn()
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
setValue: function (value) {
|
|
66
|
+
if (value) {
|
|
67
|
+
this.setOn()
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.setOff()
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
_toggleChange: function () {
|
|
75
|
+
if (this.options.readonly || this.options.disabled) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (this.element.hasClass(this.options.onClass)) {
|
|
80
|
+
this.setOff()
|
|
81
|
+
this.element.trigger('change', false)
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
this.setOn()
|
|
85
|
+
this.element.trigger('change', true)
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
_setOption: function (key, value) {
|
|
90
|
+
this._super(key, value)
|
|
91
|
+
|
|
92
|
+
switch (key) {
|
|
93
|
+
case 'readonly':
|
|
94
|
+
this.element.toggleClass('readonly', value)
|
|
95
|
+
break
|
|
96
|
+
|
|
97
|
+
case 'disabled':
|
|
98
|
+
this.element.toggleClass('disabled', value)
|
|
99
|
+
if (value) {
|
|
100
|
+
this.element.removeAttr('tabIndex')
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
this.element.attr('tabIndex', 0)
|
|
104
|
+
}
|
|
105
|
+
break
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
})
|