mdkcontroller 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cores/file/DKGrid.css +11 -1
- package/Cores/file/DKGrid.js +146 -54
- package/Cores/file/dk.js +27 -0
- package/package.json +1 -1
package/Cores/file/DKGrid.css
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
font-family: Arial, Helvetica, sans-serif;
|
|
3
3
|
border-collapse: collapse;
|
|
4
4
|
width: 100%;
|
|
5
|
-
|
|
5
|
+
table-layout: fixed;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
.dk-table td {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
margin-right: 3px;
|
|
33
33
|
border-radius: 6px;
|
|
34
34
|
cursor: pointer;
|
|
35
|
+
place-self: center;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
.dk-table .gridToolCell ul li:hover {
|
|
@@ -44,6 +45,11 @@
|
|
|
44
45
|
padding: 5px;
|
|
45
46
|
font-size: 19px;
|
|
46
47
|
font-weight: bold;
|
|
48
|
+
height: 38px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.dk-table .gridBodyCell {
|
|
52
|
+
vertical-align: text-top;
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
.dk-table .RowNavigator td {
|
|
@@ -119,4 +125,8 @@
|
|
|
119
125
|
.dk-actionsBar button:active,
|
|
120
126
|
.dk-actionsBar button:hover {
|
|
121
127
|
border-color: #0fbd7db6;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.active {
|
|
131
|
+
background: #0075ffc4;
|
|
122
132
|
}
|
package/Cores/file/DKGrid.js
CHANGED
|
@@ -7,9 +7,10 @@ class DKGrid {
|
|
|
7
7
|
this.idRaw = boxId + "_autogrid_dataraw";
|
|
8
8
|
this.idEditor = boxId + "_autogrid_editor";
|
|
9
9
|
this.config = { ...DKGrid.defaultConfig, ...config };
|
|
10
|
-
this.#cache = { updated:
|
|
10
|
+
this.#cache = { updated: {}, deleted: {}, origin: {} };
|
|
11
11
|
this.rowOnFocus = null;
|
|
12
12
|
this.#event = {};
|
|
13
|
+
this.page = { current: 1, total: 1, size: 10 };
|
|
13
14
|
if (!config) {
|
|
14
15
|
console.log("Config default cho table " + boxid, DKGrid.configDefault);
|
|
15
16
|
return;
|
|
@@ -56,13 +57,16 @@ class DKGrid {
|
|
|
56
57
|
box.innerHTML = tableTemplate;
|
|
57
58
|
this.tableRaw = document.getElementById(this.idRaw);
|
|
58
59
|
this.tableEditor = document.getElementById(this.idEditor);
|
|
60
|
+
this.statusBox = document.getElementById(this.id + "_status");
|
|
59
61
|
this.#attachEvents();
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
#generateTableHTML() {
|
|
63
65
|
const th_html = this.config.column.map(f => `<td class="GridHeader GridRow">${f.title}</td>`).join("");
|
|
66
|
+
let totalWidth = 0;
|
|
64
67
|
const colWidths = this.config.column.map(f => {
|
|
65
68
|
let width = f.width || (f.dataType === "string" ? 200 : f.dataType === "date" ? 140 : f.dataType === "number" ? 100 : 80);
|
|
69
|
+
totalWidth += width;
|
|
66
70
|
return `<col style="width: ${width}px;">`;
|
|
67
71
|
}).join("");
|
|
68
72
|
let trEditor_html = this.config.column.map(f => {
|
|
@@ -82,8 +86,9 @@ class DKGrid {
|
|
|
82
86
|
}
|
|
83
87
|
}).join("\r\n");
|
|
84
88
|
return `
|
|
85
|
-
<
|
|
86
|
-
<
|
|
89
|
+
<div style='height: 100%;width: 100%; overflow: hidden;'>
|
|
90
|
+
<table id='${this.id}' class='dk-table' style='height: 100%;'>
|
|
91
|
+
<tr style='height: 1px;'>
|
|
87
92
|
<td class='gridToolCell'>
|
|
88
93
|
<div>
|
|
89
94
|
<ul id='${this.id}_gridToolCell' style='display: flex; list-style-type: none; margin: 5px;'>
|
|
@@ -91,36 +96,51 @@ class DKGrid {
|
|
|
91
96
|
<li data-cmd='del'><i class="fa fa-times" aria-hidden="true"></i></li>
|
|
92
97
|
<li data-cmd='cancel'><i class="fa fa-recycle" aria-hidden="true"></i></li>
|
|
93
98
|
<li data-cmd='save'><i class="fa fa-cloud-upload" aria-hidden="true"></i></li>
|
|
99
|
+
<li data-cmd='refresh'><input id='${this.id}_inputSearch' type='search' style='width:150px;'></li>
|
|
94
100
|
</ul>
|
|
95
101
|
</div>
|
|
96
102
|
</td>
|
|
97
103
|
</tr>
|
|
98
|
-
<tr>
|
|
104
|
+
<tr style='height: 1px;'>
|
|
99
105
|
<td class='gridHeaderCell'>
|
|
100
|
-
<
|
|
101
|
-
<
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
<div id='${this.id}_headerTitle' style='overflow-x: hidden;'>
|
|
107
|
+
<table cellpadding="0" cellspacing="0" border="0" style="table-layout: fixed; width: ${totalWidth}px; margin-right: 17px;">
|
|
108
|
+
<colgroup>${colWidths}</colgroup>
|
|
109
|
+
<thead><tr>${th_html}</tr></thead>
|
|
110
|
+
</table>
|
|
111
|
+
</div>
|
|
104
112
|
</td>
|
|
105
113
|
</tr>
|
|
106
114
|
<tr>
|
|
107
115
|
<td class='gridBodyCell'>
|
|
108
|
-
<div style='position: relative;
|
|
109
|
-
<table id='${this.idRaw}' class='edit' cellpadding="0" cellspacing="0" border="0" style="table-layout: fixed;">
|
|
116
|
+
<div id='${this.id}_bodyContent' style='position: relative; height: 100%; overflow: scroll;'>
|
|
117
|
+
<table id='${this.idRaw}' class='edit' cellpadding="0" cellspacing="0" border="0" style="table-layout: fixed;width: ${totalWidth}px;">
|
|
110
118
|
<colgroup>${colWidths}</colgroup>
|
|
111
119
|
<tbody></tbody>
|
|
112
120
|
</table>
|
|
113
|
-
<table id='${this.idEditor}' class='edit RowNavigator' cellpadding="0" cellspacing="0" border="0" style="table-layout: fixed;width:
|
|
121
|
+
<table id='${this.idEditor}' class='edit RowNavigator' cellpadding="0" cellspacing="0" border="0" style="table-layout: fixed;width: ${totalWidth}px;position: absolute;left: 0px;top: 40px; display: none;">
|
|
114
122
|
<colgroup>${colWidths}</colgroup>
|
|
115
123
|
<tbody><tr>${trEditor_html}</tr></tbody>
|
|
116
124
|
</table>
|
|
117
125
|
</div>
|
|
118
126
|
</td>
|
|
119
127
|
</tr>
|
|
120
|
-
<tr>
|
|
121
|
-
<td class='
|
|
128
|
+
<tr style='height: 1px;'>
|
|
129
|
+
<td class='gridToolCell'>
|
|
130
|
+
<div style='display: flex; align-items: center;'>
|
|
131
|
+
<ul id='${this.id}_gridPagingCell' style='display: flex; list-style-type: none; margin: 5px; padding: 2px 32px;'>
|
|
132
|
+
<li data-cmd='1'>1</li>
|
|
133
|
+
<li data-cmd='2'>2</li>
|
|
134
|
+
<li data-cmd='3'>3</li>
|
|
135
|
+
<li data-cmd='4'>4</li>
|
|
136
|
+
<li data-cmd='5'>5</li>
|
|
137
|
+
</ul>
|
|
138
|
+
<span id='${this.id}_status' style='font-size:18px;'>xx/50</span>
|
|
139
|
+
</div>
|
|
140
|
+
</td>
|
|
122
141
|
</tr>
|
|
123
|
-
</table
|
|
142
|
+
</table>
|
|
143
|
+
</div>`;
|
|
124
144
|
}
|
|
125
145
|
|
|
126
146
|
#attachEvents() {
|
|
@@ -149,6 +169,28 @@ class DKGrid {
|
|
|
149
169
|
case "cancel": this.cancelChanges(); break;
|
|
150
170
|
}
|
|
151
171
|
});
|
|
172
|
+
this.pagingCell = document.getElementById(this.id + "_gridPagingCell");
|
|
173
|
+
this.pagingCell.addEventListener('click', (event) => {
|
|
174
|
+
const cmdElement = event.target.closest('li[data-cmd]');
|
|
175
|
+
if (!cmdElement) return;
|
|
176
|
+
|
|
177
|
+
const cmd = cmdElement.dataset.cmd;
|
|
178
|
+
const page = parseInt(cmd);
|
|
179
|
+
if (page) {
|
|
180
|
+
this.page.current = Math.min(page, this.page.total);
|
|
181
|
+
this.loadDataByPage();
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
document.getElementById(dkgrid.id + "_bodyContent").addEventListener("scroll", function () {
|
|
185
|
+
const header = document.getElementById(dkgrid.id + "_headerTitle");
|
|
186
|
+
header.scrollLeft = document.getElementById(dkgrid.id + "_bodyContent").scrollLeft;
|
|
187
|
+
});
|
|
188
|
+
document.getElementById(dkgrid.id + "_inputSearch").addEventListener("keydown", function (event) {
|
|
189
|
+
if (event.key === "Enter") {
|
|
190
|
+
event.preventDefault();
|
|
191
|
+
dkgrid.loadDataByPage();
|
|
192
|
+
}
|
|
193
|
+
});
|
|
152
194
|
}
|
|
153
195
|
#keyDownOnTable(keyCode) {
|
|
154
196
|
// ESC
|
|
@@ -197,7 +239,7 @@ class DKGrid {
|
|
|
197
239
|
|
|
198
240
|
const cache = this.#cache;
|
|
199
241
|
|
|
200
|
-
let objectCurrent = cache.updated
|
|
242
|
+
let objectCurrent = cache.updated[currentKeyValue] || cache.origin[currentKeyValue];
|
|
201
243
|
{
|
|
202
244
|
let throwX = false;
|
|
203
245
|
this.fireEvent('openEditor', (rs) => {
|
|
@@ -236,7 +278,7 @@ class DKGrid {
|
|
|
236
278
|
const currentKeyValue = trTag.dataset.primaryValue;
|
|
237
279
|
const cache = this.#cache;
|
|
238
280
|
|
|
239
|
-
let objectCurrent = cache.updated
|
|
281
|
+
let objectCurrent = cache.updated[currentKeyValue] || {...cache.origin[currentKeyValue]};
|
|
240
282
|
let objectEditing = {};
|
|
241
283
|
let hasChange = false;
|
|
242
284
|
tbEditor.querySelector('tbody').querySelectorAll('td').forEachExt(
|
|
@@ -267,11 +309,8 @@ class DKGrid {
|
|
|
267
309
|
Object.keys(objectEditing).forEach(key => {
|
|
268
310
|
objectCurrent[key] = objectEditing[key];
|
|
269
311
|
});
|
|
270
|
-
cache.updated
|
|
271
|
-
|
|
272
|
-
{
|
|
273
|
-
this.#createRow(trTag, objectCurrent);
|
|
274
|
-
}
|
|
312
|
+
cache.updated[currentKeyValue] = objectCurrent;
|
|
313
|
+
this.#createRow(trTag, objectCurrent);
|
|
275
314
|
}
|
|
276
315
|
}
|
|
277
316
|
}
|
|
@@ -301,39 +340,90 @@ class DKGrid {
|
|
|
301
340
|
trTag.appendChild(td);
|
|
302
341
|
});
|
|
303
342
|
}
|
|
304
|
-
|
|
305
|
-
if (confirm("Bạn có chắc chắn muốn hủy bỏ tất cả thay đổi không?") != true) {
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
const cache = this.#cache;
|
|
309
|
-
cache.updated = [];
|
|
310
|
-
cache.deleted = [];
|
|
311
|
-
this.loadData();
|
|
312
|
-
}
|
|
313
|
-
loadData(data = undefined) {
|
|
314
|
-
let table = this.tableRaw;
|
|
315
|
-
const tableConfig = this.config;
|
|
343
|
+
loadData(data) {
|
|
316
344
|
const cache = this.#cache;
|
|
317
345
|
if (data) {
|
|
318
|
-
cache.origin =
|
|
319
|
-
|
|
320
|
-
|
|
346
|
+
cache.origin = {};
|
|
347
|
+
data.forEach(item => {
|
|
348
|
+
cache.origin[item[this.config.primaryKey]] = item;
|
|
349
|
+
});
|
|
350
|
+
cache.updated = {};
|
|
351
|
+
cache.deleted = {};
|
|
352
|
+
this.page.total = Math.ceil(data.length / this.page.size);
|
|
321
353
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
354
|
+
this.loadDataByPage();
|
|
355
|
+
}
|
|
356
|
+
loadDataByPage() {
|
|
357
|
+
const cache = this.#cache;
|
|
358
|
+
|
|
359
|
+
const dataCollection = {};
|
|
360
|
+
Object.keys(cache.origin).forEach(key => {
|
|
361
|
+
dataCollection[key] = cache.origin[key];
|
|
325
362
|
});
|
|
326
|
-
cache.updated.forEach(
|
|
327
|
-
|
|
363
|
+
Object.keys(cache.updated).forEach(key => {
|
|
364
|
+
dataCollection[key] = cache.updated[key];
|
|
328
365
|
});
|
|
329
|
-
cache.deleted.forEach(
|
|
330
|
-
delete
|
|
366
|
+
Object.keys(cache.deleted).forEach(key => {
|
|
367
|
+
delete dataCollection[key];
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
const dataCollection_array = [];
|
|
371
|
+
const textSearch = document.getElementById(this.id + "_inputSearch").value;
|
|
372
|
+
Object.values(dataCollection).forEach(item => {
|
|
373
|
+
if (!textSearch) {
|
|
374
|
+
dataCollection_array.push(item);
|
|
375
|
+
} else {
|
|
376
|
+
this.config.column.forEach(f => {
|
|
377
|
+
let textValue = item[f.fieldName];
|
|
378
|
+
if (f.dataType == "select") {
|
|
379
|
+
textValue = f.items.find(i => i.value == item[f.fieldName])?.text ?? textValue;
|
|
380
|
+
}
|
|
381
|
+
if (textValue?.toString().toLowerCase().includes(textSearch.toLowerCase())) {
|
|
382
|
+
dataCollection_array.push(item);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
}
|
|
331
387
|
});
|
|
388
|
+
|
|
389
|
+
const page = this.page;
|
|
390
|
+
page.total = Math.ceil(dataCollection_array.length / page.size);
|
|
391
|
+
page.current = Math.min(page.current, page.total);
|
|
392
|
+
|
|
393
|
+
const start = (page.current - 1) * page.size;
|
|
394
|
+
const end = start + page.size;
|
|
395
|
+
|
|
396
|
+
this.pagingCell.innerHTML = "";
|
|
397
|
+
{
|
|
398
|
+
const min = Math.max(2, page.current - 2);
|
|
399
|
+
const max = Math.min(page.total - 1, page.current + 2);
|
|
400
|
+
this.pagingCell.appendChild(hideCreatePageLi(1, "font-weight: bold; margin-right: 15px;"));
|
|
401
|
+
for (let index = min; index <= max; index++) {
|
|
402
|
+
this.pagingCell.appendChild(hideCreatePageLi(index));
|
|
403
|
+
}
|
|
404
|
+
this.pagingCell.appendChild(hideCreatePageLi(page.total, "font-weight: bold; margin-left: 15px;"));
|
|
405
|
+
function hideCreatePageLi(num, style = '') {
|
|
406
|
+
const li = document.createElement('li');
|
|
407
|
+
li.dataset.cmd = num;
|
|
408
|
+
li.textContent = num;
|
|
409
|
+
li.style = style;
|
|
410
|
+
if (num == page.current) {
|
|
411
|
+
li.classList.add('active');
|
|
412
|
+
}
|
|
413
|
+
return li;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
const dataPrint = dataCollection_array.slice(start, end);
|
|
417
|
+
this.statusBox.textContent = `${dataPrint.length}/${dataCollection_array.length}`;
|
|
418
|
+
this.printPage(dataPrint);
|
|
419
|
+
}
|
|
420
|
+
printPage(dataPrint = []) {
|
|
421
|
+
const table = this.tableRaw;
|
|
422
|
+
const tableConfig = this.config;
|
|
332
423
|
const tbody = table.querySelector('tbody');
|
|
333
424
|
tbody.innerHTML = '';
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const item = dataPrint[key];
|
|
425
|
+
dataPrint.forEach(
|
|
426
|
+
item => {
|
|
337
427
|
const tr = document.createElement('tr');
|
|
338
428
|
tr.dataset.primaryValue = item[tableConfig.primaryKey];
|
|
339
429
|
tr.dataset.editting = '0';
|
|
@@ -374,7 +464,7 @@ class DKGrid {
|
|
|
374
464
|
}
|
|
375
465
|
newTR.dataset.primaryValue = newOb[primaryKey];
|
|
376
466
|
const cache = this.#cache;
|
|
377
|
-
cache.updated
|
|
467
|
+
cache.updated[newOb[primaryKey]] = (newOb);
|
|
378
468
|
this.#createRow(newTR, newOb);
|
|
379
469
|
}
|
|
380
470
|
|
|
@@ -387,14 +477,14 @@ class DKGrid {
|
|
|
387
477
|
const primaryKey = tableConfig.primaryKey;
|
|
388
478
|
const lastRow = this.rowOnFocus;
|
|
389
479
|
const currentKeyValue = lastRow.dataset.primaryValue;
|
|
390
|
-
const objectOriginal = cache.origin
|
|
480
|
+
const objectOriginal = cache.origin[currentKeyValue];
|
|
391
481
|
if (objectOriginal) {
|
|
392
|
-
cache.deleted
|
|
482
|
+
cache.deleted[currentKeyValue] = (objectOriginal);
|
|
393
483
|
}
|
|
394
484
|
|
|
395
|
-
let objectCache = cache.updated
|
|
485
|
+
let objectCache = cache.updated[currentKeyValue];
|
|
396
486
|
if (objectCache) {
|
|
397
|
-
|
|
487
|
+
delete cache.updated[currentKeyValue];
|
|
398
488
|
}
|
|
399
489
|
|
|
400
490
|
table.dataset.cache = JSON.stringify(cache);
|
|
@@ -412,9 +502,11 @@ class DKGrid {
|
|
|
412
502
|
return;
|
|
413
503
|
}
|
|
414
504
|
const cache = this.#cache;
|
|
415
|
-
|
|
416
|
-
cache.
|
|
417
|
-
|
|
505
|
+
const dataOrigin = [];
|
|
506
|
+
Object.keys(cache.origin).forEach(key => {
|
|
507
|
+
dataOrigin.push(cache.origin[key]);
|
|
508
|
+
});
|
|
509
|
+
this.loadData(dataOrigin);
|
|
418
510
|
}
|
|
419
511
|
static inputCheckboxReadOnly(event) {
|
|
420
512
|
event.preventDefault();
|
package/Cores/file/dk.js
CHANGED
|
@@ -122,6 +122,33 @@ const DK = {
|
|
|
122
122
|
const imgTag = dk_overlay.getElementsByTagName('img')[0];
|
|
123
123
|
imgTag.style.height = dialog.parentNode.parentNode.clientHeight + 'px';
|
|
124
124
|
},
|
|
125
|
+
DKDataCache: {},
|
|
126
|
+
buildFormEvent: () => {
|
|
127
|
+
document.querySelectorAll("input, select").forEach(field => {
|
|
128
|
+
const formP = field.closest('form');
|
|
129
|
+
if (formP && formP.id && field.parentElement.tagName != 'TD' && field.name) {
|
|
130
|
+
DK.DKDataCache[formP.id] = DK.DKDataCache[formP.id] ?? {};
|
|
131
|
+
field.addEventListener("blur", (event) => {
|
|
132
|
+
const fieldName = field.name;
|
|
133
|
+
if (DK.DKDataCache[formP.id][fieldName] != field.value) {
|
|
134
|
+
const oldOB = { ...DK.DKDataCache[formP.id] };
|
|
135
|
+
DK.DKDataCache[formP.id][fieldName] = field.value;
|
|
136
|
+
|
|
137
|
+
const fnname = `${formP.id}_${field.name}_updated`;
|
|
138
|
+
const formEvent = window[`${formP.id}_updated`];
|
|
139
|
+
const fieldEvent = window[fnname];
|
|
140
|
+
if (fieldEvent) {
|
|
141
|
+
fieldEvent(field.value, oldOB[fieldName], { ...oldOB });
|
|
142
|
+
}
|
|
143
|
+
if (formEvent) {
|
|
144
|
+
formEvent(DK.DKDataCache[formP.id], { ...oldOB });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
},
|
|
125
152
|
ImportCss: (src) => {
|
|
126
153
|
var link = document.createElement("link");
|
|
127
154
|
link.href = src;
|