@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,25 +12,27 @@
|
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
15
|
+
import {diff} from "../../../data/diff.mjs";
|
|
16
|
+
import {addAttributeToken} from "../../../dom/attributes.mjs";
|
|
17
|
+
import {ATTRIBUTE_ERRORMESSAGE} from "../../../dom/constants.mjs";
|
|
18
|
+
import {isArray} from "../../../types/is.mjs";
|
|
19
|
+
import {Datasource, dataSourceSymbol} from "../datasource.mjs";
|
|
20
|
+
import {DatasourceStyleSheet} from "../stylesheet/datasource.mjs";
|
|
21
|
+
import {instanceSymbol} from "../../../constants.mjs";
|
|
20
22
|
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
assembleMethodSymbol,
|
|
24
|
+
registerCustomElement,
|
|
23
25
|
} from "../../../dom/customelement.mjs";
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
26
|
+
import {RestAPI} from "../../../data/datasource/server/restapi.mjs";
|
|
27
|
+
import {Formatter} from "../../../text/formatter.mjs";
|
|
28
|
+
import {clone} from "../../../util/clone.mjs";
|
|
29
|
+
import {validateBoolean} from "../../../types/validate.mjs";
|
|
30
|
+
import {findElementWithIdUpwards} from "../../../dom/util.mjs";
|
|
31
|
+
import {Observer} from "../../../types/observer.mjs";
|
|
32
|
+
import {Pathfinder} from "../../../data/pathfinder.mjs";
|
|
33
|
+
import {fireCustomEvent} from "../../../dom/events.mjs";
|
|
32
34
|
|
|
33
|
-
export {
|
|
35
|
+
export {Rest};
|
|
34
36
|
|
|
35
37
|
/**
|
|
36
38
|
* @private
|
|
@@ -44,7 +46,7 @@ const intersectionObserverHandlerSymbol = Symbol("intersectionObserverHandler");
|
|
|
44
46
|
* @type {symbol}
|
|
45
47
|
*/
|
|
46
48
|
const rawDataSymbol = Symbol.for(
|
|
47
|
-
|
|
49
|
+
"@schukai/monster/data/datasource/server/restapi/rawdata",
|
|
48
50
|
);
|
|
49
51
|
|
|
50
52
|
/**
|
|
@@ -52,7 +54,7 @@ const rawDataSymbol = Symbol.for(
|
|
|
52
54
|
* @type {symbol}
|
|
53
55
|
*/
|
|
54
56
|
const intersectionObserverObserverSymbol = Symbol(
|
|
55
|
-
|
|
57
|
+
"intersectionObserverObserver",
|
|
56
58
|
);
|
|
57
59
|
|
|
58
60
|
/**
|
|
@@ -81,23 +83,23 @@ const filterObserverSymbol = Symbol("filterObserver");
|
|
|
81
83
|
* @summary A rest api datasource
|
|
82
84
|
*/
|
|
83
85
|
class Rest extends Datasource {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
86
|
+
/**
|
|
87
|
+
* the constructor of the class
|
|
88
|
+
*/
|
|
89
|
+
constructor() {
|
|
90
|
+
super();
|
|
91
|
+
this[dataSourceSymbol] = new RestAPI();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* This method is called by the `instanceof` operator.
|
|
96
|
+
* @returns {symbol}
|
|
97
|
+
*/
|
|
98
|
+
static get [instanceSymbol]() {
|
|
99
|
+
return Symbol.for("@schukai/monster/components/datasource/rest@@instance");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
101
103
|
* To set the options via the html tag the attribute `data-monster-options` must be used.
|
|
102
104
|
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
|
103
105
|
*
|
|
@@ -128,405 +130,409 @@ class Rest extends Datasource {
|
|
|
128
130
|
* @property {Object} write Write configuration
|
|
129
131
|
|
|
130
132
|
*/
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
133
|
+
get defaults() {
|
|
134
|
+
const restOptions = new RestAPI().defaults;
|
|
135
|
+
|
|
136
|
+
restOptions.read.parameters = {
|
|
137
|
+
filter: undefined,
|
|
138
|
+
oderBy: undefined,
|
|
139
|
+
page: "1",
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
return Object.assign({}, super.defaults, restOptions, {
|
|
143
|
+
templates: {
|
|
144
|
+
main: getTemplate(),
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
features: {
|
|
148
|
+
autoInit: false,
|
|
149
|
+
filter: false,
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
autoInit: {
|
|
153
|
+
intersectionObserver: false,
|
|
154
|
+
oneTime: true,
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
filter: {
|
|
158
|
+
id: undefined,
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
datatable: {
|
|
162
|
+
id: undefined,
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
response: {
|
|
166
|
+
path: {
|
|
167
|
+
message: "sys.message",
|
|
168
|
+
code: "sys.code",
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
*
|
|
176
|
+
* @param {string} page
|
|
177
|
+
* @param {string} query
|
|
178
|
+
* @param {string} orderBy
|
|
179
|
+
* @returns {Monster.Components.Datatable.Datasource.Rest}
|
|
180
|
+
*/
|
|
181
|
+
setParameters({page, query, orderBy}) {
|
|
182
|
+
const parameters = this.getOption("read.parameters");
|
|
183
|
+
if (query !== undefined) {
|
|
184
|
+
parameters.query = `${query}`;
|
|
185
|
+
parameters.page = "1";
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// after a query the page is set to 1, so if the page is not set, it is set to 1
|
|
189
|
+
if (page !== undefined) parameters.page = `${page}`;
|
|
190
|
+
if (orderBy !== undefined) parameters.order = `${orderBy}`;
|
|
191
|
+
this.setOption("read.parameters", parameters);
|
|
192
|
+
return this;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @return {void}
|
|
197
|
+
*/
|
|
198
|
+
[assembleMethodSymbol]() {
|
|
199
|
+
super[assembleMethodSymbol]();
|
|
200
|
+
|
|
201
|
+
initEventHandler.call(this);
|
|
202
|
+
initAutoInit.call(this);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @deprecated 2023-06-25
|
|
207
|
+
* @returns {Promise<never>|*}
|
|
208
|
+
*/
|
|
209
|
+
reload() {
|
|
210
|
+
return this.fetch();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Fetches the data from the rest api
|
|
215
|
+
* @returns {Promise<never>|*}
|
|
216
|
+
*/
|
|
217
|
+
fetch() {
|
|
218
|
+
const opt = clone(this.getOption("read"));
|
|
219
|
+
this[dataSourceSymbol].setOption("read", opt);
|
|
220
|
+
|
|
221
|
+
let url = this.getOption("read.url");
|
|
222
|
+
const formatter = new Formatter(this.getOption("read.parameters"));
|
|
223
|
+
|
|
224
|
+
if (!url) {
|
|
225
|
+
return Promise.reject(new Error("No url defined"));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
url = formatter.format(url);
|
|
229
|
+
|
|
230
|
+
this[dataSourceSymbol].setOption("read.url", url);
|
|
231
|
+
|
|
232
|
+
return new Promise((resolve, reject) => {
|
|
233
|
+
fireCustomEvent(this, "monster-datasource-fetch", {
|
|
234
|
+
datasource: this,
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
setTimeout(() => {
|
|
238
|
+
this[dataSourceSymbol]
|
|
239
|
+
.read()
|
|
240
|
+
.then((response) => {
|
|
241
|
+
fireCustomEvent(this, "monster-datasource-fetched", {
|
|
242
|
+
datasource: this,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
resolve(response);
|
|
246
|
+
})
|
|
247
|
+
.catch((error) => {
|
|
248
|
+
fireCustomEvent(this, "monster-datasource-error", {
|
|
249
|
+
error: error,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error.toString());
|
|
253
|
+
reject(error);
|
|
254
|
+
});
|
|
255
|
+
}, 0);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
*
|
|
261
|
+
* @return {CSSStyleSheet[]}
|
|
262
|
+
*/
|
|
263
|
+
static getCSSStyleSheet() {
|
|
264
|
+
return [DatasourceStyleSheet];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* @private
|
|
269
|
+
* @return {string}
|
|
270
|
+
*/
|
|
271
|
+
static getTag() {
|
|
272
|
+
return "monster-datasource-rest";
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* This method activates the intersection observer manually.
|
|
277
|
+
* For this purpose, the option `autoInit.intersectionObserver` must be set to `false`.
|
|
278
|
+
*
|
|
279
|
+
* @returns {Monster.Components.Datatable.Datasource.Rest}
|
|
280
|
+
*/
|
|
281
|
+
initIntersectionObserver() {
|
|
282
|
+
initIntersectionObserver.call(this);
|
|
283
|
+
return this;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* @private
|
|
288
|
+
*/
|
|
289
|
+
connectedCallback() {
|
|
290
|
+
super.connectedCallback();
|
|
291
|
+
|
|
292
|
+
setTimeout(() => {
|
|
293
|
+
if (this.getOption("features.filter", false) === true) {
|
|
294
|
+
initFilter.call(this);
|
|
295
|
+
}
|
|
296
|
+
}, 0);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* @private
|
|
301
|
+
*/
|
|
302
|
+
disconnectedCallback() {
|
|
303
|
+
super.disconnectedCallback();
|
|
304
|
+
removeFilter.call(this);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* @returns {Promise<never>|*}
|
|
309
|
+
*/
|
|
310
|
+
read() {
|
|
311
|
+
return this.fetch();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Fetches the data from the rest api
|
|
316
|
+
* @returns {Promise<never>|*}
|
|
317
|
+
*/
|
|
318
|
+
write() {
|
|
319
|
+
const opt = clone(this.getOption("write"));
|
|
320
|
+
this[dataSourceSymbol].setOption("write", opt);
|
|
321
|
+
|
|
322
|
+
let url = this.getOption("write.url");
|
|
323
|
+
const formatter = new Formatter(this.getOption("write.parameters"));
|
|
324
|
+
|
|
325
|
+
if (!url) {
|
|
326
|
+
return Promise.reject(new Error("No url defined"));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
url = formatter.format(url);
|
|
330
|
+
|
|
331
|
+
this[dataSourceSymbol].setOption("write.url", url);
|
|
332
|
+
|
|
333
|
+
return new Promise((resolve, reject) => {
|
|
334
|
+
fireCustomEvent(this, "monster-datasource-fetch", {
|
|
335
|
+
datasource: this,
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
setTimeout(() => {
|
|
339
|
+
this[dataSourceSymbol]
|
|
340
|
+
.write()
|
|
341
|
+
.then((response) => {
|
|
342
|
+
fireCustomEvent(this, "monster-datasource-fetched", {
|
|
343
|
+
datasource: this,
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
resolve(response);
|
|
347
|
+
})
|
|
348
|
+
.catch((error) => {
|
|
349
|
+
fireCustomEvent(this, "monster-datasource-error", {
|
|
350
|
+
error: error,
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error.toString());
|
|
354
|
+
reject(error);
|
|
355
|
+
});
|
|
356
|
+
}, 0);
|
|
357
|
+
});
|
|
358
|
+
}
|
|
355
359
|
}
|
|
356
360
|
|
|
357
361
|
/**
|
|
358
362
|
* @private
|
|
359
363
|
*/
|
|
360
364
|
function removeFilter() {
|
|
361
|
-
|
|
362
|
-
|
|
365
|
+
const filterID = this.getOption("filter.id", undefined);
|
|
366
|
+
if (!filterID) return;
|
|
363
367
|
|
|
364
|
-
|
|
368
|
+
const filterControl = findElementWithIdUpwards(this, filterID);
|
|
365
369
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
370
|
+
if (filterControl && this[filterObserverSymbol]) {
|
|
371
|
+
filterControl?.detachObserver(this[filterObserverSymbol]);
|
|
372
|
+
}
|
|
369
373
|
}
|
|
370
374
|
|
|
371
375
|
/**
|
|
372
376
|
* @private
|
|
373
377
|
*/
|
|
374
378
|
function initFilter() {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
379
|
+
const filterID = this.getOption("filter.id", undefined);
|
|
380
|
+
|
|
381
|
+
if (!filterID)
|
|
382
|
+
throw new Error("filter feature is enabled but no filter id is defined");
|
|
383
|
+
|
|
384
|
+
const filterControl = findElementWithIdUpwards(this, filterID);
|
|
385
|
+
if (!filterControl)
|
|
386
|
+
throw new Error(
|
|
387
|
+
"filter feature is enabled but no filter control with id " +
|
|
388
|
+
filterID +
|
|
389
|
+
" is found",
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
this[filterObserverSymbol] = new Observer(() => {
|
|
393
|
+
const query = filterControl.getOption("query");
|
|
394
|
+
if (query === undefined) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
this.setParameters({query: query});
|
|
398
|
+
this.fetch()
|
|
399
|
+
.then((response) => {
|
|
400
|
+
if (!(response instanceof Response)) {
|
|
401
|
+
throw new Error("Response is not an instance of Response");
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (response?.ok === true) {
|
|
405
|
+
this.dispatchEvent(new CustomEvent("reload", {bubbles: true}));
|
|
406
|
+
filterControl?.showSuccess();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (response.bodyUsed === true) {
|
|
410
|
+
return handleIntersectionObserver.call(
|
|
411
|
+
this,
|
|
412
|
+
response[rawDataSymbol],
|
|
413
|
+
response,
|
|
414
|
+
filterControl,
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
response
|
|
419
|
+
.text()
|
|
420
|
+
.then((jsonAsText) => {
|
|
421
|
+
let json;
|
|
422
|
+
try {
|
|
423
|
+
json = JSON.parse(jsonAsText);
|
|
424
|
+
} catch (e) {
|
|
425
|
+
const message = e instanceof Error ? e.message : `${e}`;
|
|
426
|
+
filterControl?.showFailureMessage(message);
|
|
427
|
+
return Promise.reject(e);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return handleIntersectionObserver.call(
|
|
431
|
+
this,
|
|
432
|
+
json,
|
|
433
|
+
response,
|
|
434
|
+
filterControl,
|
|
435
|
+
);
|
|
436
|
+
})
|
|
437
|
+
.catch((e) => {
|
|
438
|
+
filterControl?.showFailureMessage(e.message);
|
|
439
|
+
});
|
|
440
|
+
})
|
|
441
|
+
.catch((e) => {
|
|
442
|
+
this.dispatchEvent(
|
|
443
|
+
new CustomEvent("error", {bubbles: true, detail: e}),
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
if (!(e instanceof Error)) {
|
|
447
|
+
e = new Error(e);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
filterControl?.showFailureMessage(e.message);
|
|
451
|
+
return Promise.reject(e);
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
filterControl.attachObserver(this[filterObserverSymbol]);
|
|
452
456
|
}
|
|
453
457
|
|
|
454
458
|
function handleIntersectionObserver(json, response, filterControl) {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
459
|
+
const path = new Pathfinder(json);
|
|
460
|
+
|
|
461
|
+
const codePath = this.getOption("response.path.code");
|
|
462
|
+
|
|
463
|
+
if (path.exists(codePath)) {
|
|
464
|
+
const code = `${path.getVia(codePath)}`;
|
|
465
|
+
if (code && code === "200") {
|
|
466
|
+
filterControl?.showSuccess();
|
|
467
|
+
return Promise.resolve(response);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const messagePath = this.getOption("response.path.message");
|
|
471
|
+
if (path.exists(messagePath)) {
|
|
472
|
+
const message = path.getVia(messagePath);
|
|
473
|
+
filterControl?.showFailureMessage(message);
|
|
474
|
+
return Promise.reject(new Error(message));
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return Promise.reject(new Error("Response code is not 200"));
|
|
478
|
+
}
|
|
475
479
|
}
|
|
476
480
|
|
|
477
481
|
/**
|
|
478
482
|
* @private
|
|
479
483
|
*/
|
|
480
484
|
function initAutoInit() {
|
|
481
|
-
const autoInit = this.getOption("features.autoInit");
|
|
482
|
-
validateBoolean(autoInit);
|
|
483
485
|
|
|
484
|
-
|
|
486
|
+
const autoInit = this.getOption("features.autoInit");
|
|
487
|
+
validateBoolean(autoInit);
|
|
488
|
+
|
|
489
|
+
if (autoInit !== true) return;
|
|
485
490
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
491
|
+
if (this.getOption("autoInit.intersectionObserver") === true) {
|
|
492
|
+
initIntersectionObserver.call(this);
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
490
495
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
496
|
+
setTimeout(() => {
|
|
497
|
+
this.fetch().catch(() => {
|
|
498
|
+
});
|
|
499
|
+
}, 0);
|
|
494
500
|
}
|
|
495
501
|
|
|
496
502
|
function initEventHandler() {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
503
|
+
this[intersectionObserverHandlerSymbol] = (entries) => {
|
|
504
|
+
entries.forEach((entry) => {
|
|
505
|
+
if (entry.isIntersecting) {
|
|
506
|
+
if (entry.intersectionRatio > 0) {
|
|
507
|
+
this.fetch();
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// only load once
|
|
511
|
+
if (
|
|
512
|
+
this.getOption("autoInit.oneTime") === true &&
|
|
513
|
+
this[intersectionObserverObserverSymbol] !== undefined
|
|
514
|
+
) {
|
|
515
|
+
this[intersectionObserverObserverSymbol].unobserve(this);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
};
|
|
514
520
|
}
|
|
515
521
|
|
|
516
522
|
function initIntersectionObserver() {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
523
|
+
this.classList.add("intersection-observer");
|
|
524
|
+
|
|
525
|
+
const options = {
|
|
526
|
+
root: null,
|
|
527
|
+
rootMargin: "0px",
|
|
528
|
+
threshold: 0.1,
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
this[intersectionObserverObserverSymbol] = new IntersectionObserver(
|
|
532
|
+
this[intersectionObserverHandlerSymbol],
|
|
533
|
+
options,
|
|
534
|
+
);
|
|
535
|
+
this[intersectionObserverObserverSymbol].observe(this);
|
|
530
536
|
}
|
|
531
537
|
|
|
532
538
|
/**
|
|
@@ -534,8 +540,8 @@ function initIntersectionObserver() {
|
|
|
534
540
|
* @return {string}
|
|
535
541
|
*/
|
|
536
542
|
function getTemplate() {
|
|
537
|
-
|
|
538
|
-
|
|
543
|
+
// language=HTML
|
|
544
|
+
return `
|
|
539
545
|
<slot></slot>`;
|
|
540
546
|
}
|
|
541
547
|
|