ninegrid2 6.131.0 → 6.133.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.
@@ -0,0 +1,532 @@
1
+ import ninegrid from "../index.js";
2
+
3
+ export class ngFiltering
4
+ {
5
+ #owner;
6
+ #isFiltering;
7
+
8
+ constructor (owner) {
9
+ this.#owner = owner;
10
+ this.#isFiltering = false;
11
+
12
+ $(this.#owner.shadowRoot).append($('<ng-filter-panel></ng-filter-panel>').hide());
13
+ }
14
+
15
+ initialize = () => {
16
+ /**
17
+ * 1. grid attr == filter : on();
18
+ */
19
+ this.#isFiltering = false;
20
+ this.#owner.data.clearFilter();
21
+ };
22
+
23
+ isFiltering = () => {
24
+ return this.#isFiltering;
25
+ };
26
+
27
+ on = (v) => {
28
+
29
+ this.#on();
30
+
31
+ if (v) this.#set(v);
32
+ };
33
+
34
+ #on = () => {
35
+
36
+ this.#isFiltering = true;
37
+
38
+ var lastRowIndex = 0;
39
+ $(".ng-table thead", this.#owner.body).each((index,el) => {
40
+ lastRowIndex = Math.max(el.rows.length - 1, lastRowIndex);
41
+ });
42
+
43
+ $(".ng-table thead th,.ng-table thead td", this.#owner.body).each((index,el) => {
44
+
45
+ if (el.closest("tr").sectionRowIndex + el.rowSpan - 1 != lastRowIndex) return true;
46
+
47
+ var colnms = [];
48
+ $(this.#owner.template).find(`[data-col=${el.dataset.col}]`).each((index,el) => {
49
+ if (el.dataset.bind) colnms.push(el.dataset.bind);
50
+ });
51
+ if (colnms.length == 0) return true;
52
+
53
+ //console.log(colnms);
54
+
55
+ $(el).append($(`<ng-filter-button></ng-filter-button`));
56
+ el.querySelector("ng-filter-button").colnms = colnms;
57
+
58
+ //console.log(el.querySelector("ng-filter-button").colnms);
59
+ });
60
+ };
61
+ off = () => {
62
+ this.#isFiltering = false;
63
+ $(".ng-table ng-filter-button", this.#owner.body).remove();
64
+ };
65
+
66
+ #set = (option) => {
67
+
68
+ let jsonOption = {};
69
+ if (Array.isArray(option)) {
70
+
71
+ for (let key in option[0]) {
72
+ jsonOption[key] = Array.from(new Set(oFilter.map(item => item[key])));//oFilter.map(item => item[key]);
73
+ }
74
+ }
75
+ else {
76
+ jsonOption = option;
77
+ }
78
+
79
+ this.#owner.data.clearFilter();
80
+
81
+ for (let key in jsonOption) {
82
+ const arr = jsonOption[key];
83
+ const idx = this.#owner.fields.indexOf(key);
84
+
85
+ for (let o of this.#owner.data.getValidData()) {
86
+ if (o.v[idx] != null) {
87
+ if (typeof o.v[idx] === "number") {
88
+ for (var i = 0; i < arr.length; i++) {
89
+ arr[i] = Number(arr[i]);
90
+ }
91
+ }
92
+ break;
93
+ }
94
+ }
95
+
96
+ this.#owner.data.getValidData().filter(m => { return arr.nineBinarySearch(m.v[idx] || '') < 0; }).map(m => { m.__ng.filtered = true; });
97
+ }
98
+
99
+
100
+ this.#owner.data.refreshFilter();
101
+
102
+ var colnms = [];
103
+ for (let key in jsonOption) {
104
+ colnms.push(key);
105
+ }
106
+ //var colnms = filterData.map(item => item.colnm);
107
+
108
+ ninegrid.querySelectorAll("ng-filter-button").forEach(v => {
109
+ v.filterData = null;
110
+ });
111
+
112
+ for (let key in jsonOption) {
113
+ const arr = jsonOption[key];
114
+
115
+ ninegrid.querySelectorAll("ng-filter-button").forEach(v => {
116
+ //console.log(v.colnms);
117
+
118
+ v.colnms.forEach(colnm => {
119
+ if (colnms.includes(colnm)) {
120
+ v.filterData = arr;
121
+ }
122
+ });
123
+ });
124
+ }
125
+
126
+
127
+ this.#owner.scrollTo_V1(0);
128
+
129
+ this.#owner.paging.reset();
130
+ };
131
+ }
132
+
133
+ class ngFilterButton extends HTMLElement
134
+ {
135
+ #owner;
136
+ #filterData;
137
+ #colnms;
138
+
139
+ constructor () {
140
+ super();
141
+ }
142
+
143
+ connectedCallback() {
144
+ this.#owner = this.getRootNode().host;//this.closest("nine-grid");
145
+
146
+ $(this).off("click", this.#onClick);
147
+ $(this).on("click", this.#onClick);
148
+ };
149
+
150
+ get colnms() {
151
+ return this.#colnms || [];
152
+ };
153
+ set colnms(v) {
154
+ this.#colnms = v;
155
+ };
156
+
157
+ get filterData() {
158
+ return this.#filterData;
159
+ };
160
+ set filterData(v) {
161
+ this.#filterData = v;
162
+ v && v.length > 0 ? ninegrid.j.querySelectorAll(this).addClass('filtered') : ninegrid.j.querySelectorAll(this).removeClass('filtered');
163
+ };
164
+
165
+ #onClick = (e) => {
166
+
167
+ e.preventDefault();
168
+ e.stopPropagation();
169
+
170
+ var panel = this.#owner.shadowRoot.querySelector('ng-filter-panel');
171
+
172
+ if (this.#owner.shadowRoot.querySelectorAll('ng-filter-panel').length > 1) throw "too many ng-filter-panel";
173
+ if (!panel) throw 'ng-filter-panel is null';
174
+
175
+ var cell = e.target.closest("th,td");
176
+
177
+ var l = $(e.target).offset().left - $(this.#owner).offset().left;// - $(panel).width() + $(e.target).width() + 1;
178
+ if (l < 0) l = 0;
179
+ if (l + $(panel).width() > $(this.#owner).width()) l = $(this.#owner).width() - $(panel).width() - 5;
180
+
181
+
182
+
183
+ var t = $(cell).offset().top + $(cell).height()- $(this.#owner).offset().top;//$(e.target).offset().top + $(e.target).height() + 2;
184
+
185
+ //$(panel).offset({left: l, top: t});
186
+ $(panel).css({left: l, top: t});
187
+
188
+ panel.refresh(this.#owner, this);
189
+ };
190
+ }
191
+
192
+ class ngFilterPanel extends HTMLElement
193
+ {
194
+ #target;
195
+ #timer;
196
+
197
+ constructor () {
198
+ super();
199
+ this.attachShadow({ mode: 'open' });
200
+ }
201
+
202
+ connectedCallback() {
203
+ const cssPath = this.getRootNode().host.closest("nine-grid").getAttribute("css-path") || "";
204
+
205
+ this.shadowRoot.innerHTML = `
206
+ <style>
207
+ @import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/ngFilterPanel.css";
208
+ ${ninegrid.getCustomPath(this,"ngFilterPanel.css")}
209
+ </style>
210
+
211
+ <div class="head">
212
+ <input type="text">
213
+ </div>
214
+ <nine-grid class="simple filter" css-path="${cssPath}" select-type="row" auto-fit-col="true" col-indicator-type="collapse">
215
+ <table style="display: none;">
216
+ <colgroup>
217
+ <col width="180" />
218
+ <col width="30" />
219
+ </colgroup>
220
+ <tbody>
221
+ <tr style="height: 24px;">
222
+ <td data-bind="LVL" data-expr="data.DATA2">
223
+ <ng-tree-item />
224
+ </td>
225
+ <td data-bind="CHK">
226
+ <ng-checkbox update-row-state="false" visible="data.LVL!=1" selected-border-color="white" />
227
+ </td>
228
+ </tr>
229
+ </tbody>
230
+ </table>
231
+ </nine-grid>
232
+
233
+ <div>
234
+ <label><input type="checkbox" checked>Select All</label>
235
+ <button id="btnOk">OK</button>
236
+ <button id="btnCancel">Cancel</button>
237
+ </div>
238
+ `;
239
+
240
+ $(this.shadowRoot).find("input[type=text]") .on("input", this.#onInput);
241
+ $(this.shadowRoot).find("input[type=checkbox]") .on("change", this.#onSelectAll);
242
+ $(this.shadowRoot).find("#btnOk") .on("click", this.#onOk);
243
+ $(this.shadowRoot).find("#btnCancel") .on("click", this.#onCancel);
244
+
245
+ //$(this).on("mousedown", e => { e.preventDefault(); e.stopPropagation(); });
246
+ //$(this).on("mousedown", e => { e.stopPropagation(); });
247
+ };
248
+
249
+ #onOk = (e) => {
250
+
251
+ var grd = this.shadowRoot.querySelector("nine-grid");
252
+
253
+ //ninegrid.j.querySelectorAll(grd).addClass("loading");
254
+ ninegrid.j.querySelectorAll(this.#target.owner).addClass("loading");
255
+
256
+
257
+ setTimeout(() => {
258
+
259
+ const LVL_IDX = grd.fields.indexOf("LVL");
260
+ const CHK_IDX = grd.fields.indexOf("CHK");
261
+ const COLNM_IDX = grd.fields.indexOf("COLNM");
262
+ const DATA_IDX = grd.fields.indexOf("DATA");
263
+
264
+ const checked = grd.data.getValidDataNF().filter(m => { return m.v[LVL_IDX] == 2 && m.v[CHK_IDX] == "Y"; });
265
+ const unchecked = grd.data.getValidDataNF().filter(m => { return m.v[LVL_IDX] == 2 && m.v[CHK_IDX] != "Y"; });
266
+
267
+ if (unchecked.length == 0) {
268
+ //this.#target.button.filterData = null;
269
+ }
270
+
271
+ var filterData = [];
272
+ if (checked.length > 0) {
273
+
274
+ [...new Set(checked.map(m => { return m.v[COLNM_IDX] }))].forEach(v => {
275
+ filterData.push({
276
+ colnm : v,
277
+ data : [...new Set(grd.data.getValidData().filter(m => { return m.v[CHK_IDX] == "Y" && m.v[COLNM_IDX] == v; }).map(m => { return m.v[DATA_IDX] || ''; }))].sort((a,b) => { return a > b ? 1 : -1; }),
278
+ });
279
+ });
280
+ }
281
+
282
+ console.log(filterData);
283
+
284
+ //console.log(this.#target);
285
+
286
+ //console.log(this.#target, this.#target.button);
287
+
288
+ //this.#target.button.filterData = filterData;//grd.data.getValidData().filter(item => { return item.CHK == "Y"; });//.map(item => { return item.DATA; });
289
+
290
+
291
+ /**
292
+ this.#target.owner.data.clearFilter();
293
+
294
+ $("ng-filter-button", this.#target.owner.body).each((index,el) => {
295
+ if (!el.filterData) return true;
296
+ el.filterData.forEach(o => {
297
+ const idx = this.#target.owner.fields.indexOf(o.colnm);
298
+ this.#target.owner.data.getValidData().filter(m => { return o.data.nineBinarySearch(m.v[idx] || '') < 0; }).map(m => { m.__ng.filtered = true; });
299
+ //this.#target.owner.data.resetIndex();
300
+ });
301
+ });
302
+
303
+ this.#target.owner.data.refreshFilter();
304
+ */
305
+
306
+ console.log(this.#target, this.#target.button)
307
+
308
+ this.#target.button.filterData = [...new Set(checked.map(m => { return m.v[DATA_IDX] }))];
309
+
310
+ console.log(this.#target.button.filterData)
311
+
312
+ var oParam = {};
313
+
314
+ $("ng-filter-button", this.#target.owner.body).each((index,el) => {
315
+
316
+ //console.log(el, el.filterData);
317
+
318
+ if (!el.filterData) return true;
319
+
320
+ //console.log(el, el.filterData);
321
+
322
+ el.colnms.forEach(colnm => {
323
+ oParam[colnm] = el.filterData;
324
+ });
325
+
326
+ /**
327
+ el.filterData.forEach(o => {
328
+
329
+ oParam[o.colnm] = o.data;
330
+
331
+ //const idx = this.#target.owner.fields.indexOf(o.colnm);
332
+ //this.#target.owner.data.getValidData().filter(m => { return o.data.nineBinarySearch(m.v[idx] || '') < 0; }).map(m => { m.__ng.filtered = true; });
333
+ }); */
334
+ });
335
+
336
+ console.log(oParam);
337
+
338
+ //this.#target.owner.data.setFilter(oParam);
339
+ this.#target.owner.filtering.on(oParam);
340
+
341
+
342
+ //this.#target.owner.data.getValidDataNF().filter(rowData => { return this.#target.button.filterData.findIndex(item => (item.DATA || '') == (rowData[item.COLNM] || '') ) < 0; }).map(item => { item.__ng.filtered = true; });
343
+ //this.#target.owner.scrollTo_V1(0);
344
+
345
+ //this.#target.owner.paging.reset();
346
+
347
+ ninegrid.j.querySelectorAll(this.#target.owner).removeClass("loading");
348
+
349
+ });
350
+
351
+ $(this).hide();
352
+ };
353
+
354
+
355
+
356
+ #onCancel = (e) => {
357
+ $(this).hide();
358
+ };
359
+
360
+ #onSelectAll = (e) => {
361
+ var grd = this.shadowRoot.querySelector("nine-grid");
362
+ var idx = (grd.fields.indexOf("CHK"));
363
+
364
+ grd.data.getValidData().map(m => { m.v[idx] = $(e.target).prop("checked") ? "Y" : "N"; });
365
+
366
+ grd.refreshData();
367
+ };
368
+
369
+
370
+ #onInput = (e) => {
371
+ var grd = this.shadowRoot.querySelector("nine-grid");
372
+
373
+
374
+ ninegrid.j.querySelectorAll(grd).addClass("loading");
375
+
376
+
377
+ var data = grd.dataManager.rawRecords;
378
+
379
+ data.map(m => { m.__ng.filtered = false; });
380
+
381
+
382
+ var v = $(e.target).val().toLowerCase();
383
+
384
+
385
+ const LVL_IDX = grd.fields.indexOf("LVL");
386
+ const DATA_IDX = grd.fields.indexOf("DATA");
387
+
388
+ data.filter(m => { return m.v[LVL_IDX] == 2 && String(m.v[DATA_IDX] || '').toLowerCase().indexOf(v) < 0; }).map(m => { m.__ng.filtered = true; });
389
+
390
+ grd.data.resetRecords();
391
+
392
+ if (this.#timer) {
393
+ clearTimeout(this.#timer);
394
+ this.#timer = null;
395
+ }
396
+ this.#timer = setTimeout(() => {
397
+ grd.dataManager.viewRecords.reset();
398
+ grd.dataManager.viewRecords.touch();
399
+ //ninegrid.j.querySelectorAll(grd).removeClass("loading");
400
+ }, 200)
401
+ };
402
+
403
+ refresh = (owner, filterButton) => {
404
+
405
+ var col = filterButton.closest('th,td').dataset.col;
406
+
407
+ //if (this.#target && this.#target.uuid == owner.uuid && this.#target.col == col && $(this).is(':visible')) {
408
+ if (this.#target && this.#target.col == col && $(this).is(':visible')) {
409
+ $(this).hide();
410
+ return;
411
+ }
412
+
413
+ this.#target = {
414
+ owner : owner,
415
+ button : filterButton,
416
+ uuid : owner.uuid,
417
+ col : col,
418
+ }
419
+
420
+ $(this).show();
421
+
422
+ ninegrid.j.querySelectorAll(this).addClass("loading");
423
+
424
+ $(this.shadowRoot).find("input[type=text]").val("");
425
+
426
+ setTimeout(() => {
427
+
428
+ var ds = [];
429
+ var colnms = [];
430
+ $(owner.template).find(`[data-col=${col}]`).each((index,el) => {
431
+ if (el.dataset.bind) colnms.push(el.dataset.bind);
432
+ });
433
+
434
+ var data = owner.data.getValidDataNF();
435
+ $("ng-filter-button", owner.body).each((index,el) => {
436
+
437
+ if (el.closest('th,td').dataset.col == col || !el.filterData) return true;
438
+ /**
439
+ el.filterData.forEach(o => {
440
+ var idx = owner.fields.indexOf(o.colnm);
441
+
442
+ if (idx >= 0) {
443
+ data = data.filter(m => { return o.data.nineBinarySearch(m.v[idx] || '') >= 0; });
444
+ }
445
+ });
446
+ */
447
+
448
+ console.log(el.filterData, el.colnms, el.dataset.bind);
449
+
450
+ el.colnms.forEach(colnm => {
451
+ var idx = owner.fields.indexOf(colnm);
452
+
453
+ console.log(idx);
454
+
455
+ if (idx >= 0) {
456
+ data = data.filter(m => { return el.filterData.nineBinarySearch(m.v[idx] || '') >= 0; });
457
+ }
458
+ });
459
+
460
+ //data = data.filter(rowData => { return el.filterData.findIndex(item => (item.DATA || '') == (rowData[item.COLNM] || '') ) >= 0; });
461
+ });
462
+
463
+
464
+ colnms = [...new Set(colnms)];
465
+ colnms.forEach((colnm,i) => {
466
+
467
+ ds.push({
468
+ LVL: 1,
469
+ CHK: 'N',
470
+ DATA2: '<span class="group">' + $(filterButton).closest('th,td').text() + (colnms.length > 1 ? ` #${i+1} (${colnm})` : '') + '</span>',
471
+ });
472
+
473
+ var filterData = [];
474
+ if (filterButton.filterData) {
475
+ var idx = filterButton.filterData.findIndex(item => item.colnm == colnm);
476
+ if (idx >= 0) {
477
+ filterData = filterButton.filterData[idx].data;
478
+ }
479
+ }
480
+
481
+ /**
482
+ var cell = $(`[data-col=${col}][data-bind=${colnm}]`, owner.template);
483
+ var expr = cell.attr("data-expr");
484
+ var exprFunc = (expr) ? owner.exprFunction(expr) : null;
485
+ */
486
+
487
+ const cell = ninegrid.j.querySelectorAll(`[data-col="${col}"][data-bind="${colnm}"]`, owner.tmpl).elem();
488
+ const expr = cell.getAttribute("data-expr");
489
+ const exprFunc = (expr) ? owner.exprFunction(expr) : null;
490
+
491
+ var data2 = [];
492
+ for (var rowData of data) {
493
+ var idx = owner.fields.indexOf(colnm);
494
+
495
+ if (expr) {
496
+ var o = owner.data.conv(rowData);
497
+ data2.push({v:o[colnm],v2:exprFunc(o, rowData.__ng.rowidx, owner.data)});
498
+ }
499
+ else {
500
+ data2.push({v:rowData.v[idx],v2:rowData.v[idx]});
501
+ }
502
+ }
503
+
504
+ [...new Set(data2.sort( (a,b) => { return (a.v2||'') > (b.v2||'') ? 1 : ((a.v2||'') < (b.v2||'') ? -1 : 0); } ).map((m) => JSON.stringify(m)))].map((m) => JSON.parse(m)).forEach(o => {
505
+ ds.push({
506
+ LVL : 2,
507
+ DATA : o.v,
508
+ DATA2 : o.v2 || ` <span class="empty">(empty)</span> ${o.v}`,
509
+ COLNM : colnm,
510
+ CHK : filterData.length == 0 || filterData.nineBinarySearch(o.v || '') >= 0 ? "Y" : "N",
511
+ });
512
+ });
513
+ });
514
+
515
+ var grd = this.shadowRoot.querySelector("nine-grid");
516
+ //grd.dataSource = ds;
517
+ grd.fields.add(["DATA","DATA2","COLNM"]);
518
+
519
+ grd.data.set(ds);
520
+
521
+ $(this.shadowRoot).find("input[type=checkbox]").prop("checked", grd.data.getValidData().filter(item => { return item.LVL == 2 && item.CHK != "Y"; }).length == 0 ? true : false);
522
+
523
+ this.shadowRoot.querySelector("input").focus();
524
+
525
+ ninegrid.j.querySelectorAll(this).removeClass("loading");
526
+ });
527
+ };
528
+ }
529
+
530
+
531
+ customElements.define("ng-filter-button", ngFilterButton);
532
+ customElements.define("ng-filter-panel", ngFilterPanel);