@schukai/monster 4.43.1 → 4.43.3
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/accessibility/locale-picker.mjs +538 -538
- package/source/components/accessibility/locale-select.mjs +172 -172
- package/source/components/content/viewer.mjs +823 -823
- package/source/components/datatable/constants.mjs +15 -15
- package/source/components/datatable/datatable/header.mjs +253 -253
- package/source/components/datatable/datatable.mjs +1284 -1284
- package/source/components/datatable/filter.mjs +1339 -1342
- package/source/components/datatable/pagination.mjs +502 -502
- package/source/components/datatable/stylesheet/datatable.mjs +13 -6
- package/source/components/form/quantity.mjs +229 -229
- package/source/components/form/select.mjs +2963 -2963
- package/source/components/form/stylesheet/quantity.mjs +13 -6
- package/source/components/form/stylesheet/select.mjs +13 -6
- package/source/components/navigation/site-navigation.mjs +383 -210
- package/source/components/navigation/style/site-navigation.pcss +103 -15
- package/source/components/navigation/stylesheet/site-navigation.mjs +14 -7
- package/source/components/style/typography.css +4 -2
- package/source/dom/customelement.mjs +959 -963
- package/source/dom/slotted.mjs +87 -87
- package/source/i18n/util.mjs +149 -149
- package/source/monster.mjs +3 -0
- package/source/types/is.mjs +64 -64
- package/source/types/typeof.mjs +16 -16
- package/source/types/version.mjs +1 -1
- package/test/cases/monster.mjs +1 -1
- package/test/web/test.html +2 -2
- package/test/web/tests.js +2724 -1287
@@ -14,56 +14,56 @@
|
|
14
14
|
|
15
15
|
import { Datasource } from "./datasource.mjs";
|
16
16
|
import {
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
assembleMethodSymbol,
|
18
|
+
CustomElement,
|
19
|
+
registerCustomElement,
|
20
|
+
getSlottedElements,
|
21
|
+
updaterTransformerMethodsSymbol,
|
22
22
|
} from "../../dom/customelement.mjs";
|
23
23
|
import {
|
24
|
-
|
25
|
-
|
24
|
+
findTargetElementFromEvent,
|
25
|
+
fireCustomEvent,
|
26
26
|
} from "../../dom/events.mjs";
|
27
27
|
import { clone } from "../../util/clone.mjs";
|
28
28
|
import {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
isString,
|
30
|
+
isFunction,
|
31
|
+
isInstance,
|
32
|
+
isObject,
|
33
|
+
isArray,
|
34
34
|
} from "../../types/is.mjs";
|
35
35
|
import {
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
validateArray,
|
37
|
+
validateInteger,
|
38
|
+
validateObject,
|
39
39
|
} from "../../types/validate.mjs";
|
40
40
|
import { Observer } from "../../types/observer.mjs";
|
41
41
|
import {
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
42
|
+
ATTRIBUTE_DATATABLE_HEAD,
|
43
|
+
ATTRIBUTE_DATATABLE_GRID_TEMPLATE,
|
44
|
+
ATTRIBUTE_DATASOURCE_SELECTOR,
|
45
|
+
ATTRIBUTE_DATATABLE_ALIGN,
|
46
|
+
ATTRIBUTE_DATATABLE_SORTABLE,
|
47
|
+
ATTRIBUTE_DATATABLE_MODE,
|
48
|
+
ATTRIBUTE_DATATABLE_INDEX,
|
49
|
+
ATTRIBUTE_DATATABLE_MODE_HIDDEN,
|
50
|
+
ATTRIBUTE_DATATABLE_FEATURES,
|
51
|
+
ATTRIBUTE_DATATABLE_MODE_VISIBLE,
|
52
|
+
ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
|
53
|
+
ATTRIBUTE_DATATABLE_MODE_FIXED,
|
54
54
|
} from "./constants.mjs";
|
55
55
|
import { instanceSymbol } from "../../constants.mjs";
|
56
56
|
import {
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
Header,
|
58
|
+
createOrderStatement,
|
59
|
+
DIRECTION_ASC,
|
60
|
+
DIRECTION_DESC,
|
61
|
+
DIRECTION_NONE,
|
62
62
|
} from "./datatable/header.mjs";
|
63
63
|
import { DatatableStyleSheet } from "./stylesheet/datatable.mjs";
|
64
64
|
import {
|
65
|
-
|
66
|
-
|
65
|
+
handleDataSourceChanges,
|
66
|
+
datasourceLinkedElementSymbol,
|
67
67
|
} from "./util.mjs";
|
68
68
|
import "./columnbar.mjs";
|
69
69
|
import "./filter-button.mjs";
|
@@ -151,470 +151,470 @@ const resizeObserverSymbol = Symbol("resizeObserver");
|
|
151
151
|
* @fires monster-datatable-selection-changed
|
152
152
|
**/
|
153
153
|
class DataTable extends CustomElement {
|
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
|
-
|
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
|
-
|
154
|
+
/**
|
155
|
+
* This method is called by the `instanceof` operator.
|
156
|
+
* @return {symbol}
|
157
|
+
*/
|
158
|
+
static get [instanceSymbol]() {
|
159
|
+
return Symbol.for("@schukai/monster/components/datatable@@instance");
|
160
|
+
}
|
161
|
+
|
162
|
+
/**
|
163
|
+
* To set the options via the HTML tag, the attribute `data-monster-options` must be used.
|
164
|
+
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
165
|
+
*
|
166
|
+
* The individual configuration values can be found in the table.
|
167
|
+
*
|
168
|
+
* @property {Object} templates Template definitions
|
169
|
+
* @property {string} templates.main Main template
|
170
|
+
* @property {Object} datasource Datasource configuration
|
171
|
+
* @property {string} datasource.selector Selector for the datasource
|
172
|
+
* @property {string} datasource.orderDelimiter Order delimiter
|
173
|
+
* @property {Object} mapping Mapping configuration
|
174
|
+
* @property {string} mapping.data Data mapping
|
175
|
+
* @property {Array} data Data
|
176
|
+
* @property {Array} headers Headers
|
177
|
+
* @property {Object} responsive Responsive configuration
|
178
|
+
* @property {number} responsive.breakpoint Breakpoint for responsive mode
|
179
|
+
* @property {Object} labels Labels
|
180
|
+
* @property {string} labels.theListContainsNoEntries Label for empty state
|
181
|
+
* @property {Object} classes Classes
|
182
|
+
* @property {string} classes.container Container class
|
183
|
+
* @property {Object} features Features
|
184
|
+
* @property {boolean} features.settings Settings feature
|
185
|
+
* @property {boolean} features.footer Footer feature
|
186
|
+
* @property {boolean} features.autoInit Auto init feature (init datasource automatically)
|
187
|
+
* @property {boolean} features.doubleClickCopyToClipboard Double click copy to clipboard feature
|
188
|
+
* @property {boolean} features.copyAll Copy all feature
|
189
|
+
* @property {boolean} features.help Help feature
|
190
|
+
* @property {boolean} features.resizeable Columns are resizable
|
191
|
+
* @property {Object} copy Copy configuration
|
192
|
+
* @property {string} copy.delimiter Delimiter character
|
193
|
+
* @property {string} copy.quoteOpen Quote open character
|
194
|
+
* @property {string} copy.quoteClose Quote close character
|
195
|
+
* @property {string} copy.rowBreak Row break character
|
196
|
+
* @property {Object} templateMapping Template mapping
|
197
|
+
* @property {string} templateMapping.row-key Row key
|
198
|
+
* @property {string} templateMapping.filter-id Filter id
|
199
|
+
**/
|
200
|
+
get defaults() {
|
201
|
+
return Object.assign(
|
202
|
+
{},
|
203
|
+
super.defaults,
|
204
|
+
{
|
205
|
+
templates: {
|
206
|
+
main: getTemplate(),
|
207
|
+
emptyState: getEmptyTemplate(),
|
208
|
+
},
|
209
|
+
|
210
|
+
datasource: {
|
211
|
+
selector: null,
|
212
|
+
orderDelimiter: ",", // see initOptionsFromArguments()
|
213
|
+
},
|
214
|
+
|
215
|
+
mapping: {
|
216
|
+
data: "dataset",
|
217
|
+
},
|
218
|
+
|
219
|
+
data: [],
|
220
|
+
headers: [],
|
221
|
+
|
222
|
+
responsive: {
|
223
|
+
breakpoint: 900,
|
224
|
+
},
|
225
|
+
|
226
|
+
labels: getTranslations(),
|
227
|
+
|
228
|
+
classes: {
|
229
|
+
control: "monster-theme-control-container-1",
|
230
|
+
container: "",
|
231
|
+
row: "monster-theme-control-row-1",
|
232
|
+
},
|
233
|
+
|
234
|
+
features: {
|
235
|
+
settings: true,
|
236
|
+
footer: true,
|
237
|
+
autoInit: true,
|
238
|
+
doubleClickCopyToClipboard: true,
|
239
|
+
copyAll: true,
|
240
|
+
help: true,
|
241
|
+
resizable: true,
|
242
|
+
},
|
243
|
+
|
244
|
+
copy: {
|
245
|
+
delimiter: ";",
|
246
|
+
quoteOpen: '"',
|
247
|
+
quoteClose: '"',
|
248
|
+
rowBreak: "\n",
|
249
|
+
},
|
250
|
+
|
251
|
+
templateMapping: {
|
252
|
+
"row-key": null,
|
253
|
+
"filter-id": null,
|
254
|
+
},
|
255
|
+
},
|
256
|
+
initOptionsFromArguments.call(this),
|
257
|
+
);
|
258
|
+
}
|
259
|
+
|
260
|
+
/**
|
261
|
+
*
|
262
|
+
* @param {string} selector
|
263
|
+
* @return {NodeList}
|
264
|
+
*/
|
265
|
+
getGridElements(selector) {
|
266
|
+
return this[gridElementSymbol].querySelectorAll(selector);
|
267
|
+
}
|
268
|
+
|
269
|
+
/**
|
270
|
+
*
|
271
|
+
* @return {string}
|
272
|
+
*/
|
273
|
+
static getTag() {
|
274
|
+
return "monster-datatable";
|
275
|
+
}
|
276
|
+
|
277
|
+
/**
|
278
|
+
* @return {void}
|
279
|
+
*/
|
280
|
+
disconnectedCallback() {
|
281
|
+
super.disconnectedCallback();
|
282
|
+
if (this?.[resizeObserverSymbol] instanceof ResizeObserver) {
|
283
|
+
this[resizeObserverSymbol].disconnect();
|
284
|
+
}
|
285
|
+
}
|
286
|
+
|
287
|
+
/**
|
288
|
+
* @return {void}
|
289
|
+
*/
|
290
|
+
connectedCallback() {
|
291
|
+
const self = this;
|
292
|
+
super.connectedCallback();
|
293
|
+
|
294
|
+
this[resizeObserverSymbol] = new ResizeObserver((entries) => {
|
295
|
+
updateGrid.call(self);
|
296
|
+
});
|
297
|
+
|
298
|
+
requestAnimationFrame(() => {
|
299
|
+
let parent = this.parentNode;
|
300
|
+
while (!(parent instanceof HTMLElement) && parent !== null) {
|
301
|
+
parent = parent.parentNode;
|
302
|
+
}
|
303
|
+
|
304
|
+
if (parent instanceof HTMLElement) {
|
305
|
+
this[resizeObserverSymbol].observe(parent);
|
306
|
+
}
|
307
|
+
});
|
308
|
+
}
|
309
|
+
|
310
|
+
/**
|
311
|
+
* Get the row number of the selected rows as an array
|
312
|
+
*
|
313
|
+
* @returns {number[]}
|
314
|
+
*/
|
315
|
+
getSelectedRows() {
|
316
|
+
const rows = this.getGridElements(`[data-monster-role="select-row"]`);
|
317
|
+
const selectedRows = [];
|
318
|
+
rows.forEach((row) => {
|
319
|
+
if (row.checked) {
|
320
|
+
const key = row.parentNode.getAttribute(
|
321
|
+
"data-monster-insert-reference",
|
322
|
+
);
|
323
|
+
const index = key.split("-").pop();
|
324
|
+
selectedRows.push(parseInt(index, 10));
|
325
|
+
}
|
326
|
+
});
|
327
|
+
|
328
|
+
return selectedRows;
|
329
|
+
}
|
330
|
+
|
331
|
+
/**
|
332
|
+
* @return void
|
333
|
+
*/
|
334
|
+
[assembleMethodSymbol]() {
|
335
|
+
const self = this;
|
336
|
+
const rawKey = this.getOption("templateMapping.row-key");
|
337
|
+
|
338
|
+
if (rawKey === null) {
|
339
|
+
if (this.id !== null && this.id !== "") {
|
340
|
+
const rawKey = this.getOption("templateMapping.row-key");
|
341
|
+
if (rawKey === null) {
|
342
|
+
this.setOption("templateMapping.row-key", this.id + "-row");
|
343
|
+
}
|
344
|
+
} else {
|
345
|
+
this.setOption("templateMapping.row-key", "row");
|
346
|
+
}
|
347
|
+
}
|
348
|
+
|
349
|
+
if (this.id !== null && this.id !== "") {
|
350
|
+
this.setOption("templateMapping.filter-id", "" + this.id + "-filter");
|
351
|
+
} else {
|
352
|
+
this.setOption("templateMapping.filter-id", "filter");
|
353
|
+
}
|
354
|
+
|
355
|
+
super[assembleMethodSymbol]();
|
356
|
+
|
357
|
+
initControlReferences.call(this);
|
358
|
+
initEventHandler.call(this);
|
359
|
+
|
360
|
+
getSlottedElements
|
361
|
+
.call(this, "[data-monster-role=row-action-button]", "bar")
|
362
|
+
.forEach((i, e) => {
|
363
|
+
if (e instanceof HTMLElement) {
|
364
|
+
e.style.visibility = "hidden";
|
365
|
+
e.style.width = "max-content";
|
366
|
+
|
367
|
+
const pN = e.parentNode;
|
368
|
+
if (pN instanceof HTMLElement) {
|
369
|
+
pN.style.flexGrow = "10";
|
370
|
+
pN.style.display = "flex";
|
371
|
+
pN.style.justifyContent = "flex-start";
|
372
|
+
}
|
373
|
+
}
|
374
|
+
});
|
375
|
+
|
376
|
+
getHostConfig
|
377
|
+
.call(this, getColumnVisibilityConfigKey)
|
378
|
+
.then((config) => {
|
379
|
+
const headerOrderMap = new Map();
|
380
|
+
|
381
|
+
getHostConfig
|
382
|
+
.call(this, getStoredOrderConfigKey)
|
383
|
+
.then((orderConfig) => {
|
384
|
+
if (isArray(orderConfig) || orderConfig.length > 0) {
|
385
|
+
for (let i = 0; i < orderConfig.length; i++) {
|
386
|
+
const item = orderConfig[i];
|
387
|
+
const parts = item.split(" ");
|
388
|
+
const field = parts[0];
|
389
|
+
const direction = parts[1] || DIRECTION_ASC;
|
390
|
+
headerOrderMap.set(field, direction);
|
391
|
+
}
|
392
|
+
}
|
393
|
+
})
|
394
|
+
.then(() => {
|
395
|
+
try {
|
396
|
+
initGridAndStructs.call(this, config, headerOrderMap);
|
397
|
+
} catch (error) {
|
398
|
+
addErrorAttribute(this, error);
|
399
|
+
}
|
400
|
+
|
401
|
+
updateColumnBar.call(this);
|
402
|
+
})
|
403
|
+
.catch((error) => {
|
404
|
+
addErrorAttribute(this, error);
|
405
|
+
});
|
406
|
+
})
|
407
|
+
.catch((error) => {
|
408
|
+
addErrorAttribute(this, error);
|
409
|
+
})
|
410
|
+
.finally(() => {
|
411
|
+
const selector = this.getOption("datasource.selector");
|
412
|
+
|
413
|
+
if (isString(selector)) {
|
414
|
+
const element = findElementWithSelectorUpwards(this, selector);
|
415
|
+
if (element === null) {
|
416
|
+
throw new Error("the selector must match exactly one element");
|
417
|
+
}
|
418
|
+
|
419
|
+
if (!isInstance(element, Datasource)) {
|
420
|
+
throw new TypeError("the element must be a datasource");
|
421
|
+
}
|
422
|
+
|
423
|
+
this[datasourceLinkedElementSymbol] = element;
|
424
|
+
|
425
|
+
queueMicrotask(() => {
|
426
|
+
handleDataSourceChanges.call(this);
|
427
|
+
if (element && "datasource" in element) {
|
428
|
+
element.datasource.attachObserver(
|
429
|
+
new Observer(handleDataSourceChanges.bind(this)),
|
430
|
+
);
|
431
|
+
}
|
432
|
+
});
|
433
|
+
}
|
434
|
+
});
|
435
|
+
|
436
|
+
this.attachObserver(
|
437
|
+
new Observer((a) => {
|
438
|
+
const selectAll = this[gridHeadersElementSymbol].querySelector(
|
439
|
+
`[data-monster-role="select-all"]`,
|
440
|
+
);
|
441
|
+
if (selectAll instanceof HTMLInputElement) {
|
442
|
+
selectAll.checked = false;
|
443
|
+
}
|
444
|
+
|
445
|
+
getSlottedElements
|
446
|
+
.call(this, "[data-monster-role=row-action-button]", "bar")
|
447
|
+
.forEach((i, e) => {
|
448
|
+
const selected = self.getSelectedRows();
|
449
|
+
if (e instanceof HTMLElement) {
|
450
|
+
e.style.visibility = "hidden";
|
451
|
+
}
|
452
|
+
});
|
453
|
+
|
454
|
+
const rows = this.getGridElements(`[data-monster-role="select-row"]`);
|
455
|
+
rows.forEach((row) => {
|
456
|
+
row.checked = false;
|
457
|
+
});
|
458
|
+
}),
|
459
|
+
);
|
460
|
+
}
|
461
|
+
|
462
|
+
/**
|
463
|
+
* @return {CSSStyleSheet[]}
|
464
|
+
*/
|
465
|
+
static getCSSStyleSheet() {
|
466
|
+
return [DatatableStyleSheet];
|
467
|
+
}
|
468
|
+
|
469
|
+
/**
|
470
|
+
* Copy a row from the datatable
|
471
|
+
*
|
472
|
+
* @param {number|string} fromIndex
|
473
|
+
* @param {number|string} toIndex
|
474
|
+
* @return {DataTable}
|
475
|
+
* @fires monster-datatable-row-copied
|
476
|
+
*/
|
477
|
+
copyRow(fromIndex, toIndex) {
|
478
|
+
const datasource = this[datasourceLinkedElementSymbol];
|
479
|
+
if (!datasource) {
|
480
|
+
return this;
|
481
|
+
}
|
482
|
+
let d = datasource.data;
|
483
|
+
let c = clone(d);
|
484
|
+
|
485
|
+
let rows = c;
|
486
|
+
const mapping = this.getOption("mapping.data");
|
487
|
+
|
488
|
+
if (mapping) {
|
489
|
+
rows = c?.[mapping];
|
490
|
+
}
|
491
|
+
|
492
|
+
if (rows === undefined || rows === null) {
|
493
|
+
rows = [];
|
494
|
+
}
|
495
|
+
|
496
|
+
if (toIndex === undefined) {
|
497
|
+
toIndex = rows.length;
|
498
|
+
}
|
499
|
+
|
500
|
+
if (isString(fromIndex)) {
|
501
|
+
fromIndex = parseInt(fromIndex);
|
502
|
+
}
|
503
|
+
if (isString(toIndex)) {
|
504
|
+
toIndex = parseInt(toIndex);
|
505
|
+
}
|
506
|
+
|
507
|
+
if (toIndex < 0 || toIndex > rows.length) {
|
508
|
+
throw new RangeError("index out of bounds");
|
509
|
+
}
|
510
|
+
|
511
|
+
validateArray(rows);
|
512
|
+
validateInteger(fromIndex);
|
513
|
+
validateInteger(toIndex);
|
514
|
+
|
515
|
+
if (fromIndex < 0 || fromIndex >= rows.length) {
|
516
|
+
throw new RangeError("index out of bounds");
|
517
|
+
}
|
518
|
+
|
519
|
+
rows.splice(toIndex, 0, clone(rows[fromIndex]));
|
520
|
+
datasource.data = c;
|
521
|
+
|
522
|
+
fireCustomEvent(this, "monster-datatable-row-copied", {
|
523
|
+
index: toIndex,
|
524
|
+
});
|
525
|
+
|
526
|
+
return this;
|
527
|
+
}
|
528
|
+
|
529
|
+
/**
|
530
|
+
* Remove a row from the datatable
|
531
|
+
*
|
532
|
+
* @param {number|string} index
|
533
|
+
* @return {DataTable}
|
534
|
+
* @fires monster-datatable-row-removed
|
535
|
+
*/
|
536
|
+
removeRow(index) {
|
537
|
+
const datasource = this[datasourceLinkedElementSymbol];
|
538
|
+
if (!datasource) {
|
539
|
+
return this;
|
540
|
+
}
|
541
|
+
let d = datasource.data;
|
542
|
+
let c = clone(d);
|
543
|
+
|
544
|
+
let rows = c;
|
545
|
+
const mapping = this.getOption("mapping.data");
|
546
|
+
|
547
|
+
if (mapping) {
|
548
|
+
rows = c?.[mapping];
|
549
|
+
}
|
550
|
+
|
551
|
+
if (rows === undefined || rows === null) {
|
552
|
+
rows = [];
|
553
|
+
}
|
554
|
+
|
555
|
+
if (isString(index)) {
|
556
|
+
index = parseInt(index);
|
557
|
+
}
|
558
|
+
|
559
|
+
validateArray(rows);
|
560
|
+
validateInteger(index);
|
561
|
+
|
562
|
+
if (index < 0 || index >= rows.length) {
|
563
|
+
throw new RangeError("index out of bounds");
|
564
|
+
}
|
565
|
+
if (mapping) {
|
566
|
+
rows = c?.[mapping];
|
567
|
+
}
|
568
|
+
|
569
|
+
rows.splice(index, 1);
|
570
|
+
datasource.data = c;
|
571
|
+
|
572
|
+
fireCustomEvent(this, "monster-datatable-row-removed", {
|
573
|
+
index: index,
|
574
|
+
});
|
575
|
+
|
576
|
+
return this;
|
577
|
+
}
|
578
|
+
|
579
|
+
/**
|
580
|
+
* Add a row to the datatable
|
581
|
+
*
|
582
|
+
* @param {Object} data
|
583
|
+
* @return {DataTable}
|
584
|
+
*
|
585
|
+
* @fires monster-datatable-row-added
|
586
|
+
**/
|
587
|
+
addRow(data) {
|
588
|
+
const datasource = this[datasourceLinkedElementSymbol];
|
589
|
+
if (!datasource) {
|
590
|
+
return this;
|
591
|
+
}
|
592
|
+
let d = datasource.data;
|
593
|
+
let c = clone(d);
|
594
|
+
|
595
|
+
let rows = c;
|
596
|
+
|
597
|
+
const mapping = this.getOption("mapping.data");
|
598
|
+
if (mapping) {
|
599
|
+
rows = c?.[mapping];
|
600
|
+
}
|
601
|
+
|
602
|
+
if (rows === undefined || rows === null) {
|
603
|
+
rows = [];
|
604
|
+
}
|
605
|
+
|
606
|
+
validateArray(rows);
|
607
|
+
validateObject(data);
|
608
|
+
|
609
|
+
rows.push(data);
|
610
|
+
datasource.data = c;
|
611
|
+
|
612
|
+
fireCustomEvent(this, "monster-datatable-row-added", {
|
613
|
+
index: rows.length - 1,
|
614
|
+
});
|
615
|
+
|
616
|
+
return this;
|
617
|
+
}
|
618
618
|
}
|
619
619
|
|
620
620
|
/**
|
@@ -622,7 +622,7 @@ class DataTable extends CustomElement {
|
|
622
622
|
* @return {string}
|
623
623
|
*/
|
624
624
|
function getColumnVisibilityConfigKey() {
|
625
|
-
|
625
|
+
return generateUniqueConfigKey("datatable", this?.id, "columns-visibility");
|
626
626
|
}
|
627
627
|
|
628
628
|
/**
|
@@ -630,7 +630,7 @@ function getColumnVisibilityConfigKey() {
|
|
630
630
|
* @return {string}
|
631
631
|
*/
|
632
632
|
function getFilterConfigKey() {
|
633
|
-
|
633
|
+
return generateUniqueConfigKey("datatable", this?.id, "filter");
|
634
634
|
}
|
635
635
|
|
636
636
|
/**
|
@@ -638,625 +638,625 @@ function getFilterConfigKey() {
|
|
638
638
|
* @return {Promise}
|
639
639
|
*/
|
640
640
|
function getHostConfig(callback) {
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
641
|
+
const host = findElementWithSelectorUpwards(this, "monster-host");
|
642
|
+
|
643
|
+
if (!host) {
|
644
|
+
addErrorAttribute(this, "no host found");
|
645
|
+
return Promise.resolve({});
|
646
|
+
}
|
647
|
+
|
648
|
+
if (!this.id) {
|
649
|
+
addErrorAttribute(this, "no id found; id is required for config");
|
650
|
+
return Promise.resolve({});
|
651
|
+
}
|
652
|
+
|
653
|
+
if (!host || !isFunction(host?.getConfig)) {
|
654
|
+
throw new TypeError("the host must be a monster-host");
|
655
|
+
}
|
656
|
+
|
657
|
+
const configKey = callback.call(this);
|
658
|
+
return host.hasConfig(configKey).then((hasConfig) => {
|
659
|
+
if (hasConfig) {
|
660
|
+
return host.getConfig(configKey);
|
661
|
+
} else {
|
662
|
+
return {};
|
663
|
+
}
|
664
|
+
});
|
665
665
|
}
|
666
666
|
|
667
667
|
/**
|
668
668
|
* @private
|
669
669
|
*/
|
670
670
|
function updateColumnBar() {
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
671
|
+
if (!this[columnBarElementSymbol]) {
|
672
|
+
return;
|
673
|
+
}
|
674
|
+
|
675
|
+
const columns = [];
|
676
|
+
for (const header of this.getOption("headers")) {
|
677
|
+
const mode = header.getInternal("mode");
|
678
|
+
|
679
|
+
if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
|
680
|
+
continue;
|
681
|
+
}
|
682
|
+
|
683
|
+
columns.push({
|
684
|
+
visible: mode !== ATTRIBUTE_DATATABLE_MODE_HIDDEN,
|
685
|
+
name: header.label,
|
686
|
+
index: header.index,
|
687
|
+
});
|
688
|
+
}
|
689
|
+
|
690
|
+
this[columnBarElementSymbol].setOption("columns", columns);
|
691
691
|
}
|
692
692
|
|
693
693
|
/**
|
694
694
|
* @private
|
695
695
|
*/
|
696
696
|
function updateHeaderFromColumnBar() {
|
697
|
-
|
698
|
-
|
699
|
-
|
697
|
+
if (!this[columnBarElementSymbol]) {
|
698
|
+
return;
|
699
|
+
}
|
700
700
|
|
701
|
-
|
702
|
-
|
701
|
+
const options = this[columnBarElementSymbol].getOption("columns");
|
702
|
+
if (!isArray(options)) return;
|
703
703
|
|
704
|
-
|
704
|
+
const invisibleMap = {};
|
705
705
|
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
706
|
+
for (let i = 0; i < options.length; i++) {
|
707
|
+
const option = options[i];
|
708
|
+
invisibleMap[option.index] = option.visible;
|
709
|
+
}
|
710
710
|
|
711
|
-
|
712
|
-
|
711
|
+
for (const header of this.getOption("headers")) {
|
712
|
+
const mode = header.getInternal("mode");
|
713
713
|
|
714
|
-
|
715
|
-
|
716
|
-
|
714
|
+
if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
|
715
|
+
continue;
|
716
|
+
}
|
717
717
|
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
718
|
+
if (invisibleMap[header.index] === false) {
|
719
|
+
header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_HIDDEN);
|
720
|
+
} else {
|
721
|
+
header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_VISIBLE);
|
722
|
+
}
|
723
|
+
}
|
724
724
|
}
|
725
725
|
|
726
726
|
/**
|
727
727
|
* @private
|
728
728
|
*/
|
729
729
|
function updateConfigColumnBar() {
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
730
|
+
if (!this[columnBarElementSymbol]) {
|
731
|
+
return;
|
732
|
+
}
|
733
|
+
|
734
|
+
const options = this[columnBarElementSymbol].getOption("columns");
|
735
|
+
if (!isArray(options)) return;
|
736
|
+
|
737
|
+
const map = {};
|
738
|
+
for (let i = 0; i < options.length; i++) {
|
739
|
+
const option = options[i];
|
740
|
+
map[option.name] = option.visible;
|
741
|
+
}
|
742
|
+
|
743
|
+
const host = findElementWithSelectorUpwards(this, "monster-host");
|
744
|
+
if (!(host && this.id)) {
|
745
|
+
return;
|
746
|
+
}
|
747
|
+
const configKey = getColumnVisibilityConfigKey.call(this);
|
748
|
+
|
749
|
+
try {
|
750
|
+
host.setConfig(configKey, map);
|
751
|
+
} catch (error) {
|
752
|
+
addErrorAttribute(this, error);
|
753
|
+
}
|
754
754
|
}
|
755
755
|
|
756
756
|
/**
|
757
757
|
* @private
|
758
758
|
*/
|
759
759
|
function initEventHandler() {
|
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
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
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
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
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
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
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
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
760
|
+
const self = this;
|
761
|
+
|
762
|
+
// --- Column resizing state ---
|
763
|
+
let isResizing = false;
|
764
|
+
let resizingColumnIndex = -1;
|
765
|
+
let startX = 0;
|
766
|
+
let startWidth = 0;
|
767
|
+
|
768
|
+
// --- Pointer-based resize handlers (robust for mouse/touch/stylus) ---
|
769
|
+
const onPointerDown = (event) => {
|
770
|
+
// Important: Call helper with (attrName, value) – not with CSS selector
|
771
|
+
const resizeHandle = findTargetElementFromEvent(
|
772
|
+
event,
|
773
|
+
"data-monster-role",
|
774
|
+
"resize-handle",
|
775
|
+
);
|
776
|
+
if (!resizeHandle) return;
|
777
|
+
|
778
|
+
event.preventDefault();
|
779
|
+
isResizing = true;
|
780
|
+
|
781
|
+
const headerCell = resizeHandle.closest("[data-monster-index]");
|
782
|
+
resizingColumnIndex = parseInt(
|
783
|
+
headerCell.getAttribute("data-monster-index"),
|
784
|
+
10,
|
785
|
+
);
|
786
|
+
startX = event.clientX;
|
787
|
+
startWidth = headerCell.offsetWidth;
|
788
|
+
|
789
|
+
// Capture to prevent losing events during fast dragging
|
790
|
+
event.target.setPointerCapture?.(event.pointerId);
|
791
|
+
|
792
|
+
getWindow().addEventListener("pointermove", onPointerMove);
|
793
|
+
getWindow().addEventListener("pointerup", onPointerUp);
|
794
|
+
|
795
|
+
// Global cursor styling during resizing
|
796
|
+
self.shadowRoot.host.classList.add("is-resizing");
|
797
|
+
};
|
798
|
+
|
799
|
+
const onPointerMove = (event) => {
|
800
|
+
if (!isResizing) return;
|
801
|
+
|
802
|
+
const deltaX = event.clientX - startX;
|
803
|
+
let newWidth = startWidth + deltaX;
|
804
|
+
|
805
|
+
const headers = self.getOption("headers");
|
806
|
+
const resizingHeader = headers[resizingColumnIndex];
|
807
|
+
|
808
|
+
const minWidth = 50;
|
809
|
+
|
810
|
+
const visibleHeaders = headers.filter(
|
811
|
+
(h) => h.getInternal("mode") !== ATTRIBUTE_DATATABLE_MODE_HIDDEN,
|
812
|
+
);
|
813
|
+
const numOtherVisibleColumns =
|
814
|
+
visibleHeaders.length > 1 ? visibleHeaders.length - 1 : 0;
|
815
|
+
|
816
|
+
const reservedSpaceForOthers = numOtherVisibleColumns * 50;
|
817
|
+
const tableContainerWidth = self[gridElementSymbol].clientWidth;
|
818
|
+
const maxWidth = tableContainerWidth - reservedSpaceForOthers;
|
819
|
+
|
820
|
+
newWidth = Math.max(minWidth, Math.min(newWidth, maxWidth));
|
821
|
+
|
822
|
+
resizingHeader.setInternal("grid", `${newWidth}px`);
|
823
|
+
|
824
|
+
updateGrid.call(self);
|
825
|
+
};
|
826
|
+
|
827
|
+
const onPointerUp = () => {
|
828
|
+
if (!isResizing) return;
|
829
|
+
|
830
|
+
isResizing = false;
|
831
|
+
getWindow().removeEventListener("pointermove", onPointerMove);
|
832
|
+
getWindow().removeEventListener("pointerup", onPointerUp);
|
833
|
+
|
834
|
+
self.shadowRoot.host.classList.remove("is-resizing");
|
835
|
+
};
|
836
|
+
|
837
|
+
// Use pointer events instead of mouse: more resilient
|
838
|
+
this[gridHeadersElementSymbol].addEventListener("pointerdown", onPointerDown);
|
839
|
+
|
840
|
+
// --- Copy configuration ---
|
841
|
+
const quoteOpenChar = this.getOption("copy.quoteOpen");
|
842
|
+
const quoteCloseChar = this.getOption("copy.quoteClose");
|
843
|
+
const delimiterChar = this.getOption("copy.delimiter");
|
844
|
+
const rowBreak = this.getOption("copy.rowBreak");
|
845
|
+
|
846
|
+
// --- Column-Bar -> Header visibility & persistence ---
|
847
|
+
if (self[columnBarElementSymbol]) {
|
848
|
+
self[columnBarElementSymbol].attachObserver(
|
849
|
+
new Observer(() => {
|
850
|
+
updateHeaderFromColumnBar.call(self);
|
851
|
+
updateGrid.call(self);
|
852
|
+
updateConfigColumnBar.call(self);
|
853
|
+
}),
|
854
|
+
);
|
855
|
+
}
|
856
|
+
|
857
|
+
// --- Sorting (click on header link) ---
|
858
|
+
self[gridHeadersElementSymbol].addEventListener("click", function (event) {
|
859
|
+
const datasource = self[datasourceLinkedElementSymbol];
|
860
|
+
if (!datasource) return;
|
861
|
+
|
862
|
+
const element = findTargetElementFromEvent(event, "data-monster-sortable");
|
863
|
+
if (element instanceof HTMLElement) {
|
864
|
+
const index = element.parentNode?.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
|
865
|
+
const headers = self.getOption("headers");
|
866
|
+
|
867
|
+
event.preventDefault();
|
868
|
+
|
869
|
+
headers[index].changeDirection();
|
870
|
+
|
871
|
+
queueMicrotask(function () {
|
872
|
+
element.setAttribute(
|
873
|
+
ATTRIBUTE_DATATABLE_SORTABLE,
|
874
|
+
`${headers[index].field} ${headers[index].direction}`,
|
875
|
+
);
|
876
|
+
|
877
|
+
storeOrderStatement.call(self, true);
|
878
|
+
});
|
879
|
+
}
|
880
|
+
});
|
881
|
+
|
882
|
+
// --- Double-Click Copy (column or entire row with Shift) ---
|
883
|
+
const eventHandlerDoubleClickCopyToClipboard = (event) => {
|
884
|
+
const headCell = findTargetElementFromEvent(event, "data-monster-head");
|
885
|
+
if (!headCell) return;
|
886
|
+
|
887
|
+
let text = "";
|
888
|
+
|
889
|
+
if (event.shiftKey) {
|
890
|
+
const index = headCell.getAttribute("data-monster-insert-reference");
|
891
|
+
if (index) {
|
892
|
+
const cols = self.getGridElements(
|
893
|
+
`[data-monster-insert-reference="${index}"]`,
|
894
|
+
);
|
895
|
+
|
896
|
+
const colTexts = [];
|
897
|
+
for (let i = 0; i < cols.length; i++) {
|
898
|
+
const col = cols[i];
|
899
|
+
|
900
|
+
if (
|
901
|
+
col.querySelector("monster-button-bar") ||
|
902
|
+
col.querySelector("monster-button")
|
903
|
+
) {
|
904
|
+
continue;
|
905
|
+
}
|
906
|
+
|
907
|
+
if (col.textContent) {
|
908
|
+
colTexts.push(
|
909
|
+
quoteOpenChar + col.textContent.trim() + quoteCloseChar,
|
910
|
+
);
|
911
|
+
}
|
912
|
+
}
|
913
|
+
|
914
|
+
text = colTexts.join(delimiterChar);
|
915
|
+
}
|
916
|
+
} else {
|
917
|
+
if (
|
918
|
+
headCell.querySelector("monster-button-bar") ||
|
919
|
+
headCell.querySelector("monster-button")
|
920
|
+
) {
|
921
|
+
return;
|
922
|
+
}
|
923
|
+
text = headCell.textContent.trim();
|
924
|
+
}
|
925
|
+
|
926
|
+
if (getWindow().navigator.clipboard && text) {
|
927
|
+
getWindow()
|
928
|
+
.navigator.clipboard.writeText(text)
|
929
|
+
.then(
|
930
|
+
() => {},
|
931
|
+
() => {},
|
932
|
+
);
|
933
|
+
}
|
934
|
+
};
|
935
|
+
|
936
|
+
if (self.getOption("features.doubleClickCopyToClipboard")) {
|
937
|
+
self[gridElementSymbol].addEventListener(
|
938
|
+
"dblclick",
|
939
|
+
eventHandlerDoubleClickCopyToClipboard,
|
940
|
+
);
|
941
|
+
}
|
942
|
+
|
943
|
+
// --- Copy All ---
|
944
|
+
if (self.getOption("features.copyAll") && this[copyAllElementSymbol]) {
|
945
|
+
this[copyAllElementSymbol].addEventListener("click", (event) => {
|
946
|
+
event.preventDefault();
|
947
|
+
|
948
|
+
const table = [];
|
949
|
+
let currentRow = [];
|
950
|
+
|
951
|
+
const cols = self.getGridElements(`[data-monster-insert-reference]`);
|
952
|
+
const rowIndexes = new Map();
|
953
|
+
cols.forEach((col) => {
|
954
|
+
const index = col.getAttribute("data-monster-insert-reference");
|
955
|
+
rowIndexes.set(index, true);
|
956
|
+
});
|
957
|
+
|
958
|
+
rowIndexes.forEach((_, key) => {
|
959
|
+
const rowCols = self.getGridElements(
|
960
|
+
`[data-monster-insert-reference="${key}"]`,
|
961
|
+
);
|
962
|
+
|
963
|
+
for (let i = 0; i < rowCols.length; i++) {
|
964
|
+
const col = rowCols[i];
|
965
|
+
|
966
|
+
if (
|
967
|
+
col.querySelector("monster-button-bar") ||
|
968
|
+
col.querySelector("monster-button")
|
969
|
+
) {
|
970
|
+
continue;
|
971
|
+
}
|
972
|
+
|
973
|
+
if (col.textContent) {
|
974
|
+
currentRow.push(
|
975
|
+
quoteOpenChar + col.textContent.trim() + quoteCloseChar,
|
976
|
+
);
|
977
|
+
}
|
978
|
+
}
|
979
|
+
|
980
|
+
if (currentRow.length > 0) {
|
981
|
+
table.push(currentRow);
|
982
|
+
}
|
983
|
+
currentRow = [];
|
984
|
+
});
|
985
|
+
|
986
|
+
if (table.length > 0) {
|
987
|
+
const text = table.map((row) => row.join(delimiterChar)).join(rowBreak);
|
988
|
+
if (getWindow().navigator.clipboard && text) {
|
989
|
+
getWindow()
|
990
|
+
.navigator.clipboard.writeText(text)
|
991
|
+
.then(
|
992
|
+
() => {},
|
993
|
+
() => {},
|
994
|
+
);
|
995
|
+
}
|
996
|
+
}
|
997
|
+
});
|
998
|
+
}
|
999
|
+
|
1000
|
+
// --- Row Selection (single) ---
|
1001
|
+
const selectRowCallback = (event) => {
|
1002
|
+
const checkbox = findTargetElementFromEvent(
|
1003
|
+
event,
|
1004
|
+
"data-monster-role",
|
1005
|
+
"select-row",
|
1006
|
+
);
|
1007
|
+
|
1008
|
+
if (!(checkbox instanceof HTMLInputElement)) return;
|
1009
|
+
|
1010
|
+
const parentNode = checkbox.parentNode;
|
1011
|
+
if (!(parentNode instanceof HTMLDivElement)) return;
|
1012
|
+
|
1013
|
+
const key = parentNode.getAttribute("data-monster-insert-reference");
|
1014
|
+
const row = self.getGridElements(
|
1015
|
+
`[data-monster-insert-reference="${key}"]`,
|
1016
|
+
);
|
1017
|
+
const index = key.split("-").pop();
|
1018
|
+
|
1019
|
+
if (checkbox.checked) {
|
1020
|
+
row.forEach((col) => col.classList.add("selected"));
|
1021
|
+
fireCustomEvent(self, "monster-datatable-row-selected", { index });
|
1022
|
+
} else {
|
1023
|
+
row.forEach((col) => col.classList.remove("selected"));
|
1024
|
+
fireCustomEvent(self, "monster-datatable-row-deselected", { index });
|
1025
|
+
}
|
1026
|
+
|
1027
|
+
fireCustomEvent(this, "monster-datatable-selection-changed", {});
|
1028
|
+
|
1029
|
+
const rows = self.getGridElements(`[data-monster-role="select-row"]`);
|
1030
|
+
const allSelected = Array.from(rows).every((r) => r.checked);
|
1031
|
+
|
1032
|
+
const selectAll = this[gridHeadersElementSymbol].querySelector(
|
1033
|
+
`[data-monster-role="select-all"]`,
|
1034
|
+
);
|
1035
|
+
|
1036
|
+
// Row-Action-Buttons visible/invisible depending on selection
|
1037
|
+
getSlottedElements
|
1038
|
+
.call(this, "[data-monster-role=row-action-button]", "bar")
|
1039
|
+
.forEach((i, e) => {
|
1040
|
+
const selected = self.getSelectedRows();
|
1041
|
+
const mode = selected.length === 0 ? "hidden" : "visible";
|
1042
|
+
if (e instanceof HTMLElement) e.style.visibility = mode;
|
1043
|
+
});
|
1044
|
+
|
1045
|
+
if (selectAll) selectAll.checked = allSelected;
|
1046
|
+
};
|
1047
|
+
|
1048
|
+
this[gridElementSymbol].addEventListener("click", selectRowCallback);
|
1049
|
+
this[gridElementSymbol].addEventListener("touch", selectRowCallback);
|
1050
|
+
|
1051
|
+
// --- Row Selection (all) ---
|
1052
|
+
const selectAllCallback = (event) => {
|
1053
|
+
const toggle = findTargetElementFromEvent(
|
1054
|
+
event,
|
1055
|
+
"data-monster-role",
|
1056
|
+
"select-all",
|
1057
|
+
);
|
1058
|
+
if (!toggle) return;
|
1059
|
+
|
1060
|
+
const mode = toggle.checked;
|
1061
|
+
const rows = this.getGridElements(`[data-monster-role="select-row"]`);
|
1062
|
+
rows.forEach((row) => {
|
1063
|
+
row.checked = mode;
|
1064
|
+
});
|
1065
|
+
|
1066
|
+
if (mode) {
|
1067
|
+
fireCustomEvent(this, "monster-datatable-all-rows-selected", {});
|
1068
|
+
} else {
|
1069
|
+
fireCustomEvent(this, "monster-datatable-all-rows-deselected", {});
|
1070
|
+
}
|
1071
|
+
|
1072
|
+
getSlottedElements
|
1073
|
+
.call(this, "[data-monster-role=row-action-button]", "bar")
|
1074
|
+
.forEach((i, e) => {
|
1075
|
+
if (e instanceof HTMLElement)
|
1076
|
+
e.style.visibility = mode ? "visible" : "hidden";
|
1077
|
+
});
|
1078
|
+
|
1079
|
+
fireCustomEvent(this, "monster-datatable-selection-changed", {});
|
1080
|
+
};
|
1081
|
+
|
1082
|
+
this[gridHeadersElementSymbol].addEventListener("click", selectAllCallback);
|
1083
|
+
this[gridHeadersElementSymbol].addEventListener("touch", selectAllCallback);
|
1084
1084
|
}
|
1085
1085
|
|
1086
1086
|
/**
|
1087
1087
|
* @private
|
1088
1088
|
*/
|
1089
1089
|
function initGridAndStructs(hostConfig, headerOrderMap) {
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1090
|
+
const rowID = this.getOption("templateMapping.row-key");
|
1091
|
+
|
1092
|
+
if (!this[gridElementSymbol]) {
|
1093
|
+
addErrorAttribute(this, "no grid element found");
|
1094
|
+
return;
|
1095
|
+
}
|
1096
|
+
|
1097
|
+
let template;
|
1098
|
+
getSlottedElements.call(this).forEach((e) => {
|
1099
|
+
if (e instanceof HTMLTemplateElement && e.id === rowID) {
|
1100
|
+
template = e;
|
1101
|
+
}
|
1102
|
+
});
|
1103
|
+
|
1104
|
+
if (!template) {
|
1105
|
+
addErrorAttribute(this, "no template found, please add a template");
|
1106
|
+
return;
|
1107
|
+
}
|
1108
|
+
|
1109
|
+
const rowCount = template.content.children.length;
|
1110
|
+
|
1111
|
+
const headers = [];
|
1112
|
+
|
1113
|
+
for (let i = 0; i < rowCount; i++) {
|
1114
|
+
let hClass = "";
|
1115
|
+
const row = template.content.children[i];
|
1116
|
+
|
1117
|
+
let mode = "";
|
1118
|
+
if (row.hasAttribute(ATTRIBUTE_DATATABLE_MODE)) {
|
1119
|
+
mode = row.getAttribute(ATTRIBUTE_DATATABLE_MODE);
|
1120
|
+
}
|
1121
|
+
|
1122
|
+
let grid = row.getAttribute(ATTRIBUTE_DATATABLE_GRID_TEMPLATE);
|
1123
|
+
if (!grid || grid === "" || grid === "auto") {
|
1124
|
+
grid = "minmax(0, 1fr)";
|
1125
|
+
}
|
1126
|
+
|
1127
|
+
let label = "";
|
1128
|
+
let labelKey = "";
|
1129
|
+
|
1130
|
+
if (row.hasAttribute(ATTRIBUTE_DATATABLE_HEAD)) {
|
1131
|
+
label = row.getAttribute(ATTRIBUTE_DATATABLE_HEAD);
|
1132
|
+
labelKey = label;
|
1133
|
+
|
1134
|
+
try {
|
1135
|
+
if (label.startsWith("i18n:")) {
|
1136
|
+
label = label.substring(5, label.length);
|
1137
|
+
label = getDocumentTranslations().getText(label, label);
|
1138
|
+
}
|
1139
|
+
} catch (e) {
|
1140
|
+
label = "i18n error " + label;
|
1141
|
+
}
|
1142
|
+
}
|
1143
|
+
|
1144
|
+
if (!label) {
|
1145
|
+
label = i + 1 + "";
|
1146
|
+
mode = ATTRIBUTE_DATATABLE_MODE_FIXED;
|
1147
|
+
labelKey = label;
|
1148
|
+
}
|
1149
|
+
|
1150
|
+
if (isObject(hostConfig) && hostConfig.hasOwnProperty(label)) {
|
1151
|
+
if (hostConfig[label] === false) {
|
1152
|
+
mode = ATTRIBUTE_DATATABLE_MODE_HIDDEN;
|
1153
|
+
} else {
|
1154
|
+
mode = ATTRIBUTE_DATATABLE_MODE_VISIBLE;
|
1155
|
+
}
|
1156
|
+
}
|
1157
|
+
|
1158
|
+
let align = "";
|
1159
|
+
if (row.hasAttribute(ATTRIBUTE_DATATABLE_ALIGN)) {
|
1160
|
+
align = row.getAttribute(ATTRIBUTE_DATATABLE_ALIGN);
|
1161
|
+
}
|
1162
|
+
|
1163
|
+
switch (align) {
|
1164
|
+
case "center":
|
1165
|
+
hClass = "flex-center";
|
1166
|
+
break;
|
1167
|
+
case "end":
|
1168
|
+
hClass = "flex-end";
|
1169
|
+
break;
|
1170
|
+
case "start":
|
1171
|
+
hClass = "flex-start";
|
1172
|
+
break;
|
1173
|
+
default:
|
1174
|
+
hClass = "flex-start";
|
1175
|
+
}
|
1176
|
+
|
1177
|
+
let field = "";
|
1178
|
+
let direction = DIRECTION_NONE;
|
1179
|
+
if (row.hasAttribute(ATTRIBUTE_DATATABLE_SORTABLE)) {
|
1180
|
+
field = row.getAttribute(ATTRIBUTE_DATATABLE_SORTABLE).trim();
|
1181
|
+
const parts = field.split(" ").map((item) => item.trim());
|
1182
|
+
field = parts[0];
|
1183
|
+
|
1184
|
+
if (headerOrderMap.has(field)) {
|
1185
|
+
direction = headerOrderMap.get(field);
|
1186
|
+
} else if (
|
1187
|
+
parts.length === 2 &&
|
1188
|
+
[DIRECTION_ASC, DIRECTION_DESC].indexOf(parts[1]) !== -1
|
1189
|
+
) {
|
1190
|
+
direction = parts[1];
|
1191
|
+
}
|
1192
|
+
}
|
1193
|
+
|
1194
|
+
if (mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN) {
|
1195
|
+
hClass += " hidden";
|
1196
|
+
}
|
1197
|
+
|
1198
|
+
const features = [];
|
1199
|
+
|
1200
|
+
if (row.hasAttribute(ATTRIBUTE_DATATABLE_FEATURES)) {
|
1201
|
+
const fl = row.getAttribute(ATTRIBUTE_DATATABLE_FEATURES).split(" ");
|
1202
|
+
|
1203
|
+
fl.forEach((feature) => {
|
1204
|
+
features.push(feature.trim());
|
1205
|
+
|
1206
|
+
if (feature === "select") {
|
1207
|
+
label = "<input type='checkbox' data-monster-role='select-all' />";
|
1208
|
+
|
1209
|
+
while (row.firstChild) {
|
1210
|
+
row.removeChild(row.firstChild);
|
1211
|
+
}
|
1212
|
+
|
1213
|
+
const checkbox = document.createElement("input");
|
1214
|
+
checkbox.type = "checkbox";
|
1215
|
+
checkbox.setAttribute("data-monster-role", "select-row");
|
1216
|
+
row.appendChild(checkbox);
|
1217
|
+
}
|
1218
|
+
});
|
1219
|
+
}
|
1220
|
+
|
1221
|
+
let orderTemplate = "${field} ${direction}";
|
1222
|
+
if (row.hasAttribute("data-monster-order-template")) {
|
1223
|
+
orderTemplate = row.getAttribute("data-monster-order-template");
|
1224
|
+
}
|
1225
|
+
|
1226
|
+
const isResizable = this.getOption("features.resizable");
|
1227
|
+
const header = new Header();
|
1228
|
+
header.setInternals({
|
1229
|
+
field: field,
|
1230
|
+
label: label,
|
1231
|
+
classes: hClass,
|
1232
|
+
index: i,
|
1233
|
+
mode: mode,
|
1234
|
+
grid: grid,
|
1235
|
+
labelKey: labelKey + "-" + i,
|
1236
|
+
direction: direction,
|
1237
|
+
features: features,
|
1238
|
+
orderTemplate: orderTemplate,
|
1239
|
+
resizable: isResizable,
|
1240
|
+
});
|
1241
|
+
|
1242
|
+
headers.push(header);
|
1243
|
+
}
|
1244
|
+
|
1245
|
+
this.setOption("headers", headers);
|
1246
|
+
requestAnimationFrame(() => {
|
1247
|
+
storeOrderStatement.call(this, this.getOption("features.autoInit"));
|
1248
|
+
|
1249
|
+
const headerElements = this[gridHeadersElementSymbol].querySelectorAll(
|
1250
|
+
"[data-monster-index]",
|
1251
|
+
);
|
1252
|
+
headerElements.forEach((cell) => {
|
1253
|
+
const index = parseInt(cell.getAttribute("data-monster-index"), 10);
|
1254
|
+
if (headers[index]) {
|
1255
|
+
console.log("store initial width for header", index, cell.offsetWidth);
|
1256
|
+
headers[index].setInternal("initialWidth", cell.offsetWidth);
|
1257
|
+
}
|
1258
|
+
});
|
1259
|
+
});
|
1260
1260
|
}
|
1261
1261
|
|
1262
1262
|
/**
|
@@ -1264,101 +1264,101 @@ function initGridAndStructs(hostConfig, headerOrderMap) {
|
|
1264
1264
|
* @returns {object}
|
1265
1265
|
*/
|
1266
1266
|
function getTranslations() {
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1267
|
+
const locale = getLocaleOfDocument();
|
1268
|
+
switch (locale.language) {
|
1269
|
+
case "de":
|
1270
|
+
return {
|
1271
|
+
theListContainsNoEntries: "Die Liste enthält keine Einträge",
|
1272
|
+
copyAll: "Alles kopieren",
|
1273
|
+
helpText:
|
1274
|
+
"<p>Sie können die Werte aus einzelnen Zeilen<br>" +
|
1275
|
+
"in die Zwischenablage kopieren, indem Sie auf die entsprechende Spalte doppelklicken.</p>" +
|
1276
|
+
"<p>Um eine ganze Zeile zu kopieren, halten Sie die Umschalttaste gedrückt, während Sie klicken.<br>" +
|
1277
|
+
"Wenn Sie alle Zeilen kopieren möchten, können Sie die Schaltfläche <strong>Alles kopieren</strong> verwenden.</p>",
|
1278
|
+
};
|
1279
|
+
case "fr":
|
1280
|
+
return {
|
1281
|
+
theListContainsNoEntries: "La liste ne contient aucune entrée",
|
1282
|
+
copyAll: "Copier tout",
|
1283
|
+
helpText:
|
1284
|
+
"<p>Vous pouvez copier les valeurs des rangées individuelles<br>" +
|
1285
|
+
"dans le presse-papiers en double-cliquant sur la colonne concernée.</p>" +
|
1286
|
+
"<p>Pour copier une rangée entière, maintenez la touche Maj enfoncée tout en cliquant.<br>" +
|
1287
|
+
"Si vous souhaitez copier toutes les rangées, vous pouvez utiliser le bouton <strong>Copier tout</strong>.</p>",
|
1288
|
+
};
|
1289
|
+
case "sp":
|
1290
|
+
return {
|
1291
|
+
theListContainsNoEntries: "La lista no contiene entradas",
|
1292
|
+
copyAll: "Copiar todo",
|
1293
|
+
helpText:
|
1294
|
+
"<p>Puedes copiar los valores de filas individuales<br>" +
|
1295
|
+
"al portapapeles haciendo doble clic en la columna correspondiente.</p>" +
|
1296
|
+
"<p>Para copiar una fila entera, mantén presionada la tecla Shift mientras haces clic.<br>" +
|
1297
|
+
"Si quieres copiar todas las filas, puedes usar el botón <strong>Copiar todo</strong>.</p>",
|
1298
|
+
};
|
1299
|
+
case "it":
|
1300
|
+
return {
|
1301
|
+
theListContainsNoEntries: "L'elenco non contiene voci",
|
1302
|
+
copyAll: "Copia tutto",
|
1303
|
+
helpText:
|
1304
|
+
"<p>Puoi copiare i valori dalle singole righe<br>" +
|
1305
|
+
"negli appunti facendo doppio clic sulla colonna relativa.</p>" +
|
1306
|
+
"<p>Per copiare un'intera riga, tieni premuto il tasto Shift mentre clicchi.<br>" +
|
1307
|
+
"Se vuoi copiare tutte le righe, puoi usare il pulsante <strong>Copia tutto</strong>.</p>",
|
1308
|
+
};
|
1309
|
+
case "pl":
|
1310
|
+
return {
|
1311
|
+
theListContainsNoEntries: "Lista nie zawiera wpisów",
|
1312
|
+
copyAll: "Kopiuj wszystko",
|
1313
|
+
helpText:
|
1314
|
+
"<p>Możesz skopiować wartości z poszczególnych wierszy<br>" +
|
1315
|
+
"do schowka, klikając dwukrotnie na odpowiednią kolumnę.</p>" +
|
1316
|
+
"<p>Aby skopiować cały wiersz, przytrzymaj klawisz Shift podczas klikania.<br>" +
|
1317
|
+
"Jeśli chcesz skopiować wszystkie wiersze, możesz użyć przycisku <strong>Kopiuj wszystko</strong>.</p>",
|
1318
|
+
};
|
1319
|
+
case "no":
|
1320
|
+
return {
|
1321
|
+
theListContainsNoEntries: "Listen inneholder ingen oppføringer",
|
1322
|
+
copyAll: "Kopier alt",
|
1323
|
+
helpText:
|
1324
|
+
"<p>Du kan kopiere verdier fra enkeltrader<br>" +
|
1325
|
+
"til utklippstavlen ved å dobbeltklikke på den relevante kolonnen.</p>" +
|
1326
|
+
"<p>For å kopiere en hel rad, hold nede Skift-tasten mens du klikker.<br>" +
|
1327
|
+
"Hvis du vil kopiere alle radene, kan du bruke knappen <strong>Kopier alt</strong>.</p>",
|
1328
|
+
};
|
1329
|
+
case "dk":
|
1330
|
+
return {
|
1331
|
+
theListContainsNoEntries: "Listen indeholder ingen poster",
|
1332
|
+
copyAll: "Kopiér alt",
|
1333
|
+
helpText:
|
1334
|
+
"<p>Du kan kopiere værdier fra enkelte rækker<br>" +
|
1335
|
+
"til udklipsholderen ved at dobbeltklikke på den relevante kolonne.</p>" +
|
1336
|
+
"<p>For at kopiere en hel række, hold Shift-tasten nede, mens du klikker.<br>" +
|
1337
|
+
"Hvis du vil kopiere alle rækker, kan du bruge knappen <strong>Kopiér alt</strong>.</p>",
|
1338
|
+
};
|
1339
|
+
case "sw":
|
1340
|
+
return {
|
1341
|
+
theListContainsNoEntries: "Listan innehåller inga poster",
|
1342
|
+
copyAll: "Kopiera allt",
|
1343
|
+
helpText:
|
1344
|
+
"<p>Du kan kopiera värden från enskilda rader<br>" +
|
1345
|
+
"till urklipp genom att dubbelklicka på den relevanta kolumnen.</p>" +
|
1346
|
+
"<p>För att kopiera en hel rad, håll ned Shift-tangenten medan du klickar.<br>" +
|
1347
|
+
"Om du vill kopiera alla rader kan du använda knappen <strong>Kopiera allt</strong>.</p>",
|
1348
|
+
};
|
1349
|
+
|
1350
|
+
case "en":
|
1351
|
+
default:
|
1352
|
+
return {
|
1353
|
+
theListContainsNoEntries: "The list contains no entries",
|
1354
|
+
copyAll: "Copy all",
|
1355
|
+
helpText:
|
1356
|
+
"<p>You can copy the values from individual rows<br>" +
|
1357
|
+
"to the clipboard by double-clicking on the relevant column.</p>" +
|
1358
|
+
"<p>To copy an entire row, hold down the Shift key while clicking.<br>" +
|
1359
|
+
"If you want to copy all rows, you can use the <strong>Copy All</strong> button.</p>",
|
1360
|
+
};
|
1361
|
+
}
|
1362
1362
|
}
|
1363
1363
|
|
1364
1364
|
/**
|
@@ -1366,83 +1366,83 @@ function getTranslations() {
|
|
1366
1366
|
* @return {string}
|
1367
1367
|
*/
|
1368
1368
|
export function getStoredOrderConfigKey() {
|
1369
|
-
|
1369
|
+
return generateUniqueConfigKey("datatable", this?.id, "stored-order");
|
1370
1370
|
}
|
1371
1371
|
|
1372
1372
|
/**
|
1373
1373
|
* @private
|
1374
1374
|
*/
|
1375
1375
|
function storeOrderStatement(doFetch) {
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1376
|
+
const headers = this.getOption("headers");
|
1377
|
+
const delimiter = this.getOption("datasource.orderDelimiter");
|
1378
|
+
const statement = createOrderStatement(headers, delimiter);
|
1379
|
+
setDataSource.call(this, { order: statement }, doFetch);
|
1380
1380
|
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1381
|
+
const host = findElementWithSelectorUpwards(this, "monster-host");
|
1382
|
+
if (!(host && this.id)) {
|
1383
|
+
return;
|
1384
|
+
}
|
1385
1385
|
|
1386
|
-
|
1386
|
+
const configKey = getStoredOrderConfigKey.call(this);
|
1387
1387
|
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1388
|
+
// statement explode with , and remove all empty
|
1389
|
+
const list = statement.split(",").filter((item) => item.trim() !== "");
|
1390
|
+
if (list.length === 0) {
|
1391
|
+
return;
|
1392
|
+
}
|
1393
1393
|
|
1394
|
-
|
1394
|
+
host.setConfig(configKey, list);
|
1395
1395
|
}
|
1396
1396
|
|
1397
1397
|
/**
|
1398
1398
|
* @private
|
1399
1399
|
*/
|
1400
1400
|
function updateGrid() {
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1401
|
+
if (!this[gridElementSymbol]) {
|
1402
|
+
throw new Error("no grid element is defined");
|
1403
|
+
}
|
1404
|
+
|
1405
|
+
let gridTemplateColumns = "";
|
1406
|
+
|
1407
|
+
const headers = this.getOption("headers");
|
1408
|
+
|
1409
|
+
let styles = "";
|
1410
|
+
|
1411
|
+
for (let i = 0; i < headers.length; i++) {
|
1412
|
+
const header = headers[i];
|
1413
|
+
|
1414
|
+
if (
|
1415
|
+
header.mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN &&
|
1416
|
+
header.mode !== ATTRIBUTE_DATATABLE_MODE_FIXED
|
1417
|
+
) {
|
1418
|
+
styles += `[data-monster-role=datatable-headers]>[data-monster-index="${header.index}"] { display: none; }\n`;
|
1419
|
+
styles += `[data-monster-role=datatable] > div:nth-child(${headers.length}n+${i + 1}) { display: none; }\n`;
|
1420
|
+
} else {
|
1421
|
+
gridTemplateColumns += `${header.grid} `;
|
1422
|
+
}
|
1423
|
+
}
|
1424
|
+
|
1425
|
+
const sheet = new CSSStyleSheet();
|
1426
|
+
if (styles !== "") sheet.replaceSync(styles);
|
1427
|
+
this.shadowRoot.adoptedStyleSheets = [...DataTable.getCSSStyleSheet(), sheet];
|
1428
|
+
|
1429
|
+
const bodyWidth = this.parentNode.clientWidth;
|
1430
|
+
|
1431
|
+
const breakpoint = this.getOption("responsive.breakpoint");
|
1432
|
+
this[dataControlElementSymbol].classList.toggle(
|
1433
|
+
"small",
|
1434
|
+
bodyWidth <= breakpoint,
|
1435
|
+
);
|
1436
|
+
|
1437
|
+
if (bodyWidth > breakpoint) {
|
1438
|
+
this[gridElementSymbol].style.gridTemplateColumns =
|
1439
|
+
`${gridTemplateColumns}`;
|
1440
|
+
this[gridHeadersElementSymbol].style.gridTemplateColumns =
|
1441
|
+
`${gridTemplateColumns}`;
|
1442
|
+
} else {
|
1443
|
+
this[gridElementSymbol].style.gridTemplateColumns = "auto";
|
1444
|
+
this[gridHeadersElementSymbol].style.gridTemplateColumns = "auto";
|
1445
|
+
}
|
1446
1446
|
}
|
1447
1447
|
|
1448
1448
|
/**
|
@@ -1451,19 +1451,19 @@ function updateGrid() {
|
|
1451
1451
|
* @param {bool} doFetch
|
1452
1452
|
*/
|
1453
1453
|
function setDataSource({ order }, doFetch) {
|
1454
|
-
|
1454
|
+
const datasource = this[datasourceLinkedElementSymbol];
|
1455
1455
|
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1456
|
+
if (!datasource) {
|
1457
|
+
return;
|
1458
|
+
}
|
1459
1459
|
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1460
|
+
if (isFunction(datasource?.setParameters)) {
|
1461
|
+
datasource.setParameters({ order });
|
1462
|
+
}
|
1463
1463
|
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1464
|
+
if (doFetch !== false && isFunction(datasource?.fetch)) {
|
1465
|
+
datasource.fetch();
|
1466
|
+
}
|
1467
1467
|
}
|
1468
1468
|
|
1469
1469
|
/**
|
@@ -1471,30 +1471,30 @@ function setDataSource({ order }, doFetch) {
|
|
1471
1471
|
* @return {DataTable}
|
1472
1472
|
*/
|
1473
1473
|
function initControlReferences() {
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1474
|
+
if (!this.shadowRoot) {
|
1475
|
+
throw new Error("no shadow-root is defined");
|
1476
|
+
}
|
1477
1477
|
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1478
|
+
this[dataControlElementSymbol] = this.shadowRoot.querySelector(
|
1479
|
+
"[data-monster-role=control]",
|
1480
|
+
);
|
1481
1481
|
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1482
|
+
this[gridElementSymbol] = this.shadowRoot.querySelector(
|
1483
|
+
"[data-monster-role=datatable]",
|
1484
|
+
);
|
1485
1485
|
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1486
|
+
this[gridHeadersElementSymbol] = this.shadowRoot.querySelector(
|
1487
|
+
"[data-monster-role=datatable-headers]",
|
1488
|
+
);
|
1489
1489
|
|
1490
|
-
|
1491
|
-
|
1490
|
+
this[columnBarElementSymbol] =
|
1491
|
+
this.shadowRoot.querySelector("monster-column-bar");
|
1492
1492
|
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1493
|
+
this[copyAllElementSymbol] = this.shadowRoot.querySelector(
|
1494
|
+
"[data-monster-role=copy-all]",
|
1495
|
+
);
|
1496
1496
|
|
1497
|
-
|
1497
|
+
return this;
|
1498
1498
|
}
|
1499
1499
|
|
1500
1500
|
/**
|
@@ -1504,25 +1504,25 @@ function initControlReferences() {
|
|
1504
1504
|
* @throws {Error} the datasource could not be initialized
|
1505
1505
|
*/
|
1506
1506
|
function initOptionsFromArguments() {
|
1507
|
-
|
1508
|
-
|
1507
|
+
const options = { datasource: {} };
|
1508
|
+
const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
|
1509
1509
|
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1510
|
+
if (selector) {
|
1511
|
+
options.datasource = { selector: selector };
|
1512
|
+
}
|
1513
1513
|
|
1514
|
-
|
1514
|
+
options.datasource.orderDelimiter = ","; // workaround for the missing orderDelimiter
|
1515
1515
|
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1516
|
+
const breakpoint = this.getAttribute(
|
1517
|
+
ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
|
1518
|
+
);
|
1519
1519
|
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1520
|
+
if (breakpoint) {
|
1521
|
+
options.responsive = {};
|
1522
|
+
options.responsive.breakpoint = parseInt(breakpoint);
|
1523
|
+
}
|
1524
1524
|
|
1525
|
-
|
1525
|
+
return options;
|
1526
1526
|
}
|
1527
1527
|
|
1528
1528
|
/**
|
@@ -1530,7 +1530,7 @@ function initOptionsFromArguments() {
|
|
1530
1530
|
* @return {string}
|
1531
1531
|
*/
|
1532
1532
|
function getEmptyTemplate() {
|
1533
|
-
|
1533
|
+
return `<monster-state data-monster-role="empty-without-action">
|
1534
1534
|
<div part="visual">
|
1535
1535
|
<svg width="4rem" height="4rem" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
1536
1536
|
<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"/>
|
@@ -1548,8 +1548,8 @@ function getEmptyTemplate() {
|
|
1548
1548
|
* @return {string}
|
1549
1549
|
*/
|
1550
1550
|
function getTemplate() {
|
1551
|
-
|
1552
|
-
|
1551
|
+
// language=HTML
|
1552
|
+
return `
|
1553
1553
|
<div data-monster-role="control" part="control" data-monster-attributes="class path:classes.control">
|
1554
1554
|
<template id="headers-row">
|
1555
1555
|
<div data-monster-attributes="class path:headers-row.classes,
|