itsa-react-table 16.8.0 → 16.8.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.
package/lib/component.jsx CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
3
  /**
4
4
  * Description here
@@ -12,1265 +12,1506 @@
12
12
  * @module component.jsx
13
13
  * @class Component
14
14
  * @since 2.0.0
15
- */
15
+ */
16
16
 
17
- require('itsa-jsext');
18
- require('itsa-dom');
17
+ require("itsa-jsext");
18
+ require("itsa-dom");
19
19
 
20
- const React = require('react'),
21
- PropTypes = require('prop-types'),
22
- utils = require('itsa-utils'),
23
- async = utils.async,
24
- later = utils.later,
25
- Button = require('itsa-react-button'),
26
- serializeStyles = require('./serialize-styles'),
27
- CLICK = 'click',
28
- RESIZE = 'resize',
29
- MAIN_CLASS = 'itsa-table',
30
- ROW_CLASS = 'itsa-table-row',
31
- CELL_CLASS = 'itsa-table-cell itsa-table-col-',
32
- EDITABLE_CELL_CLASS_SPACED = ' itsa-table-editable-cell',
33
- ROW_REMOVE_CLASS = '__row-remove',
34
- ROW_ADD_CLASS = '__row-add',
35
- REGEXP_TRANSPARENT = /^rgba\(\d+\,( )?\d+\,( )?\d+\,( )?0\)$/,
36
- COPY_STYLES = [
37
- 'width',
38
- 'height',
39
- 'padding-left',
40
- 'padding-right',
41
- 'padding-top',
42
- 'padding-bottom',
43
- 'border-top-color',
44
- 'border-top-left-radius',
45
- 'border-top-right-radius',
46
- 'border-top-style',
47
- 'border-top-width',
48
- 'border-bottom-color',
49
- 'border-bottom-left-radius',
50
- 'border-bottom-right-radius',
51
- 'border-bottom-style',
52
- 'border-bottom-width',
53
- 'border-left-color',
54
- 'border-left-style',
55
- 'border-left-width',
56
- 'border-right-color',
57
- 'border-right-style',
58
- 'border-right-width',
59
- 'background-color',
60
- 'background-image',
61
- 'background-attachment',
62
- 'background-blend-mode',
63
- 'background-clip',
64
- 'background-origin',
65
- 'background-position-x',
66
- 'background-position-y',
67
- 'background-repeat-x',
68
- 'background-repeat-y',
69
- 'background-size',
70
- 'color',
71
- 'font-family',
72
- 'font-feature-settings',
73
- 'font-kerning',
74
- 'font-size',
75
- 'font-stretch',
76
- 'font-style',
77
- 'font-variant-caps',
78
- 'font-variant-east-asian',
79
- 'font-variant-ligatures',
80
- 'font-variant-numeric',
81
- 'font-variant-settings',
82
- 'font-weight',
83
- 'font-smooting',
84
- 'font-size-delta',
85
- 'opacity',
86
- 'overflow',
87
- 'white-space',
88
- 'visibility',
89
- '-webkit-font-smooting',
90
- '-webkit-font-size-delta',
91
- '-ms-font-smooting',
92
- '-ms-font-size-delta',
93
- 'text-align',
94
- 'text-align-last',
95
- 'text-combine-upright',
96
- 'text-decoration-color',
97
- 'text-decoration-line',
98
- 'text-decoration-skip-ink',
99
- 'text-decoration-style',
100
- 'text-indent',
101
- 'text-orientation',
102
- 'text-overflow',
103
- 'text-rendering',
104
- 'text-shadow',
105
- 'text-size-adjust',
106
- 'text-transform',
107
- 'text-underline-position',
108
- '-webkit-text-align',
109
- '-webkit-text-combine',
110
- '-webkit-text-decorations-in-effect',
111
- '-webkit-text-emphasis-color',
112
- '-webkit-text-emphasis-position',
113
- '-webkit-text-emphasis-style',
114
- '-webkit-text-fill-color',
115
- '-webkit-text-orientation',
116
- '-webkit-text-security',
117
- '-webkit-text-stroke-color',
118
- '-webkit-text-stroke-width',
119
- '-ms-text-align',
120
- '-ms-text-combine',
121
- '-ms-text-decorations-in-effect',
122
- '-ms-text-emphasis-color',
123
- '-ms-text-emphasis-position',
124
- '-ms-text-emphasis-style',
125
- '-ms-text-fill-color',
126
- '-ms-text-orientation',
127
- '-ms-text-security',
128
- '-ms-text-stroke-color',
129
- '-ms-text-stroke-width'
130
- ];
20
+ const React = require("react"),
21
+ PropTypes = require("prop-types"),
22
+ utils = require("itsa-utils"),
23
+ async = utils.async,
24
+ later = utils.later,
25
+ Button = require("itsa-react-button"),
26
+ serializeStyles = require("./serialize-styles"),
27
+ CLICK = "click",
28
+ RESIZE = "resize",
29
+ MAIN_CLASS = "itsa-table",
30
+ ROW_CLASS = "itsa-table-row",
31
+ CELL_CLASS = "itsa-table-cell itsa-table-col-",
32
+ EDITABLE_CELL_CLASS_SPACED = " itsa-table-editable-cell",
33
+ ROW_REMOVE_CLASS = "__row-remove",
34
+ ROW_ADD_CLASS = "__row-add",
35
+ REGEXP_TRANSPARENT = /^rgba\(\d+\,( )?\d+\,( )?\d+\,( )?0\)$/,
36
+ COPY_STYLES = [
37
+ "width",
38
+ "height",
39
+ "padding-left",
40
+ "padding-right",
41
+ "padding-top",
42
+ "padding-bottom",
43
+ "border-top-color",
44
+ "border-top-left-radius",
45
+ "border-top-right-radius",
46
+ "border-top-style",
47
+ "border-top-width",
48
+ "border-bottom-color",
49
+ "border-bottom-left-radius",
50
+ "border-bottom-right-radius",
51
+ "border-bottom-style",
52
+ "border-bottom-width",
53
+ "border-left-color",
54
+ "border-left-style",
55
+ "border-left-width",
56
+ "border-right-color",
57
+ "border-right-style",
58
+ "border-right-width",
59
+ "background-color",
60
+ "background-image",
61
+ "background-attachment",
62
+ "background-blend-mode",
63
+ "background-clip",
64
+ "background-origin",
65
+ "background-position-x",
66
+ "background-position-y",
67
+ "background-repeat-x",
68
+ "background-repeat-y",
69
+ "background-size",
70
+ "color",
71
+ "font-family",
72
+ "font-feature-settings",
73
+ "font-kerning",
74
+ "font-size",
75
+ "font-stretch",
76
+ "font-style",
77
+ "font-variant-caps",
78
+ "font-variant-east-asian",
79
+ "font-variant-ligatures",
80
+ "font-variant-numeric",
81
+ "font-variant-settings",
82
+ "font-weight",
83
+ "font-smooting",
84
+ "font-size-delta",
85
+ "opacity",
86
+ "overflow",
87
+ "white-space",
88
+ "visibility",
89
+ "-webkit-font-smooting",
90
+ "-webkit-font-size-delta",
91
+ "-ms-font-smooting",
92
+ "-ms-font-size-delta",
93
+ "text-align",
94
+ "text-align-last",
95
+ "text-combine-upright",
96
+ "text-decoration-color",
97
+ "text-decoration-line",
98
+ "text-decoration-skip-ink",
99
+ "text-decoration-style",
100
+ "text-indent",
101
+ "text-orientation",
102
+ "text-overflow",
103
+ "text-rendering",
104
+ "text-shadow",
105
+ "text-size-adjust",
106
+ "text-transform",
107
+ "text-underline-position",
108
+ "-webkit-text-align",
109
+ "-webkit-text-combine",
110
+ "-webkit-text-decorations-in-effect",
111
+ "-webkit-text-emphasis-color",
112
+ "-webkit-text-emphasis-position",
113
+ "-webkit-text-emphasis-style",
114
+ "-webkit-text-fill-color",
115
+ "-webkit-text-orientation",
116
+ "-webkit-text-security",
117
+ "-webkit-text-stroke-color",
118
+ "-webkit-text-stroke-width",
119
+ "-ms-text-align",
120
+ "-ms-text-combine",
121
+ "-ms-text-decorations-in-effect",
122
+ "-ms-text-emphasis-color",
123
+ "-ms-text-emphasis-position",
124
+ "-ms-text-emphasis-style",
125
+ "-ms-text-fill-color",
126
+ "-ms-text-orientation",
127
+ "-ms-text-security",
128
+ "-ms-text-stroke-color",
129
+ "-ms-text-stroke-width",
130
+ ];
131
131
 
132
- const retrieveFieldName = field => {
133
- return (typeof field==='object') ? field.key : field;
132
+ const retrieveFieldName = (field) => {
133
+ return typeof field === "object" ? field.key : field;
134
134
  };
135
135
 
136
- const cloneData = arr => {
137
- return arr.map(record => {
138
- let newRecord = {};
139
- record.itsa_each((value, key) => {
140
- newRecord[key] = value;
141
- });
142
- return newRecord;
136
+ const cloneData = (arr) => {
137
+ return arr.map((record) => {
138
+ let newRecord = {};
139
+ record.itsa_each((value, key) => {
140
+ newRecord[key] = value;
143
141
  });
142
+ return newRecord;
143
+ });
144
144
  };
145
145
 
146
146
  class Table extends React.Component {
147
- constructor(props) {
148
- super(props);
149
- const instance = this;
150
- instance.state = {
151
- editableRow: null,
152
- editableCol: null,
153
- editValue: ''
154
- };
155
- instance.changeCell = instance.changeCell.bind(instance);
156
- instance.handleCellKeyDown = instance.handleCellKeyDown.bind(instance);
157
- instance.focus = instance.focus.bind(instance);
158
- instance._focusActiveCell = instance._focusActiveCell.bind(instance);
159
- instance.generateHead = instance.generateHead.bind(instance);
160
- instance.generateRows = instance.generateRows.bind(instance);
161
- instance.refocus = instance.refocus.bind(instance);
162
- instance.addRow = instance.addRow.bind(instance);
163
- instance.addCol = instance.addCol.bind(instance);
164
- instance.deleteRow = instance.deleteRow.bind(instance);
165
- instance._handleDocumentClick = instance._handleDocumentClick.bind(instance);
166
- instance._handleResize = instance._handleResize.bind(instance);
167
- instance.focusTextArea = instance.focusTextArea.bind(instance);
168
- instance.setFixedHeaderDimensions = instance.setFixedHeaderDimensions.bind(instance);
169
- }
147
+ constructor(props) {
148
+ super(props);
149
+ const instance = this;
150
+ instance.state = {
151
+ editableRow: null,
152
+ editableCol: null,
153
+ editValue: "",
154
+ };
155
+ instance.changeCell = instance.changeCell.bind(instance);
156
+ instance.handleCellKeyDown = instance.handleCellKeyDown.bind(instance);
157
+ instance.focus = instance.focus.bind(instance);
158
+ instance._focusActiveCell = instance._focusActiveCell.bind(instance);
159
+ instance.generateHead = instance.generateHead.bind(instance);
160
+ instance.generateRows = instance.generateRows.bind(instance);
161
+ instance.refocus = instance.refocus.bind(instance);
162
+ instance.addRow = instance.addRow.bind(instance);
163
+ instance.addCol = instance.addCol.bind(instance);
164
+ instance.deleteRow = instance.deleteRow.bind(instance);
165
+ instance._handleDocumentClick =
166
+ instance._handleDocumentClick.bind(instance);
167
+ instance._handleResize = instance._handleResize.bind(instance);
168
+ instance.focusTextArea = instance.focusTextArea.bind(instance);
169
+ instance.setFixedHeaderDimensions =
170
+ instance.setFixedHeaderDimensions.bind(instance);
171
+ }
170
172
 
171
- componentDidMount() {
172
- const instance = this,
173
- props = instance.props;
174
- instance._tableWidth = instance._tableNode.offsetWidth;
175
- // set outside clickHandler which watches for outside clicks that will collapse the component:
176
- instance.IE8_EVENTS = !instance._componentNode.addEventListener;
177
- if (instance.IE8_EVENTS) {
178
- document.attachEvent('on'+CLICK, instance._handleDocumentClick);
179
- window.attachEvent('on'+RESIZE, instance._handleResize);
180
- }
181
- else {
182
- document.addEventListener(CLICK, instance._handleDocumentClick, true);
183
- window.addEventListener(RESIZE, instance._handleResize, true);
184
- }
185
- props.autoFocus && instance.focus();
186
- if (props.fixedHeaders) {
187
- async(instance.setFixedHeaderDimensions);
188
- instance._timer = later(instance.setFixedHeaderDimensions, 300, true);
189
- }
173
+ componentDidMount() {
174
+ const instance = this,
175
+ props = instance.props;
176
+ instance._tableWidth = instance._tableNode.offsetWidth;
177
+ // set outside clickHandler which watches for outside clicks that will collapse the component:
178
+ instance.IE8_EVENTS = !instance._componentNode.addEventListener;
179
+ if (instance.IE8_EVENTS) {
180
+ document.attachEvent("on" + CLICK, instance._handleDocumentClick);
181
+ window.attachEvent("on" + RESIZE, instance._handleResize);
182
+ } else {
183
+ document.addEventListener(CLICK, instance._handleDocumentClick, true);
184
+ window.addEventListener(RESIZE, instance._handleResize, true);
190
185
  }
191
-
192
- /**
193
- * componentWilUnmount does some cleanup.
194
- *
195
- * @method componentWillUnmount
196
- * @since 0.0.1
197
- */
198
- componentWillUnmount() {
199
- const instance = this;
200
- instance._timer && instance._timer.cancel();
201
- instance.unmounted = true;
202
- if (instance.IE8_EVENTS) {
203
- document.detachEvent('on'+CLICK, instance._handleDocumentClick);
204
- window.detachEvent('on'+RESIZE, instance._handleResize);
205
- }
206
- else {
207
- document.removeEventListener(CLICK, instance._handleDocumentClick, true);
208
- window.removeEventListener(RESIZE, instance._handleResize, true);
209
- }
186
+ props.autoFocus && instance.focus();
187
+ if (props.fixedHeaders) {
188
+ async(instance.setFixedHeaderDimensions);
189
+ instance._timer = later(instance.setFixedHeaderDimensions, 300, true);
210
190
  }
191
+ }
211
192
 
212
- componentDidUpdate() {
213
- this.setFixedHeaderDimensions();
193
+ /**
194
+ * componentWilUnmount does some cleanup.
195
+ *
196
+ * @method componentWillUnmount
197
+ * @since 0.0.1
198
+ */
199
+ componentWillUnmount() {
200
+ const instance = this;
201
+ instance._timer && instance._timer.cancel();
202
+ instance.unmounted = true;
203
+ if (instance.IE8_EVENTS) {
204
+ document.detachEvent("on" + CLICK, instance._handleDocumentClick);
205
+ window.detachEvent("on" + RESIZE, instance._handleResize);
206
+ } else {
207
+ document.removeEventListener(CLICK, instance._handleDocumentClick, true);
208
+ window.removeEventListener(RESIZE, instance._handleResize, true);
214
209
  }
210
+ }
215
211
 
216
- _handleResize() {
217
- const instance = this,
218
- newWidth = instance._tableNode.offsetWidth;
219
- if (instance._tableWidth!==newWidth) {
220
- instance._tableWidth = newWidth;
221
- instance.setFixedHeaderDimensions();
222
- }
223
- }
212
+ componentDidUpdate() {
213
+ this.setFixedHeaderDimensions();
214
+ }
224
215
 
225
- setFixedHeaderDimensions() {
226
- let headNode, ths;
227
- const instance = this,
228
- props = instance.props;
229
- if (props.fixedHeaders && props.columns && !instance.unmounted) {
230
- headNode = instance._headNode;
231
- if (headNode) {
232
- ths = headNode.itsa_getAll('th');
233
- Array.prototype.forEach.call(ths, thNode => {
234
- let inlineStyle = {},
235
- fixedNode, fixedContainerNode, contStyle, currentLeft, currentTop, prevAttr, newAttr;
236
- COPY_STYLES.forEach(style => {
237
- let nodeStyle = thNode.itsa_getStyle(style);
238
- if ((style==='background-color') && nodeStyle && REGEXP_TRANSPARENT.test(nodeStyle)) {
239
- nodeStyle = undefined; // fixed headers cannot be transparent -> revert to the class background-color
240
- }
241
- (nodeStyle===undefined) || (inlineStyle[style]=nodeStyle+' !important');
242
- });
243
- fixedContainerNode = thNode.itsa_getElement('div.itsa-table-header-cont');
244
- if (fixedContainerNode) {
245
- currentLeft = fixedContainerNode.itsa_getInlineStyle('left');
246
- if (currentLeft) {
247
- currentLeft = parseInt(currentLeft, 10);
248
- }
249
- else {
250
- currentLeft = 0;
251
- }
252
- currentTop = fixedContainerNode.itsa_getInlineStyle('top');
253
- if (currentTop) {
254
- currentTop = parseInt(currentTop, 10);
255
- }
256
- else {
257
- currentTop = 0;
258
- }
259
- contStyle = {
260
- left: (thNode.itsa_left-fixedContainerNode.itsa_left+currentLeft)+'px',
261
- top: (thNode.itsa_top-fixedContainerNode.itsa_top+currentTop)+'px'
262
- };
263
- prevAttr = fixedContainerNode.getAttribute('style');
264
- newAttr = serializeStyles.serialize(contStyle);
265
- (prevAttr===newAttr) || fixedContainerNode.setAttribute('style', newAttr);
266
- }
267
- fixedNode = thNode.itsa_getElement('div.itsa-table-header');
268
- if (fixedNode) {
269
- prevAttr = fixedNode.getAttribute('style');
270
- newAttr = serializeStyles.serialize(inlineStyle);
271
- (prevAttr===newAttr) || fixedNode.setAttribute('style', newAttr);
272
- }
273
- });
274
- }
275
- }
216
+ _handleResize() {
217
+ const instance = this,
218
+ newWidth = instance._tableNode.offsetWidth;
219
+ if (instance._tableWidth !== newWidth) {
220
+ instance._tableWidth = newWidth;
221
+ instance.setFixedHeaderDimensions();
276
222
  }
223
+ }
277
224
 
278
- changeCell(e) {
279
- const value = e.target.value;
280
- this._editValueBeforeBlur = value;
281
- this.setState({
282
- editValue: value
225
+ setFixedHeaderDimensions() {
226
+ let headNode, ths;
227
+ const instance = this,
228
+ props = instance.props;
229
+ if (props.fixedHeaders && props.columns && !instance.unmounted) {
230
+ headNode = instance._headNode;
231
+ if (headNode) {
232
+ ths = headNode.itsa_getAll("th");
233
+ Array.prototype.forEach.call(ths, (thNode) => {
234
+ let inlineStyle = {},
235
+ fixedNode,
236
+ fixedContainerNode,
237
+ contStyle,
238
+ currentLeft,
239
+ currentTop,
240
+ prevAttr,
241
+ newAttr;
242
+ COPY_STYLES.forEach((style) => {
243
+ let nodeStyle = thNode.itsa_getStyle(style);
244
+ if (
245
+ style === "background-color" &&
246
+ nodeStyle &&
247
+ REGEXP_TRANSPARENT.test(nodeStyle)
248
+ ) {
249
+ nodeStyle = undefined; // fixed headers cannot be transparent -> revert to the class background-color
250
+ }
251
+ nodeStyle === undefined ||
252
+ (inlineStyle[style] = nodeStyle + " !important");
253
+ });
254
+ fixedContainerNode = thNode.itsa_getElement(
255
+ "div.itsa-table-header-cont"
256
+ );
257
+ if (fixedContainerNode) {
258
+ currentLeft = fixedContainerNode.itsa_getInlineStyle("left");
259
+ if (currentLeft) {
260
+ currentLeft = parseInt(currentLeft, 10);
261
+ } else {
262
+ currentLeft = 0;
263
+ }
264
+ currentTop = fixedContainerNode.itsa_getInlineStyle("top");
265
+ if (currentTop) {
266
+ currentTop = parseInt(currentTop, 10);
267
+ } else {
268
+ currentTop = 0;
269
+ }
270
+ contStyle = {
271
+ left:
272
+ thNode.itsa_left -
273
+ fixedContainerNode.itsa_left +
274
+ currentLeft +
275
+ "px",
276
+ top:
277
+ thNode.itsa_top -
278
+ fixedContainerNode.itsa_top +
279
+ currentTop +
280
+ "px",
281
+ };
282
+ prevAttr = fixedContainerNode.getAttribute("style");
283
+ newAttr = serializeStyles.serialize(contStyle);
284
+ prevAttr === newAttr ||
285
+ fixedContainerNode.setAttribute("style", newAttr);
286
+ }
287
+ fixedNode = thNode.itsa_getElement("div.itsa-table-header");
288
+ if (fixedNode) {
289
+ prevAttr = fixedNode.getAttribute("style");
290
+ newAttr = serializeStyles.serialize(inlineStyle);
291
+ prevAttr === newAttr || fixedNode.setAttribute("style", newAttr);
292
+ }
283
293
  });
294
+ }
284
295
  }
296
+ }
297
+
298
+ changeCell(e) {
299
+ const value = e.target.value;
300
+ this._editValueBeforeBlur = value;
301
+ this.setState({
302
+ editValue: value,
303
+ });
304
+ }
285
305
 
286
- handleCellKeyDown(e) {
287
- const instance = this;
288
- if (e.keyCode===27) {
289
- instance.setState(prevState => {
290
- return {
291
- editValue: instance._editValueBeforeEdit,
292
- editableRow: null,
293
- editableCol: null
294
- };
295
- }, () => {
296
- instance._blurActiveCell();
297
- });
306
+ handleCellKeyDown(e) {
307
+ const instance = this;
308
+ if (e.keyCode === 27) {
309
+ instance.setState(
310
+ (prevState) => {
311
+ return {
312
+ editValue: instance._editValueBeforeEdit,
313
+ editableRow: null,
314
+ editableCol: null,
315
+ };
316
+ },
317
+ () => {
318
+ instance._blurActiveCell();
298
319
  }
320
+ );
299
321
  }
322
+ }
300
323
 
301
- implementCellChanges(rowIndex, field, force) {
302
- let changed, newData, col, secondField, x, y, columns, cells, editableCols;
303
- const instance = this,
304
- props = instance.props,
305
- propsData = props.data,
306
- state = instance.state,
307
- onChange = props.onChange,
308
- onChangeCell = props.onChangeCell,
309
- selectedRange = state.selectedRange,
310
- editValueBeforeBlur = instance._editValueBeforeBlur,
311
- editValueBeforeEdit = instance._editValueBeforeEdit;
324
+ implementCellChanges(rowIndex, field, force) {
325
+ let changed, newData, col, secondField, x, y, columns, cells, editableCols;
326
+ const instance = this,
327
+ props = instance.props,
328
+ propsData = props.data,
329
+ state = instance.state,
330
+ onChange = props.onChange,
331
+ onChangeCell = props.onChangeCell,
332
+ selectedRange = state.selectedRange,
333
+ editValueBeforeBlur = instance._editValueBeforeBlur,
334
+ editValueBeforeEdit = instance._editValueBeforeEdit;
312
335
 
313
- delete instance._editValueBeforeBlur;
314
- if (typeof field==='object') {
315
- field = field.key;
316
- }
336
+ delete instance._editValueBeforeBlur;
337
+ if (typeof field === "object") {
338
+ field = field.key;
339
+ }
317
340
 
318
- if (((editValueBeforeEdit===editValueBeforeBlur) && !selectedRange) || (editValueBeforeBlur===undefined)) {
319
- // nothing changed
320
- return;
321
- }
341
+ if (
342
+ (editValueBeforeEdit === editValueBeforeBlur && !selectedRange) ||
343
+ editValueBeforeBlur === undefined
344
+ ) {
345
+ // nothing changed
346
+ return;
347
+ }
322
348
 
323
- // if ((props.data[rowIndex][field]==editValueBeforeBlur) ||
324
- // ((props.data[rowIndex][field]===undefined) && (editValueBeforeBlur==='')) ||
325
- // ((props.data[rowIndex][field]===null) && (editValueBeforeBlur===''))) { // DO NOT tripple check -> the original value may not be a string, whereas the editvalue is!!
326
- // // nothing changed
327
- // return;
328
- // }
349
+ // if ((props.data[rowIndex][field]==editValueBeforeBlur) ||
350
+ // ((props.data[rowIndex][field]===undefined) && (editValueBeforeBlur==='')) ||
351
+ // ((props.data[rowIndex][field]===null) && (editValueBeforeBlur===''))) { // DO NOT tripple check -> the original value may not be a string, whereas the editvalue is!!
352
+ // // nothing changed
353
+ // return;
354
+ // }
329
355
 
330
- if (selectedRange) {
331
- // editableCols: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
332
- if (force!==true) {
333
- return;
334
- }
335
- columns = props.columns;
336
- if (!columns || (columns.length===0)) {
337
- columns = instance._columns;
338
- }
339
- editableCols = props.editableCols;
340
- if (typeof editableCols==='number') {
341
- editableCols = [editableCols];
342
- }
343
- }
344
- if (onChange) {
345
- changed = false;
346
- newData = cloneData(propsData);
347
- if (newData[rowIndex][field]!=editValueBeforeBlur) {
356
+ if (selectedRange) {
357
+ // editableCols: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
358
+ if (force !== true) {
359
+ return;
360
+ }
361
+ columns = props.columns;
362
+ if (!columns || columns.length === 0) {
363
+ columns = instance._columns;
364
+ }
365
+ editableCols = props.editableCols;
366
+ if (typeof editableCols === "number") {
367
+ editableCols = [editableCols];
368
+ }
369
+ }
370
+ if (onChange) {
371
+ changed = false;
372
+ newData = cloneData(propsData);
373
+ if (newData[rowIndex][field] != editValueBeforeBlur) {
374
+ changed = true;
375
+ newData[rowIndex][field] = editValueBeforeBlur;
376
+ }
377
+ // we might need to change multiple cells, in case `multiEdit` is set, which leads into a value for state.selectedRange:
378
+ if (selectedRange) {
379
+ // editableCols: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
380
+ for (x = selectedRange.x1; x <= selectedRange.x2; x++) {
381
+ if (!editableCols || editableCols.itsa_contains(x)) {
382
+ for (y = selectedRange.y1; y <= selectedRange.y2; y++) {
383
+ col = columns[x];
384
+ secondField = typeof col === "string" ? col : col.key;
385
+ if (newData[y][secondField] != editValueBeforeBlur) {
348
386
  changed = true;
349
- newData[rowIndex][field] = editValueBeforeBlur;
350
- }
351
- // we might need to change multiple cells, in case `multiEdit` is set, which leads into a value for state.selectedRange:
352
- if (selectedRange) {
353
- // editableCols: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
354
- for (x=selectedRange.x1; x<=selectedRange.x2; x++) {
355
- if (!editableCols || editableCols.itsa_contains(x)) {
356
- for (y=selectedRange.y1; y<=selectedRange.y2; y++) {
357
- col = columns[x];
358
- secondField = (typeof col==='string') ? col : col.key;
359
- if (newData[y][secondField]!=editValueBeforeBlur) {
360
- changed = true;
361
- newData[y][secondField] = editValueBeforeBlur;
362
- }
363
- }
364
- }
365
- }
387
+ newData[y][secondField] = editValueBeforeBlur;
388
+ }
366
389
  }
367
- changed && onChange(newData);
390
+ }
368
391
  }
369
- if (onChangeCell) {
370
- if (!props.multiEdit) {
371
- if (propsData[rowIndex][field]!=editValueBeforeBlur) {
372
- onChangeCell(rowIndex, field, editValueBeforeBlur);
373
- }
374
- }
375
- else {
376
- changed = false;
377
- cells = [{row: rowIndex, field}];
378
- if (propsData[rowIndex][field]!=editValueBeforeBlur) {
379
- changed = true;
380
- }
381
- // we might need to change multiple cells, in case `multiEdit` is set, which leads into a value for state.selectedRange:
382
- if (selectedRange) {
383
- // editableCols: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
384
- for (x=selectedRange.x1; x<=selectedRange.x2; x++) {
385
- if (!editableCols || editableCols.itsa_contains(x)) {
386
- for (y=selectedRange.y1; y<=selectedRange.y2; y++) {
387
- col = columns[x];
388
- secondField = (typeof col==='string') ? col : col.key;
389
- cells.push({row: y, field: secondField});
390
- if (propsData[y][secondField]!=editValueBeforeBlur) {
391
- changed = true;
392
- }
393
- }
394
- }
395
- }
396
- }
397
- changed && onChangeCell(cells, editValueBeforeBlur);
398
- }
392
+ }
393
+ changed && onChange(newData);
394
+ }
395
+ if (onChangeCell) {
396
+ if (!props.multiEdit) {
397
+ if (propsData[rowIndex][field] != editValueBeforeBlur) {
398
+ onChangeCell(rowIndex, field, editValueBeforeBlur);
399
399
  }
400
- if (selectedRange) {
401
- instance.setState({selectedRange: null});
400
+ } else {
401
+ changed = false;
402
+ cells = [{ row: rowIndex, field }];
403
+ if (propsData[rowIndex][field] != editValueBeforeBlur) {
404
+ changed = true;
402
405
  }
403
- }
404
-
405
- focus() {
406
- let editableCol, columns, hasColumns, item, editValue, editableCols;
407
- const instance = this,
408
- props = instance.props,
409
- state = instance.state;
410
- editableCols = props.editableCols;
411
- if ((state.editableRow===null) || (state.editableCol===null)) {
412
- editableCol = props.rowHeader ? 1 : 0;
413
- if (typeof editableCols==='number') {
414
- editableCols = [editableCols];
415
- }
416
- if (editableCols) {
417
- editableCol += editableCols[0];
418
- if (props.rowHeader) {
419
- editableCol--;
406
+ // we might need to change multiple cells, in case `multiEdit` is set, which leads into a value for state.selectedRange:
407
+ if (selectedRange) {
408
+ // editableCols: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
409
+ for (x = selectedRange.x1; x <= selectedRange.x2; x++) {
410
+ if (!editableCols || editableCols.itsa_contains(x)) {
411
+ for (y = selectedRange.y1; y <= selectedRange.y2; y++) {
412
+ col = columns[x];
413
+ secondField = typeof col === "string" ? col : col.key;
414
+ cells.push({ row: y, field: secondField });
415
+ if (propsData[y][secondField] != editValueBeforeBlur) {
416
+ changed = true;
420
417
  }
418
+ }
421
419
  }
422
- columns = props.columns;
423
- hasColumns = (columns && (columns.length>0));
424
- item = props.data[0];
425
- editValue = hasColumns ? item[retrieveFieldName(columns[editableCol])] : item[retrieveFieldName(instance._columns[editableCol])];
426
- instance.setState({
427
- editableRow: 0,
428
- editableCol,
429
- editValue,
430
- selectedRangeStart: {
431
- x: editableCol,
432
- y: 0
433
- }
434
- });
420
+ }
435
421
  }
436
- instance._focusActiveCell();
422
+ changed && onChangeCell(cells, editValueBeforeBlur);
423
+ }
437
424
  }
438
-
439
- focusTextArea(e) {
440
- let length;
441
- const instance = this,
442
- node = e.target;
443
- instance._editValueBeforeBlur = node.value;
444
- if (instance.props.fullSelectOnEdit) {
445
- length = node.value.length;
446
- node.setSelectionRange(length, length);
447
- }
425
+ if (selectedRange) {
426
+ instance.setState({ selectedRange: null });
448
427
  }
428
+ }
449
429
 
450
- _blurActiveCell() {
451
- const instance = this,
452
- state = instance.state,
453
- textareaNode = instance['_textarea_'+state.editableRow+'_'+state.editableCol],
454
- componentContainerNode = instance['_component_'+state.editableRow+'_'+state.editableCol],
455
- componentNode = componentContainerNode && componentContainerNode.itsa_getElement('button'),
456
- focussableNode = textareaNode || componentNode;
457
- if (focussableNode && ((document.activeElement===focussableNode) || document.activeElement.contains(focussableNode))) {
458
- focussableNode.blur();
430
+ focus() {
431
+ let editableCol, columns, hasColumns, item, editValue, editableCols;
432
+ const instance = this,
433
+ props = instance.props,
434
+ state = instance.state;
435
+ editableCols = props.editableCols;
436
+ if (state.editableRow === null || state.editableCol === null) {
437
+ editableCol = props.rowHeader ? 1 : 0;
438
+ if (typeof editableCols === "number") {
439
+ editableCols = [editableCols];
440
+ }
441
+ if (editableCols) {
442
+ editableCol += editableCols[0];
443
+ if (props.rowHeader) {
444
+ editableCol--;
459
445
  }
446
+ }
447
+ columns = props.columns;
448
+ hasColumns = columns && columns.length > 0;
449
+ item = props.data[0];
450
+ editValue = hasColumns
451
+ ? item[retrieveFieldName(columns[editableCol])]
452
+ : item[retrieveFieldName(instance._columns[editableCol])];
453
+ instance.setState({
454
+ editableRow: 0,
455
+ editableCol,
456
+ editValue,
457
+ selectedRangeStart: {
458
+ x: editableCol,
459
+ y: 0,
460
+ },
461
+ });
460
462
  }
463
+ instance._focusActiveCell();
464
+ }
461
465
 
462
- _focusActiveCell() {
463
- const instance = this;
464
- async(() => {
465
- let length;
466
- const state = instance.state,
467
- textareaNode = instance['_textarea_'+state.editableRow+'_'+state.editableCol],
468
- componentContainerNode = instance['_component_'+state.editableRow+'_'+state.editableCol],
469
- componentNode = componentContainerNode && componentContainerNode.itsa_getElement('button');
470
- if (textareaNode && (document.activeElement!==textareaNode)) {
471
- instance._editValueBeforeEdit = textareaNode.value || '';
472
- textareaNode.focus();
473
- if (textareaNode.setSelectionRange) {
474
- length = textareaNode.value.length;
475
- textareaNode.setSelectionRange(0, length);
476
- }
477
- }
478
- else if (componentNode) {
479
- componentNode.focus();
480
- }
481
- });
466
+ focusTextArea(e) {
467
+ let length;
468
+ const instance = this,
469
+ node = e.target;
470
+ instance._editValueBeforeBlur = node.value;
471
+ if (instance.props.fullSelectOnEdit) {
472
+ length = node.value.length;
473
+ node.setSelectionRange(length, length);
482
474
  }
475
+ }
483
476
 
484
- scrollTo(amount) {
485
- this._componentNode.scrollTop = amount;
477
+ _blurActiveCell() {
478
+ const instance = this,
479
+ state = instance.state,
480
+ textareaNode =
481
+ instance["_textarea_" + state.editableRow + "_" + state.editableCol],
482
+ componentContainerNode =
483
+ instance["_component_" + state.editableRow + "_" + state.editableCol],
484
+ componentNode =
485
+ componentContainerNode &&
486
+ componentContainerNode.itsa_getElement("button"),
487
+ focussableNode = textareaNode || componentNode;
488
+ if (
489
+ focussableNode &&
490
+ (document.activeElement === focussableNode ||
491
+ document.activeElement.contains(focussableNode))
492
+ ) {
493
+ focussableNode.blur();
486
494
  }
495
+ }
487
496
 
488
- generateHead() {
489
- let cols, alreadyDefined,
490
- j = -1;
491
- const instance = this,
492
- props = instance.props,
493
- removeableY = props.removeableY,
494
- extendableY = props.extendableY,
495
- columns = props.columns,
496
- fixedHeaders = props.fixedHeaders,
497
- rowHeader = props.rowHeader,
498
- onHeaderClick = props.onHeaderClick;
497
+ _focusActiveCell() {
498
+ const instance = this;
499
+ async(() => {
500
+ let length;
501
+ const state = instance.state,
502
+ textareaNode =
503
+ instance["_textarea_" + state.editableRow + "_" + state.editableCol],
504
+ componentContainerNode =
505
+ instance["_component_" + state.editableRow + "_" + state.editableCol],
506
+ componentNode =
507
+ componentContainerNode &&
508
+ componentContainerNode.itsa_getElement("button");
509
+ if (textareaNode && document.activeElement !== textareaNode) {
510
+ instance._editValueBeforeEdit = textareaNode.value || "";
511
+ textareaNode.focus();
512
+ if (textareaNode.setSelectionRange) {
513
+ length = textareaNode.value.length;
514
+ textareaNode.setSelectionRange(0, length);
515
+ }
516
+ } else if (componentNode) {
517
+ componentNode.focus();
518
+ }
519
+ });
520
+ }
499
521
 
500
- if (columns && (columns.length>0)) {
501
- // first dedupe duplicated col-keys
502
- alreadyDefined = {};
503
- cols = columns.filter(col => {
504
- let dupe;
505
- const field = (typeof col==='string') ? col : col.key;
506
- dupe = alreadyDefined[field];
507
- alreadyDefined[field] = true;
508
- return !dupe;
509
- }).map((col, i) => {
510
- let colName, classname, key, cellContent, headerClick;
511
- const field = (typeof col==='string') ? col : col.key;
512
- classname = 'itsa-table-header itsa-table-col-'+field;
513
- headerClick = e => {
514
- let selectedRange;
515
- const state = instance.state,
516
- rowIndex = state.editableRow,
517
- colIndex = state.editableCol,
518
- editCol = (typeof colIndex==='number') && columns[colIndex],
519
- editField = editCol && ((typeof editCol==='string') ? editCol : editCol.key);
520
- if (state.selectedRange) {
521
- selectedRange = state.selectedRange.itsa_deepClone();
522
- }
523
- instance.setState({
524
- editableRow: null,
525
- editableCol: null,
526
- editValue: ''
527
- }, () => {
528
- if (selectedRange) {
529
- instance.setState({selectedRange: null});
530
- }
531
- });
532
- if (typeof rowIndex==='number') {
533
- instance.implementCellChanges(rowIndex, editField);
534
- }
535
- if (onHeaderClick) {
536
- async(onHeaderClick.call(null, field, editField, state.editValue, rowIndex, colIndex, selectedRange, e));
537
- }
538
- };
539
- if ((i>0) || !rowHeader) {
540
- colName = (typeof col==='string') ? col : (col.label || col.key);
541
- key = (typeof col==='string') ? col : col.key;
542
- }
543
- else {
544
- classname += ' itsa-table-header-rowheader';
545
- key=j--;
546
- }
547
- if (fixedHeaders) {
548
- colName || (colName='&nbsp;');
549
- cellContent = '<div class="itsa-table-header-cont"><div class="itsa-table-header">'+colName+'</div></div>'+colName;
550
- return (<th className={classname} dangerouslySetInnerHTML={{__html: cellContent}} key={key} onClick={headerClick} />);
551
- }
552
- return (<th className={classname} dangerouslySetInnerHTML={{__html: colName}} key={key} onClick={headerClick} />);
553
- });
554
- if (extendableY==="full") {
555
- if (fixedHeaders) {
556
- cols.unshift((<th className={'itsa-table-header '+ROW_ADD_CLASS} key={j--}><div className="itsa-table-header-cont"><div className="itsa-table-header">&nbsp;</div></div>&nbsp;</th>));
557
- }
558
- else {
559
- cols.unshift((<th className={'itsa-table-header '+ROW_ADD_CLASS} key={j--} />));
560
- }
522
+ scrollTo(amount) {
523
+ this._componentNode.scrollTop = amount;
524
+ }
525
+
526
+ generateHead() {
527
+ let cols,
528
+ alreadyDefined,
529
+ j = -1;
530
+ const instance = this,
531
+ props = instance.props,
532
+ removeableY = props.removeableY,
533
+ extendableY = props.extendableY,
534
+ columns = props.columns,
535
+ fixedHeaders = props.fixedHeaders,
536
+ rowHeader = props.rowHeader,
537
+ onHeaderClick = props.onHeaderClick,
538
+ htmlHeaders = props.htmlHeaders;
539
+
540
+ if (columns && columns.length > 0) {
541
+ // first dedupe duplicated col-keys
542
+ alreadyDefined = {};
543
+ cols = columns
544
+ .filter((col) => {
545
+ let dupe;
546
+ const field = typeof col === "string" ? col : col.key;
547
+ dupe = alreadyDefined[field];
548
+ alreadyDefined[field] = true;
549
+ return !dupe;
550
+ })
551
+ .map((col, i) => {
552
+ let colName, classname, key, cellContent, headerClick;
553
+ const field = typeof col === "string" ? col : col.key;
554
+ classname = "itsa-table-header itsa-table-col-" + field;
555
+ headerClick = (e) => {
556
+ let selectedRange;
557
+ const state = instance.state,
558
+ rowIndex = state.editableRow,
559
+ colIndex = state.editableCol,
560
+ editCol = typeof colIndex === "number" && columns[colIndex],
561
+ editField =
562
+ editCol &&
563
+ (typeof editCol === "string" ? editCol : editCol.key);
564
+ if (state.selectedRange) {
565
+ selectedRange = state.selectedRange.itsa_deepClone();
561
566
  }
562
- if (removeableY) {
563
- if (fixedHeaders) {
564
- cols.unshift((<th className={'itsa-table-header '+ROW_REMOVE_CLASS} key={j--}><div className="itsa-table-header-cont"><div className="itsa-table-header">&nbsp;</div></div>&nbsp;</th>));
565
- }
566
- else {
567
- cols.unshift((<th className={'itsa-table-header '+ROW_REMOVE_CLASS} key={j--} />));
567
+ instance.setState(
568
+ {
569
+ editableRow: null,
570
+ editableCol: null,
571
+ editValue: "",
572
+ },
573
+ () => {
574
+ if (selectedRange) {
575
+ instance.setState({ selectedRange: null });
568
576
  }
577
+ }
578
+ );
579
+ if (typeof rowIndex === "number") {
580
+ instance.implementCellChanges(rowIndex, editField);
569
581
  }
582
+ if (onHeaderClick) {
583
+ async(
584
+ onHeaderClick.call(
585
+ null,
586
+ field,
587
+ editField,
588
+ state.editValue,
589
+ rowIndex,
590
+ colIndex,
591
+ selectedRange,
592
+ e
593
+ )
594
+ );
595
+ }
596
+ };
597
+ if (i > 0 || !rowHeader) {
598
+ colName = typeof col === "string" ? col : col.label || col.key;
599
+ key = typeof col === "string" ? col : col.key;
600
+ } else {
601
+ classname += " itsa-table-header-rowheader";
602
+ key = j--;
603
+ }
570
604
 
605
+ if (htmlHeaders) {
606
+ if (fixedHeaders) {
607
+ colName || (colName = "&nbsp;");
608
+ cellContent = (
609
+ <div>
610
+ <div class="itsa-table-header-cont">
611
+ <div class="itsa-table-header">{colName}</div>
612
+ </div>
613
+ {colName}
614
+ </div>
615
+ );
616
+ return (
617
+ <th className={classname} key={key} onClick={headerClick}>
618
+ {cellContent}
619
+ </th>
620
+ );
621
+ }
622
+ cellContent = <div>{colName}</div>;
571
623
  return (
572
- <thead ref={node => instance._headNode=node}>
573
- <tr>
574
- {cols}
575
- </tr>
576
- </thead>
624
+ <th className={classname} key={key} onClick={headerClick}>
625
+ {colName}
626
+ </th>
577
627
  );
628
+ } else {
629
+ if (fixedHeaders) {
630
+ colName || (colName = "&nbsp;");
631
+ cellContent =
632
+ '<div class="itsa-table-header-cont"><div class="itsa-table-header">' +
633
+ colName +
634
+ "</div></div>" +
635
+ colName;
636
+ return (
637
+ <th
638
+ className={classname}
639
+ dangerouslySetInnerHTML={{ __html: cellContent }}
640
+ key={key}
641
+ onClick={headerClick}
642
+ />
643
+ );
644
+ }
645
+ return (
646
+ <th
647
+ className={classname}
648
+ dangerouslySetInnerHTML={{ __html: colName }}
649
+ key={key}
650
+ onClick={headerClick}
651
+ />
652
+ );
653
+ }
654
+ });
655
+ if (extendableY === "full") {
656
+ if (fixedHeaders) {
657
+ cols.unshift(
658
+ <th className={"itsa-table-header " + ROW_ADD_CLASS} key={j--}>
659
+ <div className="itsa-table-header-cont">
660
+ <div className="itsa-table-header">&nbsp;</div>
661
+ </div>
662
+ &nbsp;
663
+ </th>
664
+ );
665
+ } else {
666
+ cols.unshift(
667
+ <th className={"itsa-table-header " + ROW_ADD_CLASS} key={j--} />
668
+ );
669
+ }
670
+ }
671
+ if (removeableY) {
672
+ if (fixedHeaders) {
673
+ cols.unshift(
674
+ <th className={"itsa-table-header " + ROW_REMOVE_CLASS} key={j--}>
675
+ <div className="itsa-table-header-cont">
676
+ <div className="itsa-table-header">&nbsp;</div>
677
+ </div>
678
+ &nbsp;
679
+ </th>
680
+ );
681
+ } else {
682
+ cols.unshift(
683
+ <th className={"itsa-table-header " + ROW_REMOVE_CLASS} key={j--} />
684
+ );
578
685
  }
686
+ }
687
+
688
+ return (
689
+ <thead ref={(node) => (instance._headNode = node)}>
690
+ <tr>{cols}</tr>
691
+ </thead>
692
+ );
579
693
  }
694
+ }
695
+
696
+ generateRows() {
697
+ let rowclass, editableColsArray;
698
+ const instance = this,
699
+ props = instance.props,
700
+ state = instance.state,
701
+ data = props.data,
702
+ disabled = props.disabled,
703
+ columns = props.columns,
704
+ selectedRange = state.selectedRange,
705
+ editableCols = props.editableCols,
706
+ rowClassRenderer = props.rowClassRenderer,
707
+ rowHeader = props.rowHeader,
708
+ editable = props.editable,
709
+ removeableY = props.removeableY,
710
+ extendableY = props.extendableY,
711
+ fullEditable = editable === "full",
712
+ hasColumns = columns && columns.length > 0;
713
+
714
+ const colIsEditable = (colIndex) => {
715
+ if (disabled) {
716
+ return false;
717
+ }
718
+ if (!editableCols) {
719
+ return true;
720
+ }
721
+ if (typeof editableCols === "number") {
722
+ return editableCols === colIndex;
723
+ }
724
+ return editableCols.itsa_contains(colIndex);
725
+ };
580
726
 
581
- generateRows() {
582
- let rowclass, editableColsArray;
583
- const instance = this,
584
- props = instance.props,
585
- state = instance.state,
586
- data = props.data,
587
- disabled = props.disabled,
588
- columns = props.columns,
589
- selectedRange = state.selectedRange,
590
- editableCols = props.editableCols,
591
- rowClassRenderer = props.rowClassRenderer,
592
- rowHeader = props.rowHeader,
593
- editable = props.editable,
594
- removeableY = props.removeableY,
595
- extendableY = props.extendableY,
596
- fullEditable = (editable==='full'),
597
- hasColumns = (columns && (columns.length>0));
727
+ if (editableCols) {
728
+ editableColsArray =
729
+ typeof editableCols === "number" ? [editableCols] : editableCols;
730
+ }
598
731
 
599
- const colIsEditable = colIndex => {
600
- if (disabled) {
601
- return false;
732
+ return data.map((rowdata, i) => {
733
+ let cells, extraClass;
734
+ if (hasColumns) {
735
+ // create based upon the columns
736
+ cells = columns.map((col, j) => {
737
+ const field = typeof col === "string" ? col : col.key;
738
+ let classname = CELL_CLASS + field,
739
+ value = rowdata[field],
740
+ cellContent,
741
+ onBlur,
742
+ textAreaValue;
743
+ if (rowHeader && j === 0) {
744
+ classname += " itsa-table-rowheader";
745
+ if (value === null) {
746
+ value = "";
602
747
  }
603
- if (!editableCols) {
604
- return true;
748
+ cellContent = String(value);
749
+ return (
750
+ <td
751
+ className={classname}
752
+ dangerouslySetInnerHTML={{ __html: cellContent }}
753
+ data-colid={j}
754
+ key={field}
755
+ />
756
+ );
757
+ } else if (Object.itsa_isObject(value)) {
758
+ return (
759
+ <td
760
+ className={classname}
761
+ data-colid={j}
762
+ key={field}
763
+ ref={(node) => (instance["_component_" + i + "_" + j] = node)}
764
+ >
765
+ {value}
766
+ </td>
767
+ );
768
+ } else if (
769
+ fullEditable ||
770
+ (editable === true &&
771
+ state.editableRow === i &&
772
+ state.editableCol === j &&
773
+ colIsEditable(j))
774
+ ) {
775
+ classname += EDITABLE_CELL_CLASS_SPACED;
776
+ typeof value === "number" || value || (value = "");
777
+ value = String(value);
778
+ if (
779
+ state.editableRow === i &&
780
+ state.editableCol === j &&
781
+ typeof instance._editValueBeforeBlur === "string"
782
+ ) {
783
+ textAreaValue = state.editValue;
784
+ } else {
785
+ textAreaValue = value;
605
786
  }
606
- if (typeof editableCols==='number') {
607
- return editableCols===colIndex;
787
+ if (textAreaValue === null || textAreaValue === undefined) {
788
+ textAreaValue = "";
608
789
  }
609
- return editableCols.itsa_contains(colIndex);
610
- };
611
-
612
- if (editableCols) {
613
- editableColsArray = (typeof editableCols==='number') ? [editableCols] : editableCols;
614
- }
615
-
616
- return data.map((rowdata, i) => {
617
- let cells, extraClass;
618
- if (hasColumns) {
619
- // create based upon the columns
620
- cells = columns.map((col, j) => {
621
- const field = (typeof col==='string') ? col : col.key;
622
- let classname = CELL_CLASS+field,
623
- value = rowdata[field],
624
- cellContent, onBlur, textAreaValue;
625
- if (rowHeader && (j===0)) {
626
- classname += ' itsa-table-rowheader';
627
- if (value===null) {
628
- value = '';
629
- }
630
- cellContent = String(value);
631
- return (
632
- <td
633
- className={classname}
634
- dangerouslySetInnerHTML={{__html: cellContent}}
635
- data-colid={j}
636
- key={field} />
637
- );
638
- }
639
- else if (Object.itsa_isObject(value)) {
640
- return (
641
- <td
642
- className={classname}
643
- data-colid={j}
644
- key={field}
645
- ref={node => instance['_component_'+i+'_'+j] = node}>
646
- {value}
647
- </td>
648
- );
649
- }
650
- else if (fullEditable || ((editable===true) && (state.editableRow===i) && (state.editableCol===j)) && colIsEditable(j)) {
651
- classname += EDITABLE_CELL_CLASS_SPACED;
652
- (typeof value==='number') || value || (value='');
653
- value = String(value);
654
- if ((state.editableRow===i) && (state.editableCol===j) && (typeof instance._editValueBeforeBlur==='string')) {
655
- textAreaValue = state.editValue;
656
- }
657
- else {
658
- textAreaValue = value;
659
- }
660
- if ((textAreaValue===null) || (textAreaValue===undefined)) {
661
- textAreaValue = '';
662
- }
663
- fullEditable && (onBlur=instance.implementCellChanges.bind(instance, i, field));
664
- cellContent = (
665
- <textarea
666
- disabled={disabled}
667
- onBlur={onBlur}
668
- onChange={instance.changeCell}
669
- onFocus={instance.focusTextArea}
670
- onKeyDown={instance.handleCellKeyDown}
671
- ref={node => instance['_textarea_'+i+'_'+j] = node}
672
- rows={1}
673
- value={textAreaValue} />
674
- );
675
- return (
676
- <td
677
- className={classname}
678
- data-colid={j}
679
- key={field}>
680
- <span>{textAreaValue}</span>
681
- {cellContent}
682
- </td>
683
- );
684
- }
685
- (typeof value==='number') || value || (value='');
686
- // we may need to add an 'selected' class:
687
- if (selectedRange &&
688
- (j>=selectedRange.x1) &&
689
- (j<=selectedRange.x2) &&
690
- (i>=selectedRange.y1) &&
691
- (i<=selectedRange.y2) &&
692
- (!editableCols || editableColsArray.itsa_contains(j))) {
693
- classname += ' selected-range';
694
- }
695
- if (typeof value!=='object') {
696
- value = String(value);
697
- (value.itsa_trim()==='') && (value='&nbsp;');
698
- cellContent = value.itsa_replaceAll('\n', '<br />');
699
- return (
700
- <td
701
- className={classname}
702
- dangerouslySetInnerHTML={{__html: cellContent}}
703
- data-colid={j}
704
- key={field} />
705
- );
706
- }
707
- // else
708
- return (
709
- <td
710
- className={classname}
711
- data-colid={j}
712
- key={field}
713
- ref={node => instance['_component_'+i+'_'+j] = node}>
714
- {value}
715
- </td>
716
- );
717
- });
790
+ fullEditable &&
791
+ (onBlur = instance.implementCellChanges.bind(instance, i, field));
792
+ cellContent = (
793
+ <textarea
794
+ disabled={disabled}
795
+ onBlur={onBlur}
796
+ onChange={instance.changeCell}
797
+ onFocus={instance.focusTextArea}
798
+ onKeyDown={instance.handleCellKeyDown}
799
+ ref={(node) => (instance["_textarea_" + i + "_" + j] = node)}
800
+ rows={1}
801
+ value={textAreaValue}
802
+ />
803
+ );
804
+ return (
805
+ <td className={classname} data-colid={j} key={field}>
806
+ <span>{textAreaValue}</span>
807
+ {cellContent}
808
+ </td>
809
+ );
810
+ }
811
+ typeof value === "number" || value || (value = "");
812
+ // we may need to add an 'selected' class:
813
+ if (
814
+ selectedRange &&
815
+ j >= selectedRange.x1 &&
816
+ j <= selectedRange.x2 &&
817
+ i >= selectedRange.y1 &&
818
+ i <= selectedRange.y2 &&
819
+ (!editableCols || editableColsArray.itsa_contains(j))
820
+ ) {
821
+ classname += " selected-range";
822
+ }
823
+ if (typeof value !== "object") {
824
+ value = String(value);
825
+ value.itsa_trim() === "" && (value = "&nbsp;");
826
+ cellContent = value.itsa_replaceAll("\n", "<br />");
827
+ return (
828
+ <td
829
+ className={classname}
830
+ dangerouslySetInnerHTML={{ __html: cellContent }}
831
+ data-colid={j}
832
+ key={field}
833
+ />
834
+ );
835
+ }
836
+ // else
837
+ return (
838
+ <td
839
+ className={classname}
840
+ data-colid={j}
841
+ key={field}
842
+ ref={(node) => (instance["_component_" + i + "_" + j] = node)}
843
+ >
844
+ {value}
845
+ </td>
846
+ );
847
+ });
848
+ } else {
849
+ // all fields
850
+ cells = [];
851
+ let j = -1;
852
+ instance._columns = [];
853
+ rowdata.itsa_each((value, key) => {
854
+ const field = typeof key === "string" ? key : key.key;
855
+ let classname = CELL_CLASS + key,
856
+ cellContent,
857
+ onBlur,
858
+ textAreaValue,
859
+ colCount = cells.length;
860
+ j++;
861
+ instance._columns[j] = key;
862
+ if (rowHeader && colCount === 0) {
863
+ classname += " itsa-table-rowheader";
864
+ if (value === null) {
865
+ value = "";
718
866
  }
719
- else {
720
- // all fields
721
- cells = [];
722
- let j = -1;
723
- instance._columns = [];
724
- rowdata.itsa_each((value, key) => {
725
- const field = (typeof key==='string') ? key : key.key;
726
- let classname = CELL_CLASS+key,
727
- cellContent, onBlur, textAreaValue,
728
- colCount = cells.length;
729
- j++;
730
- instance._columns[j] = key;
731
- if (rowHeader && (colCount===0)) {
732
- classname += ' itsa-table-rowheader';
733
- if (value===null) {
734
- value = '';
735
- }
736
- cellContent = value;
737
- cells.push((<td className={classname} dangerouslySetInnerHTML={{__html: cellContent}} data-colid={colCount} key={key} />));
738
- }
739
- else if (Object.itsa_isObject(value)) {
740
- return (
741
- <td
742
- className={classname}
743
- data-colid={j}
744
- key={field}
745
- ref={node => instance['_component_'+i+'_'+j] = node}>
746
- {value}
747
- </td>
748
- );
749
- }
750
- else if (fullEditable || ((editable===true) && (state.editableRow===i) && (state.editableCol===colCount))) {
751
- classname += EDITABLE_CELL_CLASS_SPACED;
752
- (typeof value==='number') || value || (value='');
753
- value = String(value);
754
- if ((state.editableRow===i) && (state.editableCol===j)) {
755
- textAreaValue = state.editValue;
756
- }
757
- else {
758
- textAreaValue = value;
759
- }
760
- if ((textAreaValue===null) || (textAreaValue===undefined)) {
761
- textAreaValue = '';
762
- }
763
- fullEditable && (onBlur=instance.implementCellChanges.bind(instance, i, field));
764
- cellContent = (
765
- <textarea
766
- disabled={disabled}
767
- onBlur={onBlur}
768
- onChange={instance.changeCell}
769
- onFocus={instance.focusTextArea}
770
- onKeyDown={instance.handleCellKeyDown}
771
- ref={node => instance['_textarea_'+i+'_'+colCount] = node}
772
- rows={1}
773
- value={textAreaValue} />
774
- );
775
- cells.push((
776
- <td className={classname} data-colid={colCount} key={key}>
777
- {cellContent}
778
- <span>{textAreaValue}</span>
779
- </td>
780
- ));
781
- }
782
- else {
783
- (typeof value==='number') || value || (value='');
784
- // we may need to add an 'selected' class:
785
- if (selectedRange &&
786
- (j>=selectedRange.x1) &&
787
- (j<=selectedRange.x2) &&
788
- (i>=selectedRange.y1) &&
789
- (i<=selectedRange.y2) &&
790
- (!editableCols || editableColsArray.itsa_contains(j))) {
791
- classname += ' selected-range';
792
- }
793
- if (typeof value!=='object') {
794
- value = String(value);
795
- (value.itsa_trim()==='') && (value='&nbsp;');
796
- cellContent = value.itsa_replaceAll('\n', '<br />');
797
- cells.push((<td className={classname} dangerouslySetInnerHTML={{__html: cellContent}} data-colid={colCount} key={key} />));
798
- }
799
- else {
800
- cells.push((<td className={classname} data-colid={colCount} key={key} ref={node => instance['_component_'+i+'_'+j] = node}>{value}</td>));
801
- }
802
- }
803
- });
867
+ cellContent = value;
868
+ cells.push(
869
+ <td
870
+ className={classname}
871
+ dangerouslySetInnerHTML={{ __html: cellContent }}
872
+ data-colid={colCount}
873
+ key={key}
874
+ />
875
+ );
876
+ } else if (Object.itsa_isObject(value)) {
877
+ return (
878
+ <td
879
+ className={classname}
880
+ data-colid={j}
881
+ key={field}
882
+ ref={(node) => (instance["_component_" + i + "_" + j] = node)}
883
+ >
884
+ {value}
885
+ </td>
886
+ );
887
+ } else if (
888
+ fullEditable ||
889
+ (editable === true &&
890
+ state.editableRow === i &&
891
+ state.editableCol === colCount)
892
+ ) {
893
+ classname += EDITABLE_CELL_CLASS_SPACED;
894
+ typeof value === "number" || value || (value = "");
895
+ value = String(value);
896
+ if (state.editableRow === i && state.editableCol === j) {
897
+ textAreaValue = state.editValue;
898
+ } else {
899
+ textAreaValue = value;
804
900
  }
805
- if (extendableY==='full') {
806
- cells.unshift((
807
- <td className={CELL_CLASS+ROW_ADD_CLASS} key={ROW_ADD_CLASS}>
808
- <Button buttonText="+" className="controll-btn" disabled={disabled} onClick={instance.addRow.bind(instance, i)} />
809
- </td>
810
- ));
901
+ if (textAreaValue === null || textAreaValue === undefined) {
902
+ textAreaValue = "";
811
903
  }
812
- if (removeableY) {
813
- cells.unshift((
814
- <td className={CELL_CLASS+ROW_REMOVE_CLASS} key={ROW_REMOVE_CLASS}>
815
- <Button buttonText="-" className="controll-btn" disabled={disabled} onClick={instance.deleteRow.bind(instance, i)} />
816
- </td>
817
- ));
904
+ fullEditable &&
905
+ (onBlur = instance.implementCellChanges.bind(instance, i, field));
906
+ cellContent = (
907
+ <textarea
908
+ disabled={disabled}
909
+ onBlur={onBlur}
910
+ onChange={instance.changeCell}
911
+ onFocus={instance.focusTextArea}
912
+ onKeyDown={instance.handleCellKeyDown}
913
+ ref={(node) =>
914
+ (instance["_textarea_" + i + "_" + colCount] = node)
915
+ }
916
+ rows={1}
917
+ value={textAreaValue}
918
+ />
919
+ );
920
+ cells.push(
921
+ <td className={classname} data-colid={colCount} key={key}>
922
+ {cellContent}
923
+ <span>{textAreaValue}</span>
924
+ </td>
925
+ );
926
+ } else {
927
+ typeof value === "number" || value || (value = "");
928
+ // we may need to add an 'selected' class:
929
+ if (
930
+ selectedRange &&
931
+ j >= selectedRange.x1 &&
932
+ j <= selectedRange.x2 &&
933
+ i >= selectedRange.y1 &&
934
+ i <= selectedRange.y2 &&
935
+ (!editableCols || editableColsArray.itsa_contains(j))
936
+ ) {
937
+ classname += " selected-range";
818
938
  }
819
- rowclass = ROW_CLASS;
820
- if (rowClassRenderer) {
821
- extraClass = rowClassRenderer(i, rowdata);
822
- extraClass && (rowclass+=' '+extraClass);
939
+ if (typeof value !== "object") {
940
+ value = String(value);
941
+ value.itsa_trim() === "" && (value = "&nbsp;");
942
+ cellContent = value.itsa_replaceAll("\n", "<br />");
943
+ cells.push(
944
+ <td
945
+ className={classname}
946
+ dangerouslySetInnerHTML={{ __html: cellContent }}
947
+ data-colid={colCount}
948
+ key={key}
949
+ />
950
+ );
951
+ } else {
952
+ cells.push(
953
+ <td
954
+ className={classname}
955
+ data-colid={colCount}
956
+ key={key}
957
+ ref={(node) => (instance["_component_" + i + "_" + j] = node)}
958
+ >
959
+ {value}
960
+ </td>
961
+ );
823
962
  }
824
- return (<tr className={rowclass} data-recordid={i} data-rowid={i} key={i}>{cells}</tr>);
963
+ }
825
964
  });
826
- }
965
+ }
966
+ if (extendableY === "full") {
967
+ cells.unshift(
968
+ <td className={CELL_CLASS + ROW_ADD_CLASS} key={ROW_ADD_CLASS}>
969
+ <Button
970
+ buttonText="+"
971
+ className="controll-btn"
972
+ disabled={disabled}
973
+ onClick={instance.addRow.bind(instance, i)}
974
+ />
975
+ </td>
976
+ );
977
+ }
978
+ if (removeableY) {
979
+ cells.unshift(
980
+ <td className={CELL_CLASS + ROW_REMOVE_CLASS} key={ROW_REMOVE_CLASS}>
981
+ <Button
982
+ buttonText="-"
983
+ className="controll-btn"
984
+ disabled={disabled}
985
+ onClick={instance.deleteRow.bind(instance, i)}
986
+ />
987
+ </td>
988
+ );
989
+ }
990
+ rowclass = ROW_CLASS;
991
+ if (rowClassRenderer) {
992
+ extraClass = rowClassRenderer(i, rowdata);
993
+ extraClass && (rowclass += " " + extraClass);
994
+ }
995
+ return (
996
+ <tr className={rowclass} data-recordid={i} data-rowid={i} key={i}>
997
+ {cells}
998
+ </tr>
999
+ );
1000
+ });
1001
+ }
827
1002
 
828
- refocus(e) {
829
- let focusRow, focusCol, match, maxRow, maxCol, firstItem, item, editValue, colChangedByRow, isSelectComponent, less,
830
- prevRowIndex, prevColIndex, field, editDirectionDown, arrowDown, arrowUp, node, trNode, trParentNode, tds, trs;
831
- const instance = this,
832
- props = instance.props,
833
- state = instance.state,
834
- keyCode = e.keyCode,
835
- shiftKey = e.shiftKey,
836
- ctrlKey = e.metaKey || e.ctrlKey,
837
- data = props.data,
838
- loop = props.loop,
839
- editableCols = props.editableCols,
840
- cursorNav = props.cursorNav,
841
- lowestColIndex = props.rowHeader ? 1 : 0,
842
- highestColIndex = data.itsa_keys().length-(props.rowHeader ? 0 : 1),
843
- columns = props.columns,
844
- hasColumns = (columns && (columns.length>0));
1003
+ refocus(e) {
1004
+ let focusRow,
1005
+ focusCol,
1006
+ match,
1007
+ maxRow,
1008
+ maxCol,
1009
+ firstItem,
1010
+ item,
1011
+ editValue,
1012
+ colChangedByRow,
1013
+ isSelectComponent,
1014
+ less,
1015
+ prevRowIndex,
1016
+ prevColIndex,
1017
+ field,
1018
+ editDirectionDown,
1019
+ arrowDown,
1020
+ arrowUp,
1021
+ node,
1022
+ trNode,
1023
+ trParentNode,
1024
+ tds,
1025
+ trs;
1026
+ const instance = this,
1027
+ props = instance.props,
1028
+ state = instance.state,
1029
+ keyCode = e.keyCode,
1030
+ shiftKey = e.shiftKey,
1031
+ ctrlKey = e.metaKey || e.ctrlKey,
1032
+ data = props.data,
1033
+ loop = props.loop,
1034
+ editableCols = props.editableCols,
1035
+ cursorNav = props.cursorNav,
1036
+ lowestColIndex = props.rowHeader ? 1 : 0,
1037
+ highestColIndex = data.itsa_keys().length - (props.rowHeader ? 0 : 1),
1038
+ columns = props.columns,
1039
+ hasColumns = columns && columns.length > 0;
845
1040
 
846
- const implementChanges = keepFocus => {
847
- if ((props.editable===true) || (state.selectedRange)) { // NOT 'full' for that would take care of itself
848
- field = hasColumns ? columns[prevColIndex] : instance._columns[prevColIndex];
849
- instance.implementCellChanges(prevRowIndex, field, true);
850
- keepFocus && (instance._editValueBeforeEdit=instance._editValueBeforeBlur);
851
- }
852
- };
853
- editDirectionDown = ((keyCode===9) || (keyCode===37) || (keyCode===39)) ? false : props.editDirectionDown;
854
- if (keyCode===13) {
855
- if (shiftKey) {
856
- return;
857
- }
858
- }
1041
+ const implementChanges = (keepFocus) => {
1042
+ if (props.editable === true || state.selectedRange) {
1043
+ // NOT 'full' for that would take care of itself
1044
+ field = hasColumns
1045
+ ? columns[prevColIndex]
1046
+ : instance._columns[prevColIndex];
1047
+ instance.implementCellChanges(prevRowIndex, field, true);
1048
+ keepFocus &&
1049
+ (instance._editValueBeforeEdit = instance._editValueBeforeBlur);
1050
+ }
1051
+ };
1052
+ editDirectionDown =
1053
+ keyCode === 9 || keyCode === 37 || keyCode === 39
1054
+ ? false
1055
+ : props.editDirectionDown;
1056
+ if (keyCode === 13) {
1057
+ if (shiftKey) {
1058
+ return;
1059
+ }
1060
+ }
859
1061
 
860
- match = (
861
- (keyCode===9) ||
862
- (keyCode===13) ||
863
- (cursorNav && ((keyCode===40) || (keyCode===38))) ||
864
- (cursorNav && ctrlKey && ((keyCode===37) || (keyCode===39)))
865
- ); // 40=arrowDown, 38=arrowUp
1062
+ match =
1063
+ keyCode === 9 ||
1064
+ keyCode === 13 ||
1065
+ (cursorNav && (keyCode === 40 || keyCode === 38)) ||
1066
+ (cursorNav && ctrlKey && (keyCode === 37 || keyCode === 39)); // 40=arrowDown, 38=arrowUp
866
1067
 
867
- // we need to ignore MOVING DOWN in case the focus lies on a button component
868
- if ((document.activeElement.tagName==='BUTTON') && (keyCode===13)) {
869
- match = false;
870
- }
1068
+ // we need to ignore MOVING DOWN in case the focus lies on a button component
1069
+ if (document.activeElement.tagName === "BUTTON" && keyCode === 13) {
1070
+ match = false;
1071
+ }
871
1072
 
872
- isSelectComponent = (document.activeElement.itsa_hasClass('itsa-select') || document.activeElement.itsa_inside('.itsa-select'));
873
- if (isSelectComponent && ((keyCode===13) || (cursorNav && ((keyCode===38) || (keyCode===40))))) {
874
- match = false;
875
- }
1073
+ isSelectComponent =
1074
+ document.activeElement.itsa_hasClass("itsa-select") ||
1075
+ document.activeElement.itsa_inside(".itsa-select");
1076
+ if (
1077
+ isSelectComponent &&
1078
+ (keyCode === 13 || (cursorNav && (keyCode === 38 || keyCode === 40)))
1079
+ ) {
1080
+ match = false;
1081
+ }
876
1082
 
877
- if (match) {
878
- e.preventDefault();
879
- arrowDown = (keyCode===40);
880
- arrowUp = (keyCode===38);
881
- maxRow = data.length - 1;
882
- if (columns) {
883
- maxCol = columns.length - 1;
884
- }
885
- else {
886
- firstItem = data[0];
887
- maxCol = firstItem ? firstItem.itsa_size()-1 : 0;
888
- }
1083
+ if (match) {
1084
+ e.preventDefault();
1085
+ arrowDown = keyCode === 40;
1086
+ arrowUp = keyCode === 38;
1087
+ maxRow = data.length - 1;
1088
+ if (columns) {
1089
+ maxCol = columns.length - 1;
1090
+ } else {
1091
+ firstItem = data[0];
1092
+ maxCol = firstItem ? firstItem.itsa_size() - 1 : 0;
1093
+ }
889
1094
 
890
- if (isSelectComponent) {
891
- // we need to catch editableRow and editableCol because thay are not set
892
- less = 0;
893
- if (props.removeableY) {
894
- less++;
895
- }
896
- if (props.extendableY==='full') {
897
- less++;
898
- }
1095
+ if (isSelectComponent) {
1096
+ // we need to catch editableRow and editableCol because thay are not set
1097
+ less = 0;
1098
+ if (props.removeableY) {
1099
+ less++;
1100
+ }
1101
+ if (props.extendableY === "full") {
1102
+ less++;
1103
+ }
899
1104
 
900
- node = document.activeElement;
901
- while (node && (node.tagName!=='TD')) {
902
- node = node.parentNode;
903
- }
904
- trNode = node.parentNode;
905
- tds = trNode.childNodes;
906
- prevColIndex = Array.prototype.indexOf.call(tds, node) - less;
907
- trParentNode = trNode.parentNode;
908
- trs = trParentNode.childNodes;
909
- prevRowIndex = Array.prototype.indexOf.call(trs, trNode);
910
- }
911
- else {
912
- prevRowIndex = state.editableRow;
913
- prevColIndex = state.editableCol;
914
- }
915
- focusRow = prevRowIndex;
916
- focusCol = prevColIndex;
1105
+ node = document.activeElement;
1106
+ while (node && node.tagName !== "TD") {
1107
+ node = node.parentNode;
1108
+ }
1109
+ trNode = node.parentNode;
1110
+ tds = trNode.childNodes;
1111
+ prevColIndex = Array.prototype.indexOf.call(tds, node) - less;
1112
+ trParentNode = trNode.parentNode;
1113
+ trs = trParentNode.childNodes;
1114
+ prevRowIndex = Array.prototype.indexOf.call(trs, trNode);
1115
+ } else {
1116
+ prevRowIndex = state.editableRow;
1117
+ prevColIndex = state.editableCol;
1118
+ }
1119
+ focusRow = prevRowIndex;
1120
+ focusCol = prevColIndex;
917
1121
 
918
- if (((keyCode===9) && shiftKey) || ((keyCode===37) && ctrlKey) || arrowUp) {
919
- // backwards
920
- if (editDirectionDown || arrowUp) {
921
- focusRow--;
922
- }
923
- else {
924
- do {
925
- focusCol--;
926
- if (focusCol<lowestColIndex) {
927
- break;
928
- }
929
- }
930
- while (!editableCols || !editableCols.itsa_contains(focusCol));
931
- }
1122
+ if (
1123
+ (keyCode === 9 && shiftKey) ||
1124
+ (keyCode === 37 && ctrlKey) ||
1125
+ arrowUp
1126
+ ) {
1127
+ // backwards
1128
+ if (editDirectionDown || arrowUp) {
1129
+ focusRow--;
1130
+ } else {
1131
+ do {
1132
+ focusCol--;
1133
+ if (focusCol < lowestColIndex) {
1134
+ break;
932
1135
  }
933
- else {
934
- // forewards
935
- if (editDirectionDown || arrowDown) {
936
- focusRow++;
937
- }
938
- else {
939
- do {
940
- focusCol++;
941
- if (focusCol>highestColIndex) {
942
- break;
943
- }
944
- }
945
- while (!editableCols || !editableCols.itsa_contains(focusCol));
946
- }
947
- }
948
- // now we might need to adjust the values when out of range
949
- if (focusRow<0) {
950
- if (!loop) {
951
- implementChanges(true);
952
- return;
953
- }
954
- focusRow = maxRow;
955
- do {
956
- focusCol--;
957
- if (focusCol<lowestColIndex) {
958
- focusCol = highestColIndex;
959
- }
960
- }
961
- while (!editableCols || !editableCols.itsa_contains(focusCol));
962
- colChangedByRow = true;
963
- }
964
- else if (focusRow>maxRow) {
965
- if (!loop) {
966
- implementChanges(true);
967
- return;
968
- }
969
- focusRow = 0;
970
- do {
971
- focusCol++;
972
- if (focusCol>highestColIndex) {
973
- focusCol = lowestColIndex;
974
- }
975
- }
976
- while (!editableCols || !editableCols.itsa_contains(focusCol));
977
- colChangedByRow = true;
978
- }
979
- if (focusCol<lowestColIndex) {
980
- if (!loop) {
981
- implementChanges(true);
982
- return;
983
- }
984
- colChangedByRow || focusRow--;
985
- (focusRow<0) && (focusRow=maxRow);
986
- focusCol = maxCol;
987
- }
988
- else if (focusCol>maxCol) {
989
- if (!loop) {
990
- implementChanges(true);
991
- return;
992
- }
993
- colChangedByRow || focusRow++;
994
- focusCol = lowestColIndex;
995
- (focusRow>maxRow) && (focusRow=0);
996
- }
997
- item = props.data[focusRow];
998
- if (item) {
999
- editValue = hasColumns ? item[retrieveFieldName(columns[focusCol])] : item[retrieveFieldName(instance._columns[focusCol])];
1000
- this.setState({
1001
- editableRow: focusRow,
1002
- editableCol: focusCol,
1003
- editValue,
1004
- selectedRangeStart: {
1005
- x: focusCol,
1006
- y: focusRow
1007
- },
1008
- selectedRange: null
1009
- });
1010
- instance._focusActiveCell();
1011
- implementChanges();
1136
+ } while (!editableCols || !editableCols.itsa_contains(focusCol));
1137
+ }
1138
+ } else {
1139
+ // forewards
1140
+ if (editDirectionDown || arrowDown) {
1141
+ focusRow++;
1142
+ } else {
1143
+ do {
1144
+ focusCol++;
1145
+ if (focusCol > highestColIndex) {
1146
+ break;
1012
1147
  }
1148
+ } while (!editableCols || !editableCols.itsa_contains(focusCol));
1013
1149
  }
1014
- }
1015
-
1016
- handleClick(editable, e) {
1017
- const instance = this,
1018
- props = instance.props,
1019
- onClick = instance.props.onClick,
1020
- state = instance.state,
1021
- shiftClick = e.shiftKey;
1022
- let node = e.target,
1023
- editableCols = props.editableCols,
1024
- colId, rowId, columns, hasColumns, item, editValue, newState, prevRowId, prevColId, selectedRangeStart;
1025
- (node.tagName==='TD') || (node=node.parentNode);
1026
- colId = parseInt(node.getAttribute('data-colid'), 10);
1027
- node = node.parentNode;
1028
- rowId = parseInt(node.getAttribute('data-rowid'), 10);
1029
- if (typeof editableCols==='number') {
1030
- editableCols = [editableCols];
1150
+ }
1151
+ // now we might need to adjust the values when out of range
1152
+ if (focusRow < 0) {
1153
+ if (!loop) {
1154
+ implementChanges(true);
1155
+ return;
1031
1156
  }
1032
- if (editable && (!editableCols || editableCols.itsa_contains(colId))) {
1033
- columns = props.columns;
1034
- hasColumns = (columns && (columns.length>0));
1035
- item = props.data[rowId];
1036
- editValue = hasColumns ? item[retrieveFieldName(columns[colId])] : item[retrieveFieldName(instance._columns[colId])];
1037
- newState = {
1038
- editableRow: rowId,
1039
- editableCol: colId,
1040
- editValue
1041
- };
1042
- if (props.editable && props.multiEdit) {
1043
- if (shiftClick) {
1044
- selectedRangeStart = state.selectedRangeStart;
1045
- if (selectedRangeStart) {
1046
- prevRowId = selectedRangeStart.y;
1047
- prevColId = selectedRangeStart.x;
1048
- if ((typeof prevRowId==='number') && (typeof prevColId==='number') && ((prevColId!==colId) || (prevRowId!==rowId))) {
1049
- newState.selectedRange = {
1050
- x1: Math.min(prevColId, colId),
1051
- y1: Math.min(prevRowId, rowId),
1052
- x2: Math.max(prevColId, colId),
1053
- y2: Math.max(prevRowId, rowId)
1054
- };
1055
- }
1056
- }
1057
- else {
1058
- newState.selectedRange = null;
1059
- }
1060
- }
1061
- else {
1062
- newState.selectedRange = null;
1063
- newState.selectedRangeStart = {
1064
- x: colId,
1065
- y: rowId
1066
- };
1067
- }
1068
- }
1069
- instance.setState(newState);
1070
- instance._focusActiveCell();
1157
+ focusRow = maxRow;
1158
+ do {
1159
+ focusCol--;
1160
+ if (focusCol < lowestColIndex) {
1161
+ focusCol = highestColIndex;
1162
+ }
1163
+ } while (!editableCols || !editableCols.itsa_contains(focusCol));
1164
+ colChangedByRow = true;
1165
+ } else if (focusRow > maxRow) {
1166
+ if (!loop) {
1167
+ implementChanges(true);
1168
+ return;
1169
+ }
1170
+ focusRow = 0;
1171
+ do {
1172
+ focusCol++;
1173
+ if (focusCol > highestColIndex) {
1174
+ focusCol = lowestColIndex;
1175
+ }
1176
+ } while (!editableCols || !editableCols.itsa_contains(focusCol));
1177
+ colChangedByRow = true;
1178
+ }
1179
+ if (focusCol < lowestColIndex) {
1180
+ if (!loop) {
1181
+ implementChanges(true);
1182
+ return;
1071
1183
  }
1072
- onClick && onClick(rowId, colId);
1184
+ colChangedByRow || focusRow--;
1185
+ focusRow < 0 && (focusRow = maxRow);
1186
+ focusCol = maxCol;
1187
+ } else if (focusCol > maxCol) {
1188
+ if (!loop) {
1189
+ implementChanges(true);
1190
+ return;
1191
+ }
1192
+ colChangedByRow || focusRow++;
1193
+ focusCol = lowestColIndex;
1194
+ focusRow > maxRow && (focusRow = 0);
1195
+ }
1196
+ item = props.data[focusRow];
1197
+ if (item) {
1198
+ editValue = hasColumns
1199
+ ? item[retrieveFieldName(columns[focusCol])]
1200
+ : item[retrieveFieldName(instance._columns[focusCol])];
1201
+ this.setState({
1202
+ editableRow: focusRow,
1203
+ editableCol: focusCol,
1204
+ editValue,
1205
+ selectedRangeStart: {
1206
+ x: focusCol,
1207
+ y: focusRow,
1208
+ },
1209
+ selectedRange: null,
1210
+ });
1211
+ instance._focusActiveCell();
1212
+ implementChanges();
1213
+ }
1073
1214
  }
1215
+ }
1074
1216
 
1075
- addRow(index) {
1076
- let newData, len, newRecord;
1077
- const props = this.props,
1078
- onChange = props.onChange;
1079
- if (onChange) {
1080
- newData = cloneData(props.data);
1081
- len = newData.length;
1082
- if (len==0) {
1083
- newData = [{'__row0': null}];
1084
- }
1085
- else {
1086
- newRecord = newData[0].itsa_map(() => null);
1087
- if (typeof index==='number') {
1088
- newData.itsa_insertAt(newRecord, index);
1089
- }
1090
- else {
1091
- newData[props.extendableY==="begin" ? "unshift" : "push"](newRecord);
1092
- }
1217
+ handleClick(editable, e) {
1218
+ const instance = this,
1219
+ props = instance.props,
1220
+ onClick = instance.props.onClick,
1221
+ state = instance.state,
1222
+ shiftClick = e.shiftKey;
1223
+ let node = e.target,
1224
+ editableCols = props.editableCols,
1225
+ colId,
1226
+ rowId,
1227
+ columns,
1228
+ hasColumns,
1229
+ item,
1230
+ editValue,
1231
+ newState,
1232
+ prevRowId,
1233
+ prevColId,
1234
+ selectedRangeStart;
1235
+ node.tagName === "TD" || (node = node.parentNode);
1236
+ colId = parseInt(node.getAttribute("data-colid"), 10);
1237
+ node = node.parentNode;
1238
+ rowId = parseInt(node.getAttribute("data-rowid"), 10);
1239
+ if (typeof editableCols === "number") {
1240
+ editableCols = [editableCols];
1241
+ }
1242
+ if (editable && (!editableCols || editableCols.itsa_contains(colId))) {
1243
+ columns = props.columns;
1244
+ hasColumns = columns && columns.length > 0;
1245
+ item = props.data[rowId];
1246
+ editValue = hasColumns
1247
+ ? item[retrieveFieldName(columns[colId])]
1248
+ : item[retrieveFieldName(instance._columns[colId])];
1249
+ newState = {
1250
+ editableRow: rowId,
1251
+ editableCol: colId,
1252
+ editValue,
1253
+ };
1254
+ if (props.editable && props.multiEdit) {
1255
+ if (shiftClick) {
1256
+ selectedRangeStart = state.selectedRangeStart;
1257
+ if (selectedRangeStart) {
1258
+ prevRowId = selectedRangeStart.y;
1259
+ prevColId = selectedRangeStart.x;
1260
+ if (
1261
+ typeof prevRowId === "number" &&
1262
+ typeof prevColId === "number" &&
1263
+ (prevColId !== colId || prevRowId !== rowId)
1264
+ ) {
1265
+ newState.selectedRange = {
1266
+ x1: Math.min(prevColId, colId),
1267
+ y1: Math.min(prevRowId, rowId),
1268
+ x2: Math.max(prevColId, colId),
1269
+ y2: Math.max(prevRowId, rowId),
1270
+ };
1093
1271
  }
1094
- onChange(newData);
1272
+ } else {
1273
+ newState.selectedRange = null;
1274
+ }
1275
+ } else {
1276
+ newState.selectedRange = null;
1277
+ newState.selectedRangeStart = {
1278
+ x: colId,
1279
+ y: rowId,
1280
+ };
1095
1281
  }
1282
+ }
1283
+ instance.setState(newState);
1284
+ instance._focusActiveCell();
1096
1285
  }
1286
+ onClick && onClick(rowId, colId);
1287
+ }
1097
1288
 
1098
- addCol() {
1099
- let newData, len, size;
1100
- const props = this.props,
1101
- onChange = props.onChange;
1102
- if (onChange) {
1103
- newData = cloneData(props.data);
1104
- len = newData.length;
1105
- if (len==0) {
1106
- size = 0;
1107
- }
1108
- else {
1109
- size = newData[0].itsa_size();
1110
- }
1111
- newData.forEach(record => {
1112
- record['__col'+size] = null;
1113
- });
1114
- onChange(newData);
1289
+ addRow(index) {
1290
+ let newData, len, newRecord;
1291
+ const props = this.props,
1292
+ onChange = props.onChange;
1293
+ if (onChange) {
1294
+ newData = cloneData(props.data);
1295
+ len = newData.length;
1296
+ if (len == 0) {
1297
+ newData = [{ __row0: null }];
1298
+ } else {
1299
+ newRecord = newData[0].itsa_map(() => null);
1300
+ if (typeof index === "number") {
1301
+ newData.itsa_insertAt(newRecord, index);
1302
+ } else {
1303
+ newData[props.extendableY === "begin" ? "unshift" : "push"](
1304
+ newRecord
1305
+ );
1115
1306
  }
1307
+ }
1308
+ onChange(newData);
1116
1309
  }
1310
+ }
1117
1311
 
1118
- deleteRow(index) {
1119
- let newData;
1120
- const props = this.props,
1121
- onChange = props.onChange;
1122
- if (onChange) {
1123
- newData = cloneData(props.data);
1124
- newData.splice(index, 1);
1125
- onChange(newData);
1126
- }
1312
+ addCol() {
1313
+ let newData, len, size;
1314
+ const props = this.props,
1315
+ onChange = props.onChange;
1316
+ if (onChange) {
1317
+ newData = cloneData(props.data);
1318
+ len = newData.length;
1319
+ if (len == 0) {
1320
+ size = 0;
1321
+ } else {
1322
+ size = newData[0].itsa_size();
1323
+ }
1324
+ newData.forEach((record) => {
1325
+ record["__col" + size] = null;
1326
+ });
1327
+ onChange(newData);
1127
1328
  }
1329
+ }
1128
1330
 
1129
- /**
1130
- * React render-method --> renderes the Component.
1131
- *
1132
- * @method render
1133
- * @return ReactComponent
1134
- * @since 2.0.0
1135
- */
1136
- render() {
1137
- let classname = MAIN_CLASS,
1138
- handleClick, refocus, addRowBtn, addColBtn, tableClassName, addRowClass;
1139
- const instance = this,
1140
- props = instance.props,
1141
- editable = props.editable,
1142
- disabled = props.disabled,
1143
- propsClassName = props.className;
1331
+ deleteRow(index) {
1332
+ let newData;
1333
+ const props = this.props,
1334
+ onChange = props.onChange;
1335
+ if (onChange) {
1336
+ newData = cloneData(props.data);
1337
+ newData.splice(index, 1);
1338
+ onChange(newData);
1339
+ }
1340
+ }
1144
1341
 
1145
- tableClassName = props.tableClass;
1146
- propsClassName && (classname+=' '+propsClassName);
1147
- if (props.extendableY) {
1148
- addRowClass = 'add-row controll-btn';
1149
- if ((props.removeableY) && (props.extendableY==='full')) {
1150
- addRowClass += ' add-row-indent';
1151
- }
1152
- addRowBtn = (<Button buttonText="+" className={addRowClass} disabled={disabled} onClick={instance.addRow} />);
1153
- }
1154
- if (props.extendableX && !props.columns) {
1155
- addColBtn = (<Button buttonText="+" className="controll-btn" disabled={disabled} onClick={instance.addCol} />);
1156
- }
1157
- if ((editable===true) || (editable==='full')) {
1158
- handleClick = instance.handleClick.bind(instance, true);
1159
- refocus = instance.refocus;
1160
- }
1161
- else {
1162
- handleClick = instance.handleClick.bind(instance, false);
1163
- }
1164
- if (props.fixedHeaders) {
1165
- tableClassName += ' fixed-headers';
1166
- classname += ' scrollable-y';
1167
- // fixedHeadertable = (
1168
- // <table className={props.tableClass+' fixed-headers'}>
1169
- // {instance.generateHead()}
1170
- // <tbody>
1171
- // {instance.generateRows()}
1172
- // </tbody>
1173
- // </table>
1174
- // );
1175
- }
1176
- // classname+='flex-container-vertical';
1177
- return (
1178
- <div
1179
- className={classname}
1180
- onScroll={props.onScroll}
1181
- ref={node => instance._componentNode = node}>
1182
- <table
1183
- className={tableClassName}
1184
- ref={node => instance._tableNode=node}>
1185
- {instance.generateHead()}
1186
- <tbody
1187
- onClick={handleClick}
1188
- onKeyDown={refocus}>
1189
- {instance.generateRows()}
1190
- </tbody>
1191
- </table>
1192
- {addColBtn}
1193
- {addRowBtn}
1194
- </div>
1195
- );
1342
+ /**
1343
+ * React render-method --> renderes the Component.
1344
+ *
1345
+ * @method render
1346
+ * @return ReactComponent
1347
+ * @since 2.0.0
1348
+ */
1349
+ render() {
1350
+ let classname = MAIN_CLASS,
1351
+ handleClick,
1352
+ refocus,
1353
+ addRowBtn,
1354
+ addColBtn,
1355
+ tableClassName,
1356
+ addRowClass;
1357
+ const instance = this,
1358
+ props = instance.props,
1359
+ editable = props.editable,
1360
+ disabled = props.disabled,
1361
+ propsClassName = props.className;
1362
+
1363
+ tableClassName = props.tableClass;
1364
+ propsClassName && (classname += " " + propsClassName);
1365
+ if (props.extendableY) {
1366
+ addRowClass = "add-row controll-btn";
1367
+ if (props.removeableY && props.extendableY === "full") {
1368
+ addRowClass += " add-row-indent";
1369
+ }
1370
+ addRowBtn = (
1371
+ <Button
1372
+ buttonText="+"
1373
+ className={addRowClass}
1374
+ disabled={disabled}
1375
+ onClick={instance.addRow}
1376
+ />
1377
+ );
1378
+ }
1379
+ if (props.extendableX && !props.columns) {
1380
+ addColBtn = (
1381
+ <Button
1382
+ buttonText="+"
1383
+ className="controll-btn"
1384
+ disabled={disabled}
1385
+ onClick={instance.addCol}
1386
+ />
1387
+ );
1196
1388
  }
1389
+ if (editable === true || editable === "full") {
1390
+ handleClick = instance.handleClick.bind(instance, true);
1391
+ refocus = instance.refocus;
1392
+ } else {
1393
+ handleClick = instance.handleClick.bind(instance, false);
1394
+ }
1395
+ if (props.fixedHeaders) {
1396
+ tableClassName += " fixed-headers";
1397
+ classname += " scrollable-y";
1398
+ // fixedHeadertable = (
1399
+ // <table className={props.tableClass+' fixed-headers'}>
1400
+ // {instance.generateHead()}
1401
+ // <tbody>
1402
+ // {instance.generateRows()}
1403
+ // </tbody>
1404
+ // </table>
1405
+ // );
1406
+ }
1407
+ // classname+='flex-container-vertical';
1408
+ return (
1409
+ <div
1410
+ className={classname}
1411
+ onScroll={props.onScroll}
1412
+ ref={(node) => (instance._componentNode = node)}
1413
+ >
1414
+ <table
1415
+ className={tableClassName}
1416
+ ref={(node) => (instance._tableNode = node)}
1417
+ >
1418
+ {instance.generateHead()}
1419
+ <tbody onClick={handleClick} onKeyDown={refocus}>
1420
+ {instance.generateRows()}
1421
+ </tbody>
1422
+ </table>
1423
+ {addColBtn}
1424
+ {addRowBtn}
1425
+ </div>
1426
+ );
1427
+ }
1197
1428
 
1198
- /**
1199
- * Callback for a click on the document. Is needed to close the Component when clicked outside.
1200
- *
1201
- * @method _handleDocumentClick
1202
- * @private
1203
- * @param Object e
1204
- * @since 0.0.1
1205
- */
1206
- _handleDocumentClick(e) {
1207
- let rowIndex, field, colIndex, columns, hasColumns;
1208
- const instance = this,
1209
- targetNode = e.target;
1210
- if ((instance.props.editable===true) && (!instance._componentNode.contains(targetNode) || ((targetNode.tagName!=='TEXTAREA') && !instance._headNode.contains(targetNode)))) {
1211
- rowIndex = instance.state.editableRow;
1212
- colIndex = instance.state.editableCol;
1213
- columns = instance.props.columns;
1214
- hasColumns = (columns && (columns.length>0));
1215
- field = hasColumns ? columns[colIndex] : instance._columns[colIndex];
1216
- instance.setState({
1217
- editableRow: null,
1218
- editableCol: null,
1219
- editValue: ''
1220
- }, () => {
1221
- (typeof rowIndex==='number') && instance.implementCellChanges(rowIndex, field);
1222
- });
1429
+ /**
1430
+ * Callback for a click on the document. Is needed to close the Component when clicked outside.
1431
+ *
1432
+ * @method _handleDocumentClick
1433
+ * @private
1434
+ * @param Object e
1435
+ * @since 0.0.1
1436
+ */
1437
+ _handleDocumentClick(e) {
1438
+ let rowIndex, field, colIndex, columns, hasColumns;
1439
+ const instance = this,
1440
+ targetNode = e.target;
1441
+ if (
1442
+ instance.props.editable === true &&
1443
+ (!instance._componentNode.contains(targetNode) ||
1444
+ (targetNode.tagName !== "TEXTAREA" &&
1445
+ !instance._headNode.contains(targetNode)))
1446
+ ) {
1447
+ rowIndex = instance.state.editableRow;
1448
+ colIndex = instance.state.editableCol;
1449
+ columns = instance.props.columns;
1450
+ hasColumns = columns && columns.length > 0;
1451
+ field = hasColumns ? columns[colIndex] : instance._columns[colIndex];
1452
+ instance.setState(
1453
+ {
1454
+ editableRow: null,
1455
+ editableCol: null,
1456
+ editValue: "",
1457
+ },
1458
+ () => {
1459
+ typeof rowIndex === "number" &&
1460
+ instance.implementCellChanges(rowIndex, field);
1223
1461
  }
1462
+ );
1224
1463
  }
1225
-
1464
+ }
1226
1465
  }
1227
1466
 
1228
1467
  Table.propTypes = {
1229
- autoFocus: PropTypes.bool,
1230
- columns: PropTypes.array,
1231
- /**
1232
- * The Component its children
1233
- *
1234
- * @property children
1235
- * @type Object
1236
- * @since 2.0.0
1237
- */
1238
- cursorNav: PropTypes.bool,
1239
- data: PropTypes.array,
1240
- disabled: PropTypes.bool,
1241
- editable: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
1242
- editableCols: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
1243
- editDirectionDown: PropTypes.bool,
1244
- extendableX: PropTypes.bool,
1245
- extendableY: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]), // true, "begin" or "all"
1246
- fixedHeaders: PropTypes.bool,
1247
- fullSelectOnEdit: PropTypes.bool,
1248
- loop: PropTypes.bool,
1249
- multiEdit: PropTypes.bool,
1250
- onChange: PropTypes.func,
1251
- onChangeCell: PropTypes.func,
1252
- onClick: PropTypes.func,
1253
- onHeaderClick: PropTypes.func,
1254
- onScroll: PropTypes.func,
1255
- removeableY: PropTypes.bool,
1256
- rowClassRenderer: PropTypes.func,
1257
- rowHeader: PropTypes.bool,
1258
- tableClass: PropTypes.string
1468
+ autoFocus: PropTypes.bool,
1469
+ columns: PropTypes.array,
1470
+ /**
1471
+ * The Component its children
1472
+ *
1473
+ * @property children
1474
+ * @type Object
1475
+ * @since 2.0.0
1476
+ */
1477
+ cursorNav: PropTypes.bool,
1478
+ data: PropTypes.array,
1479
+ disabled: PropTypes.bool,
1480
+ editable: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
1481
+ editableCols: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
1482
+ editDirectionDown: PropTypes.bool,
1483
+ extendableX: PropTypes.bool,
1484
+ extendableY: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]), // true, "begin" or "all"
1485
+ fixedHeaders: PropTypes.bool,
1486
+ fullSelectOnEdit: PropTypes.bool,
1487
+ htmlHeaders: PropTypes.bool,
1488
+ loop: PropTypes.bool,
1489
+ multiEdit: PropTypes.bool,
1490
+ onChange: PropTypes.func,
1491
+ onChangeCell: PropTypes.func,
1492
+ onClick: PropTypes.func,
1493
+ onHeaderClick: PropTypes.func,
1494
+ onScroll: PropTypes.func,
1495
+ removeableY: PropTypes.bool,
1496
+ rowClassRenderer: PropTypes.func,
1497
+ rowHeader: PropTypes.bool,
1498
+ tableClass: PropTypes.string,
1259
1499
  };
1260
1500
 
1261
1501
  Table.defaultProps = {
1262
- autoFocus: false,
1263
- cursorNav: false,
1264
- data: [],
1265
- editable: false,
1266
- editDirectionDown: true,
1267
- extendableX: false,
1268
- extendableY: false,
1269
- fullSelectOnEdit: true,
1270
- loop: true,
1271
- multiEdit: false,
1272
- removeableY: false,
1273
- rowHeader: false
1502
+ autoFocus: false,
1503
+ cursorNav: false,
1504
+ data: [],
1505
+ editable: false,
1506
+ editDirectionDown: true,
1507
+ extendableX: false,
1508
+ extendableY: false,
1509
+ fullSelectOnEdit: true,
1510
+ htmlHeaders: false,
1511
+ loop: true,
1512
+ multiEdit: false,
1513
+ removeableY: false,
1514
+ rowHeader: false,
1274
1515
  };
1275
1516
 
1276
1517
  module.exports = Table;