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,216 @@
1
+ import jSuites from 'jsuites';
2
+
3
+ import libraryBase from './libraryBase.js';
4
+ import { setEvents } from './events.js';
5
+ import { fullscreen, getWorksheetActive } from './internal.js';
6
+ import { hideToolbar, showToolbar, updateToolbar } from './toolbar.js';
7
+ import { buildWorksheet, createWorksheetObj, getNextDefaultWorksheetName } from './worksheets.js';
8
+ import dispatch from './dispatch.js';
9
+ import { createFromTable } from './helpers.js';
10
+ import { getSpreadsheetConfig, setConfig } from './config.js';
11
+
12
+ const factory = function () {};
13
+
14
+ const createWorksheets = async function (spreadsheet, options, el) {
15
+ // Create worksheets
16
+ let o = options.worksheets;
17
+ if (o) {
18
+ let tabsOptions = {
19
+ animation: true,
20
+ onbeforecreate: function (element, title) {
21
+ if (title) {
22
+ return title;
23
+ } else {
24
+ return getNextDefaultWorksheetName(spreadsheet);
25
+ }
26
+ },
27
+ oncreate: function (element, newTabContent) {
28
+ if (!spreadsheet.creationThroughJss) {
29
+ const worksheetName = element.tabs.headers.children[element.tabs.headers.children.length - 2].innerHTML;
30
+
31
+ createWorksheetObj.call(spreadsheet.worksheets[0], {
32
+ minDimensions: [10, 15],
33
+ worksheetName: worksheetName,
34
+ });
35
+ } else {
36
+ spreadsheet.creationThroughJss = false;
37
+ }
38
+
39
+ const newWorksheet = spreadsheet.worksheets[spreadsheet.worksheets.length - 1];
40
+
41
+ newWorksheet.element = newTabContent;
42
+
43
+ buildWorksheet.call(newWorksheet).then(function () {
44
+ updateToolbar(newWorksheet);
45
+
46
+ dispatch.call(newWorksheet, 'oncreateworksheet', newWorksheet, options, spreadsheet.worksheets.length - 1);
47
+ });
48
+ },
49
+ onchange: function (element, instance, tabIndex) {
50
+ if (spreadsheet.worksheets.length != 0 && spreadsheet.worksheets[tabIndex]) {
51
+ updateToolbar(spreadsheet.worksheets[tabIndex]);
52
+ }
53
+ },
54
+ };
55
+
56
+ if (options.tabs == true) {
57
+ tabsOptions.allowCreate = true;
58
+ } else {
59
+ tabsOptions.hideHeaders = true;
60
+ }
61
+
62
+ tabsOptions.data = [];
63
+
64
+ let sheetNumber = 1;
65
+
66
+ for (let i = 0; i < o.length; i++) {
67
+ if (!o[i].worksheetName) {
68
+ o[i].worksheetName = 'Sheet' + sheetNumber++;
69
+ }
70
+
71
+ tabsOptions.data.push({
72
+ title: o[i].worksheetName,
73
+ content: '',
74
+ });
75
+ }
76
+
77
+ el.classList.add('jss_spreadsheet');
78
+ el.tabIndex = 0;
79
+
80
+ const tabs = jSuites.tabs(el, tabsOptions);
81
+
82
+ const spreadsheetStyles = options.style;
83
+ delete options.style;
84
+
85
+ for (let i = 0; i < o.length; i++) {
86
+ if (o[i].style) {
87
+ Object.entries(o[i].style).forEach(function ([cellName, value]) {
88
+ if (typeof value === 'number') {
89
+ o[i].style[cellName] = spreadsheetStyles[value];
90
+ }
91
+ });
92
+ }
93
+
94
+ spreadsheet.worksheets.push({
95
+ parent: spreadsheet,
96
+ element: tabs.content.children[i],
97
+ options: o[i],
98
+ filters: [],
99
+ formula: [],
100
+ history: [],
101
+ selection: [],
102
+ historyIndex: -1,
103
+ });
104
+
105
+ await buildWorksheet.call(spreadsheet.worksheets[i]);
106
+ }
107
+ } else {
108
+ throw new Error('JSS: worksheets are not defined');
109
+ }
110
+ };
111
+
112
+ factory.spreadsheet = async function (el, options, worksheets) {
113
+ if (el.tagName == 'TABLE') {
114
+ if (!options) {
115
+ options = {};
116
+ }
117
+
118
+ if (!options.worksheets) {
119
+ options.worksheets = [];
120
+ }
121
+
122
+ const tableOptions = createFromTable(el, options.worksheets[0]);
123
+
124
+ options.worksheets[0] = tableOptions;
125
+
126
+ const div = document.createElement('div');
127
+ el.parentNode.insertBefore(div, el);
128
+ el.remove();
129
+ el = div;
130
+ }
131
+
132
+ let spreadsheet = {
133
+ worksheets: worksheets,
134
+ config: options,
135
+ element: el,
136
+ el,
137
+ };
138
+
139
+ // Contextmenu container
140
+ spreadsheet.contextMenu = document.createElement('div');
141
+ spreadsheet.contextMenu.className = 'jss_contextmenu';
142
+
143
+ spreadsheet.getWorksheetActive = getWorksheetActive.bind(spreadsheet);
144
+ spreadsheet.fullscreen = fullscreen.bind(spreadsheet);
145
+ spreadsheet.showToolbar = showToolbar.bind(spreadsheet);
146
+ spreadsheet.hideToolbar = hideToolbar.bind(spreadsheet);
147
+ spreadsheet.getConfig = getSpreadsheetConfig.bind(spreadsheet);
148
+ spreadsheet.setConfig = setConfig.bind(spreadsheet);
149
+
150
+ spreadsheet.setPlugins = function (newPlugins) {
151
+ if (!spreadsheet.plugins) {
152
+ spreadsheet.plugins = {};
153
+ }
154
+
155
+ if (typeof newPlugins == 'object') {
156
+ Object.entries(newPlugins).forEach(function ([pluginName, plugin]) {
157
+ spreadsheet.plugins[pluginName] = plugin.call(libraryBase.jspreadsheet, spreadsheet, {}, spreadsheet.config);
158
+ });
159
+ }
160
+ };
161
+
162
+ spreadsheet.setPlugins(options.plugins);
163
+
164
+ // Create as worksheets
165
+ await createWorksheets(spreadsheet, options, el);
166
+
167
+ spreadsheet.element.appendChild(spreadsheet.contextMenu);
168
+
169
+ // Create element
170
+ jSuites.contextmenu(spreadsheet.contextMenu, {
171
+ onclick: function () {
172
+ spreadsheet.contextMenu.contextmenu.close(false);
173
+ },
174
+ });
175
+
176
+ // Fullscreen
177
+ if (spreadsheet.config.fullscreen == true) {
178
+ spreadsheet.element.classList.add('fullscreen');
179
+ }
180
+
181
+ showToolbar.call(spreadsheet);
182
+
183
+ // Build handlers
184
+ if (options.root) {
185
+ setEvents(options.root);
186
+ } else {
187
+ setEvents(document);
188
+ }
189
+
190
+ el.spreadsheet = spreadsheet;
191
+
192
+ return spreadsheet;
193
+ };
194
+
195
+ factory.worksheet = function (spreadsheet, options, position) {
196
+ // Worksheet object
197
+ let w = {
198
+ // Parent of a worksheet is always the spreadsheet
199
+ parent: spreadsheet,
200
+ // Options for this worksheet
201
+ options: {},
202
+ };
203
+
204
+ // Create the worksheets object
205
+ if (typeof position === 'undefined') {
206
+ spreadsheet.worksheets.push(w);
207
+ } else {
208
+ spreadsheet.worksheets.splice(position, 0, w);
209
+ }
210
+ // Keep configuration used
211
+ Object.assign(w.options, options);
212
+
213
+ return w;
214
+ };
215
+
216
+ export default factory;
@@ -0,0 +1,128 @@
1
+ import jSuites from 'jsuites';
2
+ import { updateResult } from './internal.js';
3
+ import { refreshSelection } from './selection.js';
4
+
5
+ /**
6
+ * Open the column filter
7
+ */
8
+ export const openFilter = function (columnId) {
9
+ const obj = this;
10
+
11
+ if (!obj.options.filters) {
12
+ console.log('Jspreadsheet: filters not enabled.');
13
+ } else {
14
+ // Make sure is integer
15
+ columnId = parseInt(columnId);
16
+ // Reset selection
17
+ obj.resetSelection();
18
+ // Load options
19
+ let optionsFiltered = [];
20
+ if (obj.options.columns[columnId].type == 'checkbox') {
21
+ optionsFiltered.push({ id: 'true', name: 'True' });
22
+ optionsFiltered.push({ id: 'false', name: 'False' });
23
+ } else {
24
+ const options = [];
25
+ let hasBlanks = false;
26
+ for (let j = 0; j < obj.options.data.length; j++) {
27
+ const k = obj.options.data[j][columnId];
28
+ const v = obj.records[j][columnId].element.innerHTML;
29
+ if (k && v) {
30
+ options[k] = v;
31
+ } else {
32
+ hasBlanks = true;
33
+ }
34
+ }
35
+ const keys = Object.keys(options);
36
+ optionsFiltered = [];
37
+ for (let j = 0; j < keys.length; j++) {
38
+ optionsFiltered.push({ id: keys[j], name: options[keys[j]] });
39
+ }
40
+ // Has blank options
41
+ if (hasBlanks) {
42
+ optionsFiltered.push({ value: '', id: '', name: '(Blanks)' });
43
+ }
44
+ }
45
+
46
+ // Create dropdown
47
+ const div = document.createElement('div');
48
+ obj.filter.children[columnId + 1].innerHTML = '';
49
+ obj.filter.children[columnId + 1].appendChild(div);
50
+ obj.filter.children[columnId + 1].style.paddingLeft = '0px';
51
+ obj.filter.children[columnId + 1].style.paddingRight = '0px';
52
+ obj.filter.children[columnId + 1].style.overflow = 'initial';
53
+
54
+ const opt = {
55
+ data: optionsFiltered,
56
+ multiple: true,
57
+ autocomplete: true,
58
+ opened: true,
59
+ value: obj.filters[columnId] !== undefined ? obj.filters[columnId] : null,
60
+ width: '100%',
61
+ position: obj.options.tableOverflow == true || obj.parent.config.fullscreen == true ? true : false,
62
+ onclose: function (o) {
63
+ resetFilters.call(obj);
64
+ obj.filters[columnId] = o.dropdown.getValue(true);
65
+ obj.filter.children[columnId + 1].innerHTML = o.dropdown.getText();
66
+ obj.filter.children[columnId + 1].style.paddingLeft = '';
67
+ obj.filter.children[columnId + 1].style.paddingRight = '';
68
+ obj.filter.children[columnId + 1].style.overflow = '';
69
+ closeFilter.call(obj, columnId);
70
+ refreshSelection.call(obj);
71
+ },
72
+ };
73
+
74
+ // Dynamic dropdown
75
+ jSuites.dropdown(div, opt);
76
+ }
77
+ };
78
+
79
+ export const closeFilter = function (columnId) {
80
+ const obj = this;
81
+
82
+ if (!columnId) {
83
+ for (let i = 0; i < obj.filter.children.length; i++) {
84
+ if (obj.filters[i]) {
85
+ columnId = i;
86
+ }
87
+ }
88
+ }
89
+
90
+ // Search filter
91
+ const search = function (query, x, y) {
92
+ for (let i = 0; i < query.length; i++) {
93
+ const value = '' + obj.options.data[y][x];
94
+ const label = '' + obj.records[y][x].element.innerHTML;
95
+ if (query[i] == value || query[i] == label) {
96
+ return true;
97
+ }
98
+ }
99
+ return false;
100
+ };
101
+
102
+ const query = obj.filters[columnId];
103
+ obj.results = [];
104
+ for (let j = 0; j < obj.options.data.length; j++) {
105
+ if (search(query, columnId, j)) {
106
+ obj.results.push(j);
107
+ }
108
+ }
109
+ if (!obj.results.length) {
110
+ obj.results = null;
111
+ }
112
+
113
+ updateResult.call(obj);
114
+ };
115
+
116
+ export const resetFilters = function () {
117
+ const obj = this;
118
+
119
+ if (obj.options.filters) {
120
+ for (let i = 0; i < obj.filter.children.length; i++) {
121
+ obj.filter.children[i].innerHTML = '&nbsp;';
122
+ obj.filters[i] = null;
123
+ }
124
+ }
125
+
126
+ obj.results = null;
127
+ updateResult.call(obj);
128
+ };
@@ -0,0 +1,51 @@
1
+ import { parseValue } from './internal.js';
2
+
3
+ export const setFooter = function (data) {
4
+ const obj = this;
5
+
6
+ if (data) {
7
+ obj.options.footers = data;
8
+ }
9
+
10
+ if (obj.options.footers) {
11
+ if (!obj.tfoot) {
12
+ obj.tfoot = document.createElement('tfoot');
13
+ obj.table.appendChild(obj.tfoot);
14
+ }
15
+
16
+ for (let j = 0; j < obj.options.footers.length; j++) {
17
+ let tr;
18
+
19
+ if (obj.tfoot.children[j]) {
20
+ tr = obj.tfoot.children[j];
21
+ } else {
22
+ tr = document.createElement('tr');
23
+ const td = document.createElement('td');
24
+ tr.appendChild(td);
25
+ obj.tfoot.appendChild(tr);
26
+ }
27
+ for (let i = 0; i < obj.headers.length; i++) {
28
+ if (!obj.options.footers[j][i]) {
29
+ obj.options.footers[j][i] = '';
30
+ }
31
+
32
+ let td;
33
+
34
+ if (obj.tfoot.children[j].children[i + 1]) {
35
+ td = obj.tfoot.children[j].children[i + 1];
36
+ } else {
37
+ td = document.createElement('td');
38
+ tr.appendChild(td);
39
+
40
+ // Text align
41
+ const colAlign = obj.options.columns[i].align || obj.options.defaultColAlign || 'center';
42
+ td.style.textAlign = colAlign;
43
+ }
44
+ td.textContent = parseValue.call(obj, +obj.records.length + i, j, obj.options.footers[j][i]);
45
+
46
+ // Hide/Show with hideColumn()/showColumn()
47
+ td.style.display = obj.cols[i].colElement.style.display;
48
+ }
49
+ }
50
+ }
51
+ };
@@ -0,0 +1,19 @@
1
+ // Get width of all freezed cells together
2
+ export const getFreezeWidth = function () {
3
+ const obj = this;
4
+
5
+ let width = 0;
6
+ if (obj.options.freezeColumns > 0) {
7
+ for (let i = 0; i < obj.options.freezeColumns; i++) {
8
+ let columnWidth;
9
+ if (obj.options.columns && obj.options.columns[i] && obj.options.columns[i].width !== undefined) {
10
+ columnWidth = parseInt(obj.options.columns[i].width);
11
+ } else {
12
+ columnWidth = obj.options.defaultColWidth !== undefined ? parseInt(obj.options.defaultColWidth) : 100;
13
+ }
14
+
15
+ width += columnWidth;
16
+ }
17
+ }
18
+ return width;
19
+ };
@@ -0,0 +1,74 @@
1
+ import { setHistory } from './history.js';
2
+ import dispatch from './dispatch.js';
3
+ import { getColumnName } from './helpers.js';
4
+
5
+ /**
6
+ * Get the column title
7
+ *
8
+ * @param column - column number (first column is: 0)
9
+ * @param title - new column title
10
+ */
11
+ export const getHeader = function (column) {
12
+ const obj = this;
13
+
14
+ return obj.headers[column].textContent;
15
+ };
16
+
17
+ /**
18
+ * Get the headers
19
+ *
20
+ * @param asArray
21
+ * @return mixed
22
+ */
23
+ export const getHeaders = function (asArray) {
24
+ const obj = this;
25
+
26
+ const title = [];
27
+
28
+ for (let i = 0; i < obj.headers.length; i++) {
29
+ title.push(obj.getHeader(i));
30
+ }
31
+
32
+ return asArray ? title : title.join(obj.options.csvDelimiter);
33
+ };
34
+
35
+ /**
36
+ * Set the column title
37
+ *
38
+ * @param column - column number (first column is: 0)
39
+ * @param title - new column title
40
+ */
41
+ export const setHeader = function (column, newValue) {
42
+ const obj = this;
43
+
44
+ if (obj.headers[column]) {
45
+ const oldValue = obj.headers[column].textContent;
46
+ const onchangeheaderOldValue = (obj.options.columns && obj.options.columns[column] && obj.options.columns[column].title) || '';
47
+
48
+ if (!newValue) {
49
+ newValue = getColumnName(column);
50
+ }
51
+
52
+ obj.headers[column].textContent = newValue;
53
+ // Keep the title property
54
+ obj.headers[column].setAttribute('title', newValue);
55
+ // Update title
56
+ if (!obj.options.columns) {
57
+ obj.options.columns = [];
58
+ }
59
+ if (!obj.options.columns[column]) {
60
+ obj.options.columns[column] = {};
61
+ }
62
+ obj.options.columns[column].title = newValue;
63
+
64
+ setHistory.call(obj, {
65
+ action: 'setHeader',
66
+ column: column,
67
+ oldValue: oldValue,
68
+ newValue: newValue,
69
+ });
70
+
71
+ // On onchange header
72
+ dispatch.call(obj, 'onchangeheader', obj, parseInt(column), newValue, onchangeheaderOldValue);
73
+ }
74
+ };