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,409 @@
1
+ import { getColumnNameFromId } from './internalHelpers.js';
2
+
3
+ export { getColumnNameFromId };
4
+
5
+ /**
6
+ * Get carret position for one element
7
+ */
8
+ export const getCaretIndex = function (e) {
9
+ let d;
10
+
11
+ if (this.config.root) {
12
+ d = this.config.root;
13
+ } else {
14
+ d = window;
15
+ }
16
+ let pos = 0;
17
+ const s = d.getSelection();
18
+ if (s) {
19
+ if (s.rangeCount !== 0) {
20
+ const r = s.getRangeAt(0);
21
+ const p = r.cloneRange();
22
+ p.selectNodeContents(e);
23
+ p.setEnd(r.endContainer, r.endOffset);
24
+ pos = p.toString().length;
25
+ }
26
+ }
27
+ return pos;
28
+ };
29
+
30
+ /**
31
+ * Invert keys and values
32
+ */
33
+ export const invert = function (o) {
34
+ const d = [];
35
+ const k = Object.keys(o);
36
+ for (let i = 0; i < k.length; i++) {
37
+ d[o[k[i]]] = k[i];
38
+ }
39
+ return d;
40
+ };
41
+
42
+ /**
43
+ * Get letter based on a number
44
+ *
45
+ * @param {number} columnNumber
46
+ * @return string letter
47
+ */
48
+ export const getColumnName = function (columnNumber) {
49
+ let dividend = columnNumber + 1;
50
+ let columnName = '';
51
+ let modulo;
52
+
53
+ while (dividend > 0) {
54
+ modulo = (dividend - 1) % 26;
55
+ columnName = String.fromCharCode(65 + modulo).toString() + columnName;
56
+ dividend = parseInt((dividend - modulo) / 26);
57
+ }
58
+
59
+ return columnName;
60
+ };
61
+
62
+ /**
63
+ * Get column name from coords
64
+ */
65
+ export const getCellNameFromCoords = function (x, y) {
66
+ return getColumnName(parseInt(x)) + (parseInt(y) + 1);
67
+ };
68
+
69
+ export const getCoordsFromCellName = function (columnName) {
70
+ // Get the letters
71
+ const t = /^[a-zA-Z]+/.exec(columnName);
72
+
73
+ if (t) {
74
+ // Base 26 calculation
75
+ let code = 0;
76
+ for (let i = 0; i < t[0].length; i++) {
77
+ code += parseInt(t[0].charCodeAt(i) - 64) * Math.pow(26, t[0].length - 1 - i);
78
+ }
79
+ code--;
80
+ // Make sure jspreadsheet starts on zero
81
+ if (code < 0) {
82
+ code = 0;
83
+ }
84
+
85
+ // Number
86
+ let number = parseInt(/[0-9]+$/.exec(columnName)) || null;
87
+ if (number > 0) {
88
+ number--;
89
+ }
90
+
91
+ return [code, number];
92
+ }
93
+ };
94
+
95
+ export const getCoordsFromRange = function (range) {
96
+ const [start, end] = range.split(':');
97
+
98
+ return [...getCoordsFromCellName(start), ...getCoordsFromCellName(end)];
99
+ };
100
+
101
+ /**
102
+ * From stack overflow contributions
103
+ */
104
+ export const parseCSV = function (str, delimiter) {
105
+ // user-supplied delimeter or default comma
106
+ delimiter = delimiter || ',';
107
+ // Remove last line break
108
+ str = str.replace(/\r?\n$|\r$|\n$/g, '');
109
+
110
+ const arr = [];
111
+ let quote = false; // true means we're inside a quoted field
112
+ // iterate over each character, keep track of current row and column (of the returned array)
113
+ let maxCol = 0;
114
+ let row = 0,
115
+ col = 0;
116
+ for (let c = 0; c < str.length; c++) {
117
+ const cc = str[c],
118
+ nc = str[c + 1];
119
+ arr[row] = arr[row] || [];
120
+ arr[row][col] = arr[row][col] || '';
121
+
122
+ // If the current character is a quotation mark, and we're inside a quoted field, and the next character is also a quotation mark, add a quotation mark to the current column and skip the next character
123
+ if (cc == '"' && quote && nc == '"') {
124
+ arr[row][col] += cc;
125
+ ++c;
126
+ continue;
127
+ }
128
+
129
+ // If it's just one quotation mark, begin/end quoted field
130
+ if (cc == '"') {
131
+ quote = !quote;
132
+ continue;
133
+ }
134
+
135
+ // If it's a comma and we're not in a quoted field, move on to the next column
136
+ if (cc == delimiter && !quote) {
137
+ ++col;
138
+ continue;
139
+ }
140
+
141
+ // If it's a newline (CRLF) and we're not in a quoted field, skip the next character and move on to the next row and move to column 0 of that new row
142
+ if (cc == '\r' && nc == '\n' && !quote) {
143
+ ++row;
144
+ maxCol = Math.max(maxCol, col);
145
+ col = 0;
146
+ ++c;
147
+ continue;
148
+ }
149
+
150
+ // If it's a newline (LF or CR) and we're not in a quoted field, move on to the next row and move to column 0 of that new row
151
+ if (cc == '\n' && !quote) {
152
+ ++row;
153
+ maxCol = Math.max(maxCol, col);
154
+ col = 0;
155
+ continue;
156
+ }
157
+ if (cc == '\r' && !quote) {
158
+ ++row;
159
+ maxCol = Math.max(maxCol, col);
160
+ col = 0;
161
+ continue;
162
+ }
163
+
164
+ // Otherwise, append the current character to the current column
165
+ arr[row][col] += cc;
166
+ }
167
+
168
+ // fix array length
169
+ arr.forEach((row, i) => {
170
+ for (let i = row.length; i <= maxCol; i++) {
171
+ row.push('');
172
+ }
173
+ });
174
+ return arr;
175
+ };
176
+
177
+ export const createFromTable = function (el, options) {
178
+ if (el.tagName != 'TABLE') {
179
+ console.log('Element is not a table');
180
+ } else {
181
+ // Configuration
182
+ if (!options) {
183
+ options = {};
184
+ }
185
+
186
+ options.columns = [];
187
+ options.data = [];
188
+
189
+ // Colgroup
190
+ const colgroup = el.querySelectorAll('colgroup > col');
191
+ if (colgroup.length) {
192
+ // Get column width
193
+ for (let i = 0; i < colgroup.length; i++) {
194
+ let width = colgroup[i].style.width;
195
+ if (!width) {
196
+ width = colgroup[i].getAttribute('width');
197
+ }
198
+ // Set column width
199
+ if (width) {
200
+ if (!options.columns[i]) {
201
+ options.columns[i] = {};
202
+ }
203
+ options.columns[i].width = width;
204
+ }
205
+ }
206
+ }
207
+
208
+ // Parse header
209
+ const parseHeader = function (header, i) {
210
+ // Get width information
211
+ let info = header.getBoundingClientRect();
212
+ const width = info.width > 50 ? info.width : 50;
213
+
214
+ // Create column option
215
+ if (!options.columns[i]) {
216
+ options.columns[i] = {};
217
+ }
218
+ if (header.getAttribute('data-celltype')) {
219
+ options.columns[i].type = header.getAttribute('data-celltype');
220
+ } else {
221
+ options.columns[i].type = 'text';
222
+ }
223
+ options.columns[i].width = width + 'px';
224
+ options.columns[i].title = header.innerHTML;
225
+ if (header.style.textAlign) {
226
+ options.columns[i].align = header.style.textAlign;
227
+ }
228
+
229
+ if ((info = header.getAttribute('name'))) {
230
+ options.columns[i].name = info;
231
+ }
232
+ if ((info = header.getAttribute('id'))) {
233
+ options.columns[i].id = info;
234
+ }
235
+ if ((info = header.getAttribute('data-mask'))) {
236
+ options.columns[i].mask = info;
237
+ }
238
+ };
239
+
240
+ // Headers
241
+ const nested = [];
242
+ let headers = el.querySelectorAll(':scope > thead > tr');
243
+ if (headers.length) {
244
+ for (let j = 0; j < headers.length - 1; j++) {
245
+ const cells = [];
246
+ for (let i = 0; i < headers[j].children.length; i++) {
247
+ const row = {
248
+ title: headers[j].children[i].textContent,
249
+ colspan: headers[j].children[i].getAttribute('colspan') || 1,
250
+ };
251
+ cells.push(row);
252
+ }
253
+ nested.push(cells);
254
+ }
255
+ // Get the last row in the thead
256
+ headers = headers[headers.length - 1].children;
257
+ // Go though the headers
258
+ for (let i = 0; i < headers.length; i++) {
259
+ parseHeader(headers[i], i);
260
+ }
261
+ }
262
+
263
+ // Content
264
+ let rowNumber = 0;
265
+ const mergeCells = {};
266
+ const rows = {};
267
+ const style = {};
268
+ const classes = {};
269
+
270
+ let content = el.querySelectorAll(':scope > tr, :scope > tbody > tr');
271
+ for (let j = 0; j < content.length; j++) {
272
+ options.data[rowNumber] = [];
273
+ if (options.parseTableFirstRowAsHeader == true && !headers.length && j == 0) {
274
+ for (let i = 0; i < content[j].children.length; i++) {
275
+ parseHeader(content[j].children[i], i);
276
+ }
277
+ } else {
278
+ for (let i = 0; i < content[j].children.length; i++) {
279
+ // WickedGrid formula compatibility
280
+ let value = content[j].children[i].getAttribute('data-formula');
281
+ if (value) {
282
+ if (value.substr(0, 1) != '=') {
283
+ value = '=' + value;
284
+ }
285
+ } else {
286
+ value = content[j].children[i].innerHTML;
287
+ }
288
+ options.data[rowNumber].push(value);
289
+
290
+ // Key
291
+ const cellName = getColumnNameFromId([i, j]);
292
+
293
+ // Classes
294
+ const tmp = content[j].children[i].getAttribute('class');
295
+ if (tmp) {
296
+ classes[cellName] = tmp;
297
+ }
298
+
299
+ // Merged cells
300
+ const mergedColspan = parseInt(content[j].children[i].getAttribute('colspan')) || 0;
301
+ const mergedRowspan = parseInt(content[j].children[i].getAttribute('rowspan')) || 0;
302
+ if (mergedColspan || mergedRowspan) {
303
+ mergeCells[cellName] = [mergedColspan || 1, mergedRowspan || 1];
304
+ }
305
+
306
+ // Avoid problems with hidden cells
307
+ if (content[j].children[i].style && content[j].children[i].style.display == 'none') {
308
+ content[j].children[i].style.display = '';
309
+ }
310
+ // Get style
311
+ const s = content[j].children[i].getAttribute('style');
312
+ if (s) {
313
+ style[cellName] = s;
314
+ }
315
+ // Bold
316
+ if (content[j].children[i].classList.contains('styleBold')) {
317
+ if (style[cellName]) {
318
+ style[cellName] += '; font-weight:bold;';
319
+ } else {
320
+ style[cellName] = 'font-weight:bold;';
321
+ }
322
+ }
323
+ }
324
+
325
+ // Row Height
326
+ if (content[j].style && content[j].style.height) {
327
+ rows[j] = { height: content[j].style.height };
328
+ }
329
+
330
+ // Index
331
+ rowNumber++;
332
+ }
333
+ }
334
+
335
+ // Nested
336
+ if (Object.keys(nested).length > 0) {
337
+ options.nestedHeaders = nested;
338
+ }
339
+ // Style
340
+ if (Object.keys(style).length > 0) {
341
+ options.style = style;
342
+ }
343
+ // Merged
344
+ if (Object.keys(mergeCells).length > 0) {
345
+ options.mergeCells = mergeCells;
346
+ }
347
+ // Row height
348
+ if (Object.keys(rows).length > 0) {
349
+ options.rows = rows;
350
+ }
351
+ // Classes
352
+ if (Object.keys(classes).length > 0) {
353
+ options.classes = classes;
354
+ }
355
+
356
+ content = el.querySelectorAll('tfoot tr');
357
+ if (content.length) {
358
+ const footers = [];
359
+ for (let j = 0; j < content.length; j++) {
360
+ let footer = [];
361
+ for (let i = 0; i < content[j].children.length; i++) {
362
+ footer.push(content[j].children[i].textContent);
363
+ }
364
+ footers.push(footer);
365
+ }
366
+ if (Object.keys(footers).length > 0) {
367
+ options.footers = footers;
368
+ }
369
+ }
370
+ // TODO: data-hiddencolumns="3,4"
371
+
372
+ // I guess in terms the better column type
373
+ if (options.parseTableAutoCellType == true) {
374
+ const pattern = [];
375
+ for (let i = 0; i < options.columns.length; i++) {
376
+ let test = true;
377
+ let testCalendar = true;
378
+ pattern[i] = [];
379
+ for (let j = 0; j < options.data.length; j++) {
380
+ const value = options.data[j][i];
381
+ if (!pattern[i][value]) {
382
+ pattern[i][value] = 0;
383
+ }
384
+ pattern[i][value]++;
385
+ if (value.length > 25) {
386
+ test = false;
387
+ }
388
+ if (value.length == 10) {
389
+ if (!(value.substr(4, 1) == '-' && value.substr(7, 1) == '-')) {
390
+ testCalendar = false;
391
+ }
392
+ } else {
393
+ testCalendar = false;
394
+ }
395
+ }
396
+
397
+ const keys = Object.keys(pattern[i]).length;
398
+ if (testCalendar) {
399
+ options.columns[i].type = 'calendar';
400
+ } else if (test == true && keys > 1 && keys <= parseInt(options.data.length * 0.1)) {
401
+ options.columns[i].type = 'dropdown';
402
+ options.columns[i].source = Object.keys(pattern[i]);
403
+ }
404
+ }
405
+ }
406
+
407
+ return options;
408
+ }
409
+ };