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