@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
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
|
|
2
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
3
|
+
|
|
4
|
+
import {gettext} from '$qui/base/i18n.js'
|
|
5
|
+
import StockIcon from '$qui/icons/stock-icon.js'
|
|
6
|
+
import * as StringUtils from '$qui/utils/string.js'
|
|
7
|
+
|
|
8
|
+
import * as BaseWidget from '../base-widget.js' /* Needed */
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
$.widget('qui.filepicker', $.qui.basewidget, {
|
|
12
|
+
|
|
13
|
+
options: {
|
|
14
|
+
name: '',
|
|
15
|
+
placeholder: null,
|
|
16
|
+
accept: null,
|
|
17
|
+
multiple: false,
|
|
18
|
+
readonly: false,
|
|
19
|
+
disabled: false
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
_create: function () {
|
|
23
|
+
this.element.addClass('qui-file-picker')
|
|
24
|
+
|
|
25
|
+
/* Actual file input element */
|
|
26
|
+
this._input = $('<input>', {type: 'file'})
|
|
27
|
+
this.element.append(this._input)
|
|
28
|
+
this._input.on('change', function () {
|
|
29
|
+
this._button.pushbutton({caption: this.prepareCaption()})
|
|
30
|
+
}.bind(this))
|
|
31
|
+
|
|
32
|
+
/* Button */
|
|
33
|
+
this._button = $('<div>', {class: 'qui-file-picker-button qui-push-button'}).pushbutton({
|
|
34
|
+
caption: this.prepareCaption(),
|
|
35
|
+
icon: new StockIcon({name: 'file'})
|
|
36
|
+
})
|
|
37
|
+
this.element.append(this._button)
|
|
38
|
+
this._button.on('click', function () {
|
|
39
|
+
if (!this.options.readonly) {
|
|
40
|
+
this._input.trigger('click')
|
|
41
|
+
}
|
|
42
|
+
}.bind(this))
|
|
43
|
+
|
|
44
|
+
if (this.options.name) {
|
|
45
|
+
this._input.attr('name', this.options.name)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (this.options.accept) {
|
|
49
|
+
this._input.attr('accept', this.options.accept.join(','))
|
|
50
|
+
}
|
|
51
|
+
if (this.options.multiple) {
|
|
52
|
+
this._input.attr('multiple', 'multiple')
|
|
53
|
+
}
|
|
54
|
+
if (this.options.readonly) {
|
|
55
|
+
this._input.attr('readonly', 'readonly')
|
|
56
|
+
}
|
|
57
|
+
if (this.options.disabled) {
|
|
58
|
+
this._input.attr('disabled', 'disabled')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* Manually propagate some events to parent */
|
|
62
|
+
this._input.on('focus blur', function (e) {
|
|
63
|
+
this.element.triggerHandler(e.type)
|
|
64
|
+
}.bind(this))
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
_setOption: function (key, value) {
|
|
68
|
+
this._super(key, value)
|
|
69
|
+
|
|
70
|
+
switch (key) {
|
|
71
|
+
case 'accept':
|
|
72
|
+
if (value) {
|
|
73
|
+
this._input.attr('accept', value.join(','))
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
this._input.removeAttr('accept')
|
|
77
|
+
}
|
|
78
|
+
break
|
|
79
|
+
|
|
80
|
+
case 'multiple':
|
|
81
|
+
if (value) {
|
|
82
|
+
this._input.attr('multiple', 'multiple')
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
this._input.removeAttr('multiple')
|
|
86
|
+
}
|
|
87
|
+
break
|
|
88
|
+
|
|
89
|
+
case 'disabled':
|
|
90
|
+
this._button.pushbutton({disabled: value})
|
|
91
|
+
break
|
|
92
|
+
|
|
93
|
+
case 'readonly':
|
|
94
|
+
this._button.pushbutton({readonly: value})
|
|
95
|
+
break
|
|
96
|
+
|
|
97
|
+
case 'placeholder':
|
|
98
|
+
this._button.pushbutton({caption: this.prepareCaption()})
|
|
99
|
+
break
|
|
100
|
+
|
|
101
|
+
case 'warning':
|
|
102
|
+
this._button.pushbutton({style: value != null ? 'highlight' : 'interactive'})
|
|
103
|
+
break
|
|
104
|
+
|
|
105
|
+
case 'error':
|
|
106
|
+
this._button.pushbutton({style: value != null ? 'danger' : 'interactive'})
|
|
107
|
+
break
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
getValue: function () {
|
|
112
|
+
let files = this._input[0].files
|
|
113
|
+
return Array.prototype.slice.call(files)
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
setValue: function (value) {
|
|
117
|
+
/* Does nothing */
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
prepareCaption: function () {
|
|
121
|
+
let files = this._input[0].files
|
|
122
|
+
if (files.length > 1) {
|
|
123
|
+
return StringUtils.formatPercent('%(count)d files selected', {count: files.length})
|
|
124
|
+
}
|
|
125
|
+
else if (files.length > 0) {
|
|
126
|
+
return files[0].name
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
return this.options.placeholder || gettext('Choose...')
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
})
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
|
|
2
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
3
|
+
|
|
4
|
+
import * as Theme from '$qui/theme.js'
|
|
5
|
+
|
|
6
|
+
import * as BaseWidget from '../base-widget.js' /* Needed */
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
$.widget('qui.labels', $.qui.basewidget, {
|
|
10
|
+
|
|
11
|
+
options: {
|
|
12
|
+
color: '@foreground-color',
|
|
13
|
+
background: '@background-color',
|
|
14
|
+
disabled: false,
|
|
15
|
+
chevrons: false,
|
|
16
|
+
clickable: false,
|
|
17
|
+
onClick(label, index) {}
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
_create: function () {
|
|
21
|
+
this.element.addClass('qui-labels-container')
|
|
22
|
+
if (this.options.disabled) {
|
|
23
|
+
this.element.addClass('disabled')
|
|
24
|
+
}
|
|
25
|
+
if (this.options.chevrons) {
|
|
26
|
+
this.element.addClass('chevrons')
|
|
27
|
+
}
|
|
28
|
+
if (this.options.clickable) {
|
|
29
|
+
this.element.addClass('clickable')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this._labels = []
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
_makeLabel: function (labelInfo) {
|
|
36
|
+
let labelSpan = $('<span></span>', {class: 'qui-label'})
|
|
37
|
+
|
|
38
|
+
let defColor = Theme.getColor(this.options.color)
|
|
39
|
+
let defBackground = Theme.getColor(this.options.background)
|
|
40
|
+
|
|
41
|
+
let color = defColor
|
|
42
|
+
let background = defBackground
|
|
43
|
+
|
|
44
|
+
let text = labelInfo
|
|
45
|
+
if (typeof labelInfo !== 'string') {
|
|
46
|
+
text = labelInfo.text
|
|
47
|
+
if (labelInfo.color) {
|
|
48
|
+
color = labelInfo.color
|
|
49
|
+
labelSpan.data('custom-color', true)
|
|
50
|
+
}
|
|
51
|
+
if (labelInfo.background) {
|
|
52
|
+
background = labelInfo.background
|
|
53
|
+
labelSpan.data('custom-background', true)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
labelSpan.html(text)
|
|
58
|
+
labelSpan.css({
|
|
59
|
+
'color': color,
|
|
60
|
+
'background': background,
|
|
61
|
+
'border-color': background
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
if (this.options.clickable) {
|
|
65
|
+
labelSpan.addClass('qui-base-button')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return labelSpan
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
getValue: function () {
|
|
72
|
+
return this._labels.map(l => l.html())
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
setValue: function (labels) {
|
|
76
|
+
this.element.html('')
|
|
77
|
+
this._labels = []
|
|
78
|
+
|
|
79
|
+
labels.forEach(function (labelInfo, index) {
|
|
80
|
+
|
|
81
|
+
let label = this._makeLabel(labelInfo)
|
|
82
|
+
this._labels.push(label)
|
|
83
|
+
this.element.append(label)
|
|
84
|
+
|
|
85
|
+
if (this.options.clickable) {
|
|
86
|
+
label.on('click', function () {
|
|
87
|
+
this.options.onClick(label.text(), index)
|
|
88
|
+
}.bind(this))
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
}, this)
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
_setOption: function (key, value) {
|
|
95
|
+
this._super(key, value)
|
|
96
|
+
|
|
97
|
+
switch (key) {
|
|
98
|
+
case 'color':
|
|
99
|
+
this._labels.forEach(function (label) {
|
|
100
|
+
if (!label.data('custom-background')) {
|
|
101
|
+
label.css('color', value)
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
break
|
|
105
|
+
|
|
106
|
+
case 'background':
|
|
107
|
+
this._labels.forEach(function (label) {
|
|
108
|
+
if (!label.data('custom-background')) {
|
|
109
|
+
label.css({
|
|
110
|
+
'background': value,
|
|
111
|
+
'border-color': value
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
break
|
|
116
|
+
|
|
117
|
+
case 'disabled':
|
|
118
|
+
this.element.toggleClass('disabled', value)
|
|
119
|
+
break
|
|
120
|
+
|
|
121
|
+
case 'chevrons':
|
|
122
|
+
this.element.toggleClass('chevrons', value)
|
|
123
|
+
break
|
|
124
|
+
|
|
125
|
+
case 'clickable':
|
|
126
|
+
this.element.children('span.qui-label').toggleClass('qui-base-button', value)
|
|
127
|
+
this.element.toggleClass('clickable', value)
|
|
128
|
+
break
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
})
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
3
|
+
|
|
4
|
+
import {asap} from '$qui/utils/misc.js'
|
|
5
|
+
|
|
6
|
+
import * as TextInput from './text-input.js' /* Needed */
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
// TODO do not allow user input of non-numeric characters
|
|
10
|
+
$.widget('qui.numericinput', $.qui.textinput, {
|
|
11
|
+
|
|
12
|
+
options: {
|
|
13
|
+
min: null,
|
|
14
|
+
max: null
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
type: 'number',
|
|
18
|
+
|
|
19
|
+
_create: function () {
|
|
20
|
+
this._super('_create')
|
|
21
|
+
|
|
22
|
+
this._setOption('min', this.options.min)
|
|
23
|
+
this._setOption('max', this.options.max)
|
|
24
|
+
|
|
25
|
+
/* Trigger change event on widget element when scrolling, but only if focused */
|
|
26
|
+
this._input.on('mousewheel', function (e) {
|
|
27
|
+
if (!this._input.is(':focus')) {
|
|
28
|
+
e.preventDefault()
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
asap(function () {
|
|
33
|
+
this.element.trigger('change')
|
|
34
|
+
}.bind(this))
|
|
35
|
+
}.bind(this))
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
_setOption: function (key, value) {
|
|
39
|
+
this._super(key, value)
|
|
40
|
+
|
|
41
|
+
switch (key) {
|
|
42
|
+
case 'min':
|
|
43
|
+
case 'max':
|
|
44
|
+
this._input.attr(key, value != null ? value : '')
|
|
45
|
+
break
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
})
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
|
|
2
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
3
|
+
|
|
4
|
+
import StockIcon from '$qui/icons/stock-icon.js'
|
|
5
|
+
|
|
6
|
+
import * as TextInput from './text-input.js' /* Needed */
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
$.widget('qui.passwordinput', $.qui.textinput, {
|
|
10
|
+
|
|
11
|
+
options: {
|
|
12
|
+
clearEnabled: false,
|
|
13
|
+
revealOnFocus: false
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
type: 'password',
|
|
17
|
+
_autocomplete_on: 'current-password',
|
|
18
|
+
_autocomplete_off: 'new-password',
|
|
19
|
+
|
|
20
|
+
_create: function () {
|
|
21
|
+
this._super()
|
|
22
|
+
|
|
23
|
+
this._clearButton = null
|
|
24
|
+
if (this.options.clearEnabled) {
|
|
25
|
+
this._clearButton = this._makeClearButton()
|
|
26
|
+
this.element.addClass('clear-enabled')
|
|
27
|
+
this.element.append(this._clearButton)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this.element.on('focus', function () {
|
|
31
|
+
|
|
32
|
+
if (this.options.revealOnFocus) {
|
|
33
|
+
this._input.attr('type', 'text')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
}.bind(this))
|
|
37
|
+
|
|
38
|
+
this.element.on('blur', function () {
|
|
39
|
+
|
|
40
|
+
if (this.options.revealOnFocus) {
|
|
41
|
+
this._input.attr('type', this.type)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
}.bind(this))
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
_makeClearButton: function () {
|
|
48
|
+
let clearIcon = $('<div></div>', {class: 'qui-icon qui-password-input-clear-icon'})
|
|
49
|
+
let variant = 'interactive'
|
|
50
|
+
if (this.options.error != null) {
|
|
51
|
+
variant = 'error'
|
|
52
|
+
}
|
|
53
|
+
else if (this.options.warning != null) {
|
|
54
|
+
variant = 'warning'
|
|
55
|
+
}
|
|
56
|
+
new StockIcon({
|
|
57
|
+
name: 'close', variant: variant,
|
|
58
|
+
activeName: 'close', activeVariant: 'background',
|
|
59
|
+
scale: 0.5
|
|
60
|
+
}).applyTo(clearIcon)
|
|
61
|
+
|
|
62
|
+
let clearButton = $('<div></div>', {class: 'qui-base-button qui-password-input-clear-button'})
|
|
63
|
+
clearButton.append(clearIcon)
|
|
64
|
+
|
|
65
|
+
clearButton.on('click', function () {
|
|
66
|
+
|
|
67
|
+
this._input.val('')
|
|
68
|
+
this.element.trigger('change')
|
|
69
|
+
|
|
70
|
+
}.bind(this))
|
|
71
|
+
|
|
72
|
+
return clearButton
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
_setOption: function (key, value) {
|
|
76
|
+
this._super(key, value)
|
|
77
|
+
|
|
78
|
+
switch (key) {
|
|
79
|
+
case 'warning':
|
|
80
|
+
case 'error':
|
|
81
|
+
/* When warning or error change, we need to rebuild the clear button icon */
|
|
82
|
+
if (this._clearButton) {
|
|
83
|
+
let newClearButton = this._makeClearButton()
|
|
84
|
+
this._clearButton.replaceWith(newClearButton)
|
|
85
|
+
this._clearButton = newClearButton
|
|
86
|
+
}
|
|
87
|
+
break
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
})
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
|
|
2
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
3
|
+
|
|
4
|
+
import * as Theme from '$qui/theme.js'
|
|
5
|
+
import * as CSS from '$qui/utils/css.js'
|
|
6
|
+
import * as StringUtils from '$qui/utils/string.js'
|
|
7
|
+
|
|
8
|
+
import * as BaseWidget from '../base-widget.js' /* Needed */
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
$.widget('qui.progressdisk', $.qui.basewidget, {
|
|
12
|
+
|
|
13
|
+
options: {
|
|
14
|
+
radius: '1em',
|
|
15
|
+
caption: '%s%%',
|
|
16
|
+
color: '@interactive-color',
|
|
17
|
+
disabled: false
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
_create: function () {
|
|
21
|
+
let ns = 'http://www.w3.org/2000/svg'
|
|
22
|
+
|
|
23
|
+
/* Root svg element */
|
|
24
|
+
this._svg = document.createElementNS(ns, 'svg')
|
|
25
|
+
|
|
26
|
+
/* Ring */
|
|
27
|
+
this._ring = document.createElementNS(ns, 'ellipse')
|
|
28
|
+
this._ring.setAttribute('class', 'qui-progress-disk-ring')
|
|
29
|
+
this._svg.appendChild(this._ring)
|
|
30
|
+
|
|
31
|
+
/* Cursor */
|
|
32
|
+
this._cursor = document.createElementNS(ns, 'path')
|
|
33
|
+
this._cursor.setAttribute('class', 'qui-progress-disk-cursor')
|
|
34
|
+
this._svg.appendChild(this._cursor)
|
|
35
|
+
|
|
36
|
+
/* Label */
|
|
37
|
+
this._label = $('<div></div>', {class: 'qui-progress-disk-label'})
|
|
38
|
+
|
|
39
|
+
this._curVal = 0
|
|
40
|
+
this._setValue(this._curVal)
|
|
41
|
+
|
|
42
|
+
this.element.addClass('qui-progress-disk-container')
|
|
43
|
+
|
|
44
|
+
if (this.options.disabled) {
|
|
45
|
+
this.element.addClass('disabled')
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.element.append(this._svg)
|
|
49
|
+
this.element.append(this._label)
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
getValue: function () {
|
|
53
|
+
return this._curVal
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
setValue: function (value) {
|
|
57
|
+
this._setValue(this._validate(value))
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
_setValue: function (value) {
|
|
61
|
+
this._curVal = value
|
|
62
|
+
|
|
63
|
+
if (value != null && value >= 0) {
|
|
64
|
+
this._label.html(StringUtils.formatPercent(this.options.caption, value.toFixed(0)))
|
|
65
|
+
this.element.removeClass('no-value')
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this._curVal = -1
|
|
69
|
+
this._label.html('')
|
|
70
|
+
this.element.addClass('no-value')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this._updateSVG()
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
_validate: function (value) {
|
|
77
|
+
value = parseFloat(value)
|
|
78
|
+
if (isNaN(value)) {
|
|
79
|
+
return -1
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
value = Math.max(-1, value)
|
|
83
|
+
value = Math.min(100, value)
|
|
84
|
+
|
|
85
|
+
return value
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
_makeArcPath: function (x, y, startAngle, endAngle, radius) {
|
|
89
|
+
let aFlag = '0'
|
|
90
|
+
if (endAngle - startAngle >= 180) {
|
|
91
|
+
aFlag = '1'
|
|
92
|
+
}
|
|
93
|
+
if (endAngle >= 360) {
|
|
94
|
+
endAngle = 359.9999
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let x1 = x + radius * Math.cos(Math.PI * startAngle / 180)
|
|
98
|
+
let y1 = y + radius * Math.sin(Math.PI * startAngle / 180)
|
|
99
|
+
let x2 = x + radius * Math.cos(Math.PI * endAngle / 180)
|
|
100
|
+
let y2 = y + radius * Math.sin(Math.PI * endAngle / 180)
|
|
101
|
+
return (`M ${x1} ${y1} A ${radius} ${radius} 0 ${aFlag} 1 ${x2} ${y2}`)
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
_updateSVG: function () {
|
|
105
|
+
let isSmall = parseFloat(this.options.radius) < 2
|
|
106
|
+
let thickness = parseFloat(this.options.radius) / 4
|
|
107
|
+
|
|
108
|
+
this._label.toggleClass('small', isSmall)
|
|
109
|
+
|
|
110
|
+
let width = CSS.mulValue(this.options.radius, 2)
|
|
111
|
+
let fWidth = parseFloat(width)
|
|
112
|
+
let oRadius = parseFloat(this.options.radius)
|
|
113
|
+
let iRadius = oRadius - thickness / 2
|
|
114
|
+
let color = Theme.getColor(this.options.color)
|
|
115
|
+
|
|
116
|
+
this.element.width(width)
|
|
117
|
+
this.element.height(width)
|
|
118
|
+
this.element.css('line-height', width)
|
|
119
|
+
|
|
120
|
+
this._svg.setAttribute('width', width)
|
|
121
|
+
this._svg.setAttribute('height', width)
|
|
122
|
+
this._svg.setAttribute('viewBox', `0 0 ${fWidth} ${fWidth}`)
|
|
123
|
+
|
|
124
|
+
this._ring.setAttribute('cx', oRadius.toString())
|
|
125
|
+
this._ring.setAttribute('cy', oRadius.toString())
|
|
126
|
+
this._ring.setAttribute('rx', iRadius.toString())
|
|
127
|
+
this._ring.setAttribute('ry', iRadius.toString())
|
|
128
|
+
this._ring.setAttribute('stroke-width', thickness.toString())
|
|
129
|
+
this._ring.setAttribute('stroke', color)
|
|
130
|
+
|
|
131
|
+
this._cursor.setAttribute('stroke-width', thickness.toString())
|
|
132
|
+
this._cursor.setAttribute('stroke', color)
|
|
133
|
+
|
|
134
|
+
if (this._curVal >= 0) {
|
|
135
|
+
this._updateSVGPercent(iRadius, oRadius)
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
this._updateSVGLoader(iRadius, oRadius)
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
_updateSVGPercent: function (iRadius, oRadius) {
|
|
143
|
+
let angle = 360 * this._curVal / 100
|
|
144
|
+
let path = this._makeArcPath(oRadius, oRadius, 0, angle, iRadius)
|
|
145
|
+
|
|
146
|
+
this._cursor.setAttribute('d', path)
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
_updateSVGLoader: function (iRadius, oRadius) {
|
|
150
|
+
let path = this._makeArcPath(oRadius, oRadius, -90, 0, iRadius)
|
|
151
|
+
|
|
152
|
+
this._cursor.setAttribute('d', path)
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
_setOption: function (key, value) {
|
|
156
|
+
this._super(key, value)
|
|
157
|
+
|
|
158
|
+
switch (key) {
|
|
159
|
+
case 'radius':
|
|
160
|
+
case 'color':
|
|
161
|
+
this._updateSVG()
|
|
162
|
+
break
|
|
163
|
+
|
|
164
|
+
case 'disabled':
|
|
165
|
+
this.element.toggleClass('disabled', value)
|
|
166
|
+
break
|
|
167
|
+
|
|
168
|
+
case 'caption':
|
|
169
|
+
this._setValue(this._curVal)
|
|
170
|
+
break
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
})
|