@schukai/monster 3.69.2 → 3.71.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/CHANGELOG.md +29 -4
- package/package.json +1 -1
- package/source/components/datatable/dataset.mjs +278 -202
- package/source/components/datatable/datasource/dom.mjs +1 -1
- package/source/components/datatable/datasource/rest.mjs +410 -404
- package/source/components/datatable/filter.mjs +1 -0
- package/source/components/datatable/save-button.mjs +1 -9
- package/source/components/datatable/style/datatable.pcss +1 -1
- package/source/components/datatable/style/filter-controls-defaults.pcss +1 -1
- package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +8 -17
- package/source/components/form/context-error.mjs +2 -0
- package/source/components/form/context-help.mjs +1 -0
- package/source/components/form/field-set.mjs +222 -225
- package/source/components/form/form.mjs +185 -545
- package/source/components/form/select.mjs +24 -9
- package/source/components/form/style/field-set.pcss +84 -7
- package/source/components/form/style/form.pcss +5 -3
- package/source/components/form/style/select.pcss +5 -4
- package/source/components/form/stylesheet/field-set.mjs +7 -14
- package/source/components/form/stylesheet/form.mjs +8 -17
- package/source/components/form/stylesheet/select.mjs +7 -14
- package/source/components/layout/style/collapse.pcss +0 -2
- package/source/components/layout/stylesheet/collapse.mjs +7 -14
- package/source/components/style/form.pcss +66 -3
- package/source/components/style/mixin/property.pcss +8 -1
- package/source/components/style/typography.pcss +4 -12
- package/source/components/stylesheet/form.mjs +8 -17
- package/source/components/stylesheet/mixin/form.mjs +7 -16
- package/source/components/stylesheet/mixin/property.mjs +6 -13
- package/source/components/stylesheet/typography.mjs +7 -16
- package/source/data/datasource/server/restapi.mjs +191 -180
- package/source/data/datasource/server.mjs +118 -74
- package/source/data/diff.mjs +1 -1
- package/source/dom/customelement.mjs +4 -0
- package/source/dom/updater.mjs +1 -1
- package/source/types/tokenlist.mjs +2 -2
- package/test/cases/components/form/form.mjs +1 -182
- package/test/cases/components/host/details.mjs +1 -1
- package/test/cases/components/host/host.mjs +1 -1
- package/test/cases/components/host/overlay.mjs +1 -1
- package/test/cases/data/diff.mjs +37 -0
- package/test/cases/dom/customcontrol.mjs +1 -1
- package/test/cases/dom/customelement.mjs +2 -2
- package/source/components/style/mixin/form.pcss +0 -242
|
@@ -12,577 +12,217 @@
|
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
15
|
+
import {instanceSymbol} from "../../constants.mjs";
|
|
16
|
+
import {internalSymbol} from "../../constants.mjs";
|
|
17
|
+
import {TokenList} from "../../types/tokenlist.mjs";
|
|
18
|
+
import {DeadMansSwitch} from "../../util/deadmansswitch.mjs";
|
|
19
|
+
import {DataSet} from "../datatable/dataset.mjs";
|
|
20
|
+
//import { Datasource } from "../../data/datasource.mjs";
|
|
21
|
+
import {RestAPI} from "../../data/datasource/server/restapi.mjs";
|
|
22
|
+
import {WebConnect} from "../../data/datasource/server/webconnect.mjs";
|
|
23
|
+
import {WriteError} from "../../data/datasource/server/restapi/writeerror.mjs";
|
|
24
|
+
import {LocalStorage} from "../../data/datasource/storage/localstorage.mjs";
|
|
25
|
+
import {SessionStorage} from "../../data/datasource/storage/sessionstorage.mjs";
|
|
23
26
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
ATTRIBUTE_DISABLED,
|
|
28
|
+
ATTRIBUTE_ERRORMESSAGE,
|
|
29
|
+
ATTRIBUTE_PREFIX,
|
|
30
|
+
ATTRIBUTE_UPDATER_ATTRIBUTES,
|
|
31
|
+
ATTRIBUTE_UPDATER_INSERT,
|
|
32
|
+
ATTRIBUTE_UPDATER_REMOVE,
|
|
33
|
+
ATTRIBUTE_UPDATER_REPLACE,
|
|
31
34
|
} from "../../dom/constants.mjs";
|
|
32
35
|
import {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
assembleMethodSymbol,
|
|
37
|
+
CustomElement,
|
|
38
|
+
registerCustomElement,
|
|
39
|
+
getSlottedElements,
|
|
37
40
|
} from "../../dom/customelement.mjs";
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
41
|
+
import {addObjectWithUpdaterToElement} from "../../dom/updater.mjs";
|
|
42
|
+
import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
|
|
43
|
+
import {isFunction, isString} from "../../types/is.mjs";
|
|
44
|
+
import {Observer} from "../../types/observer.mjs";
|
|
45
|
+
import {ProxyObserver} from "../../types/proxyobserver.mjs";
|
|
46
|
+
import {Processing} from "../../util/processing.mjs";
|
|
47
|
+
import {datasourceLinkedElementSymbol, handleDataSourceChanges} from "../datatable/util.mjs";
|
|
48
|
+
import {MessageStateButton} from "./message-state-button.mjs";
|
|
44
49
|
import {
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
ATTRIBUTE_FORM_DATASOURCE,
|
|
51
|
+
ATTRIBUTE_FORM_DATASOURCE_ARGUMENTS,
|
|
47
52
|
} from "./constants.mjs";
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
53
|
+
import {StateButton} from "./state-button.mjs";
|
|
54
|
+
import {FormStyleSheet} from "./stylesheet/form.mjs";
|
|
50
55
|
|
|
51
|
-
export {
|
|
56
|
+
export {Form};
|
|
52
57
|
|
|
53
|
-
/**
|
|
54
|
-
* @private
|
|
55
|
-
* @since 3.1.0
|
|
56
|
-
* @type {string}
|
|
57
|
-
*/
|
|
58
|
-
const ATTRIBUTE_FORM_DATASOURCE_ACTION = `${ATTRIBUTE_PREFIX}datasource-action`;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Form data is the internal representation of the form data
|
|
62
|
-
*
|
|
63
|
-
* @private
|
|
64
|
-
* @type {symbol}
|
|
65
|
-
* @since 1.7.0
|
|
66
|
-
*/
|
|
67
|
-
const formDataSymbol = Symbol.for(
|
|
68
|
-
"@schukai/monster/components/form/form@@formdata",
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @private
|
|
73
|
-
* @type {symbol}
|
|
74
|
-
* @since 2.8.0
|
|
75
|
-
*/
|
|
76
|
-
const formDataUpdaterSymbol = Symbol.for(
|
|
77
|
-
"@schukai/component-form/form@@formdata-updater-link",
|
|
78
|
-
);
|
|
79
58
|
|
|
80
59
|
/**
|
|
81
60
|
* @private
|
|
82
61
|
* @type {symbol}
|
|
83
|
-
* @since 1.7.0
|
|
84
|
-
*/
|
|
85
|
-
const formElementSymbol = Symbol.for(
|
|
86
|
-
"@schukai/component-form/form@@form-element",
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* @private
|
|
91
|
-
* @type {symbol}
|
|
92
|
-
* @since 2.5.0
|
|
93
|
-
*/
|
|
94
|
-
const registeredDatasourcesSymbol = Symbol.for(
|
|
95
|
-
"@schukai/component-form/form@@registered-datasources",
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* @private
|
|
100
|
-
* @since 1.7.0
|
|
101
|
-
* @type {string}
|
|
102
|
-
*/
|
|
103
|
-
const PROPERTY_VALIDATION_KEY = "__validation";
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* This CustomControl creates a form element with a variety of options.
|
|
107
|
-
*
|
|
108
|
-
* <img src="./images/form.png">
|
|
109
|
-
*
|
|
110
|
-
* Dependencies: the system uses functions of the [monsterjs](https://monsterjs.org/) library.
|
|
111
|
-
*
|
|
112
|
-
* You can create this control either by specifying the HTML tag `<monster-form />` directly in the HTML or using
|
|
113
|
-
* Javascript via the `document.createElement('monster-form');` method.
|
|
114
|
-
*
|
|
115
|
-
* ```html
|
|
116
|
-
* <monster-form></monster-form>
|
|
117
|
-
* ```
|
|
118
|
-
*
|
|
119
|
-
* Or you can create this CustomControl directly in Javascript:
|
|
120
|
-
*
|
|
121
|
-
* ```js
|
|
122
|
-
* import {Form} from '@schukai/component-form/source/form.js';
|
|
123
|
-
* document.createElement('monster-form');
|
|
124
|
-
* ```
|
|
125
|
-
*
|
|
126
|
-
* @startuml form.png
|
|
127
|
-
* skinparam monochrome true
|
|
128
|
-
* skinparam shadowing false
|
|
129
|
-
* HTMLElement <|-- CustomElement
|
|
130
|
-
* CustomElement <|-- Form
|
|
131
|
-
* @enduml
|
|
132
|
-
*
|
|
133
|
-
* @since 1.6.0
|
|
134
|
-
* @copyright schukai GmbH
|
|
135
|
-
* @memberOf Monster.Components.Form
|
|
136
|
-
* @summary A configurable form control
|
|
137
62
|
*/
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
this.removeAttribute(ATTRIBUTE_DISABLED);
|
|
239
|
-
throw e;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
*
|
|
245
|
-
* @return {Monster.Components.Form.Form}
|
|
246
|
-
*/
|
|
247
|
-
[assembleMethodSymbol]() {
|
|
248
|
-
super[assembleMethodSymbol]();
|
|
249
|
-
|
|
250
|
-
initControlReferences.call(this);
|
|
251
|
-
initDatasource.call(this);
|
|
252
|
-
initUpdater.call(this);
|
|
253
|
-
initObserver.call(this);
|
|
254
|
-
|
|
255
|
-
return this;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
*
|
|
260
|
-
* @return {*}
|
|
261
|
-
*/
|
|
262
|
-
getValues() {
|
|
263
|
-
return this[formDataSymbol].getSubject();
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
*
|
|
268
|
-
* @return {string}
|
|
269
|
-
*/
|
|
270
|
-
static getTag() {
|
|
271
|
-
return "monster-form";
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
*
|
|
276
|
-
* @return {CSSStyleSheet}
|
|
277
|
-
*/
|
|
278
|
-
static getCSSStyleSheet() {
|
|
279
|
-
return [FormStyleSheet];
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
static [registeredDatasourcesSymbol] = new Map([
|
|
283
|
-
["restapi", RestAPI],
|
|
284
|
-
["localstorage", LocalStorage],
|
|
285
|
-
["sessionstorage", SessionStorage],
|
|
286
|
-
["webconnect", WebConnect],
|
|
287
|
-
]);
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Register a new datasource
|
|
291
|
-
*
|
|
292
|
-
* @param {string} name
|
|
293
|
-
* @param {Monster.Data.Datasource} datasource
|
|
294
|
-
*/
|
|
295
|
-
static registerDatasource(name, datasource) {
|
|
296
|
-
Form[registeredDatasourcesSymbol].set(name, datasource);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Unregister a registered datasource
|
|
301
|
-
*
|
|
302
|
-
* @param {string} name
|
|
303
|
-
*/
|
|
304
|
-
static unregisterDatasource(name) {
|
|
305
|
-
Form[registeredDatasourcesSymbol].delete(name);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* Get registered data sources
|
|
310
|
-
*
|
|
311
|
-
* @return {Map}
|
|
312
|
-
*/
|
|
313
|
-
static getDatasources() {
|
|
314
|
-
return Form[registeredDatasourcesSymbol];
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Run reportValidation on all child html form controls.
|
|
319
|
-
*
|
|
320
|
-
* @since 2.10.0
|
|
321
|
-
* @returns {boolean}
|
|
322
|
-
*/
|
|
323
|
-
reportValidity() {
|
|
324
|
-
let valid = true;
|
|
325
|
-
|
|
326
|
-
const selector = this.getOption("reportValidity.selector");
|
|
327
|
-
const nodes = getSlottedElements.call(this, selector);
|
|
328
|
-
nodes.forEach((node) => {
|
|
329
|
-
if (typeof node.reportValidity === "function") {
|
|
330
|
-
if (node.reportValidity() === false) {
|
|
331
|
-
valid = false;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
return valid;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
63
|
+
const debounceCallbackSymbol = Symbol("timerCallback");
|
|
64
|
+
|
|
65
|
+
class Form extends DataSet {
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* @returns {{shadowMode: string, templates: {main: *}, display: string, disabled: boolean, delegatesFocus: boolean, templateMapping: {}} & {templates: {main: string}, classes: {form: string}}}
|
|
70
|
+
*/
|
|
71
|
+
get defaults() {
|
|
72
|
+
const obj = Object.assign(
|
|
73
|
+
{},
|
|
74
|
+
super.defaults,
|
|
75
|
+
{
|
|
76
|
+
templates: {
|
|
77
|
+
main: getTemplate(),
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
classes: {
|
|
81
|
+
form: "",
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
writeBack: {
|
|
85
|
+
events: ["change", "input", "keyup"]
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
reportValidity: {
|
|
89
|
+
selector: "input,select,textarea",
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
obj['features']['mutationObserver'] = false;
|
|
96
|
+
obj['features']['writeBack'] = true;
|
|
97
|
+
|
|
98
|
+
return obj;
|
|
99
|
+
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
* @return {string}
|
|
106
|
+
*/
|
|
107
|
+
static getTag() {
|
|
108
|
+
return "monster-form";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @return {CSSStyleSheet[]}
|
|
113
|
+
*/
|
|
114
|
+
static getCSSStyleSheet() {
|
|
115
|
+
return [FormStyleSheet];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
*
|
|
120
|
+
*/
|
|
121
|
+
[assembleMethodSymbol]() {
|
|
122
|
+
super[assembleMethodSymbol]();
|
|
123
|
+
|
|
124
|
+
initControlReferences.call(this);
|
|
125
|
+
initEventHandler.call(this);
|
|
126
|
+
initDataSourceHandler.call(this);
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* This method is called when the component is created.
|
|
132
|
+
* @since 3.70.0
|
|
133
|
+
* @returns {DataSet}
|
|
134
|
+
*/
|
|
135
|
+
refresh() {
|
|
136
|
+
this.write();
|
|
137
|
+
super.refresh();
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Run reportValidation on all child html form controls.
|
|
143
|
+
*
|
|
144
|
+
* @since 2.10.0
|
|
145
|
+
* @returns {boolean}
|
|
146
|
+
*/
|
|
147
|
+
reportValidity() {
|
|
148
|
+
let valid = true;
|
|
149
|
+
|
|
150
|
+
const selector = this.getOption("reportValidity.selector");
|
|
151
|
+
const nodes = getSlottedElements.call(this, selector);
|
|
152
|
+
|
|
153
|
+
nodes.forEach((node) => {
|
|
154
|
+
if (typeof node.reportValidity === "function") {
|
|
155
|
+
if (node.reportValidity() === false) {
|
|
156
|
+
valid = false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
return valid;
|
|
162
|
+
}
|
|
339
163
|
|
|
340
|
-
/**
|
|
341
|
-
* @private
|
|
342
|
-
*/
|
|
343
|
-
function initUpdater() {
|
|
344
|
-
if (!this.shadowRoot) {
|
|
345
|
-
throw new Error("no shadow-root is defined");
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
const slots = this.shadowRoot.querySelectorAll("slot");
|
|
349
|
-
for (const [, slot] of Object.entries(slots)) {
|
|
350
|
-
for (const [, node] of Object.entries(slot.assignedNodes())) {
|
|
351
|
-
if (!(node instanceof HTMLElement)) {
|
|
352
|
-
continue;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
const query = `[${ATTRIBUTE_UPDATER_ATTRIBUTES}],[${ATTRIBUTE_UPDATER_REPLACE}],[${ATTRIBUTE_UPDATER_REMOVE}],[${ATTRIBUTE_UPDATER_INSERT}]`;
|
|
356
|
-
const controls = node.querySelectorAll(query);
|
|
357
|
-
|
|
358
|
-
const list = new Set([...controls]);
|
|
359
|
-
|
|
360
|
-
if (node.matches(query)) {
|
|
361
|
-
list.add(node);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (list.size === 0) {
|
|
365
|
-
continue;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
addObjectWithUpdaterToElement.call(
|
|
369
|
-
node,
|
|
370
|
-
list,
|
|
371
|
-
formDataUpdaterSymbol,
|
|
372
|
-
this[formDataSymbol],
|
|
373
|
-
);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
164
|
}
|
|
377
165
|
|
|
378
|
-
|
|
379
|
-
* @private
|
|
380
|
-
*/
|
|
381
|
-
function initDatasource() {
|
|
382
|
-
if (!this.shadowRoot) {
|
|
383
|
-
throw new Error("no shadow-root is defined");
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
const slots = this.shadowRoot.querySelectorAll("slot");
|
|
387
|
-
for (const [, slot] of Object.entries(slots)) {
|
|
388
|
-
for (const [, node] of Object.entries(slot.assignedNodes())) {
|
|
389
|
-
if (!(node instanceof HTMLElement)) {
|
|
390
|
-
continue;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
const query = `[${ATTRIBUTE_FORM_DATASOURCE_ACTION}=write]`;
|
|
394
|
-
const controls = node.querySelectorAll(query);
|
|
395
|
-
|
|
396
|
-
const list = new Set([...controls]);
|
|
397
|
-
|
|
398
|
-
if (node.matches(query)) {
|
|
399
|
-
list.add(node);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
if (list.size === 0) {
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
initWriteActions.call(this, list);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
166
|
+
function initDataSourceHandler() {
|
|
410
167
|
|
|
411
|
-
/**
|
|
412
|
-
* @private
|
|
413
|
-
* @param elements
|
|
414
|
-
*/
|
|
415
|
-
function initWriteActions(elements) {
|
|
416
|
-
elements.forEach((element) => {
|
|
417
|
-
if (element instanceof HTMLElement) {
|
|
418
|
-
element.addEventListener("click", () => {
|
|
419
|
-
runWriteCallback.call(this, element);
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
const g = element?.getOption;
|
|
423
|
-
if (!isFunction(g)) {
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
const s = element?.setOption;
|
|
428
|
-
if (!isFunction(s)) {
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
const fn = element.getOption("actions.click");
|
|
433
|
-
|
|
434
|
-
if (!isFunction(fn)) {
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// disable console.log of standard click event
|
|
439
|
-
element.setOption("actions.click", function () {
|
|
440
|
-
// do nothing!
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
});
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
function runWriteCallback(button) {
|
|
447
|
-
if (typeof this.reportValidity === "function") {
|
|
448
|
-
if (this.reportValidity() === false) {
|
|
449
|
-
if (
|
|
450
|
-
button instanceof StateButton ||
|
|
451
|
-
button instanceof MessageStateButton
|
|
452
|
-
) {
|
|
453
|
-
button.setState("failed");
|
|
454
|
-
}
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
const datasource = this.getOption("datasource");
|
|
460
|
-
if (!(datasource instanceof Datasource)) {
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
if (button instanceof StateButton || button instanceof MessageStateButton) {
|
|
465
|
-
button.setState("activity");
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
//const data = form?.[formDataSymbol]?.getRealSubject();
|
|
469
|
-
const writePromise = datasource
|
|
470
|
-
.set(this[formDataSymbol].getRealSubject())
|
|
471
|
-
.write();
|
|
472
|
-
if (!(writePromise instanceof Promise)) {
|
|
473
|
-
throw new Error("datasource.write() must return a promise");
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
writePromise
|
|
477
|
-
.then((r) => {
|
|
478
|
-
if (
|
|
479
|
-
button instanceof StateButton ||
|
|
480
|
-
button instanceof MessageStateButton
|
|
481
|
-
) {
|
|
482
|
-
button.setState("successful");
|
|
483
|
-
}
|
|
484
|
-
this[formDataSymbol].getSubject()[PROPERTY_VALIDATION_KEY] = {};
|
|
485
|
-
})
|
|
486
|
-
.catch((e) => {
|
|
487
|
-
if (e instanceof WriteError) {
|
|
488
|
-
this[formDataSymbol].getSubject()[PROPERTY_VALIDATION_KEY] =
|
|
489
|
-
e.getValidation();
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
if (
|
|
493
|
-
button instanceof StateButton ||
|
|
494
|
-
button instanceof MessageStateButton
|
|
495
|
-
) {
|
|
496
|
-
button.setState("failed");
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
if (button instanceof MessageStateButton) {
|
|
500
|
-
button.setMessage(e.message);
|
|
501
|
-
button.showMessage();
|
|
502
|
-
}
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
/**
|
|
507
|
-
* This attribute can be used to pass a URL to this select.
|
|
508
|
-
*
|
|
509
|
-
* ```
|
|
510
|
-
* <monster-form data-monster-datasource="restapi:....."></monster-form>
|
|
511
|
-
* ```
|
|
512
|
-
*
|
|
513
|
-
* @private
|
|
514
|
-
* @return {object}
|
|
515
|
-
*/
|
|
516
|
-
function initOptionsFromArguments() {
|
|
517
|
-
const options = {};
|
|
518
|
-
|
|
519
|
-
const datasource = this.getAttribute(ATTRIBUTE_FORM_DATASOURCE);
|
|
520
|
-
if (isString(datasource)) {
|
|
521
|
-
for (const [key, classObject] of Form.getDatasources()) {
|
|
522
|
-
if (datasource === key) {
|
|
523
|
-
let args = this.getAttribute(ATTRIBUTE_FORM_DATASOURCE_ARGUMENTS);
|
|
524
|
-
|
|
525
|
-
try {
|
|
526
|
-
args = JSON.parse(args);
|
|
527
|
-
} catch (e) {
|
|
528
|
-
this.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.toString());
|
|
529
|
-
continue;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
try {
|
|
533
|
-
options["datasource"] = new classObject(args);
|
|
534
|
-
} catch (e) {
|
|
535
|
-
this.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.toString());
|
|
536
|
-
continue;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
break;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
if (options["datasource"] instanceof Datasource) {
|
|
543
|
-
break;
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
return options;
|
|
549
168
|
}
|
|
550
169
|
|
|
551
170
|
/**
|
|
552
171
|
* @private
|
|
553
|
-
* @
|
|
172
|
+
* @returns {initEventHandler}
|
|
554
173
|
*/
|
|
555
|
-
function
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
174
|
+
function initEventHandler() {
|
|
175
|
+
|
|
176
|
+
if (this.getOption("features.writeBack") === true) {
|
|
177
|
+
const events = this.getOption("writeBack.events");
|
|
178
|
+
for (const event of events) {
|
|
179
|
+
|
|
180
|
+
this.addEventListener(event, (e) => {
|
|
181
|
+
|
|
182
|
+
if (!this.reportValidity()) {
|
|
183
|
+
|
|
184
|
+
this.classList.add("invalid");
|
|
185
|
+
setTimeout(() => {
|
|
186
|
+
this.classList.remove("invalid");
|
|
187
|
+
}, 1000)
|
|
188
|
+
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (this[debounceCallbackSymbol] instanceof DeadMansSwitch) {
|
|
193
|
+
try {
|
|
194
|
+
this[debounceCallbackSymbol].touch();
|
|
195
|
+
return;
|
|
196
|
+
} catch (e) {
|
|
197
|
+
if (e.message !== "has already run") {
|
|
198
|
+
throw e;
|
|
199
|
+
}
|
|
200
|
+
delete this[debounceCallbackSymbol];
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this[debounceCallbackSymbol] = new DeadMansSwitch(200, () => {
|
|
205
|
+
setTimeout(() => {
|
|
206
|
+
this.write();
|
|
207
|
+
}, 0);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return this;
|
|
571
215
|
}
|
|
572
216
|
|
|
573
217
|
/**
|
|
574
218
|
* @private
|
|
575
|
-
* @return {
|
|
219
|
+
* @return {FilterButton}
|
|
576
220
|
*/
|
|
577
221
|
function initControlReferences() {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
this[formElementSymbol] = this.shadowRoot.querySelector(
|
|
583
|
-
"[data-monster-role=form]",
|
|
584
|
-
);
|
|
585
|
-
return this;
|
|
222
|
+
if (!this.shadowRoot) {
|
|
223
|
+
throw new Error("no shadow-root is defined");
|
|
224
|
+
}
|
|
225
|
+
return this;
|
|
586
226
|
}
|
|
587
227
|
|
|
588
228
|
/**
|
|
@@ -590,8 +230,8 @@ function initControlReferences() {
|
|
|
590
230
|
* @return {string}
|
|
591
231
|
*/
|
|
592
232
|
function getTemplate() {
|
|
593
|
-
|
|
594
|
-
|
|
233
|
+
// language=HTML
|
|
234
|
+
return `
|
|
595
235
|
<div data-monster-role="control" part="control">
|
|
596
236
|
<form data-monster-attributes="disabled path:disabled | if:true, class path:classes.form"
|
|
597
237
|
data-monster-role="form"
|