mdkcontroller 1.2.1 → 1.2.3

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.
@@ -1,3 +1,14 @@
1
+ .dk-table textarea {
2
+ resize: none;
3
+ overflow: auto;
4
+ scrollbar-width: none;
5
+ }
6
+
7
+ .dk-table textarea::-webkit-scrollbar {
8
+ display: none;
9
+ /* Chrome & Safari */
10
+ }
11
+
1
12
  .dk-table {
2
13
  font-family: Arial, Helvetica, sans-serif;
3
14
  border-collapse: collapse;
@@ -7,6 +18,7 @@
7
18
 
8
19
  .dk-table td {
9
20
  border: 1px solid #ddd;
21
+ overflow: hidden;
10
22
  }
11
23
 
12
24
  .dk-table th {
@@ -55,7 +67,7 @@
55
67
  .dk-table .RowNavigator td {
56
68
  background: white;
57
69
  border-bottom: 1px solid #ff2828d6;
58
- border-radius: 7px;
70
+ /* border-radius: 7px; */
59
71
  }
60
72
 
61
73
  .dk-table .edit {
@@ -67,6 +79,7 @@
67
79
  }
68
80
 
69
81
  .dk-table .RowNavigator td>input,
82
+ .dk-table .RowNavigator td>textarea,
70
83
  .dk-table .RowNavigator td>select {
71
84
  height: 23px;
72
85
  font-size: 18px;
@@ -80,51 +93,28 @@
80
93
  background-color: #f1f1f1;
81
94
  }
82
95
 
83
- .dk-table .edit input[type="checkbox"] {
96
+ /* .dk-table .edit input[type="checkbox"] {
84
97
  min-height: 22px;
85
98
  width: 30px;
86
99
  margin: auto;
87
100
  display: block;
88
- }
101
+ } */
89
102
 
90
- .dk-table .edit input[type="checkbox"]:disabled {
103
+ /* .dk-table .edit input[type="checkbox"]:disabled {
91
104
  cursor: not-allowed;
92
105
  }
93
106
 
94
107
  .dk-table .edit input:not([type="checkbox"]) :focus {
95
108
  outline: 1px solid rgba(65, 185, 65, 0.705);
96
- }
109
+ } */
97
110
 
98
- .dk-table .edit input:not(:disabled),
99
- .dk-table .edit select {
111
+ .dk-table .edit td * {
100
112
  display: block;
101
- color: #495057;
102
- background-color: #fff;
103
- background-image: none;
104
- background-clip: padding-box;
105
- border: 1px solid rgba(0, 0, 0, 0.15);
106
- border-radius: 0.25rem;
107
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
108
113
  width: -webkit-fill-available;
109
114
  padding: 0;
115
+ border: 0px;
110
116
  outline: none;
111
- }
112
-
113
- .dk-actionsBar {
114
- padding: 5px 10px;
115
- width: max-content;
116
- }
117
-
118
- .dk-actionsBar button {
119
- border: 2px solid #0e9966b6;
120
- border-radius: 5px;
121
- cursor: pointer;
122
- transition: all 1s;
123
- }
124
-
125
- .dk-actionsBar button:active,
126
- .dk-actionsBar button:hover {
127
- border-color: #0fbd7db6;
117
+ font-family: sans-serif;
128
118
  }
129
119
 
130
120
  .active {
@@ -22,7 +22,7 @@ class DKGrid {
22
22
  addEventListener(eventName, callback) {
23
23
  this.#event[eventName] = this.#event[eventName] || [];
24
24
  this.#event[eventName].push(callback);
25
- //rowClick, openEditor, commitData, onCreateNewKey
25
+ //rowClick, openEditor, commitData, onAddNewRow, onOpenEditor, onSelectorSelecting
26
26
  }
27
27
  fireEvent(eventName, callback, ...args) {
28
28
  const callbacks = this.#event[eventName] || [];
@@ -48,7 +48,6 @@ class DKGrid {
48
48
  console.error(`Không tìm thấy phần tử có ID: ${this.boxId}`);
49
49
  return;
50
50
  }
51
-
52
51
  if (!this.config.primaryKey) {
53
52
  this.config.primaryKey = this.config.column[0]?.fieldName || '';
54
53
  }
@@ -66,25 +65,26 @@ class DKGrid {
66
65
  let totalWidth = 0;
67
66
  const colWidths = this.config.column.map(f => {
68
67
  let width = f.width || (f.dataType === "string" ? 200 : f.dataType === "date" ? 140 : f.dataType === "number" ? 100 : 80);
68
+ f.width = width;
69
69
  totalWidth += width;
70
70
  return `<col style="width: ${width}px;">`;
71
71
  }).join("");
72
- let trEditor_html = this.config.column.map(f => {
72
+ this.editorDefault = '<tr>' + this.config.column.map(f => {
73
73
  switch (f.dataType) {
74
- case "string": return `<td><input type='text'name='${f.fieldName}'/></td>`;
74
+ case "string": return `<td><textarea name='${f.fieldName}'></textarea></td>`;
75
75
  case "bool": return `<td><input type="checkbox" name='${f.fieldName}'></td>`;
76
76
  case "date": return `<td><input type="date" name='${f.fieldName}'></td>`;
77
77
  case "number": return `<td><input type="number" name='${f.fieldName}'></td>`;
78
78
  case "select":
79
- let items = "";
80
- for (let index = 0; index < f.items.length; index++) {
81
- const item = f.items[index];
82
- items += `<option value="${item.value}">${item.text}</option>`;
83
- }
79
+ let itemSelector = f.items;
80
+ this.fireEvent('onSelectorSelecting', (rs) => {
81
+ itemSelector = rs || itemSelector;
82
+ }, f.fieldName, null);
83
+ let items = itemSelector.map(i => `<option value="${i.value}">${i.text}</option>`).join("");
84
84
  return `<td><select name='${f.fieldName}'>${items}</select></td>`;
85
85
  default: return `<td><input type='text' name='${f.fieldName}'/></td>`;
86
86
  }
87
- }).join("\r\n");
87
+ }).join("\r\n") + '</tr>';
88
88
  return `
89
89
  <div style='height: 100%;width: 100%; overflow: hidden;'>
90
90
  <table id='${this.id}' class='dk-table' style='height: 100%;'>
@@ -96,7 +96,7 @@ class DKGrid {
96
96
  <li data-cmd='del'><i class="fa fa-times" aria-hidden="true"></i></li>
97
97
  <li data-cmd='cancel'><i class="fa fa-recycle" aria-hidden="true"></i></li>
98
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>
99
+ <li data-cmd='refresh'><input id='${this.id}_inputSearch' type='search' style='width:250px;'></li>
100
100
  </ul>
101
101
  </div>
102
102
  </td>
@@ -113,14 +113,14 @@ class DKGrid {
113
113
  </tr>
114
114
  <tr>
115
115
  <td class='gridBodyCell'>
116
- <div id='${this.id}_bodyContent' style='position: relative; height: 100%; overflow: scroll;'>
116
+ <div id='${this.id}_bodyContent' style='min-height: 100px; position: relative; height: 100%; overflow: scroll;'>
117
117
  <table id='${this.idRaw}' class='edit' cellpadding="0" cellspacing="0" border="0" style="table-layout: fixed;width: ${totalWidth}px;">
118
118
  <colgroup>${colWidths}</colgroup>
119
119
  <tbody></tbody>
120
120
  </table>
121
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;">
122
122
  <colgroup>${colWidths}</colgroup>
123
- <tbody><tr>${trEditor_html}</tr></tbody>
123
+ <tbody>${this.editorDefault}</tbody>
124
124
  </table>
125
125
  </div>
126
126
  </td>
@@ -130,12 +130,8 @@ class DKGrid {
130
130
  <div style='display: flex; align-items: center;'>
131
131
  <ul id='${this.id}_gridPagingCell' style='display: flex; list-style-type: none; margin: 5px; padding: 2px 32px;'>
132
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
133
  </ul>
138
- <span id='${this.id}_status' style='font-size:18px;'>xx/50</span>
134
+ <span id='${this.id}_status' style='font-size:18px;'>0/10</span>
139
135
  </div>
140
136
  </td>
141
137
  </tr>
@@ -147,8 +143,9 @@ class DKGrid {
147
143
  const dkgrid = this;
148
144
  this.tableEditor.addEventListener('keydown', function (event) {
149
145
  const keyCode = event.keyCode || event.which;
150
-
151
- dkgrid.#keyDownOnTable(keyCode);
146
+ if (!event.shiftKey) {
147
+ dkgrid.#keyDownOnTable(keyCode);
148
+ }
152
149
  });
153
150
 
154
151
  this.tableRaw.addEventListener('click', function (event) {
@@ -178,7 +175,7 @@ class DKGrid {
178
175
  const page = parseInt(cmd);
179
176
  if (page) {
180
177
  this.page.current = Math.min(page, this.page.total);
181
- this.loadDataByPage();
178
+ this.buildNav_List();
182
179
  }
183
180
  });
184
181
  document.getElementById(dkgrid.id + "_bodyContent").addEventListener("scroll", function () {
@@ -188,7 +185,7 @@ class DKGrid {
188
185
  document.getElementById(dkgrid.id + "_inputSearch").addEventListener("keydown", function (event) {
189
186
  if (event.key === "Enter") {
190
187
  event.preventDefault();
191
- dkgrid.loadDataByPage();
188
+ dkgrid.buildNav_List();
192
189
  }
193
190
  });
194
191
  }
@@ -196,15 +193,13 @@ class DKGrid {
196
193
  // ESC
197
194
  if (keyCode == 27) {
198
195
  if (this.rowOnFocus) {
199
- const lastRow = this.rowOnFocus;
200
- this.#closeEditor(lastRow, true);
196
+ this.#closeEditor(true);
201
197
  }
202
198
  }
203
199
  // ENTER
204
200
  if (keyCode == 13) {
205
201
  if (this.rowOnFocus) {
206
- const lastRow = this.rowOnFocus;
207
- this.#closeEditor(lastRow, false);
202
+ this.#closeEditor(false);
208
203
  }
209
204
  }
210
205
  }
@@ -214,7 +209,7 @@ class DKGrid {
214
209
  if (this.rowOnFocus) {
215
210
  const lastRow = this.rowOnFocus;
216
211
  if (lastRow.dataset.editting == "1") {
217
- this.#closeEditor(lastRow, false);
212
+ this.#closeEditor(false);
218
213
  }
219
214
  }
220
215
  this.rowOnFocus = trTag;
@@ -242,7 +237,7 @@ class DKGrid {
242
237
  let objectCurrent = cache.updated[currentKeyValue] || cache.origin[currentKeyValue];
243
238
  {
244
239
  let throwX = false;
245
- this.fireEvent('openEditor', (rs) => {
240
+ this.fireEvent('onOpenEditor', (rs) => {
246
241
  throwX = rs === false;
247
242
  return !throwX;
248
243
  }, objectCurrent, this);
@@ -252,12 +247,24 @@ class DKGrid {
252
247
  tbEditor.querySelector('tbody').querySelectorAll('td').forEachExt(
253
248
  child => {
254
249
  const input = child.firstChild;
250
+ input.style.height = (trTag.clientHeight) + 'px';
255
251
  try {
256
- if (input.tagName == "INPUT" || input.tagName == "SELECT") {
252
+ if (input.tagName == "INPUT" || input.tagName == "SELECT" || input.tagName == "TEXTAREA") {
253
+ if (input.tagName == "SELECT") {
254
+ let itemSelector = tableConfig.column.find(f => f.fieldName == input.name).items;
255
+ this.fireEvent('onSelectorSelecting', (rs) => {
256
+ itemSelector = rs || itemSelector;
257
+ }, input.name, objectCurrent);
258
+ let items = itemSelector.map(i => `<option value="${i.value}">${i.text}</option>`).join("");
259
+ input.innerHTML = items;
260
+ }
261
+
257
262
  input.value = objectCurrent[input.name] || "";
258
263
  if (input.type == 'checkbox') {
259
264
  input.checked = objectCurrent[input.name] || false;
260
265
  }
266
+
267
+ this.fireEvent('onSetInput', null, input, objectCurrent);
261
268
  }
262
269
  } catch (exx) {
263
270
  console.log("Error in openEditor: ", exx);
@@ -269,22 +276,23 @@ class DKGrid {
269
276
  trTag.dataset.editting = '1';
270
277
  return true;
271
278
  }
272
- #closeEditor(trTag = new HTMLElement(), isClear = false, isdelete = false) {
273
- const table = trTag.closest('table');
279
+ #closeEditor(isClear = false, isdelete = false) {
280
+ const trTag = this.rowOnFocus;
281
+ if (trTag == null) {
282
+ return;
283
+ }
274
284
  const tbEditor = this.tableEditor;
275
285
  if (!isdelete) {
276
- const tableConfig = this.config;
277
- const primaryKey = tableConfig.primaryKey;
278
286
  const currentKeyValue = trTag.dataset.primaryValue;
279
287
  const cache = this.#cache;
280
288
 
281
- let objectCurrent = cache.updated[currentKeyValue] || {...cache.origin[currentKeyValue]};
289
+ let objectCurrent = cache.updated[currentKeyValue] || { ...cache.origin[currentKeyValue] };
282
290
  let objectEditing = {};
283
291
  let hasChange = false;
284
292
  tbEditor.querySelector('tbody').querySelectorAll('td').forEachExt(
285
293
  child => {
286
294
  const input = child.firstChild;
287
- if (input.tagName == "INPUT" || input.tagName == "SELECT") {
295
+ if (input.tagName == "INPUT" || input.tagName == "SELECT" || input.tagName == "TEXTAREA") {
288
296
  objectEditing[input.name] = input.value;
289
297
  if (input.type == 'checkbox') {
290
298
  objectEditing[input.name] = input.checked;
@@ -333,7 +341,11 @@ class DKGrid {
333
341
  case "date": td.textContent = item[f.fieldName] || ''; break;
334
342
  case "number": td.textContent = item[f.fieldName] || ''; break;
335
343
  case "select":
336
- td.textContent = f.items.find(i => i.value == item[f.fieldName])?.text;
344
+ let itemSelector = f.items;
345
+ this.fireEvent('onSelectorSelecting', (rs) => {
346
+ itemSelector = rs || itemSelector;
347
+ }, f.fieldName, null);
348
+ td.textContent = itemSelector.find(i => i.value == item[f.fieldName])?.text;
337
349
  break;
338
350
  default: td.textContent = item[f.fieldName]; break;
339
351
  }
@@ -351,9 +363,9 @@ class DKGrid {
351
363
  cache.deleted = {};
352
364
  this.page.total = Math.ceil(data.length / this.page.size);
353
365
  }
354
- this.loadDataByPage();
366
+ this.buildNav_List();
355
367
  }
356
- loadDataByPage() {
368
+ buildNav_List(holdPage = false) {
357
369
  const cache = this.#cache;
358
370
 
359
371
  const dataCollection = {};
@@ -365,8 +377,8 @@ class DKGrid {
365
377
  });
366
378
  Object.keys(cache.deleted).forEach(key => {
367
379
  delete dataCollection[key];
368
- });
369
-
380
+ });
381
+ this.#closeEditor(false, false);
370
382
  const dataCollection_array = [];
371
383
  const textSearch = document.getElementById(this.id + "_inputSearch").value;
372
384
  Object.values(dataCollection).forEach(item => {
@@ -401,7 +413,9 @@ class DKGrid {
401
413
  for (let index = min; index <= max; index++) {
402
414
  this.pagingCell.appendChild(hideCreatePageLi(index));
403
415
  }
404
- this.pagingCell.appendChild(hideCreatePageLi(page.total, "font-weight: bold; margin-left: 15px;"));
416
+ if (page.total > 1) {
417
+ this.pagingCell.appendChild(hideCreatePageLi(page.total, "font-weight: bold; margin-left: 15px;"));
418
+ }
405
419
  function hideCreatePageLi(num, style = '') {
406
420
  const li = document.createElement('li');
407
421
  li.dataset.cmd = num;
@@ -415,6 +429,9 @@ class DKGrid {
415
429
  }
416
430
  const dataPrint = dataCollection_array.slice(start, end);
417
431
  this.statusBox.textContent = `${dataPrint.length}/${dataCollection_array.length}`;
432
+ if (holdPage) {
433
+ return;
434
+ }
418
435
  this.printPage(dataPrint);
419
436
  }
420
437
  printPage(dataPrint = []) {
@@ -437,7 +454,11 @@ class DKGrid {
437
454
  case "date": td.textContent = item[f.fieldName] || ''; break;
438
455
  case "number": td.textContent = item[f.fieldName] || ''; break;
439
456
  case "select":
440
- td.textContent = f.items.find(i => i.value == item[f.fieldName]).text;
457
+ let itemSelector = f.items;
458
+ this.fireEvent('onSelectorSelecting', (rs) => {
459
+ itemSelector = rs || itemSelector;
460
+ }, f.fieldName, null);
461
+ td.textContent = itemSelector.find(i => i.value == item[f.fieldName])?.text || '';
441
462
  break;
442
463
  default: td.textContent = item[f.fieldName]; break;
443
464
  }
@@ -455,23 +476,23 @@ class DKGrid {
455
476
  const primaryKey = tableConfig.primaryKey;
456
477
  let newOb = {};
457
478
  {
458
- this.fireEvent('onCreateNewKey', (rs) => {
459
- newOb[primaryKey] = rs;
460
- });
479
+ this.fireEvent('onAddNewRow', null, newOb);
461
480
  }
462
481
  if (!newOb[primaryKey]) {
463
- newOb[primaryKey] = DKGrid.generateRandomString(32);
482
+ newOb[primaryKey] = Date.now() + '_' + DKGrid.generateRandomString(12);
464
483
  }
465
484
  newTR.dataset.primaryValue = newOb[primaryKey];
466
485
  const cache = this.#cache;
467
486
  cache.updated[newOb[primaryKey]] = (newOb);
487
+ this.buildNav_List(true);
468
488
  this.#createRow(newTR, newOb);
489
+ newTR.querySelector('td').click();
469
490
  }
470
491
 
471
492
  deleteRow() {
472
493
  if (this.rowOnFocus) {
473
494
  if (confirm("Bạn có chắc chắn muốn xóa dữ liệu này?") != true) return;
474
- this.#closeEditor(this.rowOnFocus, true, true);
495
+ this.#closeEditor(true, true);
475
496
  const cache = this.#cache;
476
497
  const tableConfig = this.config;
477
498
  const primaryKey = tableConfig.primaryKey;
@@ -492,9 +513,36 @@ class DKGrid {
492
513
  delete this.rowOnFocus;
493
514
  }
494
515
  }
516
+ getData() {
517
+ const datas = [];
518
+ const cache = this.#cache;
519
+ const dataCollection = {};
520
+ Object.keys(cache.origin).forEach(key => {
521
+ dataCollection[key] = cache.origin[key];
522
+ });
523
+ Object.keys(cache.updated).forEach(key => {
524
+ dataCollection[key] = cache.updated[key];
525
+ });
526
+ Object.keys(cache.deleted).forEach(key => {
527
+ delete dataCollection[key];
528
+ });
495
529
 
530
+ const dataCollection_array = [];
531
+ Object.values(dataCollection).forEach(item => {
532
+ dataCollection_array.push(item);
533
+ });
534
+ return dataCollection_array;
535
+ }
496
536
  commitData() {
497
- this.fireEvent('commitData', null, ({ updated: this.#cache.updated, deleted: this.#cache.deleted }));
537
+ const cache = this.#cache;
538
+ const data = { updated: [], deleted: [] };
539
+ Object.keys(cache.updated).forEach(key => {
540
+ data.updated.push(cache.updated[key]);
541
+ });
542
+ Object.keys(cache.deleted).forEach(key => {
543
+ data.deleted.push(cache.deleted[key]);
544
+ });
545
+ this.fireEvent('commitData', null, data);
498
546
  }
499
547
 
500
548
  cancelChanges() {
package/package.json CHANGED
@@ -5,11 +5,12 @@
5
5
  "express": "^4.18.2",
6
6
  "fluent-ffmpeg": "^2.1.2",
7
7
  "handlebars": "^4.7.8",
8
+ "js-yaml": "^4.1.0",
8
9
  "lowdb": "^7.0.1",
9
10
  "socket.io": "^4.7.2"
10
11
  },
11
12
  "name": "mdkcontroller",
12
- "version": "1.2.1",
13
+ "version": "1.2.3",
13
14
  "keywords": [],
14
15
  "author": "KHANHNBD <khanh272421@gmail.com>",
15
16
  "license": "ISC",
@@ -27,4 +28,4 @@
27
28
  "Cores/",
28
29
  "dk_modules/"
29
30
  ]
30
- }
31
+ }
package/readme.md CHANGED
@@ -1 +1 @@
1
- #some thing
1
+ # Project Summary