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.
@@ -2,7 +2,7 @@
2
2
  font-family: Arial, Helvetica, sans-serif;
3
3
  border-collapse: collapse;
4
4
  width: 100%;
5
- min-width: 800px;
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
  }
@@ -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: [], deleted: [], origin: [] };
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, onCreateNewKey
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
- let trEditor_html = this.config.column.map(f => {
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 items = "";
76
- for (let index = 0; index < f.items.length; index++) {
77
- const item = f.items[index];
78
- items += `<option value="${item.value}">${item.text}</option>`;
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
- <table id='${this.id}' class='dk-table'>
86
- <tr>
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
- <table data-primary-key='${this.config.primaryKey}' cellpadding="0" cellspacing="0" border="0" style="table-layout: fixed; height: 100%; width: 0px; position: relative; left: 0px;">
101
- <colgroup>${colWidths}</colgroup>
102
- <thead><tr>${th_html}</tr></thead>
103
- </table>
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;overflow: auto hidden;vertical-align: top;'>
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: 0px;position: absolute;left: 0px;top: 40px; display: none;">
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><tr>${trEditor_html}</tr></tbody>
122
+ <tbody>${this.editorDefault}</tbody>
116
123
  </table>
117
124
  </div>
118
125
  </td>
119
126
  </tr>
120
- <tr>
121
- <td class='gridStatusCell'></td>
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
- const lastRow = this.rowOnFocus;
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
- const lastRow = this.rowOnFocus;
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(lastRow, false);
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.find(f => f[primaryKey]?.toString() == currentKeyValue) || cache.origin.find(f => f[primaryKey]?.toString() == currentKeyValue);
235
+ let objectCurrent = cache.updated[currentKeyValue] || cache.origin[currentKeyValue];
201
236
  {
202
237
  let throwX = false;
203
- this.fireEvent('openEditor', (rs) => {
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(trTag = new HTMLElement(), isClear = false, isdelete = false) {
231
- const table = trTag.closest('table');
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.find(f => f[primaryKey]?.toString() == currentKeyValue) || cache.origin.find(f => f[primaryKey]?.toString() == currentKeyValue);
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 = cache.updated.filter(obj => obj[primaryKey] !== objectCurrent[primaryKey]);
271
- cache.updated.push(objectCurrent);
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
- td.textContent = f.items.find(i => i.value == item[f.fieldName])?.text;
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
- cancelChanges() {
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 = data;
319
- cache.updated = [];
320
- cache.deleted = [];
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
- const dataPrint = {};
323
- cache.origin.forEach(item => {
324
- dataPrint[item[tableConfig.primaryKey]] = item;
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(item => {
327
- dataPrint[item[tableConfig.primaryKey]] = item;
372
+ Object.keys(cache.updated).forEach(key => {
373
+ dataCollection[key] = cache.updated[key];
328
374
  });
329
- cache.deleted.forEach(item => {
330
- delete dataPrint[item[tableConfig.primaryKey]];
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
- Object.keys(dataPrint).forEach(
335
- key => {
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
- td.textContent = f.items.find(i => i.value == item[f.fieldName]).text;
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('onCreateNewKey', (rs) => {
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.push(newOb);
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(this.rowOnFocus, true, true);
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.find(f => f[primaryKey] == currentKeyValue);
498
+ const objectOriginal = cache.origin[currentKeyValue];
391
499
  if (objectOriginal) {
392
- cache.deleted.push(objectOriginal);
500
+ cache.deleted[currentKeyValue] = (objectOriginal);
393
501
  }
394
502
 
395
- let objectCache = cache.updated.find(f => f[primaryKey] == currentKeyValue);
503
+ let objectCache = cache.updated[currentKeyValue];
396
504
  if (objectCache) {
397
- cache.updated = cache.updated.filter(obj => obj[primaryKey] !== objectCache[primaryKey]);
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
- this.fireEvent('commitData', null, ({ updated: this.#cache.updated, deleted: this.#cache.deleted }));
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
- cache.updated = [];
416
- cache.deleted = [];
417
- this.loadData();
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
@@ -9,7 +9,7 @@
9
9
  "socket.io": "^4.7.2"
10
10
  },
11
11
  "name": "mdkcontroller",
12
- "version": "1.2.0",
12
+ "version": "1.2.2",
13
13
  "keywords": [],
14
14
  "author": "KHANHNBD <khanh272421@gmail.com>",
15
15
  "license": "ISC",
package/readme.md CHANGED
@@ -1 +1 @@
1
- #some thing
1
+ # Project Summary