px-jspreadsheet-ce 0.0.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.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +292 -0
  3. package/dist/index.d.ts +2382 -0
  4. package/dist/index.js +11286 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/jspreadsheet.css +723 -0
  7. package/dist/jspreadsheet.themes.css +104 -0
  8. package/package.json +57 -0
  9. package/src/index.js +95 -0
  10. package/src/test.js +50 -0
  11. package/src/utils/cells.js +36 -0
  12. package/src/utils/columns.js +742 -0
  13. package/src/utils/comments.js +87 -0
  14. package/src/utils/config.js +46 -0
  15. package/src/utils/copyPaste.js +438 -0
  16. package/src/utils/data.js +419 -0
  17. package/src/utils/dispatch.js +115 -0
  18. package/src/utils/download.js +38 -0
  19. package/src/utils/editor.js +430 -0
  20. package/src/utils/events.js +1639 -0
  21. package/src/utils/factory.js +216 -0
  22. package/src/utils/filter.js +128 -0
  23. package/src/utils/footer.js +51 -0
  24. package/src/utils/freeze.js +19 -0
  25. package/src/utils/headers.js +74 -0
  26. package/src/utils/helpers.js +409 -0
  27. package/src/utils/history.js +336 -0
  28. package/src/utils/internal.js +1299 -0
  29. package/src/utils/internalHelpers.js +96 -0
  30. package/src/utils/keys.js +406 -0
  31. package/src/utils/lazyLoading.js +143 -0
  32. package/src/utils/libraryBase.js +5 -0
  33. package/src/utils/merges.js +275 -0
  34. package/src/utils/meta.js +81 -0
  35. package/src/utils/orderBy.js +185 -0
  36. package/src/utils/pagination.js +181 -0
  37. package/src/utils/rows.js +624 -0
  38. package/src/utils/search.js +83 -0
  39. package/src/utils/selection.js +744 -0
  40. package/src/utils/style.js +147 -0
  41. package/src/utils/toolbar.js +566 -0
  42. package/src/utils/version.js +9 -0
  43. package/src/utils/worksheets.js +731 -0
  44. package/src/webcomponent.js +59 -0
@@ -0,0 +1,430 @@
1
+ import jSuites from 'jsuites';
2
+
3
+ import dispatch from './dispatch.js';
4
+ import { getMask, isFormula, updateCell } from './internal.js';
5
+ import { setHistory } from './history.js';
6
+ import { getCellNameFromCoords } from './helpers.js';
7
+
8
+ /**
9
+ * Open the editor
10
+ *
11
+ * @param object cell
12
+ * @return void
13
+ */
14
+ export const openEditor = function (cell, empty, e) {
15
+ const obj = this;
16
+
17
+ // Get cell position
18
+ const y = cell.getAttribute('data-y');
19
+ const x = cell.getAttribute('data-x');
20
+
21
+ // On edition start
22
+ dispatch.call(obj, 'oneditionstart', obj, cell, parseInt(x), parseInt(y));
23
+
24
+ // Overflow
25
+ if (x > 0) {
26
+ obj.records[y][x - 1].element.style.overflow = 'hidden';
27
+ }
28
+
29
+ // Create editor
30
+ const createEditor = function (type) {
31
+ // Cell information
32
+ const info = cell.getBoundingClientRect();
33
+
34
+ // Create dropdown
35
+ const editor = document.createElement(type);
36
+ editor.style.width = info.width + 'px';
37
+ editor.style.height = info.height - 2 + 'px';
38
+ editor.style.minHeight = info.height - 2 + 'px';
39
+
40
+ // Edit cell
41
+ cell.classList.add('editor');
42
+ cell.innerHTML = '';
43
+ cell.appendChild(editor);
44
+
45
+ return editor;
46
+ };
47
+
48
+ // Readonly
49
+ if (cell.classList.contains('readonly') == true) {
50
+ // Do nothing
51
+ } else {
52
+ // Holder
53
+ obj.edition = [obj.records[y][x].element, obj.records[y][x].element.innerHTML, x, y];
54
+
55
+ let config = obj.options.columns && obj.options.columns[x];
56
+ const cellName = getCellNameFromCoords(x, y);
57
+ const cells = obj.options.cells;
58
+ if (typeof cells === 'object' && cells[cellName]) {
59
+ config = cells[cellName];
60
+ }
61
+
62
+ // If there is a custom editor for it
63
+ if (config && typeof config.type === 'object') {
64
+ // Custom editors
65
+ config.type.openEditor(cell, obj.options.data[y][x], parseInt(x), parseInt(y), obj, config, e);
66
+
67
+ // On edition start
68
+ dispatch.call(obj, 'oncreateeditor', obj, cell, parseInt(x), parseInt(y), null, config);
69
+ } else {
70
+ // Native functions
71
+ if (config && config.type == 'hidden') {
72
+ // Do nothing
73
+ } else if (config && (config.type == 'checkbox' || config.type == 'radio')) {
74
+ // Get value
75
+ const value = cell.children[0].checked ? false : true;
76
+ // Toogle value
77
+ obj.setValue(cell, value);
78
+ // Do not keep edition open
79
+ obj.edition = null;
80
+ } else if (config && config.type == 'dropdown') {
81
+ // Get current value
82
+ let value = obj.options.data[y][x];
83
+ if (config.multiple && !Array.isArray(value)) {
84
+ value = value.split(';');
85
+ }
86
+
87
+ // Create dropdown
88
+ let source;
89
+
90
+ if (typeof config.filter == 'function') {
91
+ source = config.filter(obj.element, cell, x, y, config.source);
92
+ } else {
93
+ source = config.source;
94
+ }
95
+
96
+ // Do not change the original source
97
+ const data = [];
98
+ if (source) {
99
+ for (let j = 0; j < source.length; j++) {
100
+ data.push(source[j]);
101
+ }
102
+ }
103
+
104
+ // Create editor
105
+ const editor = createEditor('div');
106
+
107
+ // On edition start
108
+ dispatch.call(obj, 'oncreateeditor', obj, cell, parseInt(x), parseInt(y), null, config);
109
+
110
+ const options = {
111
+ data: data,
112
+ multiple: config.multiple ? true : false,
113
+ autocomplete: config.autocomplete ? true : false,
114
+ opened: true,
115
+ value: value,
116
+ width: '100%',
117
+ height: editor.style.minHeight,
118
+ position: obj.options.tableOverflow == true || obj.parent.config.fullscreen == true ? true : false,
119
+ onclose: function () {
120
+ closeEditor.call(obj, cell, true);
121
+ },
122
+ };
123
+ if (config.options && config.options.type) {
124
+ options.type = config.options.type;
125
+ }
126
+ jSuites.dropdown(editor, options);
127
+ } else if (config && (config.type == 'calendar' || config.type == 'color')) {
128
+ // Value
129
+ const value = obj.options.data[y][x];
130
+ // Create editor
131
+ const editor = createEditor('input');
132
+
133
+ dispatch.call(obj, 'oncreateeditor', obj, cell, parseInt(x), parseInt(y), null, config);
134
+
135
+ editor.value = value;
136
+
137
+ const options = config.options ? { ...config.options } : {};
138
+
139
+ if (obj.options.tableOverflow == true || obj.parent.config.fullscreen == true) {
140
+ options.position = true;
141
+ }
142
+ options.value = obj.options.data[y][x];
143
+ options.opened = true;
144
+ options.onclose = function (el, value) {
145
+ closeEditor.call(obj, cell, true);
146
+ };
147
+ // Current value
148
+ if (config.type == 'color') {
149
+ jSuites.color(editor, options);
150
+
151
+ const rect = cell.getBoundingClientRect();
152
+
153
+ if (options.position) {
154
+ editor.nextSibling.children[1].style.top = rect.top + rect.height + 'px';
155
+ editor.nextSibling.children[1].style.left = rect.left + 'px';
156
+ }
157
+ } else {
158
+ if (!options.format) {
159
+ options.format = 'YYYY-MM-DD';
160
+ }
161
+
162
+ jSuites.calendar(editor, options);
163
+ }
164
+ // Focus on editor
165
+ editor.focus();
166
+ } else if (config && config.type == 'html') {
167
+ const value = obj.options.data[y][x];
168
+ // Create editor
169
+ const editor = createEditor('div');
170
+
171
+ dispatch.call(obj, 'oncreateeditor', obj, cell, parseInt(x), parseInt(y), null, config);
172
+
173
+ editor.style.position = 'relative';
174
+ const div = document.createElement('div');
175
+ div.classList.add('jss_richtext');
176
+ editor.appendChild(div);
177
+ jSuites.editor(div, {
178
+ focus: true,
179
+ value: value,
180
+ });
181
+ const rect = cell.getBoundingClientRect();
182
+ const rectContent = div.getBoundingClientRect();
183
+ if (window.innerHeight < rect.bottom + rectContent.height) {
184
+ div.style.top = rect.bottom - (rectContent.height + 2) + 'px';
185
+ } else {
186
+ div.style.top = rect.top + 'px';
187
+ }
188
+
189
+ if (window.innerWidth < rect.left + rectContent.width) {
190
+ div.style.left = rect.right - (rectContent.width + 2) + 'px';
191
+ } else {
192
+ div.style.left = rect.left + 'px';
193
+ }
194
+ } else if (config && config.type == 'image') {
195
+ // Value
196
+ const img = cell.children[0];
197
+ // Create editor
198
+ const editor = createEditor('div');
199
+
200
+ dispatch.call(obj, 'oncreateeditor', obj, cell, parseInt(x), parseInt(y), null, config);
201
+
202
+ editor.style.position = 'relative';
203
+ const div = document.createElement('div');
204
+ div.classList.add('jclose');
205
+ if (img && img.src) {
206
+ div.appendChild(img);
207
+ }
208
+ editor.appendChild(div);
209
+ jSuites.image(div, config);
210
+ const rect = cell.getBoundingClientRect();
211
+ const rectContent = div.getBoundingClientRect();
212
+ if (window.innerHeight < rect.bottom + rectContent.height) {
213
+ div.style.top = rect.top - (rectContent.height + 2) + 'px';
214
+ } else {
215
+ div.style.top = rect.top + 'px';
216
+ }
217
+
218
+ div.style.left = rect.left + 'px';
219
+ } else {
220
+ // Value
221
+ const value = empty == true ? '' : obj.options.data[y][x];
222
+
223
+ // Basic editor
224
+ let editor;
225
+
226
+ if ((!config || config.wordWrap != false) && (obj.options.wordWrap == true || (config && config.wordWrap == true))) {
227
+ editor = createEditor('textarea');
228
+ } else {
229
+ editor = createEditor('input');
230
+ }
231
+
232
+ dispatch.call(obj, 'oncreateeditor', obj, cell, parseInt(x), parseInt(y), null, config);
233
+
234
+ editor.focus();
235
+ editor.value = value;
236
+
237
+ // Column options
238
+ const options = config;
239
+
240
+ // Apply format when is not a formula
241
+ if (!isFormula(value)) {
242
+ if (options) {
243
+ // Format
244
+ const opt = getMask(options);
245
+
246
+ if (opt) {
247
+ // Masking
248
+ if (!options.disabledMaskOnEdition) {
249
+ if (options.mask) {
250
+ const m = options.mask.split(';');
251
+ editor.setAttribute('data-mask', m[0]);
252
+ } else if (options.locale) {
253
+ editor.setAttribute('data-locale', options.locale);
254
+ }
255
+ }
256
+ // Input
257
+ opt.input = editor;
258
+ // Configuration
259
+ editor.mask = opt;
260
+ // Do not treat the decimals
261
+ jSuites.mask.render(value, opt, false);
262
+ }
263
+ }
264
+ }
265
+
266
+ editor.onblur = function () {
267
+ closeEditor.call(obj, cell, true);
268
+ };
269
+ editor.scrollLeft = editor.scrollWidth;
270
+ }
271
+ }
272
+ }
273
+ };
274
+
275
+ /**
276
+ * Close the editor and save the information
277
+ *
278
+ * @param object cell
279
+ * @param boolean save
280
+ * @return void
281
+ */
282
+ export const closeEditor = function (cell, save) {
283
+ const obj = this;
284
+
285
+ const x = parseInt(cell.getAttribute('data-x'));
286
+ const y = parseInt(cell.getAttribute('data-y'));
287
+
288
+ let config = obj.options.columns && obj.options.columns[x];
289
+ const cellName = getCellNameFromCoords(x, y);
290
+ const cells = obj.options.cells;
291
+ if (typeof cells === 'object' && cells[cellName]) {
292
+ config = cells[cellName];
293
+ }
294
+
295
+ let value;
296
+
297
+ // Get cell properties
298
+ if (save == true) {
299
+ // If custom editor
300
+ if (config && typeof config.type === 'object') {
301
+ // Custom editor
302
+ value = config.type.closeEditor(cell, save, parseInt(x), parseInt(y), obj, config);
303
+ } else {
304
+ // Native functions
305
+ if (config && (config.type == 'checkbox' || config.type == 'radio' || config.type == 'hidden')) {
306
+ // Do nothing
307
+ } else if (config && config.type == 'dropdown') {
308
+ value = cell.children[0].dropdown.close(true);
309
+ } else if (config && config.type == 'calendar') {
310
+ value = cell.children[0].calendar.close(true);
311
+ } else if (config && config.type == 'color') {
312
+ value = cell.children[0].color.close(true);
313
+ } else if (config && config.type == 'html') {
314
+ value = cell.children[0].children[0].editor.getData();
315
+ } else if (config && config.type == 'image') {
316
+ const img = cell.children[0].children[0].children[0];
317
+ value = img && img.tagName == 'IMG' ? img.src : '';
318
+ } else if (config && config.type == 'numeric') {
319
+ value = cell.children[0].value;
320
+ if (('' + value).substr(0, 1) != '=') {
321
+ if (value == '') {
322
+ value = config.allowEmpty ? '' : 0;
323
+ }
324
+ }
325
+ cell.children[0].onblur = null;
326
+ } else {
327
+ value = cell.children[0].value;
328
+ cell.children[0].onblur = null;
329
+
330
+ // Column options
331
+ const options = config;
332
+
333
+ if (options) {
334
+ // Format
335
+ const opt = getMask(options);
336
+ if (opt) {
337
+ // Keep numeric in the raw data
338
+ if (value !== '' && !isFormula(value) && typeof value !== 'number') {
339
+ const t = jSuites.mask.extract(value, opt, true);
340
+ if (t && t.value !== '') {
341
+ value = t.value;
342
+ }
343
+ }
344
+ }
345
+ }
346
+ }
347
+ }
348
+
349
+ // Ignore changes if the value is the same
350
+ if (obj.options.data[y][x] == value) {
351
+ cell.innerHTML = obj.edition[1];
352
+ } else {
353
+ obj.setValue(cell, value); // update cell
354
+ }
355
+ } else {
356
+ if (config && typeof config.type === 'object') {
357
+ // Custom editor
358
+ config.type.closeEditor(cell, save, parseInt(x), parseInt(y), obj, config);
359
+ } else {
360
+ if (config && config.type == 'dropdown') {
361
+ cell.children[0].dropdown.close(true);
362
+ } else if (config && config.type == 'calendar') {
363
+ cell.children[0].calendar.close(true);
364
+ } else if (config && config.type == 'color') {
365
+ cell.children[0].color.close(true);
366
+ } else {
367
+ cell.children[0].onblur = null;
368
+ }
369
+ }
370
+
371
+ // Restore value
372
+ cell.innerHTML = obj.edition && obj.edition[1] ? obj.edition[1] : '';
373
+ }
374
+
375
+ // On edition end
376
+ dispatch.call(obj, 'oneditionend', obj, cell, x, y, value, save);
377
+
378
+ // Remove editor class
379
+ cell.classList.remove('editor');
380
+
381
+ // Finish edition
382
+ obj.edition = null;
383
+ };
384
+
385
+ /**
386
+ * Toogle
387
+ */
388
+ export const setCheckRadioValue = function () {
389
+ const obj = this;
390
+
391
+ const records = [];
392
+ const keys = Object.keys(obj.highlighted);
393
+ for (let i = 0; i < keys.length; i++) {
394
+ const x = obj.highlighted[i].element.getAttribute('data-x');
395
+ const y = obj.highlighted[i].element.getAttribute('data-y');
396
+
397
+ let config = obj.options.columns && obj.options.columns[x];
398
+ const cellName = getCellNameFromCoords(x, y);
399
+ const cells = obj.options.cells;
400
+ if (typeof cells === 'object' && cells[cellName]) {
401
+ config = cells[cellName];
402
+ }
403
+
404
+ if (config.type == 'checkbox' || config.type == 'radio') {
405
+ // Update cell
406
+ records.push(updateCell.call(obj, x, y, !obj.options.data[y][x]));
407
+ }
408
+ }
409
+
410
+ if (records.length) {
411
+ // Update history
412
+ setHistory.call(obj, {
413
+ action: 'setValue',
414
+ records: records,
415
+ selection: obj.selectedCell,
416
+ });
417
+
418
+ // On after changes
419
+ const onafterchangesRecords = records.map(function (record) {
420
+ return {
421
+ x: record.x,
422
+ y: record.y,
423
+ value: record.value,
424
+ oldValue: record.oldValue,
425
+ };
426
+ });
427
+
428
+ dispatch.call(obj, 'onafterchanges', obj, onafterchangesRecords);
429
+ }
430
+ };