@schukai/monster 3.55.0 → 3.55.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/source/components/datatable/datasource/rest.mjs +313 -326
- package/source/components/datatable/datatable/header.mjs +1 -1
- package/source/components/datatable/datatable.mjs +586 -591
- package/source/components/datatable/embedded-pagination.mjs +42 -49
- package/source/components/datatable/filter/util.mjs +115 -99
- package/source/components/datatable/filter.mjs +901 -842
- package/source/components/datatable/pagination.mjs +333 -334
- package/source/components/datatable/status.mjs +134 -156
- package/source/components/datatable/stylesheet/column-bar.mjs +14 -8
- package/source/components/datatable/stylesheet/dataset.mjs +14 -8
- package/source/components/datatable/stylesheet/datasource.mjs +14 -8
- package/source/components/datatable/stylesheet/datatable.mjs +14 -8
- package/source/components/datatable/stylesheet/embedded-pagination.mjs +14 -8
- package/source/components/datatable/stylesheet/filter-button.mjs +14 -8
- package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +14 -8
- package/source/components/datatable/stylesheet/filter-date-range.mjs +14 -8
- package/source/components/datatable/stylesheet/filter-range.mjs +14 -8
- package/source/components/datatable/stylesheet/filter.mjs +14 -8
- package/source/components/datatable/stylesheet/pagination.mjs +14 -8
- package/source/components/datatable/stylesheet/select-filter.mjs +14 -8
- package/source/components/datatable/stylesheet/status.mjs +14 -8
- package/source/components/form/action-button.mjs +3 -1
- package/source/components/form/confirm-button.mjs +3 -1
- package/source/components/form/context-error.mjs +161 -164
- package/source/components/form/context-help.mjs +3 -1
- package/source/components/form/form.mjs +3 -1
- package/source/components/form/message-state-button.mjs +3 -1
- package/source/components/form/popper-button.mjs +6 -4
- package/source/components/form/popper.mjs +310 -310
- package/source/components/form/select.mjs +2 -2
- package/source/components/form/state-button.mjs +3 -1
- package/source/components/form/stylesheet/action-button.mjs +14 -8
- package/source/components/form/stylesheet/api-button.mjs +14 -8
- package/source/components/form/stylesheet/button-bar.mjs +14 -8
- package/source/components/form/stylesheet/button.mjs +14 -8
- package/source/components/form/stylesheet/confirm-button.mjs +14 -8
- package/source/components/form/stylesheet/context-error.mjs +14 -8
- package/source/components/form/stylesheet/context-help.mjs +14 -8
- package/source/components/form/stylesheet/form.mjs +14 -8
- package/source/components/form/stylesheet/message-state-button.mjs +14 -8
- package/source/components/form/stylesheet/popper-button.mjs +14 -8
- package/source/components/form/stylesheet/popper.mjs +14 -8
- package/source/components/form/stylesheet/select.mjs +14 -8
- package/source/components/form/stylesheet/state-button.mjs +14 -8
- package/source/components/form/stylesheet/tabs.mjs +14 -8
- package/source/components/form/stylesheet/tree-select.mjs +14 -8
- package/source/components/form/tabs.mjs +754 -758
- package/source/components/host/collapse.mjs +2 -4
- package/source/components/host/config-manager.mjs +11 -9
- package/source/components/host/stylesheet/call-button.mjs +14 -8
- package/source/components/host/stylesheet/collapse.mjs +14 -8
- package/source/components/host/stylesheet/config-manager.mjs +14 -8
- package/source/components/host/stylesheet/details.mjs +14 -8
- package/source/components/host/stylesheet/host.mjs +14 -8
- package/source/components/host/stylesheet/overlay.mjs +14 -8
- package/source/components/host/stylesheet/toggle-button.mjs +14 -8
- package/source/components/host/stylesheet/viewer.mjs +14 -8
- package/source/components/host/util.mjs +2 -2
- package/source/components/notify/stylesheet/message.mjs +14 -8
- package/source/components/notify/stylesheet/notify.mjs +14 -8
- package/source/components/state/stylesheet/log.mjs +14 -8
- package/source/components/state/stylesheet/state.mjs +14 -8
- package/source/components/stylesheet/badge.mjs +14 -8
- package/source/components/stylesheet/border.mjs +14 -8
- package/source/components/stylesheet/button.mjs +14 -8
- package/source/components/stylesheet/card.mjs +14 -8
- package/source/components/stylesheet/color.mjs +14 -8
- package/source/components/stylesheet/common.mjs +14 -8
- package/source/components/stylesheet/control.mjs +14 -8
- package/source/components/stylesheet/data-grid.mjs +14 -8
- package/source/components/stylesheet/display.mjs +14 -8
- package/source/components/stylesheet/floating-ui.mjs +14 -8
- package/source/components/stylesheet/form.mjs +14 -8
- package/source/components/stylesheet/host.mjs +14 -8
- package/source/components/stylesheet/icons.mjs +14 -8
- package/source/components/stylesheet/link.mjs +14 -8
- package/source/components/stylesheet/normalize.mjs +14 -8
- package/source/components/stylesheet/popper.mjs +14 -8
- package/source/components/stylesheet/property.mjs +14 -8
- package/source/components/stylesheet/ripple.mjs +14 -8
- package/source/components/stylesheet/skeleton.mjs +14 -8
- package/source/components/stylesheet/space.mjs +14 -8
- package/source/components/stylesheet/spinner.mjs +14 -8
- package/source/components/stylesheet/table.mjs +14 -8
- package/source/components/stylesheet/theme.mjs +14 -8
- package/source/components/stylesheet/typography.mjs +14 -8
- package/source/components/tree-menu/stylesheet/tree-menu.mjs +14 -8
- package/source/data/transformer.mjs +6 -8
- package/source/dom/attributes.mjs +5 -5
- package/source/dom/customelement.mjs +1 -1
- package/source/dom/updater.mjs +697 -700
- package/source/dom/util.mjs +2 -2
- package/source/monster.mjs +0 -1
- package/source/types/noderecursiveiterator.mjs +9 -7
- package/source/types/version.mjs +1 -1
- package/source/util/sleep.mjs +3 -4
- package/test/cases/monster.mjs +1 -1
@@ -3,41 +3,48 @@
|
|
3
3
|
* SPDX-License-Identifier: AGPL-3.0
|
4
4
|
*/
|
5
5
|
|
6
|
-
import {instanceSymbol} from "../../constants.mjs";
|
7
|
-
import {findTargetElementFromEvent} from "../../dom/events.mjs";
|
8
|
-
import {findElementWithIdUpwards, findElementWithSelectorUpwards} from "../../dom/util.mjs";
|
6
|
+
import { instanceSymbol } from "../../constants.mjs";
|
7
|
+
import { findTargetElementFromEvent } from "../../dom/events.mjs";
|
9
8
|
import {
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
findElementWithIdUpwards,
|
10
|
+
findElementWithSelectorUpwards,
|
11
|
+
} from "../../dom/util.mjs";
|
12
|
+
import {
|
13
|
+
assembleMethodSymbol,
|
14
|
+
CustomElement,
|
15
|
+
getSlottedElements,
|
16
|
+
registerCustomElement,
|
14
17
|
} from "../../dom/customelement.mjs";
|
15
|
-
import {ID} from "../../types/id.mjs";
|
16
|
-
import {Settings} from "./filter/settings.mjs";
|
17
|
-
import {FilterStyleSheet} from "./stylesheet/filter.mjs";
|
18
|
-
import {getDocument, getWindow} from "../../dom/util.mjs";
|
19
|
-
import {getGlobal} from "../../types/global.mjs";
|
20
|
-
import {isInstance, isFunction, isObject, isArray} from "../../types/is.mjs";
|
21
|
-
import {Host} from "../host/host.mjs";
|
22
|
-
import {addAttributeToken} from "../../dom/attributes.mjs";
|
23
|
-
import {ATTRIBUTE_ERRORMESSAGE} from "../../dom/constants.mjs";
|
18
|
+
import { ID } from "../../types/id.mjs";
|
19
|
+
import { Settings } from "./filter/settings.mjs";
|
20
|
+
import { FilterStyleSheet } from "./stylesheet/filter.mjs";
|
21
|
+
import { getDocument, getWindow } from "../../dom/util.mjs";
|
22
|
+
import { getGlobal } from "../../types/global.mjs";
|
23
|
+
import { isInstance, isFunction, isObject, isArray } from "../../types/is.mjs";
|
24
|
+
import { Host } from "../host/host.mjs";
|
25
|
+
import { addAttributeToken } from "../../dom/attributes.mjs";
|
26
|
+
import { ATTRIBUTE_ERRORMESSAGE } from "../../dom/constants.mjs";
|
24
27
|
import "../form/message-state-button.mjs";
|
25
|
-
import {Formatter} from "../../text/formatter.mjs";
|
26
|
-
import {generateRangeComparisonExpression} from "../../text/util.mjs";
|
28
|
+
import { Formatter } from "../../text/formatter.mjs";
|
29
|
+
import { generateRangeComparisonExpression } from "../../text/util.mjs";
|
27
30
|
|
28
31
|
import {
|
29
|
-
|
30
|
-
|
32
|
+
parseBracketedKeyValueHash,
|
33
|
+
createBracketedKeyValueHash,
|
31
34
|
} from "../../text/bracketed-key-value-hash.mjs";
|
32
|
-
import {ThemeStyleSheet} from "../stylesheet/theme.mjs";
|
33
|
-
import {SpaceStyleSheet} from "../stylesheet/space.mjs";
|
34
|
-
import {FormStyleSheet} from "../stylesheet/form.mjs";
|
35
|
+
import { ThemeStyleSheet } from "../stylesheet/theme.mjs";
|
36
|
+
import { SpaceStyleSheet } from "../stylesheet/space.mjs";
|
37
|
+
import { FormStyleSheet } from "../stylesheet/form.mjs";
|
35
38
|
|
36
|
-
import {
|
39
|
+
import {
|
40
|
+
getStoredFilterConfigKey,
|
41
|
+
getFilterConfigKey,
|
42
|
+
parseDateInput,
|
43
|
+
} from "./filter/util.mjs";
|
37
44
|
|
38
45
|
import "./filter/select.mjs";
|
39
46
|
|
40
|
-
export {Filter};
|
47
|
+
export { Filter };
|
41
48
|
|
42
49
|
/**
|
43
50
|
* @private
|
@@ -73,7 +80,9 @@ const filterControlElementSymbol = Symbol("filterControlElement");
|
|
73
80
|
* @private
|
74
81
|
* @type {symbol}
|
75
82
|
*/
|
76
|
-
const filterSaveActionButtonElementSymbol = Symbol(
|
83
|
+
const filterSaveActionButtonElementSymbol = Symbol(
|
84
|
+
"filterSaveActionButtonElement",
|
85
|
+
);
|
77
86
|
|
78
87
|
/**
|
79
88
|
* @private
|
@@ -134,180 +143,189 @@ const settingsSymbol = Symbol("settings");
|
|
134
143
|
* @summary A data set
|
135
144
|
*/
|
136
145
|
class Filter extends CustomElement {
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
146
|
+
/**
|
147
|
+
*
|
148
|
+
*/
|
149
|
+
constructor() {
|
150
|
+
super();
|
151
|
+
this[settingsSymbol] = new Settings();
|
152
|
+
}
|
153
|
+
|
154
|
+
/**
|
155
|
+
* This method is called by the `instanceof` operator.
|
156
|
+
* @returns {symbol}
|
157
|
+
*/
|
158
|
+
static get [instanceSymbol]() {
|
159
|
+
return Symbol.for("@schukai/monster/components/filter@@instance");
|
160
|
+
}
|
161
|
+
|
162
|
+
/**
|
163
|
+
*
|
164
|
+
* @param {string} message
|
165
|
+
* @returns {Monster.Components.Datatable.Filter}
|
166
|
+
*/
|
167
|
+
showFailureMessage(message) {
|
168
|
+
this[searchButtonElementSymbol].setState(
|
169
|
+
"failed",
|
170
|
+
this.getOption("timeouts.message", 4000),
|
171
|
+
);
|
172
|
+
this[searchButtonElementSymbol]
|
173
|
+
.setMessage(message.toString())
|
174
|
+
.showMessage(this.getOption("timeouts.message", 4000));
|
175
|
+
return this;
|
176
|
+
}
|
177
|
+
|
178
|
+
/**
|
179
|
+
*
|
180
|
+
* @returns {Monster.Components.Datatable.Filter}
|
181
|
+
*/
|
182
|
+
resetFailureMessage() {
|
183
|
+
this[searchButtonElementSymbol].hideMessage();
|
184
|
+
this[searchButtonElementSymbol].removeState();
|
185
|
+
return this;
|
186
|
+
}
|
187
|
+
|
188
|
+
/**
|
189
|
+
*
|
190
|
+
* @returns {Monster.Components.Datatable.Filter}
|
191
|
+
*/
|
192
|
+
showSuccess() {
|
193
|
+
this[searchButtonElementSymbol].setState(
|
194
|
+
"successful",
|
195
|
+
this.getOption("timeouts.message", 4000),
|
196
|
+
);
|
197
|
+
return this;
|
198
|
+
}
|
199
|
+
|
200
|
+
/**
|
201
|
+
* To set the options via the html tag the attribute `data-monster-options` must be used.
|
202
|
+
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
203
|
+
*
|
204
|
+
* The individual configuration values can be found in the table.
|
205
|
+
*
|
206
|
+
* @property {Object} templates Template definitions
|
207
|
+
* @property {string} templates.main Main template
|
208
|
+
* @property {Object} labels Label definitions
|
209
|
+
* @property {string} labels.search Search button label
|
210
|
+
* @property {string} labels.reset Reset button label
|
211
|
+
* @property {Object} queries Query definitions
|
212
|
+
* @property {function} queries.wrap Wrap query
|
213
|
+
* @property {function} queries.join Join queries
|
214
|
+
* @property {string} defaultQuery Default query
|
215
|
+
*/
|
216
|
+
get defaults() {
|
217
|
+
return Object.assign({}, super.defaults, {
|
218
|
+
templates: {
|
219
|
+
main: getTemplate(),
|
220
|
+
},
|
221
|
+
|
222
|
+
labels: {
|
223
|
+
search: "Search",
|
224
|
+
reset: "Reset",
|
225
|
+
save: "Save",
|
226
|
+
"filter-name": "Filter name",
|
227
|
+
"empty-query-and-no-default": "Please select a filter",
|
228
|
+
"query-not-changed": "The query has not changed",
|
229
|
+
},
|
230
|
+
|
231
|
+
templateMapping: {
|
232
|
+
"filter-save-label": null,
|
233
|
+
"filter-name-label": name,
|
234
|
+
},
|
235
|
+
|
236
|
+
storedConfig: {
|
237
|
+
enabled: true,
|
238
|
+
selector: "",
|
239
|
+
},
|
240
|
+
|
241
|
+
timeouts: {
|
242
|
+
message: 4000,
|
243
|
+
},
|
244
|
+
|
245
|
+
queries: {
|
246
|
+
wrap: (value, definition) => {
|
247
|
+
return value;
|
248
|
+
},
|
249
|
+
join: (queries) => {
|
250
|
+
if (queries.length === 0) {
|
251
|
+
return "";
|
252
|
+
}
|
253
|
+
return queries.join(" AND ");
|
254
|
+
},
|
255
|
+
},
|
256
|
+
|
257
|
+
query: "",
|
258
|
+
defaultQuery: "",
|
259
|
+
});
|
260
|
+
}
|
261
|
+
|
262
|
+
/**
|
263
|
+
*
|
264
|
+
* @return {string}
|
265
|
+
*/
|
266
|
+
static getTag() {
|
267
|
+
return "monster-datatable-filter";
|
268
|
+
}
|
269
|
+
|
270
|
+
/**
|
271
|
+
* @return {FilterButton}
|
272
|
+
*/
|
273
|
+
[assembleMethodSymbol]() {
|
274
|
+
this.setOption(
|
275
|
+
"templateMapping.filter-save-label",
|
276
|
+
this.getOption("labels.save"),
|
277
|
+
);
|
278
|
+
this.setOption(
|
279
|
+
"templateMapping.filter-name-label",
|
280
|
+
this.getOption("labels.filter-name"),
|
281
|
+
);
|
282
|
+
|
283
|
+
super[assembleMethodSymbol]();
|
284
|
+
|
285
|
+
initControlReferences.call(this);
|
286
|
+
initEventHandler.call(this);
|
287
|
+
|
288
|
+
initFromConfig
|
289
|
+
.call(this)
|
290
|
+
.then(() => {
|
291
|
+
initFilter.call(this);
|
292
|
+
updateFilterTabs.call(this);
|
293
|
+
})
|
294
|
+
.catch((error) => {
|
295
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error?.message);
|
296
|
+
});
|
297
|
+
}
|
298
|
+
|
299
|
+
/**
|
300
|
+
*
|
301
|
+
*/
|
302
|
+
connectedCallback() {
|
303
|
+
super.connectedCallback();
|
304
|
+
|
305
|
+
getWindow().addEventListener(
|
306
|
+
"hashchange",
|
307
|
+
this[locationChangeHandlerSymbol],
|
308
|
+
);
|
309
|
+
}
|
310
|
+
|
311
|
+
/**
|
312
|
+
*
|
313
|
+
*/
|
314
|
+
disconnectedCallback() {
|
315
|
+
super.disconnectedCallback();
|
316
|
+
|
317
|
+
getWindow().removeEventListener(
|
318
|
+
"hashchange",
|
319
|
+
this[locationChangeHandlerSymbol],
|
320
|
+
);
|
321
|
+
}
|
322
|
+
|
323
|
+
/**
|
324
|
+
* @return {Array<CSSStyleSheet>}
|
325
|
+
*/
|
326
|
+
static getCSSStyleSheet() {
|
327
|
+
return [FilterStyleSheet, FormStyleSheet, ThemeStyleSheet, SpaceStyleSheet];
|
328
|
+
}
|
311
329
|
}
|
312
330
|
|
313
331
|
/**
|
@@ -315,35 +333,37 @@ class Filter extends CustomElement {
|
|
315
333
|
* @return {FilterButton}
|
316
334
|
*/
|
317
335
|
function initControlReferences() {
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
336
|
+
if (!this.shadowRoot) {
|
337
|
+
throw new Error("no shadow-root is defined");
|
338
|
+
}
|
339
|
+
|
340
|
+
this[filterControlElementSymbol] = this.shadowRoot.querySelector(
|
341
|
+
"[data-monster-role=control]",
|
342
|
+
);
|
343
|
+
this[filterSelectElementSymbol] = this.shadowRoot.querySelector(
|
344
|
+
"[data-monster-role=filter-select]",
|
345
|
+
);
|
346
|
+
this[searchButtonElementSymbol] = this.shadowRoot.querySelector(
|
347
|
+
"[data-monster-role=search-button]",
|
348
|
+
);
|
349
|
+
this[resetButtonElementSymbol] = this.shadowRoot.querySelector(
|
350
|
+
"[data-monster-role=reset-button]",
|
351
|
+
);
|
352
|
+
|
353
|
+
this[saveButtonElementSymbol] = this.shadowRoot.querySelector(
|
354
|
+
"[data-monster-role=save-button]",
|
355
|
+
);
|
356
|
+
|
357
|
+
this[filterSaveActionButtonElementSymbol] = this.shadowRoot.querySelector(
|
358
|
+
"[data-monster-role=save-action-button]",
|
359
|
+
);
|
360
|
+
|
361
|
+
this[filterTabElementSymbol] = findElementWithSelectorUpwards(
|
362
|
+
this,
|
363
|
+
this.getOption("storedConfig.selector", ""),
|
364
|
+
);
|
365
|
+
|
366
|
+
return this;
|
347
367
|
}
|
348
368
|
|
349
369
|
/**
|
@@ -351,69 +371,67 @@ function initControlReferences() {
|
|
351
371
|
* @throws {Error} no filter label is defined
|
352
372
|
*/
|
353
373
|
function initFilter() {
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
this[filterSelectElementSymbol].value = this[settingsSymbol].getSelected();
|
416
|
-
}, 10);
|
374
|
+
const storedConfig = this[settingsSymbol];
|
375
|
+
this[settingsSymbol] = new Settings();
|
376
|
+
|
377
|
+
const result = parseBracketedKeyValueHash(getGlobal().location.hash);
|
378
|
+
let valuesFromHash = {};
|
379
|
+
if (isObject(result) && result?.[this.id]) {
|
380
|
+
valuesFromHash = result[this.id];
|
381
|
+
}
|
382
|
+
|
383
|
+
getSlottedElements
|
384
|
+
.call(this, "label[data-monster-label]")
|
385
|
+
.forEach((element) => {
|
386
|
+
const label = element.getAttribute("data-monster-label");
|
387
|
+
if (!label) {
|
388
|
+
throw new Error("no filter label is defined");
|
389
|
+
}
|
390
|
+
|
391
|
+
let value = element.id;
|
392
|
+
if (!value) {
|
393
|
+
const prefix = label.replace(/\W/g, "-");
|
394
|
+
prefix.charAt(0).match(/[\d_]/g)?.length ? `f${prefix}` : prefix;
|
395
|
+
|
396
|
+
value = new ID(prefix + "-").toString();
|
397
|
+
element.id = value;
|
398
|
+
}
|
399
|
+
|
400
|
+
let setting = storedConfig.get(value);
|
401
|
+
|
402
|
+
if (setting) {
|
403
|
+
this[settingsSymbol].set(setting);
|
404
|
+
}
|
405
|
+
|
406
|
+
if (valuesFromHash?.[element.id]) {
|
407
|
+
const v = escapeAttributeValue(valuesFromHash[element.id]);
|
408
|
+
const searchInput = element.firstElementChild;
|
409
|
+
try {
|
410
|
+
// searchInput.value = valuesFromHash[element.id];
|
411
|
+
searchInput.value = v; //valuesFromHash[element.id];
|
412
|
+
} catch (error) {}
|
413
|
+
}
|
414
|
+
|
415
|
+
setting = this[settingsSymbol].get(value);
|
416
|
+
if (setting) {
|
417
|
+
setSlotAttribute(element, setting.visible);
|
418
|
+
//style.display = setting.visible ? "block" : "none";
|
419
|
+
}
|
420
|
+
|
421
|
+
//const visible = window.getComputedStyle(element).display !== "none";
|
422
|
+
const visible = getVisibilityFromSlotAttribute(element);
|
423
|
+
|
424
|
+
this[settingsSymbol].set({ value, label, visible });
|
425
|
+
});
|
426
|
+
|
427
|
+
this[filterSelectElementSymbol].setOption(
|
428
|
+
"options",
|
429
|
+
this[settingsSymbol].getOptions(),
|
430
|
+
);
|
431
|
+
|
432
|
+
setTimeout(() => {
|
433
|
+
this[filterSelectElementSymbol].value = this[settingsSymbol].getSelected();
|
434
|
+
}, 10);
|
417
435
|
}
|
418
436
|
|
419
437
|
/**
|
@@ -422,18 +440,17 @@ function initFilter() {
|
|
422
440
|
* @returns {*}
|
423
441
|
*/
|
424
442
|
function escapeAttributeValue(input) {
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
.replace(/>/g, ">");
|
443
|
+
if (input === undefined || input === null) {
|
444
|
+
debugger;
|
445
|
+
return input;
|
446
|
+
}
|
447
|
+
|
448
|
+
return input
|
449
|
+
.replace(/&/g, "&")
|
450
|
+
.replace(/"/g, """)
|
451
|
+
.replace(/'/g, "'")
|
452
|
+
.replace(/</g, "<")
|
453
|
+
.replace(/>/g, ">");
|
437
454
|
}
|
438
455
|
|
439
456
|
/**
|
@@ -442,7 +459,9 @@ function escapeAttributeValue(input) {
|
|
442
459
|
* @returns {boolean}
|
443
460
|
*/
|
444
461
|
function getVisibilityFromSlotAttribute(element) {
|
445
|
-
|
462
|
+
return !(
|
463
|
+
element.hasAttribute("slot") && element.getAttribute("slot") === "hidden"
|
464
|
+
);
|
446
465
|
}
|
447
466
|
|
448
467
|
/**
|
@@ -451,306 +470,341 @@ function getVisibilityFromSlotAttribute(element) {
|
|
451
470
|
* @param {boolean} visible
|
452
471
|
*/
|
453
472
|
function setSlotAttribute(element, visible) {
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
473
|
+
if (visible) {
|
474
|
+
element.removeAttribute("slot");
|
475
|
+
return;
|
476
|
+
}
|
458
477
|
|
459
|
-
|
478
|
+
element.setAttribute("slot", "hidden");
|
460
479
|
}
|
461
480
|
|
462
481
|
/**
|
463
482
|
* @private
|
464
483
|
*/
|
465
484
|
function initEventHandler() {
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
485
|
+
const self = this;
|
486
|
+
/**
|
487
|
+
* Monster.Components.Form.event:monster-selection-cleared
|
488
|
+
*/
|
489
|
+
if (self[filterSelectElementSymbol]) {
|
490
|
+
self[filterSelectElementSymbol].addEventListener(
|
491
|
+
"monster-selection-cleared",
|
492
|
+
function () {
|
493
|
+
const settings = self[settingsSymbol].getOptions();
|
494
|
+
|
495
|
+
for (const setting of settings) {
|
496
|
+
const filterElement = findElementWithIdUpwards(self, setting.value);
|
497
|
+
if (filterElement) {
|
498
|
+
setSlotAttribute(filterElement, false);
|
499
|
+
|
500
|
+
self[settingsSymbol].set({ value: setting.value, visible: false });
|
501
|
+
}
|
502
|
+
}
|
503
|
+
|
504
|
+
updateConfig.call(self);
|
505
|
+
},
|
506
|
+
);
|
507
|
+
|
508
|
+
self[filterSelectElementSymbol].addEventListener(
|
509
|
+
"monster-changed",
|
510
|
+
function (event) {
|
511
|
+
const filterElement = findElementWithIdUpwards(
|
512
|
+
self,
|
513
|
+
event.detail.value,
|
514
|
+
);
|
515
|
+
if (filterElement) {
|
516
|
+
//filterElement.style.display = event.detail.checked ? "block" : "none";
|
517
|
+
setSlotAttribute(filterElement, event.detail.checked);
|
518
|
+
}
|
519
|
+
|
520
|
+
self[settingsSymbol].set({
|
521
|
+
value: event.detail.value,
|
522
|
+
visible: event.detail.checked,
|
523
|
+
});
|
524
|
+
|
525
|
+
updateConfig.call(self);
|
526
|
+
},
|
527
|
+
);
|
528
|
+
}
|
529
|
+
|
530
|
+
if (self[filterSaveActionButtonElementSymbol]) {
|
531
|
+
self[filterSaveActionButtonElementSymbol].setOption(
|
532
|
+
"actions.click",
|
533
|
+
function (event) {
|
534
|
+
const button = findTargetElementFromEvent(
|
535
|
+
event,
|
536
|
+
"data-monster-role",
|
537
|
+
"save-action-button",
|
538
|
+
);
|
539
|
+
const form = button.closest("[data-monster-role=form]");
|
540
|
+
|
541
|
+
if (!form) {
|
542
|
+
button.setState("failed", self.getOption("timeouts.message", 4000));
|
543
|
+
return;
|
544
|
+
}
|
545
|
+
|
546
|
+
const input = form.querySelector("input[name=filter-name]");
|
547
|
+
if (!input) {
|
548
|
+
button.setState("failed", self.getOption("timeouts.message", 4000));
|
549
|
+
return;
|
550
|
+
}
|
551
|
+
|
552
|
+
const name = input.value;
|
553
|
+
if (!name) {
|
554
|
+
button.setState("failed", self.getOption("timeouts.message", 4000));
|
555
|
+
button.setMessage("Please enter a name").showMessage();
|
556
|
+
return;
|
557
|
+
}
|
558
|
+
|
559
|
+
doSearch
|
560
|
+
.call(self, { showEffect: false })
|
561
|
+
.then(() => {
|
562
|
+
const configKey = getStoredFilterConfigKey.call(self);
|
563
|
+
const host = getDocument().querySelector("monster-host");
|
564
|
+
if (!host) {
|
565
|
+
return;
|
566
|
+
}
|
567
|
+
|
568
|
+
const query = self.getOption("query");
|
569
|
+
if (!query) {
|
570
|
+
button.setState(
|
571
|
+
"failed",
|
572
|
+
self.getOption(
|
573
|
+
"timeouts.message",
|
574
|
+
self.getOption("timeouts.message", 4000),
|
575
|
+
),
|
576
|
+
);
|
577
|
+
button
|
578
|
+
.setMessage("No query found")
|
579
|
+
.showMessage(self.getOption("timeouts.message", 4000));
|
580
|
+
return;
|
581
|
+
}
|
582
|
+
|
583
|
+
host
|
584
|
+
.hasConfig(configKey)
|
585
|
+
.then((hasConfig) => {
|
586
|
+
return new Promise((resolve, reject) => {
|
587
|
+
if (hasConfig) {
|
588
|
+
host.getConfig(configKey).then(resolve).catch(reject);
|
589
|
+
return;
|
590
|
+
}
|
591
|
+
return resolve({});
|
592
|
+
});
|
593
|
+
})
|
594
|
+
.then((config) => {
|
595
|
+
config[name] = query;
|
596
|
+
return host.setConfig(configKey, {
|
597
|
+
...config,
|
598
|
+
});
|
599
|
+
})
|
600
|
+
.then(() => {
|
601
|
+
button.setState(
|
602
|
+
"successful",
|
603
|
+
self.getOption("timeouts.message", 4000),
|
604
|
+
);
|
605
|
+
updateFilterTabs.call(self);
|
606
|
+
})
|
607
|
+
.catch((error) => {
|
608
|
+
button.setState(
|
609
|
+
"failed",
|
610
|
+
self.getOption("timeouts.message", 4000),
|
611
|
+
);
|
612
|
+
button
|
613
|
+
.setMessage(error.message)
|
614
|
+
.showMessage(self.getOption("timeouts.message", 4000));
|
615
|
+
});
|
616
|
+
})
|
617
|
+
.catch((error) => {
|
618
|
+
button.setState("failed", self.getOption("timeouts.message", 4000));
|
619
|
+
const msg = error.message || error;
|
620
|
+
button
|
621
|
+
.setMessage(msg)
|
622
|
+
.showMessage(self.getOption("timeouts.message", 4000));
|
623
|
+
});
|
624
|
+
},
|
625
|
+
);
|
626
|
+
}
|
627
|
+
|
628
|
+
self[searchButtonElementSymbol].setOption("actions.click", () => {
|
629
|
+
doSearch
|
630
|
+
.call(self)
|
631
|
+
.then(() => {})
|
632
|
+
.catch((error) => {});
|
633
|
+
});
|
634
|
+
|
635
|
+
// the reset button should reset the filter and the search query
|
636
|
+
// all input elements should be reset to their default values
|
637
|
+
// which is the empty string. we search for all input elements
|
638
|
+
// in the filter and reset them to their default value
|
639
|
+
self[resetButtonElementSymbol].setOption("actions.click", () => {
|
640
|
+
getSlottedElements
|
641
|
+
.call(self, "label[data-monster-label]")
|
642
|
+
.forEach((element) => {
|
643
|
+
const label = element.getAttribute("data-monster-label");
|
644
|
+
if (!label) {
|
645
|
+
return;
|
646
|
+
}
|
647
|
+
|
648
|
+
const input = element.firstElementChild;
|
649
|
+
|
650
|
+
if (input) {
|
651
|
+
input.value = "";
|
652
|
+
}
|
653
|
+
});
|
654
|
+
|
655
|
+
doSearch.call(self, { showEffect: false });
|
656
|
+
});
|
657
|
+
|
658
|
+
self[locationChangeHandlerSymbol] = (event) => {
|
659
|
+
if (event instanceof HashChangeEvent) {
|
660
|
+
if (event.oldURL === event.newURL) {
|
661
|
+
return;
|
662
|
+
}
|
663
|
+
}
|
664
|
+
};
|
665
|
+
|
666
|
+
self.addEventListener("keyup", (event) => {
|
667
|
+
const path = event.composedPath();
|
668
|
+
if (path.length === 0) {
|
669
|
+
return;
|
670
|
+
}
|
671
|
+
|
672
|
+
if (!(path[0] instanceof HTMLInputElement)) {
|
673
|
+
return;
|
674
|
+
}
|
675
|
+
|
676
|
+
if (event.keyCode === 13) {
|
677
|
+
doSearch.call(self, { showEffect: false });
|
678
|
+
}
|
679
|
+
});
|
680
|
+
|
681
|
+
// tabs
|
682
|
+
const element = this[filterTabElementSymbol];
|
683
|
+
if (element) {
|
684
|
+
initTabEvents.call(this);
|
685
|
+
}
|
647
686
|
}
|
648
687
|
|
649
688
|
function initTabEvents() {
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
689
|
+
this[filterTabElementSymbol].addEventListener(
|
690
|
+
"monster-tab-changed",
|
691
|
+
(event) => {
|
692
|
+
const query = event?.detail?.data?.["data-monster-query"];
|
693
|
+
this.setOption("query", query);
|
694
|
+
},
|
695
|
+
);
|
696
|
+
|
697
|
+
this[filterTabElementSymbol].addEventListener(
|
698
|
+
"monster-tab-remove",
|
699
|
+
(event) => {
|
700
|
+
const labels = [];
|
701
|
+
const buttons = this[filterTabElementSymbol].getOption("buttons");
|
702
|
+
|
703
|
+
const keys = ["popper", "standard"];
|
704
|
+
for (let i = 0; i < keys.length; i++) {
|
705
|
+
const key = keys[i];
|
706
|
+
|
707
|
+
for (const button of buttons[key]) {
|
708
|
+
if (button.label !== event.detail.label) {
|
709
|
+
labels.push(button.label);
|
710
|
+
}
|
711
|
+
}
|
712
|
+
}
|
713
|
+
|
714
|
+
const document = getDocument();
|
715
|
+
const host = document.querySelector("monster-host");
|
716
|
+
if (!(host && this.id)) {
|
717
|
+
return;
|
718
|
+
}
|
719
|
+
|
720
|
+
const configKey = getStoredFilterConfigKey.call(this);
|
721
|
+
host
|
722
|
+
.hasConfig(configKey)
|
723
|
+
.then((hasConfig) => {
|
724
|
+
if (!hasConfig) {
|
725
|
+
return;
|
726
|
+
}
|
727
|
+
|
728
|
+
return host.getConfig(configKey);
|
729
|
+
})
|
730
|
+
.then((config) => {
|
731
|
+
for (const [name, query] of Object.entries(config)) {
|
732
|
+
if (labels.includes(name)) {
|
733
|
+
continue;
|
734
|
+
}
|
735
|
+
|
736
|
+
delete config[name];
|
737
|
+
}
|
738
|
+
|
739
|
+
return host.setConfig(configKey, {
|
740
|
+
...config,
|
741
|
+
});
|
742
|
+
});
|
743
|
+
},
|
744
|
+
);
|
707
745
|
}
|
708
746
|
|
709
747
|
/**
|
710
748
|
* @private
|
711
749
|
*/
|
712
750
|
function updateFilterTabs() {
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
751
|
+
const element = this[filterTabElementSymbol];
|
752
|
+
if (!element) {
|
753
|
+
return;
|
754
|
+
}
|
755
|
+
|
756
|
+
const document = getDocument();
|
757
|
+
const host = document.querySelector("monster-host");
|
758
|
+
if (!(host && this.id)) {
|
759
|
+
return;
|
760
|
+
}
|
761
|
+
|
762
|
+
const configKey = getStoredFilterConfigKey.call(this);
|
763
|
+
host
|
764
|
+
.hasConfig(configKey)
|
765
|
+
.then((hasConfig) => {
|
766
|
+
if (!hasConfig) {
|
767
|
+
return;
|
768
|
+
}
|
769
|
+
|
770
|
+
return host.getConfig(configKey);
|
771
|
+
})
|
772
|
+
.then((config) => {
|
773
|
+
for (const [name, query] of Object.entries(config)) {
|
774
|
+
const found = element.querySelector(
|
775
|
+
`[data-monster-button-label="${name}"]`,
|
776
|
+
);
|
777
|
+
if (found) {
|
778
|
+
continue;
|
779
|
+
}
|
780
|
+
|
781
|
+
if (query === undefined || query === null) {
|
782
|
+
continue;
|
783
|
+
}
|
784
|
+
|
785
|
+
const escapedQuery = escapeAttributeValue(query);
|
786
|
+
|
787
|
+
element.insertAdjacentHTML(
|
788
|
+
"beforeend",
|
789
|
+
`
|
748
790
|
<div data-monster-button-label="${name}"
|
749
791
|
data-monster-removable="true"
|
750
792
|
data-monster-query="${escapedQuery}" data-monster-role="filter-tab" >
|
751
|
-
</div
|
752
|
-
|
753
|
-
|
793
|
+
</div>`,
|
794
|
+
);
|
795
|
+
}
|
796
|
+
})
|
797
|
+
.catch((error) => {
|
798
|
+
if (error instanceof Error) {
|
799
|
+
addAttributeToken(
|
800
|
+
this,
|
801
|
+
ATTRIBUTE_ERRORMESSAGE,
|
802
|
+
error.message + " " + error.stack,
|
803
|
+
);
|
804
|
+
} else {
|
805
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error + "");
|
806
|
+
}
|
807
|
+
});
|
754
808
|
}
|
755
809
|
|
756
810
|
/**
|
@@ -758,74 +812,77 @@ function updateFilterTabs() {
|
|
758
812
|
* @param showEffect
|
759
813
|
* @returns {Promise<*>}
|
760
814
|
*/
|
761
|
-
function doSearch({showEffect} = {showEffect: true}) {
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
815
|
+
function doSearch({ showEffect } = { showEffect: true }) {;
|
816
|
+
|
817
|
+
this.resetFailureMessage();
|
818
|
+
|
819
|
+
if (showEffect) {
|
820
|
+
this[searchButtonElementSymbol].setState(
|
821
|
+
"activity",
|
822
|
+
this.getOption("timeouts.message", 4000),
|
823
|
+
);
|
824
|
+
}
|
825
|
+
|
826
|
+
return collectSearchQueries
|
827
|
+
.call(this)
|
828
|
+
.then((query) => {
|
829
|
+
const buildQuery = buildSearchQuery.call(this, query);
|
830
|
+
if (buildQuery === "" && !this.getOption("defaultQuery")) {
|
831
|
+
const msg = this.getOption("labels.empty-query-and-no-default");
|
832
|
+
|
833
|
+
if (showEffect) {
|
834
|
+
this[searchButtonElementSymbol].removeState();
|
835
|
+
this[searchButtonElementSymbol]
|
836
|
+
.setMessage(msg)
|
837
|
+
.showMessage(this.getOption("timeouts.message", 4000));
|
838
|
+
}
|
839
|
+
|
840
|
+
throw new Error(msg);
|
841
|
+
}
|
842
|
+
|
843
|
+
if (buildQuery === this.getOption("query")) {
|
844
|
+
const msg = this.getOption("labels.query-not-changed");
|
845
|
+
|
846
|
+
if (showEffect) {
|
847
|
+
this[searchButtonElementSymbol].removeState();
|
848
|
+
this[searchButtonElementSymbol]
|
849
|
+
.setMessage(msg)
|
850
|
+
.showMessage(this.getOption("timeouts.message", 4000));
|
851
|
+
}
|
852
|
+
|
853
|
+
throw new Error(msg);
|
854
|
+
}
|
855
|
+
|
856
|
+
if (showEffect) {
|
857
|
+
this[searchButtonElementSymbol].setState(
|
858
|
+
"activity",
|
859
|
+
this.getOption("timeouts.message", 4000),
|
860
|
+
);
|
861
|
+
}
|
862
|
+
|
863
|
+
this.setOption("query", buildSearchQuery.call(this, query));
|
864
|
+
})
|
865
|
+
.catch((error) => {
|
866
|
+
if (error instanceof Error) {
|
867
|
+
addAttributeToken(
|
868
|
+
this,
|
869
|
+
ATTRIBUTE_ERRORMESSAGE,
|
870
|
+
error.message + " " + error.stack,
|
871
|
+
);
|
872
|
+
} else {
|
873
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
|
874
|
+
}
|
875
|
+
|
876
|
+
if (showEffect) {
|
877
|
+
this[searchButtonElementSymbol].setState(
|
878
|
+
"failed",
|
879
|
+
this.getOption("timeouts.message", 4000),
|
880
|
+
);
|
881
|
+
this[searchButtonElementSymbol].setMessage(error.message).showMessage();
|
882
|
+
}
|
883
|
+
|
884
|
+
return Promise.reject(error);
|
885
|
+
});
|
829
886
|
}
|
830
887
|
|
831
888
|
/**
|
@@ -834,21 +891,21 @@ function doSearch({showEffect} = {showEffect: true}) {
|
|
834
891
|
* @returns {*|string}
|
835
892
|
*/
|
836
893
|
function buildSearchQuery(queries) {
|
837
|
-
|
838
|
-
|
839
|
-
|
894
|
+
if (!isArray(queries) || queries.length === 0) {
|
895
|
+
return this.getOption("defaultQuery");
|
896
|
+
}
|
840
897
|
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
898
|
+
const joinCallback = this.getOption("queries.join");
|
899
|
+
if (isFunction(joinCallback)) {
|
900
|
+
return joinCallback(queries);
|
901
|
+
}
|
845
902
|
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
903
|
+
const q = queries.join(" ").trim();
|
904
|
+
if (q.length === 0) {
|
905
|
+
return this.getOption("defaultQuery");
|
906
|
+
}
|
850
907
|
|
851
|
-
|
908
|
+
return q;
|
852
909
|
}
|
853
910
|
|
854
911
|
/**
|
@@ -856,200 +913,203 @@ function buildSearchQuery(queries) {
|
|
856
913
|
* @returns {Promise<unknown>}
|
857
914
|
*/
|
858
915
|
function collectSearchQueries() {
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
});
|
916
|
+
const currentHash = parseBracketedKeyValueHash(getGlobal().location.hash);
|
917
|
+
|
918
|
+
return new Promise((resolve, reject) => {
|
919
|
+
const query = [];
|
920
|
+
const wrapCallback = this.getOption("queries.wrap");
|
921
|
+
|
922
|
+
let hasNoIdError = false;
|
923
|
+
|
924
|
+
getSlottedElements
|
925
|
+
.call(this, "label[data-monster-label]")
|
926
|
+
.forEach((element) => {
|
927
|
+
const label = element.getAttribute("data-monster-label");
|
928
|
+
if (!label) {
|
929
|
+
throw new Error("no filter label is defined");
|
930
|
+
}
|
931
|
+
|
932
|
+
const id = element.id;
|
933
|
+
if (!id) {
|
934
|
+
hasNoIdError = true;
|
935
|
+
return;
|
936
|
+
}
|
937
|
+
|
938
|
+
//const visible = window.getComputedStyle(element).display !== "none";
|
939
|
+
const visible = getVisibilityFromSlotAttribute(element);
|
940
|
+
if (!visible) {
|
941
|
+
return;
|
942
|
+
}
|
943
|
+
|
944
|
+
let template = element.getAttribute("data-monster-template");
|
945
|
+
if (!template) {
|
946
|
+
template = "${id}=${value}";
|
947
|
+
}
|
948
|
+
|
949
|
+
const controlValue = getControlValuesFromLabel(element);
|
950
|
+
if (!controlValue) {
|
951
|
+
if (controlValue === "" && currentHash?.[this.id]?.[id]) {
|
952
|
+
delete currentHash[this.id][id];
|
953
|
+
}
|
954
|
+
|
955
|
+
return;
|
956
|
+
}
|
957
|
+
|
958
|
+
if (!isObject(currentHash[this.id])) {
|
959
|
+
currentHash[this.id] = {};
|
960
|
+
}
|
961
|
+
currentHash[this.id][id] = controlValue;
|
962
|
+
|
963
|
+
const mapping = {
|
964
|
+
id,
|
965
|
+
value: controlValue,
|
966
|
+
label,
|
967
|
+
};
|
968
|
+
|
969
|
+
const formatter = new Formatter(mapping, {
|
970
|
+
callbacks: {
|
971
|
+
range: (value, key) => {
|
972
|
+
return generateRangeComparisonExpression(value, key, {
|
973
|
+
urlEncode: true,
|
974
|
+
andOp: "AND",
|
975
|
+
orOp: "OR",
|
976
|
+
eqOp: "=",
|
977
|
+
gtOp: ">",
|
978
|
+
ltOp: "<",
|
979
|
+
});
|
980
|
+
},
|
981
|
+
"date-range": (value, key) => {
|
982
|
+
const query = parseDateInput(value, key);
|
983
|
+
if (!query || query === "false") {
|
984
|
+
return "";
|
985
|
+
}
|
986
|
+
|
987
|
+
// return query as url encoded
|
988
|
+
return encodeURIComponent(query);
|
989
|
+
},
|
990
|
+
},
|
991
|
+
});
|
992
|
+
|
993
|
+
let queryPart = formatter.format(template);
|
994
|
+
if (queryPart) {
|
995
|
+
if (isFunction(wrapCallback)) {
|
996
|
+
queryPart = wrapCallback(queryPart, mapping);
|
997
|
+
}
|
998
|
+
query.push(queryPart);
|
999
|
+
}
|
1000
|
+
});
|
1001
|
+
|
1002
|
+
if (hasNoIdError) {
|
1003
|
+
reject(new Error("some or all filter elements have no id"));
|
1004
|
+
return;
|
1005
|
+
}
|
1006
|
+
|
1007
|
+
getGlobal().location.hash = createBracketedKeyValueHash(currentHash);
|
1008
|
+
resolve(query);
|
1009
|
+
});
|
954
1010
|
}
|
955
1011
|
|
956
|
-
|
957
1012
|
/**
|
958
1013
|
* @private
|
959
1014
|
* @param label
|
960
1015
|
* @returns {null|Array|undefined|string}
|
961
1016
|
*/
|
962
1017
|
function getControlValuesFromLabel(label) {
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
1018
|
+
const foundControl = label.firstElementChild;
|
1019
|
+
|
1020
|
+
if (foundControl) {
|
1021
|
+
if (foundControl.tagName === "INPUT") {
|
1022
|
+
if (foundControl.type === "checkbox") {
|
1023
|
+
const checkedControls = label.querySelectorAll(
|
1024
|
+
`${foundControl}:checked`,
|
1025
|
+
);
|
1026
|
+
const values = [];
|
1027
|
+
|
1028
|
+
checkedControls.forEach((checkedControl) => {
|
1029
|
+
values.push(checkedControl.value);
|
1030
|
+
});
|
1031
|
+
|
1032
|
+
return values;
|
1033
|
+
} else if (foundControl.type === "radio") {
|
1034
|
+
const checkedControl = label.querySelector(`${foundControl}:checked`);
|
1035
|
+
|
1036
|
+
if (checkedControl) {
|
1037
|
+
return checkedControl.value;
|
1038
|
+
} else {
|
1039
|
+
return null;
|
1040
|
+
}
|
1041
|
+
} else {
|
1042
|
+
return foundControl.value;
|
1043
|
+
}
|
1044
|
+
} else {
|
1045
|
+
return foundControl.value;
|
1046
|
+
}
|
1047
|
+
}
|
1048
|
+
|
1049
|
+
return null;
|
993
1050
|
}
|
994
1051
|
|
995
|
-
|
996
1052
|
/**
|
997
1053
|
* @private
|
998
1054
|
* @returns {Promise<unknown>}
|
999
1055
|
*/
|
1000
1056
|
function initFromConfig() {
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1057
|
+
const document = getDocument();
|
1058
|
+
const host = document.querySelector("monster-host");
|
1059
|
+
|
1060
|
+
if (!(isInstance(host, Host) && this.id)) {
|
1061
|
+
return Promise.resolve();
|
1062
|
+
}
|
1063
|
+
|
1064
|
+
const configKey = getFilterConfigKey.call(this);
|
1065
|
+
|
1066
|
+
return new Promise((resolve, reject) => {
|
1067
|
+
host
|
1068
|
+
.getConfig(configKey)
|
1069
|
+
.then((config) => {
|
1070
|
+
if (config && isObject(config)) {
|
1071
|
+
this[settingsSymbol].setOptions(config);
|
1072
|
+
}
|
1073
|
+
resolve();
|
1074
|
+
})
|
1075
|
+
.catch((error) => {
|
1076
|
+
if (error === undefined) {
|
1077
|
+
resolve();
|
1078
|
+
return;
|
1079
|
+
}
|
1080
|
+
|
1081
|
+
// config not written
|
1082
|
+
if (error?.message?.match(/is not defined/)) {
|
1083
|
+
resolve();
|
1084
|
+
return;
|
1085
|
+
}
|
1086
|
+
|
1087
|
+
addAttributeToken(
|
1088
|
+
this,
|
1089
|
+
ATTRIBUTE_ERRORMESSAGE,
|
1090
|
+
error?.message || error,
|
1091
|
+
);
|
1092
|
+
reject(error);
|
1093
|
+
});
|
1094
|
+
});
|
1035
1095
|
}
|
1036
1096
|
|
1037
1097
|
/**
|
1038
1098
|
* @private
|
1039
1099
|
*/
|
1040
1100
|
function updateConfig() {
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1101
|
+
const document = getDocument();
|
1102
|
+
const host = document.querySelector("monster-host");
|
1103
|
+
if (!(host && this.id)) {
|
1104
|
+
return;
|
1105
|
+
}
|
1106
|
+
const configKey = getFilterConfigKey.call(this);
|
1107
|
+
|
1108
|
+
try {
|
1109
|
+
host.setConfig(configKey, this[settingsSymbol].getOptions());
|
1110
|
+
} catch (error) {
|
1111
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error?.message || error);
|
1112
|
+
}
|
1053
1113
|
}
|
1054
1114
|
|
1055
1115
|
/**
|
@@ -1057,9 +1117,8 @@ function updateConfig() {
|
|
1057
1117
|
* @return {string}
|
1058
1118
|
*/
|
1059
1119
|
function getTemplate() {
|
1060
|
-
|
1061
|
-
|
1062
|
-
return `
|
1120
|
+
// language=HTML
|
1121
|
+
return `
|
1063
1122
|
<div data-monster-role="control" part="control">
|
1064
1123
|
<div data-monster-role="layout">
|
1065
1124
|
<div data-monster-role="filter">
|