@schukai/monster 3.86.5 → 3.87.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/datatable.mjs +916 -778
- package/source/components/datatable/style/datatable.pcss +20 -0
- package/source/components/datatable/style/embedded-pagination.pcss +0 -2
- package/source/components/datatable/stylesheet/column-bar.mjs +6 -13
- package/source/components/datatable/stylesheet/datatable.mjs +7 -14
- package/source/components/datatable/stylesheet/embedded-pagination.mjs +7 -14
- package/source/components/form/style/select.pcss +1 -1
- package/source/components/form/stylesheet/select.mjs +7 -14
|
@@ -12,75 +12,75 @@
|
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import {Datasource} from "./datasource.mjs";
|
|
16
16
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
assembleMethodSymbol,
|
|
18
|
+
CustomElement,
|
|
19
|
+
registerCustomElement,
|
|
20
|
+
getSlottedElements,
|
|
21
21
|
} from "../../dom/customelement.mjs";
|
|
22
22
|
import {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
findTargetElementFromEvent,
|
|
24
|
+
fireCustomEvent,
|
|
25
25
|
} from "../../dom/events.mjs";
|
|
26
|
-
import {
|
|
26
|
+
import {clone} from "../../util/clone.mjs";
|
|
27
27
|
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
isString,
|
|
29
|
+
isFunction,
|
|
30
|
+
isInstance,
|
|
31
|
+
isObject,
|
|
32
|
+
isArray,
|
|
33
33
|
} from "../../types/is.mjs";
|
|
34
34
|
import {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
validateArray,
|
|
36
|
+
validateInteger,
|
|
37
|
+
validateObject,
|
|
38
38
|
} from "../../types/validate.mjs";
|
|
39
|
-
import {
|
|
39
|
+
import {Observer} from "../../types/observer.mjs";
|
|
40
40
|
import {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
ATTRIBUTE_DATATABLE_HEAD,
|
|
42
|
+
ATTRIBUTE_DATATABLE_GRID_TEMPLATE,
|
|
43
|
+
ATTRIBUTE_DATASOURCE_SELECTOR,
|
|
44
|
+
ATTRIBUTE_DATATABLE_ALIGN,
|
|
45
|
+
ATTRIBUTE_DATATABLE_SORTABLE,
|
|
46
|
+
ATTRIBUTE_DATATABLE_MODE,
|
|
47
|
+
ATTRIBUTE_DATATABLE_INDEX,
|
|
48
|
+
ATTRIBUTE_DATATABLE_MODE_HIDDEN,
|
|
49
|
+
ATTRIBUTE_DATATABLE_MODE_VISIBLE,
|
|
50
|
+
ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
|
|
51
|
+
ATTRIBUTE_DATATABLE_MODE_FIXED,
|
|
52
52
|
} from "./constants.mjs";
|
|
53
|
-
import {
|
|
53
|
+
import {instanceSymbol} from "../../constants.mjs";
|
|
54
54
|
import {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
Header,
|
|
56
|
+
createOrderStatement,
|
|
57
|
+
DIRECTION_ASC,
|
|
58
|
+
DIRECTION_DESC,
|
|
59
|
+
DIRECTION_NONE,
|
|
60
60
|
} from "./datatable/header.mjs";
|
|
61
|
-
import {
|
|
61
|
+
import {DatatableStyleSheet} from "./stylesheet/datatable.mjs";
|
|
62
62
|
import {
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
handleDataSourceChanges,
|
|
64
|
+
datasourceLinkedElementSymbol,
|
|
65
65
|
} from "./util.mjs";
|
|
66
66
|
import "./columnbar.mjs";
|
|
67
67
|
import "./filter-button.mjs";
|
|
68
68
|
import {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
findElementWithSelectorUpwards,
|
|
70
|
+
getDocument,
|
|
71
|
+
getWindow,
|
|
72
72
|
} from "../../dom/util.mjs";
|
|
73
|
-
import {
|
|
74
|
-
import {
|
|
75
|
-
import {
|
|
73
|
+
import {addAttributeToken} from "../../dom/attributes.mjs";
|
|
74
|
+
import {ATTRIBUTE_ERRORMESSAGE} from "../../dom/constants.mjs";
|
|
75
|
+
import {getDocumentTranslations} from "../../i18n/translations.mjs";
|
|
76
76
|
import "../state/state.mjs";
|
|
77
77
|
import "../host/collapse.mjs";
|
|
78
|
-
import {
|
|
78
|
+
import {generateUniqueConfigKey} from "../host/util.mjs";
|
|
79
79
|
|
|
80
80
|
import "./datasource/dom.mjs";
|
|
81
81
|
import "./datasource/rest.mjs";
|
|
82
82
|
|
|
83
|
-
export {
|
|
83
|
+
export {DataTable};
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
86
|
* @private
|
|
@@ -106,6 +106,12 @@ const gridHeadersElementSymbol = Symbol("gridHeadersElement");
|
|
|
106
106
|
*/
|
|
107
107
|
const columnBarElementSymbol = Symbol("columnBarElement");
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* @private
|
|
111
|
+
* @type {symbol}
|
|
112
|
+
*/
|
|
113
|
+
const copyAllElementSymbol = Symbol("copyAllElement");
|
|
114
|
+
|
|
109
115
|
/**
|
|
110
116
|
* @private
|
|
111
117
|
* @type {symbol}
|
|
@@ -142,387 +148,398 @@ const resizeObserverSymbol = Symbol("resizeObserver");
|
|
|
142
148
|
* @fires monster-datatable-row-added
|
|
143
149
|
**/
|
|
144
150
|
class DataTable extends CustomElement {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
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
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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
|
-
|
|
151
|
+
/**
|
|
152
|
+
* This method is called by the `instanceof` operator.
|
|
153
|
+
* @return {symbol}
|
|
154
|
+
*/
|
|
155
|
+
static get [instanceSymbol]() {
|
|
156
|
+
return Symbol.for("@schukai/monster/components/datatable@@instance");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* To set the options via the HTML tag, the attribute `data-monster-options` must be used.
|
|
161
|
+
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
|
162
|
+
*
|
|
163
|
+
* The individual configuration values can be found in the table.
|
|
164
|
+
*
|
|
165
|
+
* @property {Object} templates Template definitions
|
|
166
|
+
* @property {string} templates.main Main template
|
|
167
|
+
* @property {Object} datasource Datasource configuration
|
|
168
|
+
* @property {string} datasource.selector Selector for the datasource
|
|
169
|
+
* @property {Object} mapping Mapping configuration
|
|
170
|
+
* @property {string} mapping.data Data mapping
|
|
171
|
+
* @property {Array} data Data
|
|
172
|
+
* @property {Array} headers Headers
|
|
173
|
+
* @property {Object} responsive Responsive configuration
|
|
174
|
+
* @property {number} responsive.breakpoint Breakpoint for responsive mode
|
|
175
|
+
* @property {Object} labels Labels
|
|
176
|
+
* @property {string} labels.theListContainsNoEntries Label for empty state
|
|
177
|
+
* @property {Object} classes Classes
|
|
178
|
+
* @property {string} classes.container Container class
|
|
179
|
+
* @property {Object} features Features
|
|
180
|
+
* @property {boolean} features.settings Settings feature
|
|
181
|
+
* @property {boolean} features.footer Footer feature
|
|
182
|
+
* @property {boolean} features.autoInit Auto init feature (init datasource automatically)
|
|
183
|
+
* @property {boolean} features.doubleClickCopyToClipboard Double click copy to clipboard feature
|
|
184
|
+
* @property {Object} templateMapping Template mapping
|
|
185
|
+
* @property {string} templateMapping.row-key Row key
|
|
186
|
+
* @property {string} templateMapping.filter-id Filter id
|
|
187
|
+
**/
|
|
188
|
+
get defaults() {
|
|
189
|
+
return Object.assign(
|
|
190
|
+
{},
|
|
191
|
+
super.defaults,
|
|
192
|
+
{
|
|
193
|
+
templates: {
|
|
194
|
+
main: getTemplate(),
|
|
195
|
+
emptyState: getEmptyTemplate(),
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
datasource: {
|
|
199
|
+
selector: null,
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
mapping: {
|
|
203
|
+
data: "dataset",
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
data: [],
|
|
207
|
+
headers: [],
|
|
208
|
+
|
|
209
|
+
responsive: {
|
|
210
|
+
breakpoint: 900,
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
labels: {
|
|
214
|
+
theListContainsNoEntries: "The list contains no entries",
|
|
215
|
+
copyAll: "Copy all",
|
|
216
|
+
},
|
|
217
|
+
|
|
218
|
+
classes: {
|
|
219
|
+
control: "monster-theme-control-container-1",
|
|
220
|
+
container: "",
|
|
221
|
+
row: "monster-theme-control-row-1",
|
|
222
|
+
},
|
|
223
|
+
|
|
224
|
+
features: {
|
|
225
|
+
settings: true,
|
|
226
|
+
footer: true,
|
|
227
|
+
autoInit: true,
|
|
228
|
+
doubleClickCopyToClipboard: true,
|
|
229
|
+
copyAll: true,
|
|
230
|
+
},
|
|
231
|
+
|
|
232
|
+
copy: {
|
|
233
|
+
delimiter: ";",
|
|
234
|
+
quoteOpen: '"',
|
|
235
|
+
quoteClose: '"',
|
|
236
|
+
rowBreak: "\n",
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
templateMapping: {
|
|
240
|
+
"row-key": null,
|
|
241
|
+
"filter-id": null,
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
initOptionsFromArguments.call(this),
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
*
|
|
250
|
+
* @param {string} selector
|
|
251
|
+
* @return {NodeListOf<*>}
|
|
252
|
+
*/
|
|
253
|
+
getGridElements(selector) {
|
|
254
|
+
return this[gridElementSymbol].querySelectorAll(selector);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
*
|
|
259
|
+
* @return {string}
|
|
260
|
+
*/
|
|
261
|
+
static getTag() {
|
|
262
|
+
return "monster-datatable";
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @return {void}
|
|
267
|
+
*/
|
|
268
|
+
disconnectedCallback() {
|
|
269
|
+
super.disconnectedCallback();
|
|
270
|
+
if (this?.[resizeObserverSymbol] instanceof ResizeObserver) {
|
|
271
|
+
this[resizeObserverSymbol].disconnect();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* @return {void}
|
|
277
|
+
*/
|
|
278
|
+
connectedCallback() {
|
|
279
|
+
const self = this;
|
|
280
|
+
super.connectedCallback();
|
|
281
|
+
|
|
282
|
+
this[resizeObserverSymbol] = new ResizeObserver((entries) => {
|
|
283
|
+
updateGrid.call(self);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
this[resizeObserverSymbol].observe(this.parentNode);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* @return void
|
|
291
|
+
*/
|
|
292
|
+
[assembleMethodSymbol]() {
|
|
293
|
+
const rawKey = this.getOption("templateMapping.row-key");
|
|
294
|
+
|
|
295
|
+
if (rawKey === null) {
|
|
296
|
+
if (this.id !== null && this.id !== "") {
|
|
297
|
+
const rawKey = this.getOption("templateMapping.row-key");
|
|
298
|
+
if (rawKey === null) {
|
|
299
|
+
this.setOption("templateMapping.row-key", this.id + "-row");
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
this.setOption("templateMapping.row-key", "row");
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (this.id !== null && this.id !== "") {
|
|
307
|
+
this.setOption("templateMapping.filter-id", "" + this.id + "-filter");
|
|
308
|
+
} else {
|
|
309
|
+
this.setOption("templateMapping.filter-id", "filter");
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
super[assembleMethodSymbol]();
|
|
313
|
+
|
|
314
|
+
initControlReferences.call(this);
|
|
315
|
+
initEventHandler.call(this);
|
|
316
|
+
|
|
317
|
+
const selector = this.getOption("datasource.selector");
|
|
318
|
+
|
|
319
|
+
if (isString(selector)) {
|
|
320
|
+
const element = findElementWithSelectorUpwards(this, selector);
|
|
321
|
+
if (element === null) {
|
|
322
|
+
throw new Error("the selector must match exactly one element");
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (!isInstance(element, Datasource)) {
|
|
326
|
+
throw new TypeError("the element must be a datasource");
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
this[datasourceLinkedElementSymbol] = element;
|
|
330
|
+
|
|
331
|
+
queueMicrotask(() => {
|
|
332
|
+
handleDataSourceChanges.call(this);
|
|
333
|
+
element.datasource.attachObserver(
|
|
334
|
+
new Observer(handleDataSourceChanges.bind(this)),
|
|
335
|
+
);
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
getHostConfig
|
|
340
|
+
.call(this, getColumnVisibilityConfigKey)
|
|
341
|
+
.then((config) => {
|
|
342
|
+
const headerOrderMap = new Map();
|
|
343
|
+
|
|
344
|
+
getHostConfig
|
|
345
|
+
.call(this, getStoredOrderConfigKey)
|
|
346
|
+
.then((orderConfig) => {
|
|
347
|
+
if (isArray(orderConfig) || orderConfig.length > 0) {
|
|
348
|
+
for (let i = 0; i < orderConfig.length; i++) {
|
|
349
|
+
const item = orderConfig[i];
|
|
350
|
+
const parts = item.split(" ");
|
|
351
|
+
const field = parts[0];
|
|
352
|
+
const direction = parts[1] || DIRECTION_ASC;
|
|
353
|
+
headerOrderMap.set(field, direction);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
})
|
|
357
|
+
.then(() => {
|
|
358
|
+
try {
|
|
359
|
+
initGridAndStructs.call(this, config, headerOrderMap);
|
|
360
|
+
} catch (error) {
|
|
361
|
+
addAttributeToken(
|
|
362
|
+
this,
|
|
363
|
+
ATTRIBUTE_ERRORMESSAGE,
|
|
364
|
+
error?.message || error.toString(),
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
updateColumnBar.call(this);
|
|
369
|
+
})
|
|
370
|
+
.catch((error) => {
|
|
371
|
+
addAttributeToken(
|
|
372
|
+
this,
|
|
373
|
+
ATTRIBUTE_ERRORMESSAGE,
|
|
374
|
+
error?.message || error.toString(),
|
|
375
|
+
);
|
|
376
|
+
});
|
|
377
|
+
})
|
|
378
|
+
.catch((error) => {
|
|
379
|
+
addAttributeToken(
|
|
380
|
+
this,
|
|
381
|
+
ATTRIBUTE_ERRORMESSAGE,
|
|
382
|
+
error?.message || error.toString(),
|
|
383
|
+
);
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* @return {CSSStyleSheet[]}
|
|
389
|
+
*/
|
|
390
|
+
static getCSSStyleSheet() {
|
|
391
|
+
return [DatatableStyleSheet];
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Copy a row from the datatable
|
|
396
|
+
*
|
|
397
|
+
* @param {number|string} fromIndex
|
|
398
|
+
* @param {number|string} toIndex
|
|
399
|
+
* @return {DataTable}
|
|
400
|
+
* @fires monster-datatable-row-copied
|
|
401
|
+
*/
|
|
402
|
+
copyRow(fromIndex, toIndex) {
|
|
403
|
+
const datasource = this[datasourceLinkedElementSymbol];
|
|
404
|
+
if (!datasource) {
|
|
405
|
+
return this;
|
|
406
|
+
}
|
|
407
|
+
let d = datasource.data;
|
|
408
|
+
let c = clone(d);
|
|
409
|
+
|
|
410
|
+
let rows = c;
|
|
411
|
+
const mapping = this.getOption("mapping.data");
|
|
412
|
+
|
|
413
|
+
if (mapping) {
|
|
414
|
+
rows = c?.[mapping];
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (rows === undefined || rows === null) {
|
|
418
|
+
rows = [];
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (toIndex === undefined) {
|
|
422
|
+
toIndex = rows.length;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (isString(fromIndex)) {
|
|
426
|
+
fromIndex = parseInt(fromIndex);
|
|
427
|
+
}
|
|
428
|
+
if (isString(toIndex)) {
|
|
429
|
+
toIndex = parseInt(toIndex);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (toIndex < 0 || toIndex > rows.length) {
|
|
433
|
+
throw new RangeError("index out of bounds");
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
validateArray(rows);
|
|
437
|
+
validateInteger(fromIndex);
|
|
438
|
+
validateInteger(toIndex);
|
|
439
|
+
|
|
440
|
+
if (fromIndex < 0 || fromIndex >= rows.length) {
|
|
441
|
+
throw new RangeError("index out of bounds");
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
rows.splice(toIndex, 0, clone(rows[fromIndex]));
|
|
445
|
+
datasource.data = c;
|
|
446
|
+
|
|
447
|
+
fireCustomEvent(this, "monster-datatable-row-copied", {
|
|
448
|
+
index: toIndex,
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
return this;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Remove a row from the datatable
|
|
456
|
+
*
|
|
457
|
+
* @param {number|string} index
|
|
458
|
+
* @return {DataTable}
|
|
459
|
+
* @fires monster-datatable-row-removed
|
|
460
|
+
*/
|
|
461
|
+
removeRow(index) {
|
|
462
|
+
const datasource = this[datasourceLinkedElementSymbol];
|
|
463
|
+
if (!datasource) {
|
|
464
|
+
return this;
|
|
465
|
+
}
|
|
466
|
+
let d = datasource.data;
|
|
467
|
+
let c = clone(d);
|
|
468
|
+
|
|
469
|
+
let rows = c;
|
|
470
|
+
const mapping = this.getOption("mapping.data");
|
|
471
|
+
|
|
472
|
+
if (mapping) {
|
|
473
|
+
rows = c?.[mapping];
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (rows === undefined || rows === null) {
|
|
477
|
+
rows = [];
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (isString(index)) {
|
|
481
|
+
index = parseInt(index);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
validateArray(rows);
|
|
485
|
+
validateInteger(index);
|
|
486
|
+
|
|
487
|
+
if (index < 0 || index >= rows.length) {
|
|
488
|
+
throw new RangeError("index out of bounds");
|
|
489
|
+
}
|
|
490
|
+
if (mapping) {
|
|
491
|
+
rows = c?.[mapping];
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
rows.splice(index, 1);
|
|
495
|
+
datasource.data = c;
|
|
496
|
+
|
|
497
|
+
fireCustomEvent(this, "monster-datatable-row-removed", {
|
|
498
|
+
index: index,
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
return this;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Add a row to the datatable
|
|
506
|
+
*
|
|
507
|
+
* @param {Object} data
|
|
508
|
+
* @return {DataTable}
|
|
509
|
+
*
|
|
510
|
+
* @fires monster-datatable-row-added
|
|
511
|
+
**/
|
|
512
|
+
addRow(data) {
|
|
513
|
+
const datasource = this[datasourceLinkedElementSymbol];
|
|
514
|
+
if (!datasource) {
|
|
515
|
+
return this;
|
|
516
|
+
}
|
|
517
|
+
let d = datasource.data;
|
|
518
|
+
let c = clone(d);
|
|
519
|
+
|
|
520
|
+
let rows = c;
|
|
521
|
+
|
|
522
|
+
const mapping = this.getOption("mapping.data");
|
|
523
|
+
if (mapping) {
|
|
524
|
+
rows = c?.[mapping];
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (rows === undefined || rows === null) {
|
|
528
|
+
rows = [];
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
validateArray(rows);
|
|
532
|
+
validateObject(data);
|
|
533
|
+
|
|
534
|
+
rows.push(data);
|
|
535
|
+
datasource.data = c;
|
|
536
|
+
|
|
537
|
+
fireCustomEvent(this, "monster-datatable-row-added", {
|
|
538
|
+
index: rows.length - 1,
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
return this;
|
|
542
|
+
}
|
|
526
543
|
}
|
|
527
544
|
|
|
528
545
|
/**
|
|
@@ -530,7 +547,7 @@ class DataTable extends CustomElement {
|
|
|
530
547
|
* @return {string}
|
|
531
548
|
*/
|
|
532
549
|
function getColumnVisibilityConfigKey() {
|
|
533
|
-
|
|
550
|
+
return generateUniqueConfigKey("datatable", this?.id, "columns-visibility");
|
|
534
551
|
}
|
|
535
552
|
|
|
536
553
|
/**
|
|
@@ -538,7 +555,7 @@ function getColumnVisibilityConfigKey() {
|
|
|
538
555
|
* @return {string}
|
|
539
556
|
*/
|
|
540
557
|
function getFilterConfigKey() {
|
|
541
|
-
|
|
558
|
+
return generateUniqueConfigKey("datatable", this?.id, "filter");
|
|
542
559
|
}
|
|
543
560
|
|
|
544
561
|
/**
|
|
@@ -546,287 +563,403 @@ function getFilterConfigKey() {
|
|
|
546
563
|
* @return {Promise}
|
|
547
564
|
*/
|
|
548
565
|
function getHostConfig(callback) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
566
|
+
const host = findElementWithSelectorUpwards(this, "monster-host");
|
|
567
|
+
|
|
568
|
+
if (!(host && this.id)) {
|
|
569
|
+
return Promise.resolve({});
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
if (!host || !isFunction(host?.getConfig)) {
|
|
573
|
+
throw new TypeError("the host must be a monster-host");
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
const configKey = callback.call(this);
|
|
577
|
+
return host.hasConfig(configKey).then((hasConfig) => {
|
|
578
|
+
if (hasConfig) {
|
|
579
|
+
return host.getConfig(configKey);
|
|
580
|
+
} else {
|
|
581
|
+
return {};
|
|
582
|
+
}
|
|
583
|
+
});
|
|
567
584
|
}
|
|
568
585
|
|
|
569
586
|
/**
|
|
570
587
|
* @private
|
|
571
588
|
*/
|
|
572
589
|
function updateColumnBar() {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
590
|
+
if (!this[columnBarElementSymbol]) {
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
const columns = [];
|
|
595
|
+
for (const header of this.getOption("headers")) {
|
|
596
|
+
const mode = header.getInternal("mode");
|
|
597
|
+
|
|
598
|
+
if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
columns.push({
|
|
603
|
+
visible: mode !== ATTRIBUTE_DATATABLE_MODE_HIDDEN,
|
|
604
|
+
name: header.label,
|
|
605
|
+
index: header.index,
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
this[columnBarElementSymbol].setOption("columns", columns);
|
|
593
610
|
}
|
|
594
611
|
|
|
595
612
|
/**
|
|
596
613
|
* @private
|
|
597
614
|
*/
|
|
598
615
|
function updateHeaderFromColumnBar() {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
616
|
+
if (!this[columnBarElementSymbol]) {
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
602
619
|
|
|
603
|
-
|
|
604
|
-
|
|
620
|
+
const options = this[columnBarElementSymbol].getOption("columns");
|
|
621
|
+
if (!isArray(options)) return;
|
|
605
622
|
|
|
606
|
-
|
|
623
|
+
const invisibleMap = {};
|
|
607
624
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
625
|
+
for (let i = 0; i < options.length; i++) {
|
|
626
|
+
const option = options[i];
|
|
627
|
+
invisibleMap[option.index] = option.visible;
|
|
628
|
+
}
|
|
612
629
|
|
|
613
|
-
|
|
614
|
-
|
|
630
|
+
for (const header of this.getOption("headers")) {
|
|
631
|
+
const mode = header.getInternal("mode");
|
|
615
632
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
633
|
+
if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
619
636
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
637
|
+
if (invisibleMap[header.index] === false) {
|
|
638
|
+
header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_HIDDEN);
|
|
639
|
+
} else {
|
|
640
|
+
header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_VISIBLE);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
626
643
|
}
|
|
627
644
|
|
|
628
645
|
/**
|
|
629
646
|
* @private
|
|
630
647
|
*/
|
|
631
648
|
function updateConfigColumnBar() {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
649
|
+
if (!this[columnBarElementSymbol]) {
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
const options = this[columnBarElementSymbol].getOption("columns");
|
|
654
|
+
if (!isArray(options)) return;
|
|
655
|
+
|
|
656
|
+
const map = {};
|
|
657
|
+
for (let i = 0; i < options.length; i++) {
|
|
658
|
+
const option = options[i];
|
|
659
|
+
map[option.name] = option.visible;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
const host = findElementWithSelectorUpwards(this, "monster-host");
|
|
663
|
+
if (!(host && this.id)) {
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
const configKey = getColumnVisibilityConfigKey.call(this);
|
|
667
|
+
|
|
668
|
+
try {
|
|
669
|
+
host.setConfig(configKey, map);
|
|
670
|
+
} catch (error) {
|
|
671
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
|
|
672
|
+
}
|
|
656
673
|
}
|
|
657
674
|
|
|
658
675
|
/**
|
|
659
676
|
* @private
|
|
660
677
|
*/
|
|
661
678
|
function initEventHandler() {
|
|
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
|
-
|
|
679
|
+
const self = this;
|
|
680
|
+
|
|
681
|
+
const quoteOpenChar = this.getOption("copy.quoteOpen");
|
|
682
|
+
const quoteCloseChar = this.getOption("copy.quoteClose");
|
|
683
|
+
const delimiterChar = this.getOption("copy.delimiter");
|
|
684
|
+
const rowBreak = this.getOption("copy.rowBreak");
|
|
685
|
+
|
|
686
|
+
self[columnBarElementSymbol].attachObserver(
|
|
687
|
+
new Observer((e) => {
|
|
688
|
+
updateHeaderFromColumnBar.call(self);
|
|
689
|
+
updateGrid.call(self);
|
|
690
|
+
updateConfigColumnBar.call(self);
|
|
691
|
+
}),
|
|
692
|
+
);
|
|
693
|
+
|
|
694
|
+
self[gridHeadersElementSymbol].addEventListener("click", function (event) {
|
|
695
|
+
let element = null;
|
|
696
|
+
const datasource = self[datasourceLinkedElementSymbol];
|
|
697
|
+
if (!datasource) {
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
element = findTargetElementFromEvent(event, ATTRIBUTE_DATATABLE_SORTABLE);
|
|
702
|
+
if (element) {
|
|
703
|
+
const index = element.parentNode.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
|
|
704
|
+
const headers = self.getOption("headers");
|
|
705
|
+
|
|
706
|
+
event.preventDefault();
|
|
707
|
+
|
|
708
|
+
headers[index].changeDirection();
|
|
709
|
+
|
|
710
|
+
queueMicrotask(function () {
|
|
711
|
+
/** hotfix, normally this should be done via the updater, no idea why this is not possible. */
|
|
712
|
+
element.setAttribute(
|
|
713
|
+
ATTRIBUTE_DATATABLE_SORTABLE,
|
|
714
|
+
`${headers[index].field} ${headers[index].direction}`,
|
|
715
|
+
);
|
|
716
|
+
|
|
717
|
+
storeOrderStatement.call(self, true);
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
const eventHandlerDoubleClickCopyToClipboard = (event) => {
|
|
724
|
+
const element = findTargetElementFromEvent(event, "data-monster-head");
|
|
725
|
+
if (element) {
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
let text = "";
|
|
729
|
+
|
|
730
|
+
if (event.shiftKey) {
|
|
731
|
+
const index = element.getAttribute("data-monster-insert-reference");
|
|
732
|
+
if (index) {
|
|
733
|
+
const cols = self.getGridElements(`[data-monster-insert-reference="${index}"]`);
|
|
734
|
+
|
|
735
|
+
const colTexts = []
|
|
736
|
+
for (let i = 0; i < cols.length; i++) {
|
|
737
|
+
const col = cols[i];
|
|
738
|
+
|
|
739
|
+
if (col.querySelector("monster-button-bar") || col.querySelector("monster-button")) {
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
if (col.textContent) {
|
|
744
|
+
colTexts.push(quoteOpenChar+col.textContent.trim()+quoteCloseChar);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
text = colTexts.join(delimiterChar);
|
|
749
|
+
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
} else {
|
|
754
|
+
if (element.querySelector("monster-button-bar") || element.querySelector("monster-button")) {
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
text = element.textContent.trim();
|
|
759
|
+
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
if (getWindow().navigator.clipboard && text) {
|
|
763
|
+
getWindow().navigator.clipboard.writeText(text).then(
|
|
764
|
+
() => {
|
|
765
|
+
},
|
|
766
|
+
(err) => {
|
|
767
|
+
}
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
if (self.getOption("features.doubleClickCopyToClipboard")) {
|
|
774
|
+
self[gridElementSymbol].addEventListener("dblclick", eventHandlerDoubleClickCopyToClipboard);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
if (self.getOption("features.copyAll") && this[copyAllElementSymbol]) {
|
|
778
|
+
this[copyAllElementSymbol].addEventListener("click", (event) => {
|
|
779
|
+
event.preventDefault();
|
|
780
|
+
|
|
781
|
+
const table = [];
|
|
782
|
+
let currentRow = [];
|
|
783
|
+
let currentIndex= null;
|
|
784
|
+
|
|
785
|
+
const cols = self.getGridElements(`[data-monster-insert-reference]`);
|
|
786
|
+
const rowIndexes = new Map();
|
|
787
|
+
cols.forEach((col) => {
|
|
788
|
+
const index = col.getAttribute("data-monster-insert-reference");
|
|
789
|
+
rowIndexes.set(index, true);
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
rowIndexes.forEach((value, key) => {
|
|
793
|
+
const cols = self.getGridElements(`[data-monster-insert-reference="${key}"]`);
|
|
794
|
+
|
|
795
|
+
for (let i = 0; i < cols.length; i++) {
|
|
796
|
+
const col = cols[i];
|
|
797
|
+
|
|
798
|
+
if (col.querySelector("monster-button-bar") || col.querySelector("monster-button")) {
|
|
799
|
+
continue;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
if (col.textContent) {
|
|
803
|
+
currentRow.push(quoteOpenChar+col.textContent.trim()+quoteCloseChar);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
if(currentRow.length > 0) {
|
|
808
|
+
table.push(currentRow);
|
|
809
|
+
}
|
|
810
|
+
currentRow = [];
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
if(table.length > 0) {
|
|
814
|
+
const text = table.map(row => row.join(delimiterChar)).join(rowBreak);
|
|
815
|
+
if (getWindow().navigator.clipboard && text) {
|
|
816
|
+
getWindow().navigator.clipboard.writeText(text).then(
|
|
817
|
+
() => {
|
|
818
|
+
},
|
|
819
|
+
(err) => {
|
|
820
|
+
}
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
|
|
699
832
|
}
|
|
700
833
|
|
|
701
834
|
/**
|
|
702
835
|
* @private
|
|
703
836
|
*/
|
|
704
837
|
function initGridAndStructs(hostConfig, headerOrderMap) {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
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
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
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
|
-
|
|
829
|
-
|
|
838
|
+
const rowID = this.getOption("templateMapping.row-key");
|
|
839
|
+
|
|
840
|
+
if (!this[gridElementSymbol]) {
|
|
841
|
+
throw new Error("no grid element is defined");
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
let template;
|
|
845
|
+
getSlottedElements.call(this).forEach((e) => {
|
|
846
|
+
if (e instanceof HTMLTemplateElement && e.id === rowID) {
|
|
847
|
+
template = e;
|
|
848
|
+
}
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
if (!template) {
|
|
852
|
+
throw new Error("no template is defined");
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
const rowCount = template.content.children.length;
|
|
856
|
+
|
|
857
|
+
const headers = [];
|
|
858
|
+
|
|
859
|
+
for (let i = 0; i < rowCount; i++) {
|
|
860
|
+
let hClass = "";
|
|
861
|
+
const row = template.content.children[i];
|
|
862
|
+
|
|
863
|
+
let mode = "";
|
|
864
|
+
if (row.hasAttribute(ATTRIBUTE_DATATABLE_MODE)) {
|
|
865
|
+
mode = row.getAttribute(ATTRIBUTE_DATATABLE_MODE);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
let grid = row.getAttribute(ATTRIBUTE_DATATABLE_GRID_TEMPLATE);
|
|
869
|
+
if (!grid || grid === "" || grid === "auto") {
|
|
870
|
+
grid = "minmax(0, 1fr)";
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
let label = "";
|
|
874
|
+
let labelKey = "";
|
|
875
|
+
|
|
876
|
+
if (row.hasAttribute(ATTRIBUTE_DATATABLE_HEAD)) {
|
|
877
|
+
label = row.getAttribute(ATTRIBUTE_DATATABLE_HEAD);
|
|
878
|
+
labelKey = label;
|
|
879
|
+
|
|
880
|
+
try {
|
|
881
|
+
if (label.startsWith("i18n:")) {
|
|
882
|
+
label = label.substring(5, label.length);
|
|
883
|
+
label = getDocumentTranslations().getText(label, label);
|
|
884
|
+
}
|
|
885
|
+
} catch (e) {
|
|
886
|
+
label = "i18n error " + label;
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if (!label) {
|
|
891
|
+
label = i + 1 + "";
|
|
892
|
+
mode = ATTRIBUTE_DATATABLE_MODE_FIXED;
|
|
893
|
+
labelKey = label;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
if (isObject(hostConfig) && hostConfig.hasOwnProperty(label)) {
|
|
897
|
+
if (hostConfig[label] === false) {
|
|
898
|
+
mode = ATTRIBUTE_DATATABLE_MODE_HIDDEN;
|
|
899
|
+
} else {
|
|
900
|
+
mode = ATTRIBUTE_DATATABLE_MODE_VISIBLE;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
let align = "";
|
|
905
|
+
if (row.hasAttribute(ATTRIBUTE_DATATABLE_ALIGN)) {
|
|
906
|
+
align = row.getAttribute(ATTRIBUTE_DATATABLE_ALIGN);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
switch (align) {
|
|
910
|
+
case "center":
|
|
911
|
+
hClass = "flex-center";
|
|
912
|
+
break;
|
|
913
|
+
case "end":
|
|
914
|
+
hClass = "flex-end";
|
|
915
|
+
break;
|
|
916
|
+
case "start":
|
|
917
|
+
hClass = "flex-start";
|
|
918
|
+
break;
|
|
919
|
+
default:
|
|
920
|
+
hClass = "flex-start";
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
let field = "";
|
|
924
|
+
let direction = DIRECTION_NONE;
|
|
925
|
+
if (row.hasAttribute(ATTRIBUTE_DATATABLE_SORTABLE)) {
|
|
926
|
+
field = row.getAttribute(ATTRIBUTE_DATATABLE_SORTABLE).trim();
|
|
927
|
+
const parts = field.split(" ").map((item) => item.trim());
|
|
928
|
+
field = parts[0];
|
|
929
|
+
|
|
930
|
+
if (headerOrderMap.has(field)) {
|
|
931
|
+
direction = headerOrderMap.get(field);
|
|
932
|
+
} else if (
|
|
933
|
+
parts.length === 2 &&
|
|
934
|
+
[DIRECTION_ASC, DIRECTION_DESC].indexOf(parts[1]) !== -1
|
|
935
|
+
) {
|
|
936
|
+
direction = parts[1];
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
if (mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN) {
|
|
941
|
+
hClass += " hidden";
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
const header = new Header();
|
|
945
|
+
header.setInternals({
|
|
946
|
+
field: field,
|
|
947
|
+
label: label,
|
|
948
|
+
classes: hClass,
|
|
949
|
+
index: i,
|
|
950
|
+
mode: mode,
|
|
951
|
+
grid: grid,
|
|
952
|
+
labelKey: labelKey,
|
|
953
|
+
direction: direction,
|
|
954
|
+
});
|
|
955
|
+
|
|
956
|
+
headers.push(header);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
this.setOption("headers", headers);
|
|
960
|
+
queueMicrotask(() => {
|
|
961
|
+
storeOrderStatement.call(this, this.getOption("features.autoInit"));
|
|
962
|
+
});
|
|
830
963
|
}
|
|
831
964
|
|
|
832
965
|
/**
|
|
@@ -834,79 +967,79 @@ function initGridAndStructs(hostConfig, headerOrderMap) {
|
|
|
834
967
|
* @return {string}
|
|
835
968
|
*/
|
|
836
969
|
export function getStoredOrderConfigKey() {
|
|
837
|
-
|
|
970
|
+
return generateUniqueConfigKey("datatable", this?.id, "stored-order");
|
|
838
971
|
}
|
|
839
972
|
|
|
840
973
|
/**
|
|
841
974
|
* @private
|
|
842
975
|
*/
|
|
843
976
|
function storeOrderStatement(doFetch) {
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
977
|
+
const headers = this.getOption("headers");
|
|
978
|
+
const statement = createOrderStatement(headers);
|
|
979
|
+
setDataSource.call(this, {orderBy: statement}, doFetch);
|
|
847
980
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
981
|
+
const host = findElementWithSelectorUpwards(this, "monster-host");
|
|
982
|
+
if (!(host && this.id)) {
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
852
985
|
|
|
853
|
-
|
|
986
|
+
const configKey = getStoredOrderConfigKey.call(this);
|
|
854
987
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
988
|
+
// statement explode with , and remove all empty
|
|
989
|
+
const list = statement.split(",").filter((item) => item.trim() !== "");
|
|
990
|
+
if (list.length === 0) {
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
860
993
|
|
|
861
|
-
|
|
994
|
+
host.setConfig(configKey, list);
|
|
862
995
|
}
|
|
863
996
|
|
|
864
997
|
/**
|
|
865
998
|
* @private
|
|
866
999
|
*/
|
|
867
1000
|
function updateGrid() {
|
|
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
|
-
|
|
1001
|
+
if (!this[gridElementSymbol]) {
|
|
1002
|
+
throw new Error("no grid element is defined");
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
let gridTemplateColumns = "";
|
|
1006
|
+
|
|
1007
|
+
const headers = this.getOption("headers");
|
|
1008
|
+
|
|
1009
|
+
let styles = "";
|
|
1010
|
+
|
|
1011
|
+
for (let i = 0; i < headers.length; i++) {
|
|
1012
|
+
const header = headers[i];
|
|
1013
|
+
|
|
1014
|
+
if (header.mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN) {
|
|
1015
|
+
styles += `[data-monster-role=datatable]>[data-monster-head="${header.labelKey}"] { display: none; }\n`;
|
|
1016
|
+
styles += `[data-monster-role=datatable-headers]>[data-monster-index="${header.index}"] { display: none; }\n`;
|
|
1017
|
+
} else {
|
|
1018
|
+
gridTemplateColumns += `${header.grid} `;
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
const sheet = new CSSStyleSheet();
|
|
1023
|
+
if (styles !== "") sheet.replaceSync(styles);
|
|
1024
|
+
this.shadowRoot.adoptedStyleSheets = [...DataTable.getCSSStyleSheet(), sheet];
|
|
1025
|
+
|
|
1026
|
+
const bodyWidth = this.parentNode.clientWidth;
|
|
1027
|
+
|
|
1028
|
+
const breakpoint = this.getOption("responsive.breakpoint");
|
|
1029
|
+
this[dataControlElementSymbol].classList.toggle(
|
|
1030
|
+
"small",
|
|
1031
|
+
bodyWidth <= breakpoint,
|
|
1032
|
+
);
|
|
1033
|
+
|
|
1034
|
+
if (bodyWidth > breakpoint) {
|
|
1035
|
+
this[gridElementSymbol].style.gridTemplateColumns =
|
|
1036
|
+
`${gridTemplateColumns}`;
|
|
1037
|
+
this[gridHeadersElementSymbol].style.gridTemplateColumns =
|
|
1038
|
+
`${gridTemplateColumns}`;
|
|
1039
|
+
} else {
|
|
1040
|
+
this[gridElementSymbol].style.gridTemplateColumns = "auto";
|
|
1041
|
+
this[gridHeadersElementSymbol].style.gridTemplateColumns = "auto";
|
|
1042
|
+
}
|
|
910
1043
|
}
|
|
911
1044
|
|
|
912
1045
|
/**
|
|
@@ -914,20 +1047,20 @@ function updateGrid() {
|
|
|
914
1047
|
* @param {Header[]} headers
|
|
915
1048
|
* @param {bool} doFetch
|
|
916
1049
|
*/
|
|
917
|
-
function setDataSource({
|
|
918
|
-
|
|
1050
|
+
function setDataSource({orderBy}, doFetch) {
|
|
1051
|
+
const datasource = this[datasourceLinkedElementSymbol];
|
|
919
1052
|
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
1053
|
+
if (!datasource) {
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
923
1056
|
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
1057
|
+
if (isFunction(datasource?.setParameters)) {
|
|
1058
|
+
datasource.setParameters({orderBy});
|
|
1059
|
+
}
|
|
927
1060
|
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
1061
|
+
if (doFetch !== false && isFunction(datasource?.fetch)) {
|
|
1062
|
+
datasource.fetch();
|
|
1063
|
+
}
|
|
931
1064
|
}
|
|
932
1065
|
|
|
933
1066
|
/**
|
|
@@ -935,24 +1068,28 @@ function setDataSource({ orderBy }, doFetch) {
|
|
|
935
1068
|
* @return {DataTable}
|
|
936
1069
|
*/
|
|
937
1070
|
function initControlReferences() {
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
1071
|
+
if (!this.shadowRoot) {
|
|
1072
|
+
throw new Error("no shadow-root is defined");
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
this[dataControlElementSymbol] = this.shadowRoot.querySelector(
|
|
1076
|
+
"[data-monster-role=control]",
|
|
1077
|
+
);
|
|
1078
|
+
|
|
1079
|
+
this[gridElementSymbol] = this.shadowRoot.querySelector(
|
|
1080
|
+
"[data-monster-role=datatable]",
|
|
1081
|
+
);
|
|
1082
|
+
this[gridHeadersElementSymbol] = this.shadowRoot.querySelector(
|
|
1083
|
+
"[data-monster-role=datatable-headers]",
|
|
1084
|
+
);
|
|
1085
|
+
this[columnBarElementSymbol] =
|
|
1086
|
+
this.shadowRoot.querySelector("monster-column-bar");
|
|
1087
|
+
|
|
1088
|
+
this[copyAllElementSymbol] = this.shadowRoot.querySelector(
|
|
1089
|
+
"[data-monster-role=copy-all]",
|
|
1090
|
+
);
|
|
1091
|
+
|
|
1092
|
+
return this;
|
|
956
1093
|
}
|
|
957
1094
|
|
|
958
1095
|
/**
|
|
@@ -962,22 +1099,22 @@ function initControlReferences() {
|
|
|
962
1099
|
* @throws {Error} the datasource could not be initialized
|
|
963
1100
|
*/
|
|
964
1101
|
function initOptionsFromArguments() {
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1102
|
+
const options = {};
|
|
1103
|
+
const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
|
|
1104
|
+
|
|
1105
|
+
if (selector) {
|
|
1106
|
+
options.datasource = {selector: selector};
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
const breakpoint = this.getAttribute(
|
|
1110
|
+
ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
|
|
1111
|
+
);
|
|
1112
|
+
if (breakpoint) {
|
|
1113
|
+
options.responsive = {};
|
|
1114
|
+
options.responsive.breakpoint = parseInt(breakpoint);
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
return options;
|
|
981
1118
|
}
|
|
982
1119
|
|
|
983
1120
|
/**
|
|
@@ -985,7 +1122,7 @@ function initOptionsFromArguments() {
|
|
|
985
1122
|
* @return {string}
|
|
986
1123
|
*/
|
|
987
1124
|
function getEmptyTemplate() {
|
|
988
|
-
|
|
1125
|
+
return `<monster-state data-monster-role="empty-without-action">
|
|
989
1126
|
<div part="visual">
|
|
990
1127
|
<svg width="4rem" height="4rem" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
991
1128
|
<path d="m21.5 22h-19c-1.378 0-2.5-1.121-2.5-2.5v-7c0-.07.015-.141.044-.205l3.969-8.82c.404-.896 1.299-1.475 2.28-1.475h11.414c.981 0 1.876.579 2.28 1.475l3.969 8.82c.029.064.044.135.044.205v7c0 1.379-1.122 2.5-2.5 2.5zm-20.5-9.393v6.893c0 .827.673 1.5 1.5 1.5h19c.827 0 1.5-.673 1.5-1.5v-6.893l-3.925-8.723c-.242-.536-.779-.884-1.368-.884h-11.414c-.589 0-1.126.348-1.368.885z"/>
|
|
@@ -1003,8 +1140,8 @@ function getEmptyTemplate() {
|
|
|
1003
1140
|
* @return {string}
|
|
1004
1141
|
*/
|
|
1005
1142
|
function getTemplate() {
|
|
1006
|
-
|
|
1007
|
-
|
|
1143
|
+
// language=HTML
|
|
1144
|
+
return `
|
|
1008
1145
|
<div data-monster-role="control" part="control" data-monster-attributes="class path:classes.control">
|
|
1009
1146
|
<template id="headers-row">
|
|
1010
1147
|
<div data-monster-attributes="class path:headers-row.classes,
|
|
@@ -1018,6 +1155,7 @@ function getTemplate() {
|
|
|
1018
1155
|
<slot name="filter"></slot>
|
|
1019
1156
|
</div>
|
|
1020
1157
|
<div class="bar">
|
|
1158
|
+
<a href="#" data-monster-attributes="class path:features.copyAll | ?::hidden" data-monster-role="copy-all" data-monster-replace="path:locale.copyAll">Copy all</a>
|
|
1021
1159
|
<monster-column-bar
|
|
1022
1160
|
data-monster-attributes="class path:features.settings | ?::hidden"></monster-column-bar>
|
|
1023
1161
|
<slot name="bar"></slot>
|