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