@schukai/monster 3.53.0 → 3.55.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 (72) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/package.json +1 -1
  3. package/source/components/datatable/datasource/rest.mjs +358 -309
  4. package/source/components/datatable/datatable/header.mjs +8 -0
  5. package/source/components/datatable/datatable.mjs +606 -557
  6. package/source/components/datatable/embedded-pagination.mjs +50 -62
  7. package/source/components/datatable/filter/util.mjs +122 -0
  8. package/source/components/datatable/filter.mjs +893 -708
  9. package/source/components/datatable/pagination.mjs +335 -310
  10. package/source/components/datatable/status.mjs +248 -0
  11. package/source/components/datatable/style/datatable.pcss +1 -0
  12. package/source/components/datatable/style/embedded-pagination.pcss +59 -2
  13. package/source/components/datatable/style/filter.pcss +4 -0
  14. package/source/components/datatable/style/pagination.pcss +28 -4
  15. package/source/components/datatable/style/status.pcss +42 -0
  16. package/source/components/datatable/stylesheet/column-bar.mjs +1 -1
  17. package/source/components/datatable/stylesheet/datatable.mjs +1 -1
  18. package/source/components/datatable/stylesheet/filter-button.mjs +1 -1
  19. package/source/components/datatable/stylesheet/filter.mjs +1 -1
  20. package/source/components/datatable/stylesheet/pagination.mjs +1 -1
  21. package/source/components/datatable/stylesheet/status.mjs +27 -0
  22. package/source/components/form/action-button.mjs +1 -1
  23. package/source/components/form/api-button.mjs +1 -1
  24. package/source/components/form/button-bar.mjs +1 -1
  25. package/source/components/form/button.mjs +1 -1
  26. package/source/components/form/confirm-button.mjs +1 -1
  27. package/source/components/form/context-error.mjs +275 -0
  28. package/source/components/form/context-help.mjs +5 -5
  29. package/source/components/form/form.mjs +2 -2
  30. package/source/components/form/message-state-button.mjs +2 -2
  31. package/source/components/form/popper-button.mjs +7 -4
  32. package/source/components/form/popper.mjs +317 -309
  33. package/source/components/form/reload.mjs +1 -1
  34. package/source/components/form/select.mjs +9 -3
  35. package/source/components/form/shadow-reload.mjs +1 -1
  36. package/source/components/form/state-button.mjs +2 -1
  37. package/source/components/form/style/context-error.pcss +32 -0
  38. package/source/components/form/style/context-help.pcss +22 -5
  39. package/source/components/form/stylesheet/context-error.mjs +27 -0
  40. package/source/components/form/stylesheet/context-help.mjs +1 -1
  41. package/source/components/form/stylesheet/select.mjs +1 -1
  42. package/source/components/form/stylesheet/tabs.mjs +1 -1
  43. package/source/components/form/tabs.mjs +757 -707
  44. package/source/components/form/template.mjs +1 -1
  45. package/source/components/form/tree-select.mjs +1 -1
  46. package/source/components/host/collapse.mjs +22 -5
  47. package/source/components/host/config-manager.mjs +39 -2
  48. package/source/components/host/host.mjs +14 -0
  49. package/source/components/host/stylesheet/call-button.mjs +1 -1
  50. package/source/components/host/stylesheet/overlay.mjs +1 -1
  51. package/source/components/host/stylesheet/toggle-button.mjs +1 -1
  52. package/source/components/host/util.mjs +6 -1
  53. package/source/components/notify/stylesheet/message.mjs +1 -1
  54. package/source/components/stylesheet/icons.mjs +1 -1
  55. package/source/data/transformer.mjs +39 -42
  56. package/source/dom/customelement.mjs +1 -1
  57. package/source/dom/updater.mjs +700 -688
  58. package/source/dom/util.mjs +42 -0
  59. package/source/i18n/providers/embed.mjs +3 -3
  60. package/source/monster.mjs +6 -0
  61. package/source/text/formatter.mjs +2 -2
  62. package/source/types/observer.mjs +1 -1
  63. package/source/types/version.mjs +1 -1
  64. package/source/util/sleep.mjs +18 -0
  65. package/test/cases/components/form/button.mjs +2 -1
  66. package/test/cases/components/form/select.mjs +1 -1
  67. package/test/cases/components/form/tree-select.mjs +1 -1
  68. package/test/cases/data/transformer.mjs +2 -2
  69. package/test/cases/dom/updater.mjs +67 -46
  70. package/test/cases/monster.mjs +1 -1
  71. package/test/web/test.html +2 -2
  72. package/test/web/tests.js +18 -13
@@ -3,25 +3,25 @@
3
3
  * SPDX-License-Identifier: AGPL-3.0
4
4
  */
5
5
 
6
- import { addAttributeToken } from "../../../dom/attributes.mjs";
7
- import { ATTRIBUTE_ERRORMESSAGE } from "../../../dom/constants.mjs";
8
- import { Datasource, dataSourceSymbol } from "../datasource.mjs";
9
- import { DatasourceStyleSheet } from "../stylesheet/datasource.mjs";
10
- import { instanceSymbol } from "../../../constants.mjs";
6
+ import {addAttributeToken} from "../../../dom/attributes.mjs";
7
+ import {ATTRIBUTE_ERRORMESSAGE} from "../../../dom/constants.mjs";
8
+ import {Datasource, dataSourceSymbol} from "../datasource.mjs";
9
+ import {DatasourceStyleSheet} from "../stylesheet/datasource.mjs";
10
+ import {instanceSymbol} from "../../../constants.mjs";
11
11
  import {
12
- assembleMethodSymbol,
13
- registerCustomElement,
12
+ assembleMethodSymbol,
13
+ registerCustomElement,
14
14
  } from "../../../dom/customelement.mjs";
15
- import { RestAPI } from "../../../data/datasource/server/restapi.mjs";
16
- import { Formatter } from "../../../text/formatter.mjs";
17
- import { clone } from "../../../util/clone.mjs";
18
- import { validateBoolean } from "../../../types/validate.mjs";
19
- import { findElementWithIdUpwards } from "../../../dom/util.mjs";
20
- import { Observer } from "../../../types/observer.mjs";
21
- import { Pathfinder } from "../../../data/pathfinder.mjs";
22
- import { fireCustomEvent } from "../../../dom/events.mjs";
15
+ import {RestAPI} from "../../../data/datasource/server/restapi.mjs";
16
+ import {Formatter} from "../../../text/formatter.mjs";
17
+ import {clone} from "../../../util/clone.mjs";
18
+ import {validateBoolean} from "../../../types/validate.mjs";
19
+ import {findElementWithIdUpwards} from "../../../dom/util.mjs";
20
+ import {Observer} from "../../../types/observer.mjs";
21
+ import {Pathfinder} from "../../../data/pathfinder.mjs";
22
+ import {fireCustomEvent} from "../../../dom/events.mjs";
23
23
 
24
- export { Rest };
24
+ export {Rest};
25
25
 
26
26
  /**
27
27
  * @private
@@ -34,7 +34,7 @@ const intersectionObserverHandlerSymbol = Symbol("intersectionObserverHandler");
34
34
  * @type {symbol}
35
35
  */
36
36
  const intersectionObserverObserverSymbol = Symbol(
37
- "intersectionObserverObserver",
37
+ "intersectionObserverObserver",
38
38
  );
39
39
 
40
40
  /**
@@ -63,322 +63,371 @@ const filterObserverSymbol = Symbol("filterObserver");
63
63
  * @summary A rest api datasource
64
64
  */
65
65
  class Rest extends Datasource {
66
- /**
67
- * the constructor of the class
68
- */
69
- constructor() {
70
- super();
71
- this[dataSourceSymbol] = new RestAPI();
72
- }
73
-
74
- /**
75
- * This method is called by the `instanceof` operator.
76
- * @returns {symbol}
77
- */
78
- static get [instanceSymbol]() {
79
- return Symbol.for("@schukai/monster/components/datasource/rest@@instance");
80
- }
81
-
82
- /**
83
- * To set the options via the html tag the attribute `data-monster-options` must be used.
84
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
85
- *
86
- * The individual configuration values can be found in the table.
87
- *
88
- * @property {Object} templates Template definitions
89
- * @property {string} templates.main Main template
90
- * @property {Object} features Feature definitions
91
- * @property {boolean} features.autoInit If true, the component is initialized automatically
92
- * @property {Object} read Read configuration
93
- * @property {string} read.url The url of the rest api
94
- * @property {string} read.method The method of the rest api
95
- * @property {Object} read.parameters The parameters of the rest api
96
- * @property {Object} read.parameters.filter The filter of the rest api
97
- * @property {Object} read.parameters.orderBy The order by of the rest api
98
- * @property {Object} read.parameters.page The page of the rest api
99
- * @property {Object} write Write configuration
100
- */
101
- get defaults() {
102
- const restOptions = new RestAPI().defaults;
103
-
104
- restOptions.read.parameters = {
105
- filter: undefined,
106
- oderBy: undefined,
107
- page: "1",
108
- };
109
-
110
- return Object.assign({}, super.defaults, restOptions, {
111
- templates: {
112
- main: getTemplate(),
113
- },
114
-
115
- features: {
116
- autoInit: true,
117
- filter: false,
118
- },
119
-
120
- autoInit: {
121
- intersectionObserver: false,
122
- oneTime: true,
123
- },
124
-
125
- filter: {
126
- id: undefined,
127
- },
128
-
129
- response: {
130
- errorMessagePath: "sys.message",
131
- },
132
- });
133
- }
134
-
135
- /**
136
- *
137
- * @param {string} page
138
- * @param {string} query
139
- * @param {string} orderBy
140
- * @returns {Monster.Components.Datatable.Datasource.Rest}
141
- */
142
- setParameters({ page, query, orderBy }) {
143
- const parameters = this.getOption("read.parameters");
144
- if (query !== undefined) {
145
- parameters.query = `${query}`;
146
- parameters.page = "1";
147
- }
148
-
149
- // after a query the page is set to 1, so if the page is not set, it is set to 1
150
- if (page !== undefined) parameters.page = `${page}`;
151
- if (orderBy !== undefined) parameters.order = `${orderBy}`;
152
- this.setOption("read.parameters", parameters);
153
- return this;
154
- }
155
-
156
- /**
157
- *
158
- * @return {Monster.Components.Form.Form}
159
- */
160
- [assembleMethodSymbol]() {
161
- super[assembleMethodSymbol]();
162
-
163
- initEventHandler.call(this);
164
- initAutoInit.call(this);
165
- }
166
-
167
- /**
168
- * @deprecated 2023-06-25
169
- * @returns {Promise<never>|*}
170
- */
171
- reload() {
172
- return this.fetch();
173
- }
174
-
175
- /**
176
- * Fetches the data from the rest api
177
- * @returns {Promise<never>|*}
178
- */
179
- fetch() {
180
- const opt = clone(this.getOption("read"));
181
- this[dataSourceSymbol].setOption("read", opt);
182
-
183
- let url = this.getOption("read.url");
184
- const formatter = new Formatter(this.getOption("read.parameters"));
185
-
186
- if (!url) {
187
- return Promise.reject(new Error("No url defined"));
188
- }
189
-
190
- url = formatter.format(url);
191
-
192
- this[dataSourceSymbol].setOption("read.url", url);
193
- return this[dataSourceSymbol].read();
194
- }
195
-
196
- /**
197
- *
198
- * @return {CSSStyleSheet[]}
199
- */
200
- static getCSSStyleSheet() {
201
- return [DatasourceStyleSheet];
202
- }
203
-
204
- /**
205
- * @private
206
- * @return {string}
207
- */
208
- static getTag() {
209
- return "monster-datasource-rest";
210
- }
211
-
212
- /**
213
- * This method activates the intersection observer manually.
214
- * For this purpose, the option `autoInit.intersectionObserver` must be set to `false`.
215
- *
216
- * @returns {Monster.Components.Datatable.Datasource.Rest}
217
- */
218
- initIntersectionObserver() {
219
- initIntersectionObserver.call(this);
220
- return this;
221
- }
222
-
223
- /**
224
- * @private
225
- */
226
- connectedCallback() {
227
- super.connectedCallback();
228
-
229
- setTimeout(() => {
230
- if (this.getOption("features.filter", false) === true) {
231
- initFilter.call(this);
232
- }
233
- }, 0);
234
- }
235
-
236
- /**
237
- * @private
238
- */
239
- disconnectedCallback() {
240
- super.disconnectedCallback();
241
- removeFilter.call(this);
242
- }
66
+ /**
67
+ * the constructor of the class
68
+ */
69
+ constructor() {
70
+ super();
71
+ this[dataSourceSymbol] = new RestAPI();
72
+ }
73
+
74
+ /**
75
+ * This method is called by the `instanceof` operator.
76
+ * @returns {symbol}
77
+ */
78
+ static get [instanceSymbol]() {
79
+ return Symbol.for("@schukai/monster/components/datasource/rest@@instance");
80
+ }
81
+
82
+ /**
83
+ * To set the options via the html tag the attribute `data-monster-options` must be used.
84
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
85
+ *
86
+ * The individual configuration values can be found in the table.
87
+ *
88
+ * @property {Object} templates Template definitions
89
+ * @property {string} templates.main Main template
90
+ * @property {Object} features Feature definitions
91
+ * @property {boolean} features.autoInit If true, the component is initialized automatically
92
+ * @property {boolean} features.filter If true, the component is initialized automatically
93
+ * @property {Object} autoInit Auto init definitions
94
+ * @property {boolean} autoInit.intersectionObserver If true, the intersection observer is initialized automatically
95
+ * @property {boolean} autoInit.oneTime If true, the intersection observer is initialized only once
96
+ * @property {Object} filter Filter definitions
97
+ * @property {string} filter.id The id of the filter control
98
+ * @property {Object} datatable Datatable definitions
99
+ * @property {string} datatable.id The id of the datatable control
100
+ * @property {Object} response Response definitions
101
+ * @property {string} response.errorMessagePath The path to the error message in the response
102
+ * @property {Object} read Read configuration
103
+ * @property {string} read.url The url of the rest api
104
+ * @property {string} read.method The method of the rest api
105
+ * @property {Object} read.parameters The parameters of the rest api
106
+ * @property {Object} read.parameters.filter The filter of the rest api
107
+ * @property {Object} read.parameters.orderBy The order by of the rest api
108
+ * @property {Object} read.parameters.page The page of the rest api
109
+ * @property {Object} write Write configuration
110
+
111
+ */
112
+ get defaults() {
113
+ const restOptions = new RestAPI().defaults;
114
+
115
+ restOptions.read.parameters = {
116
+ filter: undefined,
117
+ oderBy: undefined,
118
+ page: "1",
119
+ };
120
+
121
+ return Object.assign({}, super.defaults, restOptions, {
122
+ templates: {
123
+ main: getTemplate(),
124
+ },
125
+
126
+ features: {
127
+ autoInit: true,
128
+ filter: false,
129
+ },
130
+
131
+ autoInit: {
132
+ intersectionObserver: false,
133
+ oneTime: true,
134
+ },
135
+
136
+ filter: {
137
+ id: undefined,
138
+ },
139
+
140
+ datatable: {
141
+ id: undefined,
142
+ },
143
+
144
+ response: {
145
+ errorMessagePath: "sys.message",
146
+ },
147
+ });
148
+ }
149
+
150
+ /**
151
+ *
152
+ * @param {string} page
153
+ * @param {string} query
154
+ * @param {string} orderBy
155
+ * @returns {Monster.Components.Datatable.Datasource.Rest}
156
+ */
157
+ setParameters({page, query, orderBy}) {
158
+ const parameters = this.getOption("read.parameters");
159
+ if (query !== undefined) {
160
+ parameters.query = `${query}`;
161
+ parameters.page = "1";
162
+ }
163
+
164
+ // after a query the page is set to 1, so if the page is not set, it is set to 1
165
+ if (page !== undefined) parameters.page = `${page}`;
166
+ if (orderBy !== undefined) parameters.order = `${orderBy}`;
167
+ this.setOption("read.parameters", parameters);
168
+ return this;
169
+ }
170
+
171
+ /**
172
+ *
173
+ * @return {Monster.Components.Form.Form}
174
+ */
175
+ [assembleMethodSymbol]() {
176
+ super[assembleMethodSymbol]();
177
+
178
+ initEventHandler.call(this);
179
+ initAutoInit.call(this);
180
+ }
181
+
182
+ /**
183
+ * @deprecated 2023-06-25
184
+ * @returns {Promise<never>|*}
185
+ */
186
+ reload() {
187
+ return this.fetch();
188
+ }
189
+
190
+ /**
191
+ * Fetches the data from the rest api
192
+ * @returns {Promise<never>|*}
193
+ */
194
+ fetch() {
195
+ const self = this;
196
+ const opt = clone(this.getOption("read"));
197
+ this[dataSourceSymbol].setOption("read", opt);
198
+
199
+ let url = this.getOption("read.url");
200
+ const formatter = new Formatter(this.getOption("read.parameters"));
201
+
202
+ if (!url) {
203
+ return Promise.reject(new Error("No url defined"));
204
+ }
205
+
206
+ url = formatter.format(url);
207
+
208
+ this[dataSourceSymbol].setOption("read.url", url);
209
+
210
+ return new Promise((resolve, reject) => {
211
+
212
+ fireCustomEvent(self, "monster-datasource-fetch", {
213
+ datasource: self,
214
+ });
215
+
216
+ setTimeout(() => {
217
+ self[dataSourceSymbol].read().then((response) => {
218
+ fireCustomEvent(self, "monster-datasource-fetched", {
219
+ datasource: self,
220
+ });
221
+
222
+ resolve(response);
223
+
224
+ })
225
+ .catch((error) => {
226
+ fireCustomEvent(self, "monster-datasource-error", {
227
+ error: error,
228
+ });
229
+
230
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, error.toString());
231
+ reject(error);
232
+
233
+ });
234
+ },0);
235
+
236
+ });
237
+
238
+
239
+ }
240
+
241
+ /**
242
+ *
243
+ * @return {CSSStyleSheet[]}
244
+ */
245
+ static getCSSStyleSheet() {
246
+ return [DatasourceStyleSheet];
247
+ }
248
+
249
+ /**
250
+ * @private
251
+ * @return {string}
252
+ */
253
+ static getTag() {
254
+ return "monster-datasource-rest";
255
+ }
256
+
257
+ /**
258
+ * This method activates the intersection observer manually.
259
+ * For this purpose, the option `autoInit.intersectionObserver` must be set to `false`.
260
+ *
261
+ * @returns {Monster.Components.Datatable.Datasource.Rest}
262
+ */
263
+ initIntersectionObserver() {
264
+ initIntersectionObserver.call(this);
265
+ return this;
266
+ }
267
+
268
+ /**
269
+ * @private
270
+ */
271
+ connectedCallback() {
272
+ super.connectedCallback();
273
+
274
+ setTimeout(() => {
275
+ if (this.getOption("features.filter", false) === true) {
276
+ initFilter.call(this);
277
+ }
278
+ }, 0);
279
+ }
280
+
281
+ /**
282
+ * @private
283
+ */
284
+ disconnectedCallback() {
285
+ super.disconnectedCallback();
286
+ removeFilter.call(this);
287
+ }
243
288
  }
244
289
 
245
290
  /**
246
291
  * @private
247
292
  */
248
293
  function removeFilter() {
249
- const filterID = this.getOption("filter.id", undefined);
250
- if (!filterID) return;
294
+ const filterID = this.getOption("filter.id", undefined);
295
+ if (!filterID) return;
251
296
 
252
- const filterControl = findElementWithIdUpwards(this, filterID);
297
+ const filterControl = findElementWithIdUpwards(this, filterID);
253
298
 
254
- if (filterControl && this[filterObserverSymbol]) {
255
- filterControl?.detachObserver(this[filterObserverSymbol]);
256
- }
299
+ if (filterControl && this[filterObserverSymbol]) {
300
+ filterControl?.detachObserver(this[filterObserverSymbol]);
301
+ }
257
302
  }
258
303
 
304
+
259
305
  /**
260
306
  * @private
261
307
  */
262
308
  function initFilter() {
263
- const filterID = this.getOption("filter.id", undefined);
264
-
265
- if (!filterID)
266
- throw new Error("filter feature is enabled but no filter id is defined");
267
-
268
- const filterControl = findElementWithIdUpwards(this, filterID);
269
- if (!filterControl)
270
- throw new Error(
271
- "filter feature is enabled but no filter control with id " +
272
- filterID +
273
- " is found",
274
- );
275
-
276
- this[filterObserverSymbol] = new Observer(() => {
277
- const query = filterControl.getOption("query", undefined);
278
- this.setParameters({ query: query });
279
- this.fetch()
280
- .then(() => {
281
- this.dispatchEvent(new CustomEvent("reload", { bubbles: true }));
282
- filterControl?.showSuccess();
283
- })
284
- .catch((e) => {
285
- this.dispatchEvent(
286
- new CustomEvent("error", { bubbles: true, detail: e }),
287
- );
288
-
289
- const response = e?.getResponse();
290
- if (response && response.status === 400) {
291
- response
292
- .json()
293
- .then((json) => {
294
- const path = new Pathfinder(json);
295
- const error = path.getVia(
296
- this.getOption("response.errorMessagePath"),
297
- );
298
- if (error) {
299
- filterControl?.showFailureMessage(error);
300
- return;
301
- }
302
-
303
- filterControl?.showFailureMessage(e.message);
304
- })
305
- .catch((e) => {
306
- filterControl?.showFailureMessage(e.message);
307
- });
308
- } else {
309
- filterControl?.showFailureMessage(e.message);
310
- }
311
- });
312
- });
313
-
314
- filterControl.attachObserver(this[filterObserverSymbol]);
309
+ const filterID = this.getOption("filter.id", undefined);
310
+
311
+ if (!filterID)
312
+ throw new Error("filter feature is enabled but no filter id is defined");
313
+
314
+ const filterControl = findElementWithIdUpwards(this, filterID);
315
+ if (!filterControl)
316
+ throw new Error(
317
+ "filter feature is enabled but no filter control with id " +
318
+ filterID +
319
+ " is found",
320
+ );
321
+
322
+ this[filterObserverSymbol] = new Observer(() => {
323
+
324
+ const query = filterControl.getOption("query", undefined);
325
+ this.setParameters({query: query});
326
+ this.fetch()
327
+ .then((response) => {
328
+
329
+ if(!(response instanceof Response) ){
330
+ throw new Error("Response is not an instance of Response");
331
+ }
332
+
333
+ if (response?.ok === true) {
334
+ this.dispatchEvent(new CustomEvent("reload", {bubbles: true}));
335
+ filterControl?.showSuccess();
336
+ }
337
+
338
+ response
339
+ .json()
340
+ .then((json) => {
341
+ const path = new Pathfinder(json);
342
+ const error = path.getVia(
343
+ this.getOption("response.errorMessagePath"),
344
+ );
345
+ if (error) {
346
+ filterControl?.showFailureMessage(error);
347
+ return;
348
+ }
349
+
350
+ filterControl?.showFailureMessage(e.message);
351
+ })
352
+ .catch((e) => {
353
+ filterControl?.showFailureMessage(e.message);
354
+ });
355
+
356
+
357
+ })
358
+ .catch((e) => {
359
+ this.dispatchEvent(
360
+ new CustomEvent("error", {bubbles: true, detail: e}),
361
+ );
362
+
363
+ if (!(e instanceof Error)) {
364
+ e = new Error(e);
365
+ }
366
+
367
+ filterControl?.showFailureMessage(e.message);
368
+ return Promise.reject(e);
369
+
370
+ });
371
+ });
372
+
373
+ filterControl.attachObserver(this[filterObserverSymbol]);
315
374
  }
316
375
 
317
376
  /**
318
377
  * @private
319
378
  */
320
379
  function initAutoInit() {
321
- const autoInit = this.getOption("features.autoInit");
322
- validateBoolean(autoInit);
323
-
324
- if (autoInit !== true) return;
325
-
326
- if (this.getOption("autoInit.intersectionObserver") === true) {
327
- initIntersectionObserver.call(this);
328
- return;
329
- }
330
-
331
- setTimeout(() => {
332
- this.fetch()
333
- .then(() => {
334
- fireCustomEvent(this, "monster-datasource-fetched", {
335
- datasource: this,
336
- });
337
- })
338
- .catch((error) => {
339
- fireCustomEvent(this, "monster-datasource-error", {
340
- error: error,
341
- });
342
-
343
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
344
- });
345
- }, 0);
380
+ const autoInit = this.getOption("features.autoInit");
381
+ validateBoolean(autoInit);
382
+
383
+ if (autoInit !== true) return;
384
+
385
+ if (this.getOption("autoInit.intersectionObserver") === true) {
386
+ initIntersectionObserver.call(this);
387
+ return;
388
+ }
389
+
390
+ setTimeout(() => {
391
+ this.fetch().catch(() => {
392
+
393
+ });
394
+ }, 0);
346
395
  }
347
396
 
348
397
  function initEventHandler() {
349
- this[intersectionObserverHandlerSymbol] = (entries) => {
350
- entries.forEach((entry) => {
351
- if (entry.isIntersecting) {
352
- if (entry.intersectionRatio > 0) {
353
- this.fetch();
354
- }
355
-
356
- // only load once
357
- if (
358
- this.getOption("autoInit.oneTime") === true &&
359
- this[intersectionObserverObserverSymbol] !== undefined
360
- ) {
361
- this[intersectionObserverObserverSymbol].unobserve(this);
362
- }
363
- }
364
- });
365
- };
398
+ this[intersectionObserverHandlerSymbol] = (entries) => {
399
+ entries.forEach((entry) => {
400
+ if (entry.isIntersecting) {
401
+ if (entry.intersectionRatio > 0) {
402
+ this.fetch();
403
+ }
404
+
405
+ // only load once
406
+ if (
407
+ this.getOption("autoInit.oneTime") === true &&
408
+ this[intersectionObserverObserverSymbol] !== undefined
409
+ ) {
410
+ this[intersectionObserverObserverSymbol].unobserve(this);
411
+ }
412
+ }
413
+ });
414
+ };
366
415
  }
367
416
 
368
417
  function initIntersectionObserver() {
369
- this.classList.add("intersection-observer");
370
-
371
- const options = {
372
- root: null,
373
- rootMargin: "0px",
374
- threshold: 0.1,
375
- };
376
-
377
- this[intersectionObserverObserverSymbol] = new IntersectionObserver(
378
- this[intersectionObserverHandlerSymbol],
379
- options,
380
- );
381
- this[intersectionObserverObserverSymbol].observe(this);
418
+ this.classList.add("intersection-observer");
419
+
420
+ const options = {
421
+ root: null,
422
+ rootMargin: "0px",
423
+ threshold: 0.1,
424
+ };
425
+
426
+ this[intersectionObserverObserverSymbol] = new IntersectionObserver(
427
+ this[intersectionObserverHandlerSymbol],
428
+ options,
429
+ );
430
+ this[intersectionObserverObserverSymbol].observe(this);
382
431
  }
383
432
 
384
433
  /**
@@ -386,8 +435,8 @@ function initIntersectionObserver() {
386
435
  * @return {string}
387
436
  */
388
437
  function getTemplate() {
389
- // language=HTML
390
- return `
438
+ // language=HTML
439
+ return `
391
440
  <slot></slot>`;
392
441
  }
393
442