@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
package/js/config.js ADDED
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Configuration registry.
3
+ * @namespace qui.config
4
+ */
5
+
6
+ import * as ObjectUtils from '$qui/utils/object.js'
7
+
8
+
9
+ const _TRUE_VALUES = ['true', 'True', 'TRUE', 'on', 'On', 'ON', 'enabled', 'Enabled', 'ENABLED', 1]
10
+
11
+ const Config = {
12
+
13
+ /**
14
+ * Flag indicating whether app runs in debug mode or not.
15
+ * @memberof qui.config
16
+ * @type Boolean
17
+ */
18
+ debug: false,
19
+
20
+ /**
21
+ * Build hash used to append to static URLs to prevent caching.
22
+ * @memberof qui.config
23
+ * @type String
24
+ */
25
+ buildHash: '',
26
+
27
+ /**
28
+ * Flag indicating whether navigation uses URL fragment or regular path.
29
+ * @memberof qui.config
30
+ * @type Boolean
31
+ */
32
+ navigationUsesFragment: false,
33
+
34
+ /**
35
+ * Common prefix used for all QUI paths.
36
+ * @memberof qui.config
37
+ * @type String
38
+ */
39
+ navigationBasePrefix: '',
40
+
41
+ /**
42
+ * Application name.
43
+ * @memberof qui.config
44
+ * @type String
45
+ */
46
+ appName: '',
47
+
48
+ /**
49
+ * Application display name.
50
+ * @memberof qui.config
51
+ * @type String
52
+ */
53
+ appDisplayName: '',
54
+
55
+ /**
56
+ * Latest application version, indicated by the server.
57
+ * @memberof qui.config
58
+ * @type String
59
+ */
60
+ appLatestVersion: '',
61
+
62
+ /**
63
+ * Current application version, indicated by the frontend.
64
+ * @memberof qui.config
65
+ * @type String
66
+ */
67
+ appCurrentVersion: 'unknown-version',
68
+
69
+ /**
70
+ * QUI static base URL.
71
+ * @memberof qui.config
72
+ * @type String
73
+ */
74
+ quiStaticURL: '',
75
+
76
+ /**
77
+ * App's static base URL; should be identical to {@link qui.config.quiStaticURL} in production mode.
78
+ * @memberof qui.config
79
+ * @type String
80
+ */
81
+ appStaticURL: '',
82
+
83
+ /**
84
+ * The name of the main QUI script.
85
+ * @memberof qui.config
86
+ * @type String
87
+ */
88
+ quiIndexName: '',
89
+
90
+ /**
91
+ * The name of the main app script.
92
+ * @memberof qui.config
93
+ * @type String
94
+ */
95
+ appIndexName: '',
96
+
97
+ /**
98
+ * The theme to be initially loaded, by default.
99
+ * @memberof qui.config
100
+ * @type String
101
+ */
102
+ defaultTheme: 'dark',
103
+
104
+ /**
105
+ * The list of comma-separated available themes.
106
+ * @memberof qui.config
107
+ * @type String
108
+ */
109
+ themes: 'dark,light',
110
+
111
+ /**
112
+ * Flag that indicates whether effects are enabled or disabled by default when app is loaded.
113
+ * @memberof qui.config
114
+ * @type Boolean
115
+ */
116
+ defaultEffectsDisabled: false,
117
+
118
+ /**
119
+ * Default small screen threshold to use when app is loaded.
120
+ * @memberof qui.config
121
+ * @type Number
122
+ */
123
+ defaultSmallScreenThreshold: 700,
124
+
125
+ /**
126
+ * Default scaling factor to use when app is loaded.
127
+ * @memberof qui.config
128
+ * @type Number
129
+ */
130
+ defaultScalingFactor: 1,
131
+
132
+ /**
133
+ * Return a configuration item value.
134
+ * @memberof qui.config
135
+ * @param {String} name configuration item name
136
+ * @param {*} [def = null] optional default value returned if missing
137
+ */
138
+ get: function (name, def = null) {
139
+ let nameLower = name.toLowerCase()
140
+ let value = ObjectUtils.findValue(this, k => k.toLowerCase() === nameLower)
141
+ if (value === undefined) {
142
+ value = def
143
+ }
144
+
145
+ return value
146
+ },
147
+
148
+ /**
149
+ * Set a configuration item value.
150
+ * @memberof qui.config
151
+ * @param {String} name configuration item name
152
+ * @param {*} value new configuration item value
153
+ */
154
+ set: function (name, value) {
155
+ let nameLower = name.toLowerCase()
156
+ let existingName = Object.keys(this).find(k => k.toLowerCase() === nameLower)
157
+
158
+ if (existingName) {
159
+ let existingValue = this[existingName]
160
+
161
+ /* Try to coerce the given type to existing type */
162
+ if (typeof existingValue !== typeof value) {
163
+ if (typeof existingValue === 'boolean') {
164
+ value = _TRUE_VALUES.some(v => v === value)
165
+ }
166
+ else if (typeof existingValue === 'number') {
167
+ value = parseFloat(value)
168
+ }
169
+ }
170
+ }
171
+
172
+ this[existingName || name] = value
173
+ },
174
+
175
+ dump: function () {
176
+ return ObjectUtils.filter(this, function (key, value) {
177
+ return (typeof value !== 'function')
178
+ })
179
+ }
180
+
181
+ }
182
+
183
+
184
+ export default Config
@@ -0,0 +1,42 @@
1
+
2
+ import * as ObjectUtils from '$qui/utils/object.js'
3
+
4
+ import JQueryUIField from './jquery-ui-field.js'
5
+
6
+
7
+ /**
8
+ * A check box field. The value data type is `Boolean`.
9
+ * @alias qui.forms.commonfields.CheckField
10
+ * @extends qui.forms.commonfields.JQueryUIField
11
+ */
12
+ class CheckField extends JQueryUIField {
13
+
14
+ static WIDGET_CLASS = 'checkbutton'
15
+
16
+
17
+ /**
18
+ * @constructs
19
+ * @param {String} [onClass] the CSS class to add to the check button in *on* state (defaults to `on`)
20
+ * @param {...*} args parent class parameters
21
+ */
22
+ constructor({onClass = 'on', ...args}) {
23
+ /* We always prefer having the check box on the same line with its label */
24
+ ObjectUtils.setDefault(args, 'forceOneLine', true)
25
+
26
+ super({widgetAttrs: {onClass: onClass}, ...args})
27
+ }
28
+
29
+ setForm(form) {
30
+ super.setForm(form)
31
+
32
+ /* On compact forms, reduce the value width when showing on the same line with label, so that label can take as
33
+ * much space as needed */
34
+ if (form.isCompact() && this.isForceOneLine() && this.getValueWidth() == null) {
35
+ this.setValueWidth(0)
36
+ }
37
+ }
38
+
39
+ }
40
+
41
+
42
+ export default CheckField
@@ -0,0 +1,30 @@
1
+
2
+ import JQueryUIField from './jquery-ui-field.js'
3
+
4
+
5
+ /**
6
+ * A field backed by choice buttons. The value data type can be anything.
7
+ * @alias qui.forms.commonfields.ChoiceButtonsField
8
+ * @extends qui.forms.commonfields.JQueryUIField
9
+ */
10
+ class ChoiceButtonsField extends JQueryUIField {
11
+
12
+ static WIDGET_CLASS = 'choicebuttons'
13
+
14
+
15
+ /**
16
+ * @constructs
17
+ * @param {Object[]|Object[][]} choices choices or groups of choices (pairs/arrays of pairs of `label` and `value`)
18
+ * @param {String} [onClass] the CSS class to add to buttons in *on* state (defaults to `on`)
19
+ * @param {...*} args parent class parameters
20
+ */
21
+ constructor({choices, onClass = 'on', ...args}) {
22
+ super({widgetAttrs: {choices: choices, onClass: onClass}, ...args})
23
+ }
24
+
25
+ // TODO add setters and getters for choices
26
+
27
+ }
28
+
29
+
30
+ export default ChoiceButtonsField
@@ -0,0 +1,37 @@
1
+
2
+ import * as Colors from '$qui/utils/colors.js'
3
+
4
+ import JQueryUIField from './jquery-ui-field.js'
5
+
6
+
7
+ /**
8
+ * A color combo field based on preconfigured combo choices. The value data type is `String`.
9
+ * @alias qui.forms.commonfields.ColorComboField
10
+ * @extends qui.forms.commonfields.JQueryUIField
11
+ */
12
+ class ColorComboField extends JQueryUIField {
13
+
14
+ static WIDGET_CLASS = 'colorcombo'
15
+
16
+
17
+ /**
18
+ * @constructs
19
+ * @param {Boolean} [filterEnabled] set to `true` to enable filter input box
20
+ * @param {...*} args parent class parameters
21
+ */
22
+ constructor({filterEnabled = false, ...args}) {
23
+ super({widgetAttrs: {filterEnabled: filterEnabled}, ...args})
24
+ }
25
+
26
+ valueToWidget(value) {
27
+ if (value && typeof value === 'string' && !value.startsWith('@')) {
28
+ value = Colors.normalize(value)
29
+ }
30
+
31
+ super.valueToWidget(value)
32
+ }
33
+
34
+ }
35
+
36
+
37
+ export default ColorComboField
@@ -0,0 +1,108 @@
1
+
2
+ import JQueryUIField from './jquery-ui-field.js'
3
+
4
+
5
+ /**
6
+ * A combo box field. The value data type can be anything.
7
+ * @alias qui.forms.commonfields.ComboField
8
+ * @extends qui.forms.commonfields.JQueryUIField
9
+ */
10
+ class ComboField extends JQueryUIField {
11
+
12
+ static WIDGET_CLASS = 'combo'
13
+
14
+
15
+ // TODO add setters and getters for widget properties
16
+
17
+ /**
18
+ * @constructs
19
+ * @param {Object[]} [choices] choices (pairs of `label` and `value`)
20
+ * @param {Function} [makeChoices] a function that generates choices (see
21
+ * {@link qui.forms.commonfields.ComboField#makeChoices}))
22
+ * @param {Number} [fastFactor] determines how fast the page-up/page-down actions work (defaults to `5`)
23
+ * @param {Boolean} [filterEnabled] set to `true` to enable filter input box
24
+ * @param {Function} [filterFunc] custom filtering function (see
25
+ * {@link qui.forms.commonfields.ComboField#makeChoices})
26
+ * @param {...*} args parent class parameters
27
+ */
28
+
29
+ constructor({
30
+ choices = [],
31
+ makeChoices = null,
32
+ fastFactor = null,
33
+ filterEnabled = false,
34
+ filterFunc = null,
35
+ ...args
36
+ }) {
37
+ super({
38
+ widgetAttrs: {
39
+ choices: choices,
40
+ fastFactor: fastFactor,
41
+ filterEnabled: filterEnabled,
42
+ makeChoices: function () {
43
+ return that.makeChoices()
44
+ }
45
+ },
46
+ ...args
47
+ })
48
+
49
+ /* "that" needs to be assigned here because we can't refer to "this" before super() */
50
+ let that = this
51
+
52
+ this._filterFunc = filterFunc
53
+ this._makeChoices = makeChoices
54
+
55
+ if (filterFunc || (this.filterFunc !== ComboField.prototype.filterFunc)) {
56
+ this._widgetCall('option', {filterFunc: this.filterFunc.bind(this)})
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Set the list of choices.
62
+ * @param {Object[]} choices choices (pairs of `label` and `value`)
63
+ */
64
+ setChoices(choices) {
65
+ this._widgetCall({choices: choices})
66
+ }
67
+
68
+ /**
69
+ * Create choices.
70
+ * @returns {Object[]} choices (pairs of `label` and `value`)
71
+ */
72
+ makeChoices() {
73
+ if (this._makeChoices) {
74
+ return this._makeChoices()
75
+ }
76
+
77
+ return []
78
+ }
79
+
80
+ /**
81
+ * Tell if a choice matches a search text or not.
82
+ * @param {Object} choice
83
+ * @param {String} searchText
84
+ * @returns {Boolean}
85
+ */
86
+ filterFunc(choice, searchText) {
87
+ if (this._filterFunc) {
88
+ return this._filterFunc(choice, searchText)
89
+ }
90
+
91
+ return true
92
+ }
93
+
94
+ /**
95
+ * Update the list of choices, calling makeChoices.
96
+ */
97
+ updateChoices() {
98
+ let value = this._widgetCall('getValue')
99
+ this._widgetCall('updateChoices')
100
+ if (value != null) {
101
+ this._widgetCall('setValue', value)
102
+ }
103
+ }
104
+
105
+ }
106
+
107
+
108
+ export default ComboField
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @namespace qui.forms.commonfields
3
+ */
4
+
5
+ export {default as CheckField} from './check-field.js'
6
+ export {default as ChoiceButtonsField} from './choice-buttons-field.js'
7
+ export {default as ColorComboField} from './color-combo-field.js'
8
+ export {default as ComboField} from './combo-field.js'
9
+ export {default as CompositeField} from './composite-field.js'
10
+ export {default as CustomHTMLField} from './custom-html-field.js'
11
+ export {default as EmailField} from './email-field.js'
12
+ export {default as FilePickerField} from './file-picker-field.js'
13
+ export {default as JQueryUIField} from './jquery-ui-field.js'
14
+ export {default as LabelsField} from './labels-field.js'
15
+ export {default as NumericField} from './numeric-field.js'
16
+ export {default as PasswordField} from './password-field.js'
17
+ export {default as PhoneField} from './phone-field.js'
18
+ export {default as ProgressDiskField} from './progress-disk-field.js'
19
+ export {default as PushButtonField} from './push-button-field.js'
20
+ export {default as SliderField} from './slider-field.js'
21
+ export {default as TextAreaField} from './text-area-field.js'
22
+ export {default as TextField} from './text-field.js'
23
+ export {default as UpDownField} from './up-down-field.js'
@@ -0,0 +1,132 @@
1
+
2
+ import $ from '$qui/lib/jquery.module.js'
3
+
4
+ import FormField from '../form-field.js'
5
+
6
+
7
+ /**
8
+ * A form field composed by multiple subfields.
9
+ * @alias qui.forms.commonfields.CompositeField
10
+ * @extends qui.forms.FormField
11
+ */
12
+ class CompositeField extends FormField {
13
+
14
+ /**
15
+ * @constructs
16
+ * @param {qui.forms.FormField[]} fields the list of subfields
17
+ * @param {String} [flow] arrange subfield widgets vertically (`"vertical"`) or horizontally (`"horizontal"`,
18
+ * default)
19
+ * @param {Number} [columns] number of columns (unlimited by default, when `flow` is `"horizontal"`, otherwise
20
+ * defaults to `1`)
21
+ * @param {Number} [rows] number of rows (unlimited by default, when `flow` is `"vertical"`, otherwise defaults to
22
+ * `1`)
23
+ * @param {Boolean} [equalSize] set to `true` to make all cells of equal width/height (defaults to `false`)
24
+ * @param {...*} args parent class parameters
25
+ */
26
+ constructor({fields, flow = 'horizontal', columns = null, rows = null, equalSize = false, ...args}) {
27
+ super(args)
28
+
29
+ this._fields = fields.map(this._preprocessField)
30
+ this._flow = flow
31
+ this._columns = columns
32
+ this._rows = rows
33
+ this._equalSize = equalSize
34
+ }
35
+
36
+ focus() {
37
+ /* Focus the first field */
38
+ this._fields.some(f => f.focus(), true)
39
+ }
40
+
41
+ makeWidget() {
42
+ let div = $('<div></div>', {class: 'qui-composite-field-container'})
43
+ let sizeSpec = this._equalSize ? '1fr' : 'auto'
44
+ if (this._flow === 'horizontal') {
45
+ if (this._columns) {
46
+ div.css('grid-template-columns', `repeat(${this._columns}, ${sizeSpec})`)
47
+ div.css('grid-auto-flow', 'row')
48
+ }
49
+ else {
50
+ div.css('grid-auto-flow', 'column')
51
+ }
52
+ }
53
+ else {
54
+ if (this._rows) {
55
+ div.css('grid-template-rows', `repeat(${this._rows}, ${sizeSpec})`)
56
+ div.css('grid-auto-flow', 'column')
57
+ }
58
+ else {
59
+ div.css('grid-auto-flow', 'row')
60
+ }
61
+ }
62
+
63
+ this._fields.forEach(function (field) {
64
+ div.append(field.getHTML())
65
+
66
+ })
67
+
68
+ return div
69
+ }
70
+
71
+ validateWidget(value) {
72
+ /* Return the first validation error among fields */
73
+
74
+ let error = null
75
+ this._fields.some(function (field) {
76
+ let e = field.validateWidget(value[field.getName()])
77
+ if (e != null) {
78
+ error = e
79
+ return true
80
+ }
81
+ })
82
+
83
+ return error
84
+ }
85
+
86
+ valueToWidget(value) {
87
+ this._fields.forEach(f => f.valueToWidget(value[f.getName()]))
88
+ }
89
+
90
+ widgetToValue() {
91
+ return Object.fromEntries(this._fields.map(f => [f.getName(), f.widgetToValue()]))
92
+ }
93
+
94
+ setWidgetReadonly(readonly) {
95
+ this._fields.forEach(f => f.setWidgetReadonly(readonly))
96
+ }
97
+
98
+ enableWidget() {
99
+ this._fields.forEach(f => f.enableWidget())
100
+ }
101
+
102
+ disableWidget() {
103
+ this._fields.forEach(f => f.disableWidget())
104
+ }
105
+
106
+ setForm(form) {
107
+ super.setForm(form)
108
+
109
+ this._fields.forEach(f => f.setForm(form))
110
+ }
111
+
112
+ /**
113
+ * Return the subfield with a given name. If no such field is found, `null` is returned.
114
+ * @param {String} name the name of the subfield
115
+ * @returns {?qui.forms.FormField}
116
+ */
117
+ getField(name) {
118
+ return this._fields.find(f => f.getName() === name) || null
119
+ }
120
+
121
+ _preprocessField(field) {
122
+ field.setLabel('') /* Subfields of composite field can't have label */
123
+ field.setValueWidth(100) /* The value always occupies the entire space */
124
+ field._forceOneLine = true // TODO: this should be a field setter
125
+
126
+ return field
127
+ }
128
+
129
+ }
130
+
131
+
132
+ export default CompositeField
@@ -0,0 +1,51 @@
1
+
2
+ import $ from '$qui/lib/jquery.module.js'
3
+
4
+ import FormField from '../form-field.js'
5
+
6
+
7
+ /**
8
+ * A form field whose widget's HTML content is supplied by user.
9
+ * @alias qui.forms.commonfields.CustomHTMLField
10
+ * @extends qui.forms.FormField
11
+ */
12
+ class CustomHTMLField extends FormField {
13
+
14
+ /**
15
+ * @constructs
16
+ * @param {String|jQuery} content the HTML content
17
+ * @param {...*} args parent class parameters
18
+ */
19
+ constructor({content, ...args}) {
20
+ super(args)
21
+
22
+ if (typeof content === 'string') {
23
+ content = $(content)
24
+ }
25
+ this._content = content
26
+ }
27
+
28
+ makeWidget() {
29
+ return this._content
30
+ }
31
+
32
+ valueToWidget(value) {
33
+ }
34
+
35
+ widgetToValue() {
36
+ return null
37
+ }
38
+
39
+ setWidgetReadonly(readonly) {
40
+ }
41
+
42
+ enableWidget() {
43
+ }
44
+
45
+ disableWidget() {
46
+ }
47
+
48
+ }
49
+
50
+
51
+ export default CustomHTMLField
@@ -0,0 +1,30 @@
1
+
2
+ import TextField from './text-field.js'
3
+
4
+
5
+ /**
6
+ * An email text field. The value data type is `String`.
7
+ * @alias qui.forms.commonfields.EmailField
8
+ * @extends qui.forms.commonfields.TextField
9
+ */
10
+ class EmailField extends TextField {
11
+
12
+ static WIDGET_CLASS = 'emailinput'
13
+
14
+
15
+ /**
16
+ * @constructs
17
+ * @param {...*} args parent class parameters
18
+ */
19
+ constructor({...args}) {
20
+ super(args)
21
+ }
22
+
23
+ validateWidget(value) {
24
+ return null // TODO implement me
25
+ }
26
+
27
+ }
28
+
29
+
30
+ export default EmailField
@@ -0,0 +1,46 @@
1
+
2
+ import JQueryUIField from './jquery-ui-field.js'
3
+
4
+
5
+ /**
6
+ * A file picker field. The value data type is `File[]`.
7
+ * @alias qui.forms.commonfields.FilePickerField
8
+ * @extends qui.forms.commonfields.JQueryUIField
9
+ */
10
+ class FilePickerField extends JQueryUIField {
11
+
12
+ static WIDGET_CLASS = 'filepicker'
13
+
14
+
15
+ /**
16
+ * @constructs
17
+ * @param {?String} [placeholder] an empty-selection placeholder
18
+ * @param {?String[]} [accept] an optional list of file types to accept
19
+ * @param {Boolean} [multiple] enable or disable multiple file selection (disabled by default)
20
+ * @param {Object} [widgetAttrs] extra attributes to pass to underlying JQueryUI widget
21
+ * @param {...*} args parent class parameters
22
+ */
23
+ constructor({
24
+ placeholder = null,
25
+ accept = null,
26
+ multiple = false,
27
+ widgetAttrs = {},
28
+ ...args
29
+ }) {
30
+ Object.assign(widgetAttrs, {
31
+ placeholder: placeholder,
32
+ accept: accept,
33
+ multiple: multiple
34
+ })
35
+
36
+ super({widgetAttrs: widgetAttrs, ...args})
37
+ }
38
+
39
+ getFocusableElement() {
40
+ return this.getWidget().children('input')
41
+ }
42
+
43
+ }
44
+
45
+
46
+ export default FilePickerField