neo.mjs 8.12.0 → 8.13.0

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.
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='8.12.0'
23
+ * @member {String} version='8.13.0'
24
24
  */
25
- version: '8.12.0'
25
+ version: '8.13.0'
26
26
  }
27
27
 
28
28
  /**
@@ -57,7 +57,7 @@ class TableContainer extends Container {
57
57
  dock : 'left',
58
58
  minWidth : 40,
59
59
  text : '#',
60
- renderer : data => ({cls: ['neo-index-column', 'neo-table-cell'], html: data.index + 1}),
60
+ renderer : data => ({cls: ['neo-index-column', 'neo-table-cell'], html: data.rowIndex + 1}),
61
61
  width : 40
62
62
  }],
63
63
  currentChar;
@@ -40,7 +40,7 @@ class Util extends Base {
40
40
  let value = data.value;
41
41
 
42
42
  if (!Neo.isNumber(value)) {
43
- return value || 'N/A';
43
+ return value || 'N/A'
44
44
  }
45
45
 
46
46
  value = Math.round(value / 100);
@@ -48,7 +48,7 @@ class Util extends Base {
48
48
 
49
49
  value = value.toFixed(2) + ' %';
50
50
 
51
- return value.toLocaleString(Util.locales);
51
+ return value.toLocaleString(Util.locales)
52
52
  }
53
53
 
54
54
  /**
@@ -67,7 +67,7 @@ class Util extends Base {
67
67
 
68
68
  value = value.toLocaleString(Util.locales);
69
69
 
70
- return typeof color !== 'string' ? value : `<span style="color:${color};">${value}</span>`;
70
+ return typeof color !== 'string' ? value : `<span style="color:${color};">${value}</span>`
71
71
  }
72
72
 
73
73
  /**
@@ -136,25 +136,25 @@ class Util extends Base {
136
136
  let path = `../../../../resources_pub/images/flaticon/country_flags/png/${imageName}.png`;
137
137
 
138
138
  if (Neo.config.environment !== 'development') {
139
- path = `../../${path}`;
139
+ path = `../../${path}`
140
140
  }
141
141
 
142
- return path;
142
+ return path
143
143
  }
144
144
 
145
- return `https://raw.githubusercontent.com/neomjs/pages/main/resources_pub/images/flaticon/country_flags/png/${imageName}.png`;
145
+ return `https://raw.githubusercontent.com/neomjs/pages/main/resources_pub/images/flaticon/country_flags/png/${imageName}.png`
146
146
  }
147
147
 
148
148
  /**
149
149
  * @param {Object} data
150
- * @param {Number} data.index
150
+ * @param {Number} data.rowIndex
151
151
  * @returns {Object}
152
152
  */
153
153
  static indexRenderer(data) {
154
154
  return {
155
155
  cls : ['neo-index-column', 'neo-table-cell'],
156
- html: data.index + 1
157
- };
156
+ html: data.rowIndex + 1
157
+ }
158
158
  }
159
159
  }
160
160
 
@@ -16,7 +16,7 @@
16
16
  "@type": "Organization",
17
17
  "name": "Neo.mjs"
18
18
  },
19
- "datePublished": "2025-01-29",
19
+ "datePublished": "2025-01-30",
20
20
  "publisher": {
21
21
  "@type": "Organization",
22
22
  "name": "Neo.mjs"
@@ -107,7 +107,7 @@ class FooterContainer extends Container {
107
107
  }, {
108
108
  module: Component,
109
109
  cls : ['neo-version'],
110
- html : 'v8.12.0'
110
+ html : 'v8.13.0'
111
111
  }]
112
112
  }],
113
113
  /**
@@ -147,13 +147,13 @@ class Util extends Base {
147
147
 
148
148
  /**
149
149
  * @param {Object} data
150
- * @param {Number} data.index
150
+ * @param {Number} data.rowIndex
151
151
  * @returns {Object}
152
152
  */
153
153
  static indexRenderer(data) {
154
154
  return {
155
155
  cls : ['neo-index-column', 'neo-table-cell'],
156
- html: data.index + 1
156
+ html: data.rowIndex + 1
157
157
  }
158
158
  }
159
159
  }
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='8.12.0'
23
+ * @member {String} version='8.13.0'
24
24
  */
25
- version: '8.12.0'
25
+ version: '8.13.0'
26
26
  }
27
27
 
28
28
  /**
@@ -147,13 +147,13 @@ class Util extends Base {
147
147
 
148
148
  /**
149
149
  * @param {Object} data
150
- * @param {Number} data.index
150
+ * @param {Number} data.rowIndex
151
151
  * @returns {Object}
152
152
  */
153
153
  static indexRenderer(data) {
154
154
  return {
155
- cls : ['neo-index-column', 'neo-grid-cell'],
156
- html: data.index + 1
155
+ cls : ['neo-index-column', 'neo-table-cell'],
156
+ html: data.rowIndex + 1
157
157
  }
158
158
  }
159
159
  }
@@ -147,13 +147,13 @@ class Util extends Base {
147
147
 
148
148
  /**
149
149
  * @param {Object} data
150
- * @param {Number} data.index
150
+ * @param {Number} data.rowIndex
151
151
  * @returns {Object}
152
152
  */
153
153
  static indexRenderer(data) {
154
154
  return {
155
155
  cls : ['neo-index-column', 'neo-table-cell'],
156
- html: data.index + 1
156
+ html: data.rowIndex + 1
157
157
  }
158
158
  }
159
159
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "8.12.0",
3
+ "version": "8.13.0",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -262,12 +262,12 @@ const DefaultConfig = {
262
262
  useVdomWorker: true,
263
263
  /**
264
264
  * buildScripts/injectPackageVersion.mjs will update this value
265
- * @default '8.12.0'
265
+ * @default '8.13.0'
266
266
  * @memberOf! module:Neo
267
267
  * @name config.version
268
268
  * @type String
269
269
  */
270
- version: '8.12.0'
270
+ version: '8.13.0'
271
271
  };
272
272
 
273
273
  Object.assign(DefaultConfig, {
package/src/grid/View.mjs CHANGED
@@ -381,13 +381,14 @@ class GridView extends Component {
381
381
  * @param {Object} data
382
382
  * @param {String} [data.cellId]
383
383
  * @param {Object} data.column
384
+ * @param {Number} data.columnIndex
384
385
  * @param {Neo.grid.Container} data.gridContainer
385
- * @param {Number} data.index
386
386
  * @param {Object} data.record
387
+ * @param {Number} data.rowIndex
387
388
  * @returns {Object}
388
389
  */
389
390
  applyRendererOutput(data) {
390
- let {cellId, column, gridContainer, index, record} = data,
391
+ let {cellId, column, columnIndex, gridContainer, record, rowIndex} = data,
391
392
  me = this,
392
393
  cellCls = ['neo-grid-cell'],
393
394
  colspan = record[me.colspanField],
@@ -401,10 +402,11 @@ class GridView extends Component {
401
402
 
402
403
  rendererOutput = column.renderer.call(column.rendererScope || gridContainer, {
403
404
  column,
405
+ columnIndex,
404
406
  dataField,
405
407
  gridContainer,
406
- index,
407
408
  record,
409
+ rowIndex,
408
410
  value: fieldValue
409
411
  });
410
412
 
@@ -447,7 +449,7 @@ class GridView extends Component {
447
449
  }
448
450
 
449
451
  cellConfig = {
450
- 'aria-colindex': index + 1, // 1 based
452
+ 'aria-colindex': columnIndex + 1, // 1 based
451
453
  id : cellId,
452
454
  cls : cellCls,
453
455
  role : 'gridcell',
@@ -511,10 +513,7 @@ class GridView extends Component {
511
513
 
512
514
  if (selectedRows?.includes(id)) {
513
515
  trCls.push('neo-selected');
514
-
515
- gridContainer.fire('select', {
516
- record
517
- })
516
+ gridContainer.fire('select', {record})
518
517
  }
519
518
 
520
519
  gridRow = {
@@ -535,7 +534,7 @@ class GridView extends Component {
535
534
 
536
535
  for (i=startIndex; i <= endIndex; i++) {
537
536
  column = columns[i];
538
- config = me.applyRendererOutput({column, gridContainer, index: rowIndex, record});
537
+ config = me.applyRendererOutput({column, columnIndex: i, gridContainer, record, rowIndex});
539
538
 
540
539
  if (column.dock) {
541
540
  config.cls = ['neo-locked', ...config.cls || []]
@@ -817,17 +816,16 @@ class GridView extends Component {
817
816
  * @param {Object} opts.record
818
817
  */
819
818
  onStoreRecordChange({fields, record}) {
820
- let me = this,
821
- fieldNames = fields.map(field => field.name),
822
- needsUpdate = false,
823
- {gridContainer} = me,
824
- {selectionModel} = gridContainer.view,
825
- {vdom} = me,
826
- cellId, cellNode, cellStyle, cellVdom, column, index;
819
+ let me = this,
820
+ fieldNames = fields.map(field => field.name),
821
+ needsUpdate = false,
822
+ {gridContainer} = me,
823
+ rowIndex = me.store.indexOf(record),
824
+ {selectionModel, vdom} = me,
825
+ cellId, cellNode, cellStyle, cellVdom, column, columnIndex;
827
826
 
828
827
  if (fieldNames.includes(me.colspanField)) {
829
- index = me.store.indexOf(record);
830
- me.vdom.cn[index] = me.createRow({record, rowIndex: index});
828
+ me.vdom.cn[rowIndex] = me.createRow({record, rowIndex});
831
829
  me.update()
832
830
  } else {
833
831
  fields.forEach(field => {
@@ -843,8 +841,8 @@ class GridView extends Component {
843
841
  if (cellNode?.vdom) {
844
842
  cellStyle = cellNode.vdom.style;
845
843
  column = me.getColumn(field.name);
846
- index = cellNode.index;
847
- cellVdom = me.applyRendererOutput({cellId, column, gridContainer, index, record});
844
+ columnIndex = cellNode.index;
845
+ cellVdom = me.applyRendererOutput({cellId, column, columnIndex, gridContainer, record, rowIndex});
848
846
  needsUpdate = true;
849
847
 
850
848
  // The cell-positioning logic happens outside applyRendererOutput()
@@ -854,7 +852,7 @@ class GridView extends Component {
854
852
  width: cellStyle.width
855
853
  });
856
854
 
857
- cellNode.parentNode.cn[index] = cellVdom
855
+ cellNode.parentNode.cn[columnIndex] = cellVdom
858
856
  }
859
857
  }
860
858
  })
@@ -228,13 +228,14 @@ class Button extends BaseButton {
228
228
  }
229
229
 
230
230
  /**
231
- * @param {Object} data
232
- * @param {Neo.button.Base} data.column
233
- * @param {String} data.dataField
231
+ * @param {Object} data
232
+ * @param {Neo.button.Base} data.column
233
+ * @param {Number} data.columnIndex
234
+ * @param {String} data.dataField
234
235
  * @param {Neo.grid.Container} data.gridContainer
235
- * @param {Number} data.index
236
- * @param {Object} data.record
237
- * @param {Number|String} data.value
236
+ * @param {Object} data.record
237
+ * @param {Number} data.rowIndex
238
+ * @param {Number|String} data.value
238
239
  * @returns {*}
239
240
  */
240
241
  cellRenderer(data) {
@@ -576,7 +576,7 @@ class DomAccess extends Base {
576
576
  * Include a script into the document.head
577
577
  * You can add more attributes if needed. See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
578
578
  * @param {String} src
579
- * @param {Object} opts=defer:true}
579
+ * @param {Object} opts={defer:true}
580
580
  * @param {Boolean} [opts.async]
581
581
  * @param {Boolean} [opts.defer]
582
582
  * @returns {Promise<unknown>}
@@ -28,15 +28,15 @@ class AmCharts extends Base {
28
28
  */
29
29
  dataMap: {},
30
30
  /**
31
- * @member {String} downloadPath='https//www.amcharts.com/lib/4/'
31
+ * @member {String} downloadPath='https//cdn.amcharts.com/lib/4/'
32
32
  * @protected
33
33
  */
34
- downloadPath: 'https://www.amcharts.com/lib/4/',
34
+ downloadPath: 'https://cdn.amcharts.com/lib/4/',
35
35
  /**
36
- * @member {String} fallbackPath='https://neomjs.github.io/pages/resources_pub/amCharts/'
36
+ * @member {String} fallbackPath='https://raw.githubusercontent.com/neomjs/pages/main/resources_pub/amCharts'
37
37
  * @protected
38
38
  */
39
- fallbackPath: 'https://neomjs.github.io/pages/resources_pub/amCharts/',
39
+ fallbackPath: 'https://raw.githubusercontent.com/neomjs/pages/main/resources_pub/amCharts/',
40
40
  /**
41
41
  * Remote method access for other workers
42
42
  * @member {Object} remote
@@ -51,7 +51,13 @@ class AmCharts extends Base {
51
51
  'setProperty',
52
52
  'updateData'
53
53
  ]
54
- }
54
+ },
55
+ /**
56
+ * Enforce using the fallbackPath
57
+ * @member {Boolean} useFallbackPath=false
58
+ * @protected
59
+ */
60
+ useFallbackPath: false
55
61
  }
56
62
 
57
63
  /**
@@ -187,8 +193,19 @@ class AmCharts extends Base {
187
193
  * @param {Boolean} useFallback=false
188
194
  */
189
195
  loadFiles(useFallback=false) {
190
- let me = this,
191
- basePath = useFallback ? me.fallbackPath : me.downloadPath;
196
+ let me = this,
197
+ useFallbackPath = me.useFallbackPath || useFallback,
198
+ basePath;
199
+
200
+ if (useFallbackPath && Neo.config.isGitHubPages) {
201
+ basePath = '../../../../resources_pub/amCharts/';
202
+
203
+ if (Neo.config.environment !== 'development') {
204
+ basePath = `../../${basePath}`
205
+ }
206
+ } else {
207
+ basePath = useFallbackPath ? me.fallbackPath : me.downloadPath
208
+ }
192
209
 
193
210
  me.isLoading = true;
194
211
 
@@ -203,8 +220,10 @@ class AmCharts extends Base {
203
220
  me.isReady = true
204
221
  })
205
222
  }).catch(e => {
206
- console.log('Download from amcharts.com failed, switching to fallback', e);
207
- me.loadFiles(true)
223
+ if (!useFallback && !me.useFallbackPath) {
224
+ console.log('Download from amcharts.com failed, switching to fallback', e);
225
+ me.loadFiles(true)
226
+ }
208
227
  })
209
228
  }
210
229
 
@@ -115,18 +115,24 @@ class DeltaUpdates extends Base {
115
115
  * @param {String} delta.index
116
116
  * @param {String} delta.parentId
117
117
  */
118
- du_moveNode(delta) {
119
- let {index} = delta,
120
- node = this.getElement(delta.id),
121
- parentNode = this.getElement(delta.parentId);
118
+ du_moveNode({id, index, parentId}) {
119
+ let node = this.getElement(id),
120
+ parentNode = this.getElement(parentId),
121
+ currentNode;
122
122
 
123
123
  if (node && parentNode) {
124
124
  if (index >= parentNode.children.length) {
125
125
  parentNode.appendChild(node)
126
126
  } else {
127
- //index++; // todo?: increase the index in case same parent, oldIndex < newIndex, direct swap
128
- if (node && parentNode.children[index].id !== delta.id) {
129
- parentNode.insertBefore(node, parentNode.children[index])
127
+ currentNode = parentNode.children[index];
128
+
129
+ if (node && currentNode.id !== id) {
130
+ // Check for a direct swap OP
131
+ if (node === currentNode.nextElementSibling) {
132
+ node.replaceWith(currentNode)
133
+ }
134
+
135
+ parentNode.insertBefore(node, currentNode)
130
136
  }
131
137
  }
132
138
  }
@@ -1,5 +1,4 @@
1
1
  import BaseModel from './BaseModel.mjs';
2
- import VDomUtil from '../../util/VDom.mjs';
3
2
 
4
3
  /**
5
4
  * @class Neo.selection.grid.RowModel
@@ -44,6 +43,14 @@ class RowModel extends BaseModel {
44
43
  super.destroy(...args)
45
44
  }
46
45
 
46
+ /**
47
+ * @param {Record} record
48
+ * @returns {Boolean}
49
+ */
50
+ hasAnnotations(record) {
51
+ return !!Object.getOwnPropertyDescriptor(record.__proto__, this.view.selectedRecordField)
52
+ }
53
+
47
54
  /**
48
55
  * @param {Object} data
49
56
  */
@@ -65,28 +72,31 @@ class RowModel extends BaseModel {
65
72
  let me = this,
66
73
  {view} = me,
67
74
  {store} = view,
75
+ countRecords = store.getCount(),
68
76
  currentIndex = 0,
69
- newIndex, newRecord, rowId;
77
+ newIndex, record, rowId;
70
78
 
71
79
  if (me.hasSelection()) {
72
80
  currentIndex = store.indexOf(view.getRecordByRowId(me.items[0]))
73
81
  }
74
82
 
75
- newIndex = (currentIndex + step) % store.getCount();
83
+ newIndex = (currentIndex + step) % countRecords;
76
84
 
77
85
  while (newIndex < 0) {
78
- newIndex += store.getCount()
86
+ newIndex += countRecords
79
87
  }
80
88
 
81
- newRecord = store.getAt(newIndex);
82
- rowId = view.getRowId(newRecord);
89
+ record = store.getAt(newIndex);
83
90
 
84
- if (rowId) {
85
- me.select(rowId);
91
+ if (me.hasAnnotations(record)) {
92
+ me.updateAnnotations(record)
93
+ } else {
94
+ rowId = view.getRowId(record);
86
95
 
87
- view.fire('select', {
88
- record: store.getAt(newIndex)
89
- })
96
+ if (rowId) {
97
+ me.select(rowId);
98
+ view.fire('select', {record})
99
+ }
90
100
  }
91
101
  }
92
102
 
@@ -100,16 +110,19 @@ class RowModel extends BaseModel {
100
110
  isSelected, record;
101
111
 
102
112
  if (id) {
103
- me.toggleSelection(id);
113
+ record = view.getRecord(id);
114
+
115
+ if (me.hasAnnotations(record)) {
116
+ me.updateAnnotations(record)
117
+ } else {
118
+ me.toggleSelection(id);
104
119
 
105
- isSelected = me.isSelected(id);
106
- record = view.getRecord(id);
120
+ isSelected = me.isSelected(id);
107
121
 
108
- !isSelected && view.onDeselect?.(record);
122
+ !isSelected && view.onDeselect?.(record);
109
123
 
110
- view.fire(isSelected ? 'select' : 'deselect', {
111
- record
112
- })
124
+ view.fire(isSelected ? 'select' : 'deselect', {record})
125
+ }
113
126
  }
114
127
  }
115
128
 
@@ -140,6 +153,32 @@ class RowModel extends BaseModel {
140
153
 
141
154
  super.unregister()
142
155
  }
156
+
157
+ /**
158
+ * @param {Record} record
159
+ */
160
+ updateAnnotations(record) {
161
+ let me = this,
162
+ {view} = me,
163
+ rowId = view.getRowId(record),
164
+ isSelected = me.isSelected(rowId),
165
+ annotationsField = view.selectedRecordField;
166
+
167
+ if (me.singleSelect) {
168
+ if (isSelected) {
169
+ record[annotationsField] = false
170
+ } else {
171
+ me.items.forEach(rowId => {
172
+ // We can use setSilent(), since the last change will trigger a view update
173
+ view.getRecordByRowId(rowId).setSilent({[annotationsField]: false})
174
+ });
175
+
176
+ record[annotationsField] = true
177
+ }
178
+ } else {
179
+ record[annotationsField] = !record[annotationsField]
180
+ }
181
+ }
143
182
  }
144
183
 
145
184
  export default Neo.setupClass(RowModel);
@@ -23,6 +23,14 @@ class RowModel extends BaseModel {
23
23
  cls: 'neo-selection-rowmodel'
24
24
  }
25
25
 
26
+ /**
27
+ * @param {Record} record
28
+ * @returns {Boolean}
29
+ */
30
+ hasAnnotations(record) {
31
+ return !!Object.getOwnPropertyDescriptor(record.__proto__, this.view.selectedRecordField)
32
+ }
33
+
26
34
  /**
27
35
  *
28
36
  */
@@ -64,28 +72,31 @@ class RowModel extends BaseModel {
64
72
  let me = this,
65
73
  {view} = me,
66
74
  {store} = view,
75
+ countRecords = store.getCount(),
67
76
  currentIndex = 0,
68
- newIndex, newRecord, rowId;
77
+ newIndex, record, rowId;
69
78
 
70
79
  if (me.hasSelection()) {
71
80
  currentIndex = store.indexOf(view.getRecordByRowId(me.items[0]))
72
81
  }
73
82
 
74
- newIndex = (currentIndex + step) % store.getCount();
83
+ newIndex = (currentIndex + step) % countRecords;
75
84
 
76
85
  while (newIndex < 0) {
77
- newIndex += store.getCount()
86
+ newIndex += countRecords
78
87
  }
79
88
 
80
- newRecord = store.getAt(newIndex);
81
- rowId = view.getRowId(newRecord);
89
+ record = store.getAt(newIndex);
82
90
 
83
- if (rowId) {
84
- me.select(rowId);
91
+ if (me.hasAnnotations(record)) {
92
+ me.updateAnnotations(record)
93
+ } else {
94
+ rowId = view.getRowId(record);
85
95
 
86
- view.fire('select', {
87
- record: store.getAt(newIndex)
88
- })
96
+ if (rowId) {
97
+ me.select(rowId);
98
+ view.fire('select', {record})
99
+ }
89
100
  }
90
101
  }
91
102
 
@@ -99,16 +110,19 @@ class RowModel extends BaseModel {
99
110
  isSelected, record;
100
111
 
101
112
  if (id) {
102
- me.toggleSelection(id);
113
+ record = view.getRecord(id);
114
+
115
+ if (me.hasAnnotations(record)) {
116
+ me.updateAnnotations(record)
117
+ } else {
118
+ me.toggleSelection(id);
103
119
 
104
- isSelected = me.isSelected(id);
105
- record = view.getRecord(id);
120
+ isSelected = me.isSelected(id);
106
121
 
107
- !isSelected && view.onDeselect?.(record);
122
+ !isSelected && view.onDeselect?.(record);
108
123
 
109
- view.fire(isSelected ? 'select' : 'deselect', {
110
- record
111
- })
124
+ view.fire(isSelected ? 'select' : 'deselect', {record})
125
+ }
112
126
  }
113
127
  }
114
128
 
@@ -139,6 +153,32 @@ class RowModel extends BaseModel {
139
153
 
140
154
  super.unregister()
141
155
  }
156
+
157
+ /**
158
+ * @param {Record} record
159
+ */
160
+ updateAnnotations(record) {
161
+ let me = this,
162
+ {view} = me,
163
+ rowId = view.getRowId(record),
164
+ isSelected = me.isSelected(rowId),
165
+ annotationsField = view.selectedRecordField;
166
+
167
+ if (me.singleSelect) {
168
+ if (isSelected) {
169
+ record[annotationsField] = false
170
+ } else {
171
+ me.items.forEach(rowId => {
172
+ // We can use setSilent(), since the last change will trigger a view update
173
+ view.getRecordByRowId(rowId).setSilent({[annotationsField]: false})
174
+ });
175
+
176
+ record[annotationsField] = true
177
+ }
178
+ } else {
179
+ record[annotationsField] = !record[annotationsField]
180
+ }
181
+ }
142
182
  }
143
183
 
144
184
  export default Neo.setupClass(RowModel);
@@ -116,13 +116,14 @@ class View extends Component {
116
116
  * @param {Object} data
117
117
  * @param {String} [data.cellId]
118
118
  * @param {Object} data.column
119
+ * @param {Number} data.columnIndex
119
120
  * @param {Object} data.record
120
- * @param {Number} data.index
121
+ * @param {Number} data.rowIndex
121
122
  * @param {Neo.table.Container} data.tableContainer
122
123
  * @returns {Object}
123
124
  */
124
125
  applyRendererOutput(data) {
125
- let {cellId, column, record, index, tableContainer} = data,
126
+ let {cellId, column, columnIndex, record, rowIndex, tableContainer} = data,
126
127
  me = this,
127
128
  cellCls = ['neo-table-cell'],
128
129
  colspan = record[me.colspanField],
@@ -138,9 +139,10 @@ class View extends Component {
138
139
 
139
140
  rendererOutput = column.renderer.call(column.rendererScope || tableContainer, {
140
141
  column,
142
+ columnIndex,
141
143
  dataField,
142
- index,
143
144
  record,
145
+ rowIndex,
144
146
  tableContainer,
145
147
  value: fieldValue
146
148
  });
@@ -184,7 +186,7 @@ class View extends Component {
184
186
  if (hasStore) {
185
187
  cellId = me.getCellId(record, column.dataField)
186
188
  } else {
187
- cellId = vdom.cn[index]?.cn[me.getColumn(column.dataField, true)]?.id || Neo.getId('td')
189
+ cellId = vdom.cn[rowIndex]?.cn[me.getColumn(column.dataField, true)]?.id || Neo.getId('td')
188
190
  }
189
191
  }
190
192
 
@@ -267,7 +269,7 @@ class View extends Component {
267
269
 
268
270
  for (i=0; i < colCount; i++) {
269
271
  column = columns[i];
270
- config = me.applyRendererOutput({column, record, index: rowIndex, tableContainer});
272
+ config = me.applyRendererOutput({column, columnIndex: i, record, rowIndex, tableContainer});
271
273
 
272
274
  if (column.dock) {
273
275
  config.cls = ['neo-locked', ...config.cls || []];
@@ -522,17 +524,16 @@ class View extends Component {
522
524
  * @param {Object} opts.record
523
525
  */
524
526
  onStoreRecordChange({fields, model, record}) {
525
- let me = this,
526
- fieldNames = fields.map(field => field.name),
527
- needsUpdate = false,
528
- tableContainer = me.parent,
529
- {selectionModel} = tableContainer,
530
- {vdom} = me,
531
- cellId, cellNode, column, index, scope;
527
+ let me = this,
528
+ fieldNames = fields.map(field => field.name),
529
+ needsUpdate = false,
530
+ tableContainer = me.parent,
531
+ rowIndex = me.store.indexOf(record),
532
+ {selectionModel, vdom} = me,
533
+ cellId, cellNode, cellVdom, column, columnIndex, scope;
532
534
 
533
535
  if (fieldNames.includes(me.colspanField)) {
534
- index = me.store.indexOf(record);
535
- me.vdom.cn[index] = me.createRow({record, rowIndex: index});
536
+ me.vdom.cn[rowIndex] = me.createRow({record, rowIndex});
536
537
  me.update()
537
538
  } else {
538
539
  fields.forEach(field => {
@@ -547,11 +548,12 @@ class View extends Component {
547
548
  // the vdom might not exist yet => nothing to do in this case
548
549
  if (cellNode?.vdom) {
549
550
  column = me.getColumn(field.name);
550
- index = cellNode.index;
551
+ columnIndex = cellNode.index;
551
552
  needsUpdate = true;
552
553
  scope = column.rendererScope || tableContainer;
554
+ cellVdom = me.applyRendererOutput({cellId, column, columnIndex, record, rowIndex, tableContainer});
553
555
 
554
- cellNode.parentNode.cn[index] = me.applyRendererOutput({cellId, column, record, index, tableContainer})
556
+ cellNode.parentNode.cn[columnIndex] = cellVdom
555
557
  }
556
558
  }
557
559
  })
@@ -242,13 +242,14 @@ class Button extends BaseButton {
242
242
  }
243
243
 
244
244
  /**
245
- * @param {Object} data
246
- * @param {Neo.button.Base} data.column
247
- * @param {String} data.dataField
248
- * @param {Number} data.index
249
- * @param {Object} data.record
245
+ * @param {Object} data
246
+ * @param {Neo.button.Base} data.column
247
+ * @param {Number} data.columnIndex
248
+ * @param {String} data.dataField
249
+ * @param {Object} data.record
250
+ * @param {Number} data.rowIndex
250
251
  * @param {Neo.table.Container} data.tableContainer
251
- * @param {Number|String} data.value
252
+ * @param {Number|String} data.value
252
253
  * @returns {*}
253
254
  */
254
255
  cellRenderer(data) {