mdkcontroller 1.2.0 → 1.2.2
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 +218 -81
- package/Cores/file/dk.js +27 -0
- package/package.json +1 -1
- package/readme.md +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;
|
|
@@ -21,7 +22,7 @@ class DKGrid {
|
|
|
21
22
|
addEventListener(eventName, callback) {
|
|
22
23
|
this.#event[eventName] = this.#event[eventName] || [];
|
|
23
24
|
this.#event[eventName].push(callback);
|
|
24
|
-
//rowClick, openEditor, commitData,
|
|
25
|
+
//rowClick, openEditor, commitData, onAddNewRow, onOpenEditor, onSelectorSelecting
|
|
25
26
|
}
|
|
26
27
|
fireEvent(eventName, callback, ...args) {
|
|
27
28
|
const callbacks = this.#event[eventName] || [];
|
|
@@ -47,7 +48,6 @@ class DKGrid {
|
|
|
47
48
|
console.error(`Không tìm thấy phần tử có ID: ${this.boxId}`);
|
|
48
49
|
return;
|
|
49
50
|
}
|
|
50
|
-
|
|
51
51
|
if (!this.config.primaryKey) {
|
|
52
52
|
this.config.primaryKey = this.config.column[0]?.fieldName || '';
|
|
53
53
|
}
|
|
@@ -56,34 +56,38 @@ class DKGrid {
|
|
|
56
56
|
box.innerHTML = tableTemplate;
|
|
57
57
|
this.tableRaw = document.getElementById(this.idRaw);
|
|
58
58
|
this.tableEditor = document.getElementById(this.idEditor);
|
|
59
|
+
this.statusBox = document.getElementById(this.id + "_status");
|
|
59
60
|
this.#attachEvents();
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
#generateTableHTML() {
|
|
63
64
|
const th_html = this.config.column.map(f => `<td class="GridHeader GridRow">${f.title}</td>`).join("");
|
|
65
|
+
let totalWidth = 0;
|
|
64
66
|
const colWidths = this.config.column.map(f => {
|
|
65
67
|
let width = f.width || (f.dataType === "string" ? 200 : f.dataType === "date" ? 140 : f.dataType === "number" ? 100 : 80);
|
|
68
|
+
totalWidth += width;
|
|
66
69
|
return `<col style="width: ${width}px;">`;
|
|
67
70
|
}).join("");
|
|
68
|
-
|
|
71
|
+
this.editorDefault = '<tr>' + this.config.column.map(f => {
|
|
69
72
|
switch (f.dataType) {
|
|
70
73
|
case "string": return `<td><input type='text'name='${f.fieldName}'/></td>`;
|
|
71
74
|
case "bool": return `<td><input type="checkbox" name='${f.fieldName}'></td>`;
|
|
72
75
|
case "date": return `<td><input type="date" name='${f.fieldName}'></td>`;
|
|
73
76
|
case "number": return `<td><input type="number" name='${f.fieldName}'></td>`;
|
|
74
77
|
case "select":
|
|
75
|
-
let
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
78
|
+
let itemSelector = f.items;
|
|
79
|
+
this.fireEvent('onSelectorSelecting', (rs) => {
|
|
80
|
+
itemSelector = rs || itemSelector;
|
|
81
|
+
}, f.fieldName, null);
|
|
82
|
+
let items = itemSelector.map(i => `<option value="${i.value}">${i.text}</option>`).join("");
|
|
80
83
|
return `<td><select name='${f.fieldName}'>${items}</select></td>`;
|
|
81
84
|
default: return `<td><input type='text' name='${f.fieldName}'/></td>`;
|
|
82
85
|
}
|
|
83
|
-
}).join("\r\n");
|
|
86
|
+
}).join("\r\n") + '</tr>';
|
|
84
87
|
return `
|
|
85
|
-
<
|
|
86
|
-
<
|
|
88
|
+
<div style='height: 100%;width: 100%; overflow: hidden;'>
|
|
89
|
+
<table id='${this.id}' class='dk-table' style='height: 100%;'>
|
|
90
|
+
<tr style='height: 1px;'>
|
|
87
91
|
<td class='gridToolCell'>
|
|
88
92
|
<div>
|
|
89
93
|
<ul id='${this.id}_gridToolCell' style='display: flex; list-style-type: none; margin: 5px;'>
|
|
@@ -91,36 +95,47 @@ class DKGrid {
|
|
|
91
95
|
<li data-cmd='del'><i class="fa fa-times" aria-hidden="true"></i></li>
|
|
92
96
|
<li data-cmd='cancel'><i class="fa fa-recycle" aria-hidden="true"></i></li>
|
|
93
97
|
<li data-cmd='save'><i class="fa fa-cloud-upload" aria-hidden="true"></i></li>
|
|
98
|
+
<li data-cmd='refresh'><input id='${this.id}_inputSearch' type='search' style='width:250px;'></li>
|
|
94
99
|
</ul>
|
|
95
100
|
</div>
|
|
96
101
|
</td>
|
|
97
102
|
</tr>
|
|
98
|
-
<tr>
|
|
103
|
+
<tr style='height: 1px;'>
|
|
99
104
|
<td class='gridHeaderCell'>
|
|
100
|
-
<
|
|
101
|
-
<
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
<div id='${this.id}_headerTitle' style='overflow-x: hidden;'>
|
|
106
|
+
<table cellpadding="0" cellspacing="0" border="0" style="table-layout: fixed; width: ${totalWidth}px; margin-right: 17px;">
|
|
107
|
+
<colgroup>${colWidths}</colgroup>
|
|
108
|
+
<thead><tr>${th_html}</tr></thead>
|
|
109
|
+
</table>
|
|
110
|
+
</div>
|
|
104
111
|
</td>
|
|
105
112
|
</tr>
|
|
106
113
|
<tr>
|
|
107
114
|
<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;">
|
|
115
|
+
<div id='${this.id}_bodyContent' style='min-height: 100px; position: relative; height: 100%; overflow: scroll;'>
|
|
116
|
+
<table id='${this.idRaw}' class='edit' cellpadding="0" cellspacing="0" border="0" style="table-layout: fixed;width: ${totalWidth}px;">
|
|
110
117
|
<colgroup>${colWidths}</colgroup>
|
|
111
118
|
<tbody></tbody>
|
|
112
119
|
</table>
|
|
113
|
-
<table id='${this.idEditor}' class='edit RowNavigator' cellpadding="0" cellspacing="0" border="0" style="table-layout: fixed;width:
|
|
120
|
+
<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
121
|
<colgroup>${colWidths}</colgroup>
|
|
115
|
-
<tbody
|
|
122
|
+
<tbody>${this.editorDefault}</tbody>
|
|
116
123
|
</table>
|
|
117
124
|
</div>
|
|
118
125
|
</td>
|
|
119
126
|
</tr>
|
|
120
|
-
<tr>
|
|
121
|
-
<td class='
|
|
127
|
+
<tr style='height: 1px;'>
|
|
128
|
+
<td class='gridToolCell'>
|
|
129
|
+
<div style='display: flex; align-items: center;'>
|
|
130
|
+
<ul id='${this.id}_gridPagingCell' style='display: flex; list-style-type: none; margin: 5px; padding: 2px 32px;'>
|
|
131
|
+
<li data-cmd='1'>1</li>
|
|
132
|
+
</ul>
|
|
133
|
+
<span id='${this.id}_status' style='font-size:18px;'>0/10</span>
|
|
134
|
+
</div>
|
|
135
|
+
</td>
|
|
122
136
|
</tr>
|
|
123
|
-
</table
|
|
137
|
+
</table>
|
|
138
|
+
</div>`;
|
|
124
139
|
}
|
|
125
140
|
|
|
126
141
|
#attachEvents() {
|
|
@@ -149,20 +164,40 @@ class DKGrid {
|
|
|
149
164
|
case "cancel": this.cancelChanges(); break;
|
|
150
165
|
}
|
|
151
166
|
});
|
|
167
|
+
this.pagingCell = document.getElementById(this.id + "_gridPagingCell");
|
|
168
|
+
this.pagingCell.addEventListener('click', (event) => {
|
|
169
|
+
const cmdElement = event.target.closest('li[data-cmd]');
|
|
170
|
+
if (!cmdElement) return;
|
|
171
|
+
|
|
172
|
+
const cmd = cmdElement.dataset.cmd;
|
|
173
|
+
const page = parseInt(cmd);
|
|
174
|
+
if (page) {
|
|
175
|
+
this.page.current = Math.min(page, this.page.total);
|
|
176
|
+
this.buildNav_List();
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
document.getElementById(dkgrid.id + "_bodyContent").addEventListener("scroll", function () {
|
|
180
|
+
const header = document.getElementById(dkgrid.id + "_headerTitle");
|
|
181
|
+
header.scrollLeft = document.getElementById(dkgrid.id + "_bodyContent").scrollLeft;
|
|
182
|
+
});
|
|
183
|
+
document.getElementById(dkgrid.id + "_inputSearch").addEventListener("keydown", function (event) {
|
|
184
|
+
if (event.key === "Enter") {
|
|
185
|
+
event.preventDefault();
|
|
186
|
+
dkgrid.buildNav_List();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
152
189
|
}
|
|
153
190
|
#keyDownOnTable(keyCode) {
|
|
154
191
|
// ESC
|
|
155
192
|
if (keyCode == 27) {
|
|
156
193
|
if (this.rowOnFocus) {
|
|
157
|
-
|
|
158
|
-
this.#closeEditor(lastRow, true);
|
|
194
|
+
this.#closeEditor(true);
|
|
159
195
|
}
|
|
160
196
|
}
|
|
161
197
|
// ENTER
|
|
162
198
|
if (keyCode == 13) {
|
|
163
199
|
if (this.rowOnFocus) {
|
|
164
|
-
|
|
165
|
-
this.#closeEditor(lastRow, false);
|
|
200
|
+
this.#closeEditor(false);
|
|
166
201
|
}
|
|
167
202
|
}
|
|
168
203
|
}
|
|
@@ -172,7 +207,7 @@ class DKGrid {
|
|
|
172
207
|
if (this.rowOnFocus) {
|
|
173
208
|
const lastRow = this.rowOnFocus;
|
|
174
209
|
if (lastRow.dataset.editting == "1") {
|
|
175
|
-
this.#closeEditor(
|
|
210
|
+
this.#closeEditor(false);
|
|
176
211
|
}
|
|
177
212
|
}
|
|
178
213
|
this.rowOnFocus = trTag;
|
|
@@ -197,10 +232,10 @@ class DKGrid {
|
|
|
197
232
|
|
|
198
233
|
const cache = this.#cache;
|
|
199
234
|
|
|
200
|
-
let objectCurrent = cache.updated
|
|
235
|
+
let objectCurrent = cache.updated[currentKeyValue] || cache.origin[currentKeyValue];
|
|
201
236
|
{
|
|
202
237
|
let throwX = false;
|
|
203
|
-
this.fireEvent('
|
|
238
|
+
this.fireEvent('onOpenEditor', (rs) => {
|
|
204
239
|
throwX = rs === false;
|
|
205
240
|
return !throwX;
|
|
206
241
|
}, objectCurrent, this);
|
|
@@ -212,10 +247,21 @@ class DKGrid {
|
|
|
212
247
|
const input = child.firstChild;
|
|
213
248
|
try {
|
|
214
249
|
if (input.tagName == "INPUT" || input.tagName == "SELECT") {
|
|
250
|
+
if (input.tagName == "SELECT") {
|
|
251
|
+
let itemSelector = tableConfig.column.find(f => f.fieldName == input.name).items;
|
|
252
|
+
this.fireEvent('onSelectorSelecting', (rs) => {
|
|
253
|
+
itemSelector = rs || itemSelector;
|
|
254
|
+
}, input.name, objectCurrent);
|
|
255
|
+
let items = itemSelector.map(i => `<option value="${i.value}">${i.text}</option>`).join("");
|
|
256
|
+
input.innerHTML = items;
|
|
257
|
+
}
|
|
258
|
+
|
|
215
259
|
input.value = objectCurrent[input.name] || "";
|
|
216
260
|
if (input.type == 'checkbox') {
|
|
217
261
|
input.checked = objectCurrent[input.name] || false;
|
|
218
262
|
}
|
|
263
|
+
|
|
264
|
+
this.fireEvent('onSetInput', null, input, objectCurrent);
|
|
219
265
|
}
|
|
220
266
|
} catch (exx) {
|
|
221
267
|
console.log("Error in openEditor: ", exx);
|
|
@@ -227,16 +273,17 @@ class DKGrid {
|
|
|
227
273
|
trTag.dataset.editting = '1';
|
|
228
274
|
return true;
|
|
229
275
|
}
|
|
230
|
-
#closeEditor(
|
|
231
|
-
const
|
|
276
|
+
#closeEditor(isClear = false, isdelete = false) {
|
|
277
|
+
const trTag = this.rowOnFocus;
|
|
278
|
+
if (trTag == null) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
232
281
|
const tbEditor = this.tableEditor;
|
|
233
282
|
if (!isdelete) {
|
|
234
|
-
const tableConfig = this.config;
|
|
235
|
-
const primaryKey = tableConfig.primaryKey;
|
|
236
283
|
const currentKeyValue = trTag.dataset.primaryValue;
|
|
237
284
|
const cache = this.#cache;
|
|
238
285
|
|
|
239
|
-
let objectCurrent = cache.updated
|
|
286
|
+
let objectCurrent = cache.updated[currentKeyValue] || { ...cache.origin[currentKeyValue] };
|
|
240
287
|
let objectEditing = {};
|
|
241
288
|
let hasChange = false;
|
|
242
289
|
tbEditor.querySelector('tbody').querySelectorAll('td').forEachExt(
|
|
@@ -267,11 +314,8 @@ class DKGrid {
|
|
|
267
314
|
Object.keys(objectEditing).forEach(key => {
|
|
268
315
|
objectCurrent[key] = objectEditing[key];
|
|
269
316
|
});
|
|
270
|
-
cache.updated
|
|
271
|
-
|
|
272
|
-
{
|
|
273
|
-
this.#createRow(trTag, objectCurrent);
|
|
274
|
-
}
|
|
317
|
+
cache.updated[currentKeyValue] = objectCurrent;
|
|
318
|
+
this.#createRow(trTag, objectCurrent);
|
|
275
319
|
}
|
|
276
320
|
}
|
|
277
321
|
}
|
|
@@ -294,46 +338,106 @@ class DKGrid {
|
|
|
294
338
|
case "date": td.textContent = item[f.fieldName] || ''; break;
|
|
295
339
|
case "number": td.textContent = item[f.fieldName] || ''; break;
|
|
296
340
|
case "select":
|
|
297
|
-
|
|
341
|
+
let itemSelector = f.items;
|
|
342
|
+
this.fireEvent('onSelectorSelecting', (rs) => {
|
|
343
|
+
itemSelector = rs || itemSelector;
|
|
344
|
+
}, f.fieldName, null);
|
|
345
|
+
td.textContent = itemSelector.find(i => i.value == item[f.fieldName])?.text;
|
|
298
346
|
break;
|
|
299
347
|
default: td.textContent = item[f.fieldName]; break;
|
|
300
348
|
}
|
|
301
349
|
trTag.appendChild(td);
|
|
302
350
|
});
|
|
303
351
|
}
|
|
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;
|
|
352
|
+
loadData(data) {
|
|
316
353
|
const cache = this.#cache;
|
|
317
354
|
if (data) {
|
|
318
|
-
cache.origin =
|
|
319
|
-
|
|
320
|
-
|
|
355
|
+
cache.origin = {};
|
|
356
|
+
data.forEach(item => {
|
|
357
|
+
cache.origin[item[this.config.primaryKey]] = item;
|
|
358
|
+
});
|
|
359
|
+
cache.updated = {};
|
|
360
|
+
cache.deleted = {};
|
|
361
|
+
this.page.total = Math.ceil(data.length / this.page.size);
|
|
321
362
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
363
|
+
this.buildNav_List();
|
|
364
|
+
}
|
|
365
|
+
buildNav_List(holdPage = false) {
|
|
366
|
+
const cache = this.#cache;
|
|
367
|
+
|
|
368
|
+
const dataCollection = {};
|
|
369
|
+
Object.keys(cache.origin).forEach(key => {
|
|
370
|
+
dataCollection[key] = cache.origin[key];
|
|
325
371
|
});
|
|
326
|
-
cache.updated.forEach(
|
|
327
|
-
|
|
372
|
+
Object.keys(cache.updated).forEach(key => {
|
|
373
|
+
dataCollection[key] = cache.updated[key];
|
|
328
374
|
});
|
|
329
|
-
cache.deleted.forEach(
|
|
330
|
-
delete
|
|
375
|
+
Object.keys(cache.deleted).forEach(key => {
|
|
376
|
+
delete dataCollection[key];
|
|
331
377
|
});
|
|
378
|
+
this.#closeEditor(false, false);
|
|
379
|
+
const dataCollection_array = [];
|
|
380
|
+
const textSearch = document.getElementById(this.id + "_inputSearch").value;
|
|
381
|
+
Object.values(dataCollection).forEach(item => {
|
|
382
|
+
if (!textSearch) {
|
|
383
|
+
dataCollection_array.push(item);
|
|
384
|
+
} else {
|
|
385
|
+
this.config.column.forEach(f => {
|
|
386
|
+
let textValue = item[f.fieldName];
|
|
387
|
+
if (f.dataType == "select") {
|
|
388
|
+
textValue = f.items.find(i => i.value == item[f.fieldName])?.text ?? textValue;
|
|
389
|
+
}
|
|
390
|
+
if (textValue?.toString().toLowerCase().includes(textSearch.toLowerCase())) {
|
|
391
|
+
dataCollection_array.push(item);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
const page = this.page;
|
|
399
|
+
page.total = Math.ceil(dataCollection_array.length / page.size);
|
|
400
|
+
page.current = Math.min(page.current, page.total);
|
|
401
|
+
|
|
402
|
+
const start = (page.current - 1) * page.size;
|
|
403
|
+
const end = start + page.size;
|
|
404
|
+
|
|
405
|
+
this.pagingCell.innerHTML = "";
|
|
406
|
+
{
|
|
407
|
+
const min = Math.max(2, page.current - 2);
|
|
408
|
+
const max = Math.min(page.total - 1, page.current + 2);
|
|
409
|
+
this.pagingCell.appendChild(hideCreatePageLi(1, "font-weight: bold; margin-right: 15px;"));
|
|
410
|
+
for (let index = min; index <= max; index++) {
|
|
411
|
+
this.pagingCell.appendChild(hideCreatePageLi(index));
|
|
412
|
+
}
|
|
413
|
+
if (page.total > 1) {
|
|
414
|
+
this.pagingCell.appendChild(hideCreatePageLi(page.total, "font-weight: bold; margin-left: 15px;"));
|
|
415
|
+
}
|
|
416
|
+
function hideCreatePageLi(num, style = '') {
|
|
417
|
+
const li = document.createElement('li');
|
|
418
|
+
li.dataset.cmd = num;
|
|
419
|
+
li.textContent = num;
|
|
420
|
+
li.style = style;
|
|
421
|
+
if (num == page.current) {
|
|
422
|
+
li.classList.add('active');
|
|
423
|
+
}
|
|
424
|
+
return li;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
const dataPrint = dataCollection_array.slice(start, end);
|
|
428
|
+
this.statusBox.textContent = `${dataPrint.length}/${dataCollection_array.length}`;
|
|
429
|
+
if (holdPage) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
this.printPage(dataPrint);
|
|
433
|
+
}
|
|
434
|
+
printPage(dataPrint = []) {
|
|
435
|
+
const table = this.tableRaw;
|
|
436
|
+
const tableConfig = this.config;
|
|
332
437
|
const tbody = table.querySelector('tbody');
|
|
333
438
|
tbody.innerHTML = '';
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const item = dataPrint[key];
|
|
439
|
+
dataPrint.forEach(
|
|
440
|
+
item => {
|
|
337
441
|
const tr = document.createElement('tr');
|
|
338
442
|
tr.dataset.primaryValue = item[tableConfig.primaryKey];
|
|
339
443
|
tr.dataset.editting = '0';
|
|
@@ -347,7 +451,11 @@ class DKGrid {
|
|
|
347
451
|
case "date": td.textContent = item[f.fieldName] || ''; break;
|
|
348
452
|
case "number": td.textContent = item[f.fieldName] || ''; break;
|
|
349
453
|
case "select":
|
|
350
|
-
|
|
454
|
+
let itemSelector = f.items;
|
|
455
|
+
this.fireEvent('onSelectorSelecting', (rs) => {
|
|
456
|
+
itemSelector = rs || itemSelector;
|
|
457
|
+
}, f.fieldName, null);
|
|
458
|
+
td.textContent = itemSelector.find(i => i.value == item[f.fieldName])?.text || '';
|
|
351
459
|
break;
|
|
352
460
|
default: td.textContent = item[f.fieldName]; break;
|
|
353
461
|
}
|
|
@@ -365,36 +473,36 @@ class DKGrid {
|
|
|
365
473
|
const primaryKey = tableConfig.primaryKey;
|
|
366
474
|
let newOb = {};
|
|
367
475
|
{
|
|
368
|
-
this.fireEvent('
|
|
369
|
-
newOb[primaryKey] = rs;
|
|
370
|
-
});
|
|
476
|
+
this.fireEvent('onAddNewRow', null, newOb);
|
|
371
477
|
}
|
|
372
478
|
if (!newOb[primaryKey]) {
|
|
373
479
|
newOb[primaryKey] = DKGrid.generateRandomString(32);
|
|
374
480
|
}
|
|
375
481
|
newTR.dataset.primaryValue = newOb[primaryKey];
|
|
376
482
|
const cache = this.#cache;
|
|
377
|
-
cache.updated
|
|
483
|
+
cache.updated[newOb[primaryKey]] = (newOb);
|
|
484
|
+
this.buildNav_List(true);
|
|
378
485
|
this.#createRow(newTR, newOb);
|
|
486
|
+
newTR.querySelector('td').click();
|
|
379
487
|
}
|
|
380
488
|
|
|
381
489
|
deleteRow() {
|
|
382
490
|
if (this.rowOnFocus) {
|
|
383
491
|
if (confirm("Bạn có chắc chắn muốn xóa dữ liệu này?") != true) return;
|
|
384
|
-
this.#closeEditor(
|
|
492
|
+
this.#closeEditor(true, true);
|
|
385
493
|
const cache = this.#cache;
|
|
386
494
|
const tableConfig = this.config;
|
|
387
495
|
const primaryKey = tableConfig.primaryKey;
|
|
388
496
|
const lastRow = this.rowOnFocus;
|
|
389
497
|
const currentKeyValue = lastRow.dataset.primaryValue;
|
|
390
|
-
const objectOriginal = cache.origin
|
|
498
|
+
const objectOriginal = cache.origin[currentKeyValue];
|
|
391
499
|
if (objectOriginal) {
|
|
392
|
-
cache.deleted
|
|
500
|
+
cache.deleted[currentKeyValue] = (objectOriginal);
|
|
393
501
|
}
|
|
394
502
|
|
|
395
|
-
let objectCache = cache.updated
|
|
503
|
+
let objectCache = cache.updated[currentKeyValue];
|
|
396
504
|
if (objectCache) {
|
|
397
|
-
|
|
505
|
+
delete cache.updated[currentKeyValue];
|
|
398
506
|
}
|
|
399
507
|
|
|
400
508
|
table.dataset.cache = JSON.stringify(cache);
|
|
@@ -402,9 +510,36 @@ class DKGrid {
|
|
|
402
510
|
delete this.rowOnFocus;
|
|
403
511
|
}
|
|
404
512
|
}
|
|
513
|
+
getData() {
|
|
514
|
+
const datas = [];
|
|
515
|
+
const cache = this.#cache;
|
|
516
|
+
const dataCollection = {};
|
|
517
|
+
Object.keys(cache.origin).forEach(key => {
|
|
518
|
+
dataCollection[key] = cache.origin[key];
|
|
519
|
+
});
|
|
520
|
+
Object.keys(cache.updated).forEach(key => {
|
|
521
|
+
dataCollection[key] = cache.updated[key];
|
|
522
|
+
});
|
|
523
|
+
Object.keys(cache.deleted).forEach(key => {
|
|
524
|
+
delete dataCollection[key];
|
|
525
|
+
});
|
|
405
526
|
|
|
527
|
+
const dataCollection_array = [];
|
|
528
|
+
Object.values(dataCollection).forEach(item => {
|
|
529
|
+
dataCollection_array.push(item);
|
|
530
|
+
});
|
|
531
|
+
return dataCollection_array;
|
|
532
|
+
}
|
|
406
533
|
commitData() {
|
|
407
|
-
|
|
534
|
+
const cache = this.#cache;
|
|
535
|
+
const data = { updated: [], deleted: [] };
|
|
536
|
+
Object.keys(cache.updated).forEach(key => {
|
|
537
|
+
data.updated.push(cache.updated[key]);
|
|
538
|
+
});
|
|
539
|
+
Object.keys(cache.deleted).forEach(key => {
|
|
540
|
+
data.deleted.push(cache.deleted[key]);
|
|
541
|
+
});
|
|
542
|
+
this.fireEvent('commitData', null, data);
|
|
408
543
|
}
|
|
409
544
|
|
|
410
545
|
cancelChanges() {
|
|
@@ -412,9 +547,11 @@ class DKGrid {
|
|
|
412
547
|
return;
|
|
413
548
|
}
|
|
414
549
|
const cache = this.#cache;
|
|
415
|
-
|
|
416
|
-
cache.
|
|
417
|
-
|
|
550
|
+
const dataOrigin = [];
|
|
551
|
+
Object.keys(cache.origin).forEach(key => {
|
|
552
|
+
dataOrigin.push(cache.origin[key]);
|
|
553
|
+
});
|
|
554
|
+
this.loadData(dataOrigin);
|
|
418
555
|
}
|
|
419
556
|
static inputCheckboxReadOnly(event) {
|
|
420
557
|
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;
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Project Summary
|