@schukai/monster 3.99.2 → 3.99.4

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.
@@ -12,46 +12,46 @@
12
12
  * SPDX-License-Identifier: AGPL-3.0
13
13
  */
14
14
 
15
- import { instanceSymbol } from "../../constants.mjs";
15
+ import {instanceSymbol} from "../../constants.mjs";
16
16
  import {
17
- findTargetElementFromEvent,
18
- fireCustomEvent,
17
+ findTargetElementFromEvent,
18
+ fireCustomEvent,
19
19
  } from "../../dom/events.mjs";
20
20
  import {
21
- findElementWithIdUpwards,
22
- findElementWithSelectorUpwards,
21
+ findElementWithIdUpwards,
22
+ findElementWithSelectorUpwards,
23
23
  } from "../../dom/util.mjs";
24
24
  import {
25
- assembleMethodSymbol,
26
- CustomElement,
27
- getSlottedElements,
28
- registerCustomElement,
25
+ assembleMethodSymbol,
26
+ CustomElement,
27
+ getSlottedElements,
28
+ registerCustomElement,
29
29
  } from "../../dom/customelement.mjs";
30
- import { ID } from "../../types/id.mjs";
31
- import { Settings } from "./filter/settings.mjs";
32
- import { FilterStyleSheet } from "./stylesheet/filter.mjs";
33
- import { getDocument, getWindow } from "../../dom/util.mjs";
34
- import { getGlobal } from "../../types/global.mjs";
35
- import { isInstance, isFunction, isObject, isArray } from "../../types/is.mjs";
36
- import { Host } from "../host/host.mjs";
37
- import { addAttributeToken } from "../../dom/attributes.mjs";
38
- import { ATTRIBUTE_ERRORMESSAGE } from "../../dom/constants.mjs";
30
+ import {ID} from "../../types/id.mjs";
31
+ import {Settings} from "./filter/settings.mjs";
32
+ import {FilterStyleSheet} from "./stylesheet/filter.mjs";
33
+ import {getDocument, getWindow} from "../../dom/util.mjs";
34
+ import {getGlobal} from "../../types/global.mjs";
35
+ import {isInstance, isFunction, isObject, isArray} from "../../types/is.mjs";
36
+ import {Host} from "../host/host.mjs";
37
+ import {addAttributeToken} from "../../dom/attributes.mjs";
38
+ import {ATTRIBUTE_ERRORMESSAGE} from "../../dom/constants.mjs";
39
39
  import "../form/message-state-button.mjs";
40
- import { Formatter } from "../../text/formatter.mjs";
41
- import { generateRangeComparisonExpression } from "../../text/util.mjs";
40
+ import {Formatter} from "../../text/formatter.mjs";
41
+ import {generateRangeComparisonExpression} from "../../text/util.mjs";
42
42
 
43
43
  import {
44
- parseBracketedKeyValueHash,
45
- createBracketedKeyValueHash,
44
+ parseBracketedKeyValueHash,
45
+ createBracketedKeyValueHash,
46
46
  } from "../../text/bracketed-key-value-hash.mjs";
47
- import { ThemeStyleSheet } from "../stylesheet/theme.mjs";
48
- import { SpaceStyleSheet } from "../stylesheet/space.mjs";
49
- import { FormStyleSheet } from "../stylesheet/form.mjs";
47
+ import {ThemeStyleSheet} from "../stylesheet/theme.mjs";
48
+ import {SpaceStyleSheet} from "../stylesheet/space.mjs";
49
+ import {FormStyleSheet} from "../stylesheet/form.mjs";
50
50
 
51
51
  import {
52
- getStoredFilterConfigKey,
53
- getFilterConfigKey,
54
- parseDateInput,
52
+ getStoredFilterConfigKey,
53
+ getFilterConfigKey,
54
+ parseDateInput,
55
55
  } from "./filter/util.mjs";
56
56
 
57
57
  import "./filter/select.mjs";
@@ -63,9 +63,10 @@ import "../form/toggle-switch.mjs";
63
63
  import "../form/context-help.mjs";
64
64
  import "../form/context-error.mjs";
65
65
  import "../form/message-state-button.mjs";
66
- import { getLocaleOfDocument } from "../../dom/locale.mjs";
67
66
 
68
- export { Filter };
67
+ import {getLocaleOfDocument} from "../../dom/locale.mjs";
68
+
69
+ export {Filter};
69
70
 
70
71
  /**
71
72
  * @private
@@ -102,7 +103,7 @@ const filterControlElementSymbol = Symbol("filterControlElement");
102
103
  * @type {symbol}
103
104
  */
104
105
  const filterSaveActionButtonElementSymbol = Symbol(
105
- "filterSaveActionButtonElement",
106
+ "filterSaveActionButtonElement",
106
107
  );
107
108
 
108
109
  /**
@@ -162,222 +163,226 @@ const hashChangeSymbol = Symbol("hashChange");
162
163
  * @summary The Filter component is used to show and handle the filter values.
163
164
  */
164
165
  class Filter extends CustomElement {
165
- /**
166
- *
167
- */
168
- constructor() {
169
- super();
170
- this[settingsSymbol] = new Settings();
171
-
172
- // debounce the hash change event if doSearch is called by click the search button
173
- this[hashChangeSymbol] = 0;
174
- }
175
-
176
- /**
177
- * This method is called by the `instanceof` operator.
178
- * @return {symbol}
179
- */
180
- static get [instanceSymbol]() {
181
- return Symbol.for("@schukai/monster/components/filter@@instance");
182
- }
183
-
184
- /**
185
- *
186
- * @param {string} message
187
- * @return {Filter}
188
- */
189
- showFailureMessage(message) {
190
- this[searchButtonElementSymbol].setState(
191
- "failed",
192
- this.getOption("timeouts.message", 4000),
193
- );
194
- this[searchButtonElementSymbol]
195
- .setMessage(message.toString())
196
- .showMessage(this.getOption("timeouts.message", 4000));
197
- return this;
198
- }
199
-
200
- /**
201
- *
202
- * @return {Filter}
203
- */
204
- resetFailureMessage() {
205
- this[searchButtonElementSymbol].hideMessage();
206
- this[searchButtonElementSymbol].removeState();
207
- return this;
208
- }
209
-
210
- /**
211
- *
212
- * @return {Filter}
213
- */
214
- showSuccess() {
215
- this[searchButtonElementSymbol].setState(
216
- "successful",
217
- this.getOption("timeouts.message", 4000),
218
- );
219
- return this;
220
- }
221
-
222
- /**
223
- * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
224
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
225
- *
226
- * The individual configuration values can be found in the table.
227
- *
228
- * @property {Object} templates Template definitions
229
- * @property {string} templates.main Main template
230
- * @property {Object} labels Label definitions
231
- * @property {string} labels.search Search button label
232
- * @property {string} labels.reset Reset button label
233
- * @property {string} labels.save Save button label
234
- * @property {string} labels.filter-name Filter name label
235
- * @property {string} labels.empty-query-and-no-default Empty query and no default query label
236
- * @property {string} labels.query-not-changed Query not changed label
237
- * @property {Object} formatter Formatter definitions
238
- * @property {Object} formatter.marker Marker definitions
239
- * @property {Object} formatter.marker.open Marker open
240
- * @property {Object} formatter.marker.close Marker close
241
- * @property {Object} features Feature definitions
242
- * @property {boolean} features.storedConfig Stored configuration, this replaces the setting `storedConfig.enabled` @since 3.97.0
243
- * @property {Object} storedConfig Stored configuration
244
- * @property {boolean} storedConfig.enabled The store has been enabled, this option will no longer have any effect. @deprecated 20250101
245
- * @property {string} storedConfig.selector Selector
246
- * @property {Object} timeouts Timeout definitions
247
- * @property {number} timeouts.message Message timeout
248
- * @property {Object} queries Query definitions
249
- * @property {Function} queries.wrap Wrap callback
250
- * @property {Function} queries.join Join callback
251
- * @property {string} query Query
252
- * @property {string} defaultQuery Default query
253
- * @property {boolean} eventProcessing Event processing
254
- */
255
- get defaults() {
256
- return Object.assign({}, super.defaults, {
257
- templates: {
258
- main: getTemplate(),
259
- },
260
-
261
- formatter: {
262
- marker: {
263
- open: null,
264
- close: null,
265
- },
266
- },
267
-
268
- labels: getTranslations(),
269
-
270
- templateMapping: {
271
- "filter-save-label": null,
272
- "filter-name-label": name,
273
- },
274
-
275
- features: {
276
- storedConfig: false,
277
- },
278
-
279
- storedConfig: {
280
- enabled: true,
281
- selector: "",
282
- },
283
-
284
- timeouts: {
285
- message: 4000,
286
- },
287
-
288
- queries: {
289
- wrap: (value, definition) => {
290
- return value;
291
- },
292
- join: (queries) => {
293
- if (queries.length === 0) {
294
- return "";
295
- }
296
- return queries.join(" AND ");
297
- },
298
- },
299
-
300
- query: null,
301
- defaultQuery: null,
302
- eventProcessing: true,
303
- });
304
- }
305
-
306
- /**
307
- *
308
- * @return {string}
309
- */
310
- static getTag() {
311
- return "monster-datatable-filter";
312
- }
313
-
314
- /**
315
- * @return {FilterButton}
316
- * @fires monster-filter-initialized
317
- */
318
- [assembleMethodSymbol]() {
319
- this.setOption(
320
- "templateMapping.filter-save-label",
321
- this.getOption("labels.save"),
322
- );
323
-
324
- this.setOption(
325
- "templateMapping.filter-name-label",
326
- this.getOption("labels.filter-name"),
327
- );
328
-
329
- super[assembleMethodSymbol]();
330
-
331
- initControlReferences.call(this);
332
- initEventHandler.call(this);
333
-
334
- initFromConfig
335
- .call(this)
336
- .then(() => {})
337
- .catch((error) => {
338
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error?.message);
339
- })
340
- .finally(() => {
341
- initFilter.call(this);
342
- updateFilterTabs.call(this);
343
- doSearch
344
- .call(this, { showEffect: false })
345
- .then(() => {
346
- fireCustomEvent(this, "monster-filter-initialized");
347
- })
348
- .catch(() => {});
349
- });
350
- }
351
-
352
- /**
353
- *
354
- */
355
- connectedCallback() {
356
- super.connectedCallback();
357
- getWindow().addEventListener(
358
- "hashchange",
359
- this[locationChangeHandlerSymbol],
360
- );
361
- }
362
-
363
- /**
364
- *
365
- */
366
- disconnectedCallback() {
367
- super.disconnectedCallback();
368
-
369
- getWindow().removeEventListener(
370
- "hashchange",
371
- this[locationChangeHandlerSymbol],
372
- );
373
- }
374
-
375
- /**
376
- * @return {Array<CSSStyleSheet>}
377
- */
378
- static getCSSStyleSheet() {
379
- return [FilterStyleSheet, FormStyleSheet, ThemeStyleSheet, SpaceStyleSheet];
380
- }
166
+ /**
167
+ *
168
+ */
169
+ constructor() {
170
+ super();
171
+ this[settingsSymbol] = new Settings();
172
+
173
+ // debounce the hash change event if doSearch is called by click the search button
174
+ this[hashChangeSymbol] = 0;
175
+ }
176
+
177
+ /**
178
+ * This method is called by the `instanceof` operator.
179
+ * @return {symbol}
180
+ */
181
+ static get [instanceSymbol]() {
182
+ return Symbol.for("@schukai/monster/components/filter@@instance");
183
+ }
184
+
185
+ /**
186
+ *
187
+ * @param {string} message
188
+ * @return {Filter}
189
+ */
190
+ showFailureMessage(message) {
191
+ this[searchButtonElementSymbol].setState(
192
+ "failed",
193
+ this.getOption("timeouts.message", 4000),
194
+ );
195
+ this[searchButtonElementSymbol]
196
+ .setMessage(message.toString())
197
+ .showMessage(this.getOption("timeouts.message", 4000));
198
+ return this;
199
+ }
200
+
201
+ /**
202
+ *
203
+ * @return {Filter}
204
+ */
205
+ resetFailureMessage() {
206
+ this[searchButtonElementSymbol].hideMessage();
207
+ this[searchButtonElementSymbol].removeState();
208
+ return this;
209
+ }
210
+
211
+ /**
212
+ *
213
+ * @return {Filter}
214
+ */
215
+ showSuccess() {
216
+ this[searchButtonElementSymbol].setState(
217
+ "successful",
218
+ this.getOption("timeouts.message", 4000),
219
+ );
220
+ return this;
221
+ }
222
+
223
+ /**
224
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
225
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
226
+ *
227
+ * The individual configuration values can be found in the table.
228
+ *
229
+ * @property {Object} templates Template definitions
230
+ * @property {string} templates.main Main template
231
+ * @property {Object} labels Label definitions
232
+ * @property {string} labels.search Search button label
233
+ * @property {string} labels.reset Reset button label
234
+ * @property {string} labels.save Save button label
235
+ * @property {string} labels.filter-name Filter name label
236
+ * @property {string} labels.empty-query-and-no-default Empty query and no default query label
237
+ * @property {string} labels.query-not-changed Query not changed label
238
+ * @property {Object} formatter Formatter definitions
239
+ * @property {Object} formatter.marker Marker definitions
240
+ * @property {Object} formatter.marker.open Marker open
241
+ * @property {Object} formatter.marker.close Marker close
242
+ * @property {Object} features Feature definitions
243
+ * @property {boolean} features.storedConfig Stored configuration, this replaces the setting `storedConfig.enabled` @since 3.97.0
244
+ * @property {Object} storedConfig Stored configuration
245
+ * @property {boolean} storedConfig.enabled The store has been enabled, this option will no longer have any effect. @deprecated 20250101
246
+ * @property {string} storedConfig.selector Selector
247
+ * @property {Object} timeouts Timeout definitions
248
+ * @property {number} timeouts.message Message timeout
249
+ * @property {Object} queries Query definitions
250
+ * @property {Function} queries.wrap Wrap callback
251
+ * @property {Function} queries.join Join callback
252
+ * @property {string} query Query
253
+ * @property {string} defaultQuery Default query
254
+ * @property {boolean} eventProcessing Event processing
255
+ */
256
+ get defaults() {
257
+ return Object.assign({}, super.defaults, {
258
+ templates: {
259
+ main: getTemplate(),
260
+ },
261
+
262
+ formatter: {
263
+ marker: {
264
+ open: null,
265
+ close: null,
266
+ },
267
+ },
268
+
269
+ labels: getTranslations(),
270
+
271
+ templateMapping: {
272
+ "filter-save-label": null,
273
+ "filter-name-label": name,
274
+ },
275
+
276
+ features: {
277
+ storedConfig: false,
278
+ },
279
+
280
+ storedConfig: {
281
+ enabled: true,
282
+ selector: "",
283
+ },
284
+
285
+ timeouts: {
286
+ message: 4000,
287
+ },
288
+
289
+ queries: {
290
+ wrap: (value, definition) => {
291
+ return value;
292
+ },
293
+ join: (queries) => {
294
+ if (queries.length === 0) {
295
+ return "";
296
+ }
297
+ return queries.join(" AND ");
298
+ },
299
+ },
300
+
301
+ query: null,
302
+ defaultQuery: null,
303
+ eventProcessing: true,
304
+ });
305
+ }
306
+
307
+ /**
308
+ *
309
+ * @return {string}
310
+ */
311
+ static getTag() {
312
+ return "monster-datatable-filter";
313
+ }
314
+
315
+ /**
316
+ * @return {FilterButton}
317
+ * @fires monster-filter-initialized
318
+ */
319
+ [assembleMethodSymbol]() {
320
+ this.setOption(
321
+ "templateMapping.filter-save-label",
322
+ this.getOption("labels.save"),
323
+ );
324
+
325
+ this.setOption(
326
+ "templateMapping.filter-name-label",
327
+ this.getOption("labels.filter-name"),
328
+ );
329
+
330
+ super[assembleMethodSymbol]();
331
+
332
+ initControlReferences.call(this);
333
+ getWindow().requestAnimationFrame(() => {
334
+ initEventHandler.call(this);
335
+ });
336
+
337
+ initFromConfig
338
+ .call(this)
339
+ .then(() => {
340
+ })
341
+ .catch((error) => {
342
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error?.message);
343
+ })
344
+ .finally(() => {
345
+ initFilter.call(this);
346
+ updateFilterTabs.call(this);
347
+ doSearch
348
+ .call(this, {showEffect: false})
349
+ .then(() => {
350
+ fireCustomEvent(this, "monster-filter-initialized");
351
+ })
352
+ .catch(() => {
353
+ });
354
+ });
355
+ }
356
+
357
+ /**
358
+ *
359
+ */
360
+ connectedCallback() {
361
+ super.connectedCallback();
362
+ getWindow().addEventListener(
363
+ "hashchange",
364
+ this[locationChangeHandlerSymbol],
365
+ );
366
+ }
367
+
368
+ /**
369
+ *
370
+ */
371
+ disconnectedCallback() {
372
+ super.disconnectedCallback();
373
+
374
+ getWindow().removeEventListener(
375
+ "hashchange",
376
+ this[locationChangeHandlerSymbol],
377
+ );
378
+ }
379
+
380
+ /**
381
+ * @return {Array<CSSStyleSheet>}
382
+ */
383
+ static getCSSStyleSheet() {
384
+ return [FilterStyleSheet, FormStyleSheet, ThemeStyleSheet, SpaceStyleSheet];
385
+ }
381
386
  }
382
387
 
383
388
  /**
@@ -385,109 +390,109 @@ class Filter extends CustomElement {
385
390
  * @returns {object}
386
391
  */
387
392
  function getTranslations() {
388
- const locale = getLocaleOfDocument();
389
- switch (locale.language) {
390
- case "de":
391
- return {
392
- search: "Suchen",
393
- reset: "Zurücksetzen",
394
- save: "Speichern",
395
- "filter-name": "Filtername",
396
- "empty-query-and-no-default":
397
- "Die Abfrage ist leer und es gibt keine Standardabfrage.",
398
- "query-not-changed":
399
- "Die Suchanfrage hat sich nicht verändert, daher ist keine Suche erforderlich.",
400
- };
401
- case "fr":
402
- return {
403
- search: "Chercher",
404
- reset: "Réinitialiser",
405
- save: "Sauvegarder",
406
- "filter-name": "Nom du filtre",
407
- "empty-query-and-no-default":
408
- "La requête est vide et il n'y a pas de requête par défaut.",
409
- "query-not-changed":
410
- "La requête de recherche n'a pas changé, donc aucune recherche n'est nécessaire.",
411
- };
412
- case "sp":
413
- return {
414
- search: "Buscar",
415
- reset: "Restablecer",
416
- save: "Guardar",
417
- "filter-name": "Nombre del filtro",
418
- "empty-query-and-no-default":
419
- "La consulta está vacía y no hay una consulta predeterminada.",
420
- "query-not-changed":
421
- "La solicitud de búsqueda no ha cambiado, por lo que no se requiere búsqueda.",
422
- };
423
- case "it":
424
- return {
425
- search: "Cerca",
426
- reset: "Reimposta",
427
- save: "Salva",
428
- "filter-name": "Nome del filtro",
429
- "empty-query-and-no-default":
430
- "La query è vuota e non c'è una query predefinita.",
431
- "query-not-changed":
432
- "La richiesta di ricerca non è cambiata, quindi non è necessaria una ricerca.",
433
- };
434
- case "pl":
435
- return {
436
- search: "Szukaj",
437
- reset: "Resetuj",
438
- save: "Zapisz",
439
- "filter-name": "Nazwa filtra",
440
- "empty-query-and-no-default":
441
- "Zapytanie jest puste i nie ma domyślnego zapytania.",
442
- "query-not-changed":
443
- "Żądanie wyszukiwania nie zmieniło się, więc wyszukiwanie nie jest wymagane.",
444
- };
445
- case "no":
446
- return {
447
- search: "Søk",
448
- reset: "Tilbakestill",
449
- save: "Lagre",
450
- "filter-name": "Filternavn",
451
- "empty-query-and-no-default":
452
- "Spørringen er tom og det er ingen standardspørring.",
453
- "query-not-changed":
454
- "Søkeforespørselen har ikke endret seg, så ingen søk er nødvendig.",
455
- };
456
- case "dk":
457
- return {
458
- search: "Søg",
459
- reset: "Nulstil",
460
- save: "Gem",
461
- "filter-name": "Filternavn",
462
- "empty-query-and-no-default":
463
- "Forespørgslen er tom og der er ingen standardforespørgsel.",
464
- "query-not-changed":
465
- "Søgeanmodningen er ikke ændret, så ingen søgning er nødvendig.",
466
- };
467
- case "sw":
468
- return {
469
- search: "Sök",
470
- reset: "Återställ",
471
- save: "Spara",
472
- "filter-name": "Filternamn",
473
- "empty-query-and-no-default":
474
- "Förfrågan är tom och det finns ingen standardförfrågan.",
475
- "query-not-changed":
476
- "Sökförfrågan har inte ändrats, så ingen sökning krävs.",
477
- };
478
- default:
479
- case "en":
480
- return {
481
- search: "Search",
482
- reset: "Reset",
483
- save: "Save",
484
- "filter-name": "Filter name",
485
- "empty-query-and-no-default":
486
- "The query is empty and there is no default query.",
487
- "query-not-changed":
488
- "The search request has not changed, so no search is required.",
489
- };
490
- }
393
+ const locale = getLocaleOfDocument();
394
+ switch (locale.language) {
395
+ case "de":
396
+ return {
397
+ search: "Suchen",
398
+ reset: "Zurücksetzen",
399
+ save: "Speichern",
400
+ "filter-name": "Filtername",
401
+ "empty-query-and-no-default":
402
+ "Die Abfrage ist leer und es gibt keine Standardabfrage.",
403
+ "query-not-changed":
404
+ "Die Suchanfrage hat sich nicht verändert, daher ist keine Suche erforderlich.",
405
+ };
406
+ case "fr":
407
+ return {
408
+ search: "Chercher",
409
+ reset: "Réinitialiser",
410
+ save: "Sauvegarder",
411
+ "filter-name": "Nom du filtre",
412
+ "empty-query-and-no-default":
413
+ "La requête est vide et il n'y a pas de requête par défaut.",
414
+ "query-not-changed":
415
+ "La requête de recherche n'a pas changé, donc aucune recherche n'est nécessaire.",
416
+ };
417
+ case "sp":
418
+ return {
419
+ search: "Buscar",
420
+ reset: "Restablecer",
421
+ save: "Guardar",
422
+ "filter-name": "Nombre del filtro",
423
+ "empty-query-and-no-default":
424
+ "La consulta está vacía y no hay una consulta predeterminada.",
425
+ "query-not-changed":
426
+ "La solicitud de búsqueda no ha cambiado, por lo que no se requiere búsqueda.",
427
+ };
428
+ case "it":
429
+ return {
430
+ search: "Cerca",
431
+ reset: "Reimposta",
432
+ save: "Salva",
433
+ "filter-name": "Nome del filtro",
434
+ "empty-query-and-no-default":
435
+ "La query è vuota e non c'è una query predefinita.",
436
+ "query-not-changed":
437
+ "La richiesta di ricerca non è cambiata, quindi non è necessaria una ricerca.",
438
+ };
439
+ case "pl":
440
+ return {
441
+ search: "Szukaj",
442
+ reset: "Resetuj",
443
+ save: "Zapisz",
444
+ "filter-name": "Nazwa filtra",
445
+ "empty-query-and-no-default":
446
+ "Zapytanie jest puste i nie ma domyślnego zapytania.",
447
+ "query-not-changed":
448
+ "Żądanie wyszukiwania nie zmieniło się, więc wyszukiwanie nie jest wymagane.",
449
+ };
450
+ case "no":
451
+ return {
452
+ search: "Søk",
453
+ reset: "Tilbakestill",
454
+ save: "Lagre",
455
+ "filter-name": "Filternavn",
456
+ "empty-query-and-no-default":
457
+ "Spørringen er tom og det er ingen standardspørring.",
458
+ "query-not-changed":
459
+ "Søkeforespørselen har ikke endret seg, så ingen søk er nødvendig.",
460
+ };
461
+ case "dk":
462
+ return {
463
+ search: "Søg",
464
+ reset: "Nulstil",
465
+ save: "Gem",
466
+ "filter-name": "Filternavn",
467
+ "empty-query-and-no-default":
468
+ "Forespørgslen er tom og der er ingen standardforespørgsel.",
469
+ "query-not-changed":
470
+ "Søgeanmodningen er ikke ændret, så ingen søgning er nødvendig.",
471
+ };
472
+ case "sw":
473
+ return {
474
+ search: "Sök",
475
+ reset: "Återställ",
476
+ save: "Spara",
477
+ "filter-name": "Filternamn",
478
+ "empty-query-and-no-default":
479
+ "Förfrågan är tom och det finns ingen standardförfrågan.",
480
+ "query-not-changed":
481
+ "Sökförfrågan har inte ändrats, så ingen sökning krävs.",
482
+ };
483
+ default:
484
+ case "en":
485
+ return {
486
+ search: "Search",
487
+ reset: "Reset",
488
+ save: "Save",
489
+ "filter-name": "Filter name",
490
+ "empty-query-and-no-default":
491
+ "The query is empty and there is no default query.",
492
+ "query-not-changed":
493
+ "The search request has not changed, so no search is required.",
494
+ };
495
+ }
491
496
  }
492
497
 
493
498
  /**
@@ -495,51 +500,51 @@ function getTranslations() {
495
500
  * @return {FilterButton}
496
501
  */
497
502
  function initControlReferences() {
498
- if (!this.shadowRoot) {
499
- throw new Error("no shadow-root is defined");
500
- }
501
-
502
- this[filterControlElementSymbol] = this.shadowRoot.querySelector(
503
- "[data-monster-role=control]",
504
- );
505
- this[filterSelectElementSymbol] = this.shadowRoot.querySelector(
506
- "[data-monster-role=filter-select]",
507
- );
508
- this[searchButtonElementSymbol] = this.shadowRoot.querySelector(
509
- "[data-monster-role=search-button]",
510
- );
511
- this[resetButtonElementSymbol] = this.shadowRoot.querySelector(
512
- "[data-monster-role=reset-button]",
513
- );
514
-
515
- this[saveButtonElementSymbol] = this.shadowRoot.querySelector(
516
- "[data-monster-role=save-button]",
517
- );
518
-
519
- this[filterSaveActionButtonElementSymbol] = this.shadowRoot.querySelector(
520
- "[data-monster-role=save-action-button]",
521
- );
522
-
523
- this[filterTabElementSymbol] = findElementWithSelectorUpwards(
524
- this,
525
- this.getOption("storedConfig.selector", ""),
526
- );
527
-
528
- return this;
503
+ if (!this.shadowRoot) {
504
+ throw new Error("no shadow-root is defined");
505
+ }
506
+
507
+ this[filterControlElementSymbol] = this.shadowRoot.querySelector(
508
+ "[data-monster-role=control]",
509
+ );
510
+ this[filterSelectElementSymbol] = this.shadowRoot.querySelector(
511
+ "[data-monster-role=filter-select]",
512
+ );
513
+ this[searchButtonElementSymbol] = this.shadowRoot.querySelector(
514
+ "[data-monster-role=search-button]",
515
+ );
516
+ this[resetButtonElementSymbol] = this.shadowRoot.querySelector(
517
+ "[data-monster-role=reset-button]",
518
+ );
519
+
520
+ this[saveButtonElementSymbol] = this.shadowRoot.querySelector(
521
+ "[data-monster-role=save-button]",
522
+ );
523
+
524
+ this[filterSaveActionButtonElementSymbol] = this.shadowRoot.querySelector(
525
+ "[data-monster-role=save-action-button]",
526
+ );
527
+
528
+ this[filterTabElementSymbol] = findElementWithSelectorUpwards(
529
+ this,
530
+ this.getOption("storedConfig.selector", ""),
531
+ );
532
+
533
+ return this;
529
534
  }
530
535
 
531
536
  function updateFilterSelections() {
532
- queueMicrotask(() => {
533
- const options = this[settingsSymbol].getOptions();
534
- this[filterSelectElementSymbol].setOption("options", options);
535
-
536
- setTimeout(() => {
537
- window.requestAnimationFrame(() => {
538
- this[filterSelectElementSymbol].value =
539
- this[settingsSymbol].getSelected();
540
- });
541
- }, 0);
542
- });
537
+ queueMicrotask(() => {
538
+ const options = this[settingsSymbol].getOptions();
539
+ this[filterSelectElementSymbol].setOption("options", options);
540
+
541
+ setTimeout(() => {
542
+ window.requestAnimationFrame(() => {
543
+ this[filterSelectElementSymbol].value =
544
+ this[settingsSymbol].getSelected();
545
+ });
546
+ }, 0);
547
+ });
543
548
  }
544
549
 
545
550
  /**
@@ -547,64 +552,65 @@ function updateFilterSelections() {
547
552
  * @throws {Error} no filter label is defined
548
553
  */
549
554
  function initFilter() {
550
- const storedSetting = this[settingsSymbol];
551
- this[settingsSymbol] = new Settings();
552
-
553
- const result = parseBracketedKeyValueHash(getGlobal().location.hash);
554
- let valuesFromHash = {};
555
- if (isObject(result) && result?.[this.id]) {
556
- valuesFromHash = result[this.id];
557
- }
558
-
559
- getSlottedElements
560
- .call(this, "label[data-monster-label]")
561
- .forEach((element) => {
562
- const label = element.getAttribute("data-monster-label");
563
- if (!label) {
564
- addAttributeToken(
565
- this,
566
- ATTRIBUTE_ERRORMESSAGE,
567
- "no filter label is defined",
568
- );
569
- return;
570
- }
571
-
572
- let value = element.id;
573
- if (!value) {
574
- const prefix = label.replace(/\W/g, "-");
575
- prefix.charAt(0).match(/[\d_]/g)?.length ? `f${prefix}` : prefix;
576
-
577
- value = new ID(prefix + "-").toString();
578
- element.id = value;
579
- }
580
-
581
- let setting = storedSetting.get(value);
582
-
583
- if (setting) {
584
- this[settingsSymbol].set(setting);
585
- }
586
-
587
- if (valuesFromHash?.[element.id]) {
588
- const v = escapeAttributeValue(valuesFromHash[element.id]);
589
- const searchInput = element.firstElementChild;
590
- try {
591
- searchInput.value = v;
592
- } catch (error) {}
593
- }
594
-
595
- setting = this[settingsSymbol].get(value);
596
- let visible = false;
597
- if (setting) {
598
- setSlotAttribute(element, setting.visible);
599
- visible = setting.visible;
600
- } else {
601
- visible = getVisibilityFromSlotAttribute(element);
602
- }
603
-
604
- this[settingsSymbol].set({ value, label, visible });
605
- });
606
-
607
- updateFilterSelections.call(this);
555
+ const storedSetting = this[settingsSymbol];
556
+ this[settingsSymbol] = new Settings();
557
+
558
+ const result = parseBracketedKeyValueHash(getGlobal().location.hash);
559
+ let valuesFromHash = {};
560
+ if (isObject(result) && result?.[this.id]) {
561
+ valuesFromHash = result[this.id];
562
+ }
563
+
564
+ getSlottedElements
565
+ .call(this, "label[data-monster-label]")
566
+ .forEach((element) => {
567
+ const label = element.getAttribute("data-monster-label");
568
+ if (!label) {
569
+ addAttributeToken(
570
+ this,
571
+ ATTRIBUTE_ERRORMESSAGE,
572
+ "no filter label is defined",
573
+ );
574
+ return;
575
+ }
576
+
577
+ let value = element.id;
578
+ if (!value) {
579
+ const prefix = label.replace(/\W/g, "-");
580
+ prefix.charAt(0).match(/[\d_]/g)?.length ? `f${prefix}` : prefix;
581
+
582
+ value = new ID(prefix + "-").toString();
583
+ element.id = value;
584
+ }
585
+
586
+ let setting = storedSetting.get(value);
587
+
588
+ if (setting) {
589
+ this[settingsSymbol].set(setting);
590
+ }
591
+
592
+ if (valuesFromHash?.[element.id]) {
593
+ const v = escapeAttributeValue(valuesFromHash[element.id]);
594
+ const searchInput = element.firstElementChild;
595
+ try {
596
+ searchInput.value = v;
597
+ } catch (error) {
598
+ }
599
+ }
600
+
601
+ setting = this[settingsSymbol].get(value);
602
+ let visible = false;
603
+ if (setting) {
604
+ setSlotAttribute(element, setting.visible);
605
+ visible = setting.visible;
606
+ } else {
607
+ visible = getVisibilityFromSlotAttribute(element);
608
+ }
609
+
610
+ this[settingsSymbol].set({value, label, visible});
611
+ });
612
+
613
+ updateFilterSelections.call(this);
608
614
  }
609
615
 
610
616
  /**
@@ -613,16 +619,16 @@ function initFilter() {
613
619
  * @return {*}
614
620
  */
615
621
  function escapeAttributeValue(input) {
616
- if (input === undefined || input === null) {
617
- return input;
618
- }
619
-
620
- return input
621
- .replace(/&/g, "&amp;")
622
- .replace(/"/g, "&quot;")
623
- .replace(/'/g, "&#x27;")
624
- .replace(/</g, "&lt;")
625
- .replace(/>/g, "&gt;");
622
+ if (input === undefined || input === null) {
623
+ return input;
624
+ }
625
+
626
+ return input
627
+ .replace(/&/g, "&amp;")
628
+ .replace(/"/g, "&quot;")
629
+ .replace(/'/g, "&#x27;")
630
+ .replace(/</g, "&lt;")
631
+ .replace(/>/g, "&gt;");
626
632
  }
627
633
 
628
634
  /**
@@ -631,9 +637,9 @@ function escapeAttributeValue(input) {
631
637
  * @return {boolean}
632
638
  */
633
639
  function getVisibilityFromSlotAttribute(element) {
634
- return !(
635
- element.hasAttribute("slot") && element.getAttribute("slot") === "hidden"
636
- );
640
+ return !(
641
+ element.hasAttribute("slot") && element.getAttribute("slot") === "hidden"
642
+ );
637
643
  }
638
644
 
639
645
  /**
@@ -642,369 +648,376 @@ function getVisibilityFromSlotAttribute(element) {
642
648
  * @param {boolean} visible
643
649
  */
644
650
  function setSlotAttribute(element, visible) {
645
- if (visible) {
646
- element.removeAttribute("slot");
647
- return;
648
- }
651
+ if (visible) {
652
+ element.removeAttribute("slot");
653
+ return;
654
+ }
649
655
 
650
- element.setAttribute("slot", "hidden");
656
+ element.setAttribute("slot", "hidden");
651
657
  }
652
658
 
653
659
  /**
654
660
  * @private
655
661
  */
656
662
  function initEventHandler() {
657
- const self = this;
658
-
659
- let lastHash = getGlobal().location.hash;
660
- self[locationChangeHandlerSymbol] = () => {
661
- if (lastHash === getGlobal().location.hash) {
662
- return;
663
- }
664
-
665
- /**
666
- * debounce the hash change event if doSearch
667
- * is called by click the search button
668
- */
669
- if (self[hashChangeSymbol] > 0) {
670
- self[hashChangeSymbol]--;
671
- return;
672
- }
673
-
674
- initFilter.call(this);
675
-
676
- doSearch
677
- .call(self)
678
- .then(() => {})
679
- .catch((error) => {})
680
- .finally(() => {
681
- lastHash = getGlobal().location.hash;
682
- });
683
- };
684
-
685
- /**
686
- * Monster.Components.Form.event:monster-selection-cleared
687
- */
688
- if (self[filterSelectElementSymbol]) {
689
- self[filterSelectElementSymbol].addEventListener(
690
- "monster-selection-cleared",
691
- function () {
692
- const settings = self[settingsSymbol].getOptions();
693
-
694
- for (const setting of settings) {
695
- const filterElement = findElementWithIdUpwards(self, setting.value);
696
- if (filterElement) {
697
- setSlotAttribute(filterElement, false);
698
-
699
- self[settingsSymbol].set({ value: setting.value, visible: false });
700
- }
701
- }
702
-
703
- updateConfig.call(self);
704
- },
705
- );
706
-
707
- self[filterSelectElementSymbol].addEventListener(
708
- "monster-changed",
709
- function (event) {
710
- const filterElement = findElementWithIdUpwards(
711
- self,
712
- event.detail.value,
713
- );
714
- if (filterElement) {
715
- setSlotAttribute(filterElement, event.detail.checked);
716
- }
717
-
718
- self[settingsSymbol].set({
719
- value: event.detail.value,
720
- visible: event.detail.checked,
721
- });
722
-
723
- updateConfig.call(self);
724
- },
725
- );
726
- }
727
-
728
- /** save the current filter */
729
- if (self[filterSaveActionButtonElementSymbol]) {
730
- self[filterSaveActionButtonElementSymbol].setOption(
731
- "actions.click",
732
- function (event) {
733
- const button = findTargetElementFromEvent(
734
- event,
735
- "data-monster-role",
736
- "save-action-button",
737
- );
738
- const form = button.closest("[data-monster-role=form]");
739
-
740
- if (!form) {
741
- button.setState("failed", self.getOption("timeouts.message", 4000));
742
- return;
743
- }
744
-
745
- const input = form.querySelector("input[name=filter-name]");
746
- if (!input) {
747
- button.setState("failed", self.getOption("timeouts.message", 4000));
748
- return;
749
- }
750
-
751
- const name = input.value;
752
- if (!name) {
753
- button.setState("failed", self.getOption("timeouts.message", 4000));
754
- button.setMessage("Please enter a name").showMessage();
755
- return;
756
- }
757
-
758
- doSearch
759
- .call(self, { showEffect: false })
760
- .then(() => {
761
- const configKey = getStoredFilterConfigKey.call(self);
762
- const host = getDocument().querySelector("monster-host");
763
- if (!host) {
764
- return;
765
- }
766
-
767
- const query = self.getOption("query");
768
- if (!query) {
769
- button.setState(
770
- "failed",
771
- self.getOption(
772
- "timeouts.message",
773
- self.getOption("timeouts.message", 4000),
774
- ),
775
- );
776
- button
777
- .setMessage("No query found")
778
- .showMessage(self.getOption("timeouts.message", 4000));
779
- return;
780
- }
781
-
782
- host
783
- .hasConfig(configKey)
784
- .then((hasConfig) => {
785
- return new Promise((resolve, reject) => {
786
- if (hasConfig) {
787
- host.getConfig(configKey).then(resolve).catch(reject);
788
- return;
789
- }
790
- return resolve({});
791
- });
792
- })
793
- .then((config) => {
794
- config[name] = query;
795
- return host.setConfig(configKey, {
796
- ...config,
797
- });
798
- })
799
- .then(() => {
800
- button.setState(
801
- "successful",
802
- self.getOption("timeouts.message", 4000),
803
- );
804
- updateFilterTabs.call(self);
805
- })
806
- .catch((error) => {
807
- button.setState(
808
- "failed",
809
- self.getOption("timeouts.message", 4000),
810
- );
811
- button
812
- .setMessage(error.message)
813
- .showMessage(self.getOption("timeouts.message", 4000));
814
- });
815
- })
816
- .catch((error) => {
817
- button.setState("failed", self.getOption("timeouts.message", 4000));
818
- const msg = error.message || error;
819
- button
820
- .setMessage(msg)
821
- .showMessage(self.getOption("timeouts.message", 4000));
822
- });
823
- },
824
- );
825
- }
826
-
827
- self[searchButtonElementSymbol].setOption("actions.click", () => {
828
- self[hashChangeSymbol] = 1;
829
-
830
- doSearch
831
- .call(self)
832
- .then(() => {})
833
- .catch((error) => {});
834
- });
835
-
836
- // the reset button should reset the filter and the search query
837
- // all input elements should be reset to their default values
838
- // which is the empty string. we search for all input elements
839
- // in the filter and reset them to their default value
840
- self[resetButtonElementSymbol].setOption("actions.click", () => {
841
- getSlottedElements
842
- .call(self, "label[data-monster-label]")
843
- .forEach((element) => {
844
- const label = element.getAttribute("data-monster-label");
845
- if (!label) {
846
- return;
847
- }
848
-
849
- const input = element.firstElementChild;
850
-
851
- if (input) {
852
- input.value = "";
853
- }
854
- });
855
-
856
- doSearch
857
- .call(self, { showEffect: false })
858
- .then(() => {})
859
- .catch((e) => addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.message));
860
- });
861
-
862
- self.addEventListener("keyup", (event) => {
863
- const path = event.composedPath();
864
- if (path.length === 0) {
865
- return;
866
- }
867
-
868
- if (!(path[0] instanceof HTMLInputElement)) {
869
- return;
870
- }
871
-
872
- if (event.keyCode === 13) {
873
- doSearch
874
- .call(self, { showEffect: false })
875
- .then(() => {})
876
- .catch((error) => {});
877
- }
878
- });
879
-
880
- // tabs
881
- const element = this[filterTabElementSymbol];
882
- if (element) {
883
- initTabEvents.call(this);
884
- }
663
+ const self = this;
664
+
665
+ let lastHash = getGlobal().location.hash;
666
+ self[locationChangeHandlerSymbol] = () => {
667
+ if (lastHash === getGlobal().location.hash) {
668
+ return;
669
+ }
670
+
671
+ /**
672
+ * debounce the hash change event if doSearch
673
+ * is called by click the search button
674
+ */
675
+ if (self[hashChangeSymbol] > 0) {
676
+ self[hashChangeSymbol]--;
677
+ return;
678
+ }
679
+
680
+ initFilter.call(this);
681
+
682
+ doSearch
683
+ .call(self)
684
+ .then(() => {
685
+ })
686
+ .catch((error) => {
687
+ })
688
+ .finally(() => {
689
+ lastHash = getGlobal().location.hash;
690
+ });
691
+ };
692
+
693
+ /**
694
+ * Monster.Components.Form.event:monster-selection-cleared
695
+ */
696
+ if (self[filterSelectElementSymbol]) {
697
+ self[filterSelectElementSymbol].addEventListener(
698
+ "monster-selection-cleared",
699
+ function () {
700
+ const settings = self[settingsSymbol].getOptions();
701
+
702
+ for (const setting of settings) {
703
+ const filterElement = findElementWithIdUpwards(self, setting.value);
704
+ if (filterElement) {
705
+ setSlotAttribute(filterElement, false);
706
+
707
+ self[settingsSymbol].set({value: setting.value, visible: false});
708
+ }
709
+ }
710
+
711
+ updateConfig.call(self);
712
+ },
713
+ );
714
+
715
+ self[filterSelectElementSymbol].addEventListener(
716
+ "monster-changed",
717
+ function (event) {
718
+ const filterElement = findElementWithIdUpwards(
719
+ self,
720
+ event.detail.value,
721
+ );
722
+ if (filterElement) {
723
+ setSlotAttribute(filterElement, event.detail.checked);
724
+ }
725
+
726
+ self[settingsSymbol].set({
727
+ value: event.detail.value,
728
+ visible: event.detail.checked,
729
+ });
730
+
731
+ updateConfig.call(self);
732
+ },
733
+ );
734
+ }
735
+
736
+ /** save the current filter */
737
+ if (self[filterSaveActionButtonElementSymbol]) {
738
+ self[filterSaveActionButtonElementSymbol].setOption(
739
+ "actions.click",
740
+ function (event) {
741
+ const button = findTargetElementFromEvent(
742
+ event,
743
+ "data-monster-role",
744
+ "save-action-button",
745
+ );
746
+ const form = button.closest("[data-monster-role=form]");
747
+
748
+ if (!form) {
749
+ button.setState("failed", self.getOption("timeouts.message", 4000));
750
+ return;
751
+ }
752
+
753
+ const input = form.querySelector("input[name=filter-name]");
754
+ if (!input) {
755
+ button.setState("failed", self.getOption("timeouts.message", 4000));
756
+ return;
757
+ }
758
+
759
+ const name = input.value;
760
+ if (!name) {
761
+ button.setState("failed", self.getOption("timeouts.message", 4000));
762
+ button.setMessage("Please enter a name").showMessage();
763
+ return;
764
+ }
765
+
766
+ doSearch
767
+ .call(self, {showEffect: false})
768
+ .then(() => {
769
+ const configKey = getStoredFilterConfigKey.call(self);
770
+ const host = getDocument().querySelector("monster-host");
771
+ if (!host) {
772
+ return;
773
+ }
774
+
775
+ const query = self.getOption("query");
776
+ if (!query) {
777
+ button.setState(
778
+ "failed",
779
+ self.getOption(
780
+ "timeouts.message",
781
+ self.getOption("timeouts.message", 4000),
782
+ ),
783
+ );
784
+ button
785
+ .setMessage("No query found")
786
+ .showMessage(self.getOption("timeouts.message", 4000));
787
+ return;
788
+ }
789
+
790
+ host
791
+ .hasConfig(configKey)
792
+ .then((hasConfig) => {
793
+ return new Promise((resolve, reject) => {
794
+ if (hasConfig) {
795
+ host.getConfig(configKey).then(resolve).catch(reject);
796
+ return;
797
+ }
798
+ return resolve({});
799
+ });
800
+ })
801
+ .then((config) => {
802
+ config[name] = query;
803
+ return host.setConfig(configKey, {
804
+ ...config,
805
+ });
806
+ })
807
+ .then(() => {
808
+ button.setState(
809
+ "successful",
810
+ self.getOption("timeouts.message", 4000),
811
+ );
812
+ updateFilterTabs.call(self);
813
+ })
814
+ .catch((error) => {
815
+ button.setState(
816
+ "failed",
817
+ self.getOption("timeouts.message", 4000),
818
+ );
819
+ button
820
+ .setMessage(error.message)
821
+ .showMessage(self.getOption("timeouts.message", 4000));
822
+ });
823
+ })
824
+ .catch((error) => {
825
+ button.setState("failed", self.getOption("timeouts.message", 4000));
826
+ const msg = error.message || error;
827
+ button
828
+ .setMessage(msg)
829
+ .showMessage(self.getOption("timeouts.message", 4000));
830
+ });
831
+ },
832
+ );
833
+ }
834
+
835
+ self[searchButtonElementSymbol].setOption("actions.click", () => {
836
+ self[hashChangeSymbol] = 1;
837
+
838
+ doSearch
839
+ .call(self)
840
+ .then(() => {
841
+ })
842
+ .catch((error) => {
843
+ });
844
+ });
845
+
846
+ // the reset button should reset the filter and the search query
847
+ // all input elements should be reset to their default values
848
+ // which is the empty string. we search for all input elements
849
+ // in the filter and reset them to their default value
850
+ self[resetButtonElementSymbol].setOption("actions.click", () => {
851
+ getSlottedElements
852
+ .call(self, "label[data-monster-label]")
853
+ .forEach((element) => {
854
+ const label = element.getAttribute("data-monster-label");
855
+ if (!label) {
856
+ return;
857
+ }
858
+
859
+ const input = element.firstElementChild;
860
+
861
+ if (input) {
862
+ input.value = "";
863
+ }
864
+ });
865
+
866
+ doSearch
867
+ .call(self, {showEffect: false})
868
+ .then(() => {
869
+ })
870
+ .catch((e) => addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.message));
871
+ });
872
+
873
+ self.addEventListener("keyup", (event) => {
874
+ const path = event.composedPath();
875
+ if (path.length === 0) {
876
+ return;
877
+ }
878
+
879
+ if (!(path[0] instanceof HTMLInputElement)) {
880
+ return;
881
+ }
882
+
883
+ if (event.keyCode === 13) {
884
+ doSearch
885
+ .call(self, {showEffect: false})
886
+ .then(() => {
887
+ })
888
+ .catch((error) => {
889
+ });
890
+ }
891
+ });
892
+
893
+ // tabs
894
+ const element = this[filterTabElementSymbol];
895
+ if (element) {
896
+ initTabEvents.call(this);
897
+ }
885
898
  }
886
899
 
887
900
  function initTabEvents() {
888
- const self = this;
889
- this[filterTabElementSymbol].addEventListener(
890
- "monster-tab-changed",
891
- (event) => {
892
- const query = event?.detail?.data?.["data-monster-query"];
893
- const q = this.getOption("query");
894
- if (query !== q) {
895
- this.setOption("query", query);
896
- }
897
- },
898
- );
899
-
900
- this[filterTabElementSymbol].addEventListener(
901
- "monster-tab-remove",
902
- (event) => {
903
- const labels = [];
904
- const buttons = this[filterTabElementSymbol].getOption("buttons");
905
-
906
- const keys = ["popper", "standard"];
907
- for (let i = 0; i < keys.length; i++) {
908
- const key = keys[i];
909
-
910
- for (const button of buttons[key]) {
911
- if (button.label !== event.detail.label) {
912
- labels.push(button.label);
913
- }
914
- }
915
- }
916
-
917
- const host = findElementWithSelectorUpwards(this, "monster-host");
918
- if (!(host && this.id)) {
919
- return;
920
- }
921
-
922
- const configKey = getStoredFilterConfigKey.call(this);
923
- host
924
- .hasConfig(configKey)
925
- .then((hasConfig) => {
926
- if (!hasConfig) {
927
- return;
928
- }
929
-
930
- return host.getConfig(configKey);
931
- })
932
- .then((config) => {
933
- for (const [name, query] of Object.entries(config)) {
934
- if (labels.includes(name)) {
935
- continue;
936
- }
937
-
938
- delete config[name];
939
- }
940
-
941
- return host.setConfig(configKey, {
942
- ...config,
943
- });
944
- });
945
- },
946
- );
901
+ const self = this;
902
+ this[filterTabElementSymbol].addEventListener(
903
+ "monster-tab-changed",
904
+ (event) => {
905
+ const query = event?.detail?.data?.["data-monster-query"];
906
+ const q = this.getOption("query");
907
+ if (query !== q) {
908
+ this.setOption("query", query);
909
+ }
910
+ },
911
+ );
912
+
913
+ this[filterTabElementSymbol].addEventListener(
914
+ "monster-tab-remove",
915
+ (event) => {
916
+ const labels = [];
917
+ const buttons = this[filterTabElementSymbol].getOption("buttons");
918
+
919
+ const keys = ["popper", "standard"];
920
+ for (let i = 0; i < keys.length; i++) {
921
+ const key = keys[i];
922
+
923
+ for (const button of buttons[key]) {
924
+ if (button.label !== event.detail.label) {
925
+ labels.push(button.label);
926
+ }
927
+ }
928
+ }
929
+
930
+ const host = findElementWithSelectorUpwards(this, "monster-host");
931
+ if (!(host && this.id)) {
932
+ return;
933
+ }
934
+
935
+ const configKey = getStoredFilterConfigKey.call(this);
936
+ host
937
+ .hasConfig(configKey)
938
+ .then((hasConfig) => {
939
+ if (!hasConfig) {
940
+ return;
941
+ }
942
+
943
+ return host.getConfig(configKey);
944
+ })
945
+ .then((config) => {
946
+ for (const [name, query] of Object.entries(config)) {
947
+ if (labels.includes(name)) {
948
+ continue;
949
+ }
950
+
951
+ delete config[name];
952
+ }
953
+
954
+ return host.setConfig(configKey, {
955
+ ...config,
956
+ });
957
+ });
958
+ },
959
+ );
947
960
  }
948
961
 
949
962
  /**
950
963
  * @private
951
964
  */
952
965
  function updateFilterTabs() {
953
- const element = this[filterTabElementSymbol];
954
- if (!element) {
955
- return;
956
- }
957
-
958
- const host = findElementWithSelectorUpwards(this, "monster-host");
959
- if (!(host && this.id)) {
960
- return;
961
- }
962
-
963
- const configKey = getStoredFilterConfigKey.call(this);
964
- host
965
- .hasConfig(configKey)
966
- .then((hasConfig) => {
967
- if (!hasConfig) {
968
- return;
969
- }
970
-
971
- return host.getConfig(configKey);
972
- })
973
- .then((config) => {
974
- for (const [name, query] of Object.entries(config)) {
975
- const found = element.querySelector(
976
- `[data-monster-button-label="${name}"]`,
977
- );
978
- if (found) {
979
- continue;
980
- }
981
-
982
- if (query === undefined || query === null) {
983
- continue;
984
- }
985
-
986
- const escapedQuery = escapeAttributeValue(query);
987
-
988
- element.insertAdjacentHTML(
989
- "beforeend",
990
- `<div data-monster-button-label="${name}"
966
+ const element = this[filterTabElementSymbol];
967
+ if (!element) {
968
+ return;
969
+ }
970
+
971
+ const host = findElementWithSelectorUpwards(this, "monster-host");
972
+ if (!(host && this.id)) {
973
+ return;
974
+ }
975
+
976
+ const configKey = getStoredFilterConfigKey.call(this);
977
+ host
978
+ .hasConfig(configKey)
979
+ .then((hasConfig) => {
980
+ if (!hasConfig) {
981
+ return;
982
+ }
983
+
984
+ return host.getConfig(configKey);
985
+ })
986
+ .then((config) => {
987
+ for (const [name, query] of Object.entries(config)) {
988
+ const found = element.querySelector(
989
+ `[data-monster-button-label="${name}"]`,
990
+ );
991
+ if (found) {
992
+ continue;
993
+ }
994
+
995
+ if (query === undefined || query === null) {
996
+ continue;
997
+ }
998
+
999
+ const escapedQuery = escapeAttributeValue(query);
1000
+
1001
+ element.insertAdjacentHTML(
1002
+ "beforeend",
1003
+ `<div data-monster-button-label="${name}"
991
1004
  data-monster-removable="true"
992
1005
  data-monster-query="${escapedQuery}" data-monster-role="filter-tab" >
993
1006
  </div>`,
994
- );
995
- }
996
- })
997
- .catch((error) => {
998
- if (error instanceof Error) {
999
- addAttributeToken(
1000
- this,
1001
- ATTRIBUTE_ERRORMESSAGE,
1002
- error.message + " " + error.stack,
1003
- );
1004
- } else {
1005
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error + "");
1006
- }
1007
- });
1007
+ );
1008
+ }
1009
+ })
1010
+ .catch((error) => {
1011
+ if (error instanceof Error) {
1012
+ addAttributeToken(
1013
+ this,
1014
+ ATTRIBUTE_ERRORMESSAGE,
1015
+ error.message + " " + error.stack,
1016
+ );
1017
+ } else {
1018
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error + "");
1019
+ }
1020
+ });
1008
1021
  }
1009
1022
 
1010
1023
  /**
@@ -1012,89 +1025,89 @@ function updateFilterTabs() {
1012
1025
  * @param showEffect
1013
1026
  * @return {Promise}
1014
1027
  */
1015
- function doSearch({ showEffect } = { showEffect: true }) {
1016
- this.resetFailureMessage();
1017
-
1018
- if (showEffect) {
1019
- this[searchButtonElementSymbol].setState(
1020
- "activity",
1021
- this.getOption("timeouts.message", 4000),
1022
- );
1023
- }
1024
-
1025
- return collectSearchQueries
1026
- .call(this)
1027
- .then((query) => {
1028
- const buildQuery = buildSearchQuery.call(this, query);
1029
- if (buildQuery === null) {
1030
- const msg = this.getOption("labels.empty-query-and-no-default");
1031
- if (showEffect) {
1032
- this[searchButtonElementSymbol].removeState();
1033
- this[searchButtonElementSymbol]
1034
- .setMessage(msg)
1035
- .showMessage(this.getOption("timeouts.message", 4000));
1036
- }
1037
- return Promise.reject(new Error(msg));
1038
- }
1039
-
1040
- if (buildQuery === "" && this.getOption("defaultQuery") === null) {
1041
- const msg = this.getOption("labels.empty-query-and-no-default");
1042
-
1043
- if (showEffect) {
1044
- this[searchButtonElementSymbol].removeState();
1045
- this[searchButtonElementSymbol]
1046
- .setMessage(msg)
1047
- .showMessage(this.getOption("timeouts.message", 4000));
1048
- }
1049
-
1050
- return Promise.reject(new Error(msg));
1051
- }
1052
-
1053
- if (buildQuery === this.getOption("query")) {
1054
- const msg = this.getOption("labels.query-not-changed");
1055
-
1056
- if (showEffect) {
1057
- this[searchButtonElementSymbol].removeState();
1058
- this[searchButtonElementSymbol]
1059
- .setMessage(msg)
1060
- .showMessage(this.getOption("timeouts.message", 4000));
1061
- }
1062
-
1063
- return Promise.reject(new Error(msg));
1064
- }
1065
-
1066
- if (showEffect) {
1067
- this[searchButtonElementSymbol].setState(
1068
- "activity",
1069
- this.getOption("timeouts.message", 4000),
1070
- );
1071
- }
1072
-
1073
- this.setOption("query", buildSearchQuery.call(this, query));
1074
-
1075
- return Promise.resolve();
1076
- })
1077
- .catch((error) => {
1078
- if (error instanceof Error) {
1079
- addAttributeToken(
1080
- this,
1081
- ATTRIBUTE_ERRORMESSAGE,
1082
- error.message + " " + error.stack,
1083
- );
1084
- } else {
1085
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
1086
- }
1087
-
1088
- if (showEffect) {
1089
- this[searchButtonElementSymbol].setState(
1090
- "failed",
1091
- this.getOption("timeouts.message", 4000),
1092
- );
1093
- this[searchButtonElementSymbol].setMessage(error.message).showMessage();
1094
- }
1095
-
1096
- return Promise.reject(error);
1097
- });
1028
+ function doSearch({showEffect} = {showEffect: true}) {
1029
+ this.resetFailureMessage();
1030
+
1031
+ if (showEffect) {
1032
+ this[searchButtonElementSymbol].setState(
1033
+ "activity",
1034
+ this.getOption("timeouts.message", 4000),
1035
+ );
1036
+ }
1037
+
1038
+ return collectSearchQueries
1039
+ .call(this)
1040
+ .then((query) => {
1041
+ const buildQuery = buildSearchQuery.call(this, query);
1042
+ if (buildQuery === null) {
1043
+ const msg = this.getOption("labels.empty-query-and-no-default");
1044
+ if (showEffect) {
1045
+ this[searchButtonElementSymbol].removeState();
1046
+ this[searchButtonElementSymbol]
1047
+ .setMessage(msg)
1048
+ .showMessage(this.getOption("timeouts.message", 4000));
1049
+ }
1050
+ return Promise.reject(new Error(msg));
1051
+ }
1052
+
1053
+ if (buildQuery === "" && this.getOption("defaultQuery") === null) {
1054
+ const msg = this.getOption("labels.empty-query-and-no-default");
1055
+
1056
+ if (showEffect) {
1057
+ this[searchButtonElementSymbol].removeState();
1058
+ this[searchButtonElementSymbol]
1059
+ .setMessage(msg)
1060
+ .showMessage(this.getOption("timeouts.message", 4000));
1061
+ }
1062
+
1063
+ return Promise.reject(new Error(msg));
1064
+ }
1065
+
1066
+ if (buildQuery === this.getOption("query")) {
1067
+ const msg = this.getOption("labels.query-not-changed");
1068
+
1069
+ if (showEffect) {
1070
+ this[searchButtonElementSymbol].removeState();
1071
+ this[searchButtonElementSymbol]
1072
+ .setMessage(msg)
1073
+ .showMessage(this.getOption("timeouts.message", 4000));
1074
+ }
1075
+
1076
+ return Promise.reject(new Error(msg));
1077
+ }
1078
+
1079
+ if (showEffect) {
1080
+ this[searchButtonElementSymbol].setState(
1081
+ "activity",
1082
+ this.getOption("timeouts.message", 4000),
1083
+ );
1084
+ }
1085
+
1086
+ this.setOption("query", buildSearchQuery.call(this, query));
1087
+
1088
+ return Promise.resolve();
1089
+ })
1090
+ .catch((error) => {
1091
+ if (error instanceof Error) {
1092
+ addAttributeToken(
1093
+ this,
1094
+ ATTRIBUTE_ERRORMESSAGE,
1095
+ error.message + " " + error.stack,
1096
+ );
1097
+ } else {
1098
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
1099
+ }
1100
+
1101
+ if (showEffect) {
1102
+ this[searchButtonElementSymbol].setState(
1103
+ "failed",
1104
+ this.getOption("timeouts.message", 4000),
1105
+ );
1106
+ this[searchButtonElementSymbol].setMessage(error.message).showMessage();
1107
+ }
1108
+
1109
+ return Promise.reject(error);
1110
+ });
1098
1111
  }
1099
1112
 
1100
1113
  /**
@@ -1103,21 +1116,21 @@ function doSearch({ showEffect } = { showEffect: true }) {
1103
1116
  * @return {*|string}
1104
1117
  */
1105
1118
  function buildSearchQuery(queries) {
1106
- if (!isArray(queries) || queries.length === 0) {
1107
- return this.getOption("defaultQuery");
1108
- }
1119
+ if (!isArray(queries) || queries.length === 0) {
1120
+ return this.getOption("defaultQuery");
1121
+ }
1109
1122
 
1110
- const joinCallback = this.getOption("queries.join");
1111
- if (isFunction(joinCallback)) {
1112
- return joinCallback(queries);
1113
- }
1123
+ const joinCallback = this.getOption("queries.join");
1124
+ if (isFunction(joinCallback)) {
1125
+ return joinCallback(queries);
1126
+ }
1114
1127
 
1115
- const q = queries.join(" ").trim();
1116
- if (q.length === 0) {
1117
- return this.getOption("defaultQuery");
1118
- }
1128
+ const q = queries.join(" ").trim();
1129
+ if (q.length === 0) {
1130
+ return this.getOption("defaultQuery");
1131
+ }
1119
1132
 
1120
- return q;
1133
+ return q;
1121
1134
  }
1122
1135
 
1123
1136
  /**
@@ -1125,107 +1138,107 @@ function buildSearchQuery(queries) {
1125
1138
  * @return {Promise<unknown>}
1126
1139
  */
1127
1140
  function collectSearchQueries() {
1128
- const currentHash = parseBracketedKeyValueHash(getGlobal().location.hash);
1129
- const self = this;
1130
-
1131
- return new Promise((resolve, reject) => {
1132
- const query = [];
1133
- const wrapCallback = this.getOption("queries.wrap");
1134
-
1135
- let hasNoIdError = false;
1136
-
1137
- getSlottedElements
1138
- .call(this, "label[data-monster-label]")
1139
- .forEach((element) => {
1140
- const label = element.getAttribute("data-monster-label");
1141
- if (!label) {
1142
- throw new Error("no filter label is defined");
1143
- }
1144
-
1145
- const id = element.id;
1146
- if (!id) {
1147
- hasNoIdError = true;
1148
- return;
1149
- }
1150
-
1151
- const visible = getVisibilityFromSlotAttribute(element);
1152
- if (!visible) {
1153
- return;
1154
- }
1155
-
1156
- let template = element.getAttribute("data-monster-template");
1157
- if (!template) {
1158
- template = "${id}=${value}";
1159
- }
1160
-
1161
- const controlValue = getControlValuesFromLabel(element);
1162
- if (!controlValue) {
1163
- if (controlValue === "" && currentHash?.[this.id]?.[id]) {
1164
- delete currentHash[this.id][id];
1165
- }
1166
-
1167
- return;
1168
- }
1169
-
1170
- if (!isObject(currentHash[this.id])) {
1171
- currentHash[this.id] = {};
1172
- }
1173
- currentHash[this.id][id] = controlValue;
1174
-
1175
- const mapping = {
1176
- id,
1177
- value: controlValue,
1178
- label,
1179
- };
1180
-
1181
- const formatter = new Formatter(mapping, {
1182
- callbacks: {
1183
- range: (value, key) => {
1184
- return generateRangeComparisonExpression(value, key, {
1185
- urlEncode: true,
1186
- andOp: "AND",
1187
- orOp: "OR",
1188
- eqOp: "=",
1189
- gtOp: ">",
1190
- ltOp: "<",
1191
- });
1192
- },
1193
- "date-range": (value, key) => {
1194
- const query = parseDateInput(value, key);
1195
- if (!query || query === "false") {
1196
- return "";
1197
- }
1198
-
1199
- // return query as url encoded
1200
- return encodeURIComponent(query);
1201
- },
1202
- },
1203
- });
1204
-
1205
- if (self.getOption("formatter.marker.open")) {
1206
- formatter.setMarker(
1207
- self.getOption("formatter.marker.open"),
1208
- self.getOption("formatter.marker.close"),
1209
- );
1210
- }
1211
-
1212
- let queryPart = formatter.format(template);
1213
- if (queryPart) {
1214
- if (isFunction(wrapCallback)) {
1215
- queryPart = wrapCallback(queryPart, mapping);
1216
- }
1217
- query.push(queryPart);
1218
- }
1219
- });
1220
-
1221
- if (hasNoIdError) {
1222
- reject(new Error("some or all filter elements have no id"));
1223
- return;
1224
- }
1225
-
1226
- getGlobal().location.hash = createBracketedKeyValueHash(currentHash);
1227
- resolve(query);
1228
- });
1141
+ const currentHash = parseBracketedKeyValueHash(getGlobal().location.hash);
1142
+ const self = this;
1143
+
1144
+ return new Promise((resolve, reject) => {
1145
+ const query = [];
1146
+ const wrapCallback = this.getOption("queries.wrap");
1147
+
1148
+ let hasNoIdError = false;
1149
+
1150
+ getSlottedElements
1151
+ .call(this, "label[data-monster-label]")
1152
+ .forEach((element) => {
1153
+ const label = element.getAttribute("data-monster-label");
1154
+ if (!label) {
1155
+ throw new Error("no filter label is defined");
1156
+ }
1157
+
1158
+ const id = element.id;
1159
+ if (!id) {
1160
+ hasNoIdError = true;
1161
+ return;
1162
+ }
1163
+
1164
+ const visible = getVisibilityFromSlotAttribute(element);
1165
+ if (!visible) {
1166
+ return;
1167
+ }
1168
+
1169
+ let template = element.getAttribute("data-monster-template");
1170
+ if (!template) {
1171
+ template = "${id}=${value}";
1172
+ }
1173
+
1174
+ const controlValue = getControlValuesFromLabel(element);
1175
+ if (!controlValue) {
1176
+ if (controlValue === "" && currentHash?.[this.id]?.[id]) {
1177
+ delete currentHash[this.id][id];
1178
+ }
1179
+
1180
+ return;
1181
+ }
1182
+
1183
+ if (!isObject(currentHash[this.id])) {
1184
+ currentHash[this.id] = {};
1185
+ }
1186
+ currentHash[this.id][id] = controlValue;
1187
+
1188
+ const mapping = {
1189
+ id,
1190
+ value: controlValue,
1191
+ label,
1192
+ };
1193
+
1194
+ const formatter = new Formatter(mapping, {
1195
+ callbacks: {
1196
+ range: (value, key) => {
1197
+ return generateRangeComparisonExpression(value, key, {
1198
+ urlEncode: true,
1199
+ andOp: "AND",
1200
+ orOp: "OR",
1201
+ eqOp: "=",
1202
+ gtOp: ">",
1203
+ ltOp: "<",
1204
+ });
1205
+ },
1206
+ "date-range": (value, key) => {
1207
+ const query = parseDateInput(value, key);
1208
+ if (!query || query === "false") {
1209
+ return "";
1210
+ }
1211
+
1212
+ // return query as url encoded
1213
+ return encodeURIComponent(query);
1214
+ },
1215
+ },
1216
+ });
1217
+
1218
+ if (self.getOption("formatter.marker.open")) {
1219
+ formatter.setMarker(
1220
+ self.getOption("formatter.marker.open"),
1221
+ self.getOption("formatter.marker.close"),
1222
+ );
1223
+ }
1224
+
1225
+ let queryPart = formatter.format(template);
1226
+ if (queryPart) {
1227
+ if (isFunction(wrapCallback)) {
1228
+ queryPart = wrapCallback(queryPart, mapping);
1229
+ }
1230
+ query.push(queryPart);
1231
+ }
1232
+ });
1233
+
1234
+ if (hasNoIdError) {
1235
+ reject(new Error("some or all filter elements have no id"));
1236
+ return;
1237
+ }
1238
+
1239
+ getGlobal().location.hash = createBracketedKeyValueHash(currentHash);
1240
+ resolve(query);
1241
+ });
1229
1242
  }
1230
1243
 
1231
1244
  /**
@@ -1234,41 +1247,41 @@ function collectSearchQueries() {
1234
1247
  * @return {null|Array|undefined|string}
1235
1248
  */
1236
1249
  function getControlValuesFromLabel(label) {
1237
- // finde das erste Kind-Element vom type input
1238
- // wenn es ein input-Element ist, dann @todo
1239
-
1240
- const foundControl = label.firstElementChild;
1241
-
1242
- if (foundControl) {
1243
- if (foundControl.tagName === "INPUT") {
1244
- if (foundControl.type === "checkbox") {
1245
- const checkedControls = label.querySelectorAll(
1246
- `${foundControl}:checked`,
1247
- );
1248
- const values = [];
1249
-
1250
- checkedControls.forEach((checkedControl) => {
1251
- values.push(checkedControl.value);
1252
- });
1253
-
1254
- return values;
1255
- } else if (foundControl.type === "radio") {
1256
- const checkedControl = label.querySelector(`${foundControl}:checked`);
1257
-
1258
- if (checkedControl) {
1259
- return checkedControl.value;
1260
- } else {
1261
- return null;
1262
- }
1263
- } else {
1264
- return foundControl.value;
1265
- }
1266
- } else {
1267
- return foundControl.value;
1268
- }
1269
- }
1270
-
1271
- return null;
1250
+ // finde das erste Kind-Element vom type input
1251
+ // wenn es ein input-Element ist, dann @todo
1252
+
1253
+ const foundControl = label.firstElementChild;
1254
+
1255
+ if (foundControl) {
1256
+ if (foundControl.tagName === "INPUT") {
1257
+ if (foundControl.type === "checkbox") {
1258
+ const checkedControls = label.querySelectorAll(
1259
+ `${foundControl}:checked`,
1260
+ );
1261
+ const values = [];
1262
+
1263
+ checkedControls.forEach((checkedControl) => {
1264
+ values.push(checkedControl.value);
1265
+ });
1266
+
1267
+ return values;
1268
+ } else if (foundControl.type === "radio") {
1269
+ const checkedControl = label.querySelector(`${foundControl}:checked`);
1270
+
1271
+ if (checkedControl) {
1272
+ return checkedControl.value;
1273
+ } else {
1274
+ return null;
1275
+ }
1276
+ } else {
1277
+ return foundControl.value;
1278
+ }
1279
+ } else {
1280
+ return foundControl.value;
1281
+ }
1282
+ }
1283
+
1284
+ return null;
1272
1285
  }
1273
1286
 
1274
1287
  /**
@@ -1276,60 +1289,60 @@ function getControlValuesFromLabel(label) {
1276
1289
  * @return {Promise<unknown>}
1277
1290
  */
1278
1291
  function initFromConfig() {
1279
- const host = findElementWithSelectorUpwards(this, "monster-host");
1280
-
1281
- if (!(isInstance(host, Host) && this.id)) {
1282
- return Promise.resolve();
1283
- }
1284
-
1285
- const configKey = getFilterConfigKey.call(this);
1286
-
1287
- return new Promise((resolve, reject) => {
1288
- host
1289
- .getConfig(configKey)
1290
- .then((config) => {
1291
- if ((config && isObject(config)) || isArray(config)) {
1292
- this[settingsSymbol].setOptions(config);
1293
- }
1294
- resolve();
1295
- })
1296
- .catch((error) => {
1297
- if (error === undefined) {
1298
- resolve();
1299
- return;
1300
- }
1301
-
1302
- // config not written
1303
- if (error?.message?.match(/is not defined/)) {
1304
- resolve();
1305
- return;
1306
- }
1307
-
1308
- addAttributeToken(
1309
- this,
1310
- ATTRIBUTE_ERRORMESSAGE,
1311
- error?.message || error,
1312
- );
1313
- reject(error);
1314
- });
1315
- });
1292
+ const host = findElementWithSelectorUpwards(this, "monster-host");
1293
+
1294
+ if (!(isInstance(host, Host) && this.id)) {
1295
+ return Promise.resolve();
1296
+ }
1297
+
1298
+ const configKey = getFilterConfigKey.call(this);
1299
+
1300
+ return new Promise((resolve, reject) => {
1301
+ host
1302
+ .getConfig(configKey)
1303
+ .then((config) => {
1304
+ if ((config && isObject(config)) || isArray(config)) {
1305
+ this[settingsSymbol].setOptions(config);
1306
+ }
1307
+ resolve();
1308
+ })
1309
+ .catch((error) => {
1310
+ if (error === undefined) {
1311
+ resolve();
1312
+ return;
1313
+ }
1314
+
1315
+ // config not written
1316
+ if (error?.message?.match(/is not defined/)) {
1317
+ resolve();
1318
+ return;
1319
+ }
1320
+
1321
+ addAttributeToken(
1322
+ this,
1323
+ ATTRIBUTE_ERRORMESSAGE,
1324
+ error?.message || error,
1325
+ );
1326
+ reject(error);
1327
+ });
1328
+ });
1316
1329
  }
1317
1330
 
1318
1331
  /**
1319
1332
  * @private
1320
1333
  */
1321
1334
  function updateConfig() {
1322
- const host = findElementWithSelectorUpwards(this, "monster-host");
1323
- if (!(host && this.id)) {
1324
- return;
1325
- }
1326
- const configKey = getFilterConfigKey.call(this);
1327
-
1328
- try {
1329
- host.setConfig(configKey, this[settingsSymbol].getOptions());
1330
- } catch (error) {
1331
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error?.message || error);
1332
- }
1335
+ const host = findElementWithSelectorUpwards(this, "monster-host");
1336
+ if (!(host && this.id)) {
1337
+ return;
1338
+ }
1339
+ const configKey = getFilterConfigKey.call(this);
1340
+
1341
+ try {
1342
+ host.setConfig(configKey, this[settingsSymbol].getOptions());
1343
+ } catch (error) {
1344
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error?.message || error);
1345
+ }
1333
1346
  }
1334
1347
 
1335
1348
  /**
@@ -1337,8 +1350,8 @@ function updateConfig() {
1337
1350
  * @return {string}
1338
1351
  */
1339
1352
  function getTemplate() {
1340
- // language=HTML
1341
- return `
1353
+ // language=HTML
1354
+ return `
1342
1355
  <div data-monster-role="control" part="control">
1343
1356
  <div data-monster-role="container">
1344
1357
  <div data-monster-role="layout">