neo.mjs 8.20.2 → 8.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/grid/bigData/ControlsContainer.mjs +57 -0
- package/examples/grid/bigData/MainStore.mjs +12 -0
- package/examples/grid/cellEditing/MainContainer.mjs +21 -9
- package/package.json +3 -3
- package/resources/scss/src/grid/View.scss +5 -3
- package/resources/scss/src/grid/plugin/CellEditing.scss +1 -0
- package/src/DefaultConfig.mjs +8 -16
- package/src/collection/Base.mjs +6 -3
- package/src/data/Store.mjs +32 -20
- package/src/form/field/Base.mjs +4 -0
- package/src/grid/Scrollbar.mjs +1 -1
- package/src/grid/View.mjs +5 -24
- package/src/grid/plugin/CellEditing.mjs +5 -1
- package/src/main/DomEvents.mjs +3 -3
- package/src/main/mixin/DeltaUpdates.mjs +14 -14
- package/src/main/mixin/TouchDomEvents.mjs +1 -1
- package/src/selection/grid/BaseModel.mjs +16 -0
- package/src/selection/grid/CellModel.mjs +4 -4
- package/src/selection/grid/ColumnModel.mjs +2 -2
- package/src/selection/grid/RowModel.mjs +2 -2
- package/src/table/plugin/CellEditing.mjs +33 -22
package/apps/ServiceWorker.mjs
CHANGED
package/apps/portal/index.html
CHANGED
@@ -84,6 +84,33 @@ class ControlsContainer extends Container {
|
|
84
84
|
style : {marginTop: '.3em'},
|
85
85
|
value : 'neo-theme-light',
|
86
86
|
valueLabelText: 'Light'
|
87
|
+
}, {
|
88
|
+
ntype: 'label',
|
89
|
+
style: {marginTop: '2em'},
|
90
|
+
text : 'Filters'
|
91
|
+
}, {
|
92
|
+
ntype : 'textfield',
|
93
|
+
clearable : true,
|
94
|
+
editable : true,
|
95
|
+
labelText : 'Firstname',
|
96
|
+
labelWidth: 90,
|
97
|
+
listeners : {change: 'up.onFilterFieldChange'},
|
98
|
+
name : 'firstname',
|
99
|
+
style : {marginTop: '.3em'},
|
100
|
+
width : 200
|
101
|
+
}, {
|
102
|
+
ntype : 'textfield',
|
103
|
+
clearable : true,
|
104
|
+
editable : true,
|
105
|
+
labelText : 'Lastname',
|
106
|
+
labelWidth: 90,
|
107
|
+
listeners : {change: 'up.onFilterFieldChange'},
|
108
|
+
name : 'lastname',
|
109
|
+
width : 200
|
110
|
+
}, {
|
111
|
+
ntype : 'label',
|
112
|
+
reference: 'count-rows-label',
|
113
|
+
style : {marginTop: '1em'}
|
87
114
|
}]
|
88
115
|
}],
|
89
116
|
/**
|
@@ -154,6 +181,36 @@ class ControlsContainer extends Container {
|
|
154
181
|
|
155
182
|
me.grid.toggleCls('neo-extend-margin-right');
|
156
183
|
}
|
184
|
+
|
185
|
+
onConstructed() {
|
186
|
+
super.onConstructed();
|
187
|
+
|
188
|
+
let me = this,
|
189
|
+
{store} = me.grid;
|
190
|
+
|
191
|
+
store.on({
|
192
|
+
filter: me.updateRowsLabel,
|
193
|
+
load : me.updateRowsLabel,
|
194
|
+
scope : me
|
195
|
+
});
|
196
|
+
|
197
|
+
store.getCount() > 0 && me.updateRowsLabel()
|
198
|
+
}
|
199
|
+
|
200
|
+
/**
|
201
|
+
* @param {Object} data
|
202
|
+
*/
|
203
|
+
onFilterFieldChange(data) {
|
204
|
+
this.grid.store.getFilter(data.component.name).value = data.value
|
205
|
+
}
|
206
|
+
|
207
|
+
updateRowsLabel() {
|
208
|
+
let {store} = this.grid;
|
209
|
+
|
210
|
+
if (!store.isLoading) {
|
211
|
+
this.getItem('count-rows-label').text = 'Filtered rows: ' + store.getCount()
|
212
|
+
}
|
213
|
+
}
|
157
214
|
}
|
158
215
|
|
159
216
|
export default Neo.setupClass(ControlsContainer);
|
@@ -20,6 +20,18 @@ class MainStore extends Store {
|
|
20
20
|
* @member {Number} amountRows_=1000
|
21
21
|
*/
|
22
22
|
amountRows_: 1000,
|
23
|
+
/**
|
24
|
+
* @member {Object[]} filters
|
25
|
+
*/
|
26
|
+
filters: [{
|
27
|
+
property: 'firstname',
|
28
|
+
operator: 'like',
|
29
|
+
value : null
|
30
|
+
}, {
|
31
|
+
property: 'lastname',
|
32
|
+
operator: 'like',
|
33
|
+
value : null
|
34
|
+
}],
|
23
35
|
/**
|
24
36
|
* @member {Neo.data.Model} model=Model
|
25
37
|
*/
|
@@ -44,7 +44,8 @@ class MainContainer extends ConfigurationViewport {
|
|
44
44
|
* @returns {Object[]}
|
45
45
|
*/
|
46
46
|
createConfigurationComponents() {
|
47
|
-
let me
|
47
|
+
let me = this,
|
48
|
+
{selectionModel} = me.exampleComponent.view;
|
48
49
|
|
49
50
|
const selectionModelRadioDefaults = {
|
50
51
|
module : Radio,
|
@@ -64,25 +65,25 @@ class MainContainer extends ConfigurationViewport {
|
|
64
65
|
value : me.exampleComponent.height
|
65
66
|
}, {
|
66
67
|
...selectionModelRadioDefaults,
|
67
|
-
checked :
|
68
|
+
checked : selectionModel.ntype === 'selection-grid-cellmodel',
|
68
69
|
labelText : 'selectionModel',
|
69
|
-
listeners : {change: me.
|
70
|
+
listeners : {change: me.onRadioViewChange.bind(me, 'selectionModel', CellModel)},
|
70
71
|
style : {marginTop: '10px'},
|
71
72
|
valueLabelText: 'Cell'
|
72
73
|
}, {
|
73
74
|
...selectionModelRadioDefaults,
|
74
|
-
checked :
|
75
|
-
listeners : {change: me.
|
75
|
+
checked : selectionModel.ntype === 'selection-grid-cellcolumnmodel',
|
76
|
+
listeners : {change: me.onRadioViewChange.bind(me, 'selectionModel', CellColumnModel)},
|
76
77
|
valueLabelText: 'Cell & Column'
|
77
78
|
}, {
|
78
79
|
...selectionModelRadioDefaults,
|
79
|
-
checked :
|
80
|
-
listeners : {change: me.
|
80
|
+
checked : selectionModel.ntype === 'selection-grid-cellrowmodel',
|
81
|
+
listeners : {change: me.onRadioViewChange.bind(me, 'selectionModel', CellRowModel)},
|
81
82
|
valueLabelText: 'Cell & Row'
|
82
83
|
}, {
|
83
84
|
...selectionModelRadioDefaults,
|
84
|
-
checked :
|
85
|
-
listeners : {change: me.
|
85
|
+
checked : selectionModel.ntype === 'selection-grid-cellcolumnrowmodel',
|
86
|
+
listeners : {change: me.onRadioViewChange.bind(me, 'selectionModel', CellColumnRowModel)},
|
86
87
|
valueLabelText: 'Cell & Column & Row'
|
87
88
|
}, {
|
88
89
|
module : CheckBox,
|
@@ -173,6 +174,17 @@ class MainContainer extends ConfigurationViewport {
|
|
173
174
|
onPluginConfigChange(config, opts) {
|
174
175
|
this.exampleComponent.getPlugin('grid-cell-editing')[config] = opts.value
|
175
176
|
}
|
177
|
+
|
178
|
+
/**
|
179
|
+
* @param {String} config
|
180
|
+
* @param {String} value
|
181
|
+
* @param {Object} opts
|
182
|
+
*/
|
183
|
+
onRadioViewChange(config, value, opts) {
|
184
|
+
if (opts.value === true) { // we only want to listen to check events, not uncheck
|
185
|
+
this.exampleComponent.view[config] = value
|
186
|
+
}
|
187
|
+
}
|
176
188
|
}
|
177
189
|
|
178
190
|
export default Neo.setupClass(MainContainer);
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "neo.mjs",
|
3
|
-
"version": "8.
|
3
|
+
"version": "8.21.1",
|
4
4
|
"description": "The webworkers driven UI framework",
|
5
5
|
"type": "module",
|
6
6
|
"repository": {
|
@@ -55,11 +55,11 @@
|
|
55
55
|
"fs-extra": "^11.3.0",
|
56
56
|
"highlightjs-line-numbers.js": "^2.9.0",
|
57
57
|
"inquirer": "^12.4.1",
|
58
|
-
"marked": "^15.0.
|
58
|
+
"marked": "^15.0.7",
|
59
59
|
"monaco-editor": "0.50.0",
|
60
60
|
"neo-jsdoc": "1.0.1",
|
61
61
|
"neo-jsdoc-x": "1.0.5",
|
62
|
-
"postcss": "^8.5.
|
62
|
+
"postcss": "^8.5.2",
|
63
63
|
"sass": "^1.84.0",
|
64
64
|
"siesta-lite": "5.5.2",
|
65
65
|
"url": "^0.11.4",
|
@@ -98,9 +98,11 @@
|
|
98
98
|
|
99
99
|
.neo-mouse {
|
100
100
|
.neo-grid-row {
|
101
|
-
&:
|
102
|
-
|
103
|
-
|
101
|
+
&:not(.neo-selected) {
|
102
|
+
&:hover {
|
103
|
+
.neo-grid-cell {
|
104
|
+
background-color: var(--grid-cell-background-color-hover);
|
105
|
+
}
|
104
106
|
}
|
105
107
|
}
|
106
108
|
}
|
package/src/DefaultConfig.mjs
CHANGED
@@ -46,12 +46,12 @@ const DefaultConfig = {
|
|
46
46
|
/**
|
47
47
|
* Pass a token in case you are using the CesiumJS main thread addon
|
48
48
|
* See: https://github.com/neomjs/neo/blob/dev/src/main/addon/CesiumJS.mjs
|
49
|
-
* @default
|
49
|
+
* @default undefined
|
50
50
|
* @memberOf! module:Neo
|
51
51
|
* @name config.cesiumJsToken
|
52
52
|
* @type String|null
|
53
53
|
*/
|
54
|
-
|
54
|
+
|
55
55
|
/**
|
56
56
|
* Set this config to false to disable the component logging using Ctrl-Right-Click
|
57
57
|
* @default true
|
@@ -79,21 +79,21 @@ const DefaultConfig = {
|
|
79
79
|
environment: 'dist/production',
|
80
80
|
/**
|
81
81
|
* In case you are using the GoogleMaps main thread addon, you can pass the API key here.
|
82
|
-
* @default
|
82
|
+
* @default undefined
|
83
83
|
* @memberOf! module:Neo
|
84
84
|
* @name config.googleMapsApiKey
|
85
85
|
* @type String
|
86
86
|
*/
|
87
|
-
|
87
|
+
|
88
88
|
/**
|
89
89
|
* In case you are using the GoogleAnalytics main thread addon or useGoogleAnalytics: true,
|
90
90
|
* you can change the gtag id here. Required for the online examples (gh pages)
|
91
|
-
* @default
|
91
|
+
* @default undefined
|
92
92
|
* @memberOf! module:Neo
|
93
93
|
* @name config.gtagId
|
94
94
|
* @type String
|
95
95
|
*/
|
96
|
-
|
96
|
+
|
97
97
|
/**
|
98
98
|
* Flag for running on https://neomjs.github.io/pages/
|
99
99
|
* => to use local images paths instead of raw.githubusercontent.com
|
@@ -253,14 +253,6 @@ const DefaultConfig = {
|
|
253
253
|
* @type Boolean
|
254
254
|
*/
|
255
255
|
useTaskWorker: false,
|
256
|
-
/**
|
257
|
-
* Adds global dom event listeners for mobile related events like rotate, swipe, tap
|
258
|
-
* @default true
|
259
|
-
* @memberOf! module:Neo
|
260
|
-
* @name config.useTouchEvents
|
261
|
-
* @type Boolean
|
262
|
-
*/
|
263
|
-
useTouchEvents: true,
|
264
256
|
/**
|
265
257
|
* False will create the vdom.Helper within the App worker (experimental!)
|
266
258
|
* @default true
|
@@ -271,12 +263,12 @@ const DefaultConfig = {
|
|
271
263
|
useVdomWorker: true,
|
272
264
|
/**
|
273
265
|
* buildScripts/injectPackageVersion.mjs will update this value
|
274
|
-
* @default '8.
|
266
|
+
* @default '8.21.1'
|
275
267
|
* @memberOf! module:Neo
|
276
268
|
* @name config.version
|
277
269
|
* @type String
|
278
270
|
*/
|
279
|
-
version: '8.
|
271
|
+
version: '8.21.1'
|
280
272
|
};
|
281
273
|
|
282
274
|
Object.assign(DefaultConfig, {
|
package/src/collection/Base.mjs
CHANGED
@@ -234,7 +234,7 @@ class Collection extends Base {
|
|
234
234
|
me.sortDirections = [];
|
235
235
|
me.sortProperties = [];
|
236
236
|
|
237
|
-
me.sorters.forEach(sorter => {
|
237
|
+
me.sorters.forEach(sorter => {
|
238
238
|
me.sortDirections.push(sorter.directionMultiplier);
|
239
239
|
me.sortProperties.push(sorter.property)
|
240
240
|
})
|
@@ -1050,9 +1050,12 @@ class Collection extends Base {
|
|
1050
1050
|
onMutate(opts) {
|
1051
1051
|
let me = this;
|
1052
1052
|
|
1053
|
-
|
1053
|
+
// todo: inspect the bubbling chain
|
1054
|
+
/*if (opts.preventBubbleUp) {
|
1054
1055
|
me.preventBubbleUp = true
|
1055
|
-
}
|
1056
|
+
}*/
|
1057
|
+
|
1058
|
+
me.preventBubbleUp = true;
|
1056
1059
|
|
1057
1060
|
me.splice(null, opts.removedItems, opts.addedItems)
|
1058
1061
|
}
|
package/src/data/Store.mjs
CHANGED
@@ -132,7 +132,7 @@ class Store extends Base {
|
|
132
132
|
* @returns {Number} the collection count
|
133
133
|
*/
|
134
134
|
add(item) {
|
135
|
-
return super.add(this.
|
135
|
+
return super.add(this.createRecord(item))
|
136
136
|
}
|
137
137
|
|
138
138
|
/**
|
@@ -161,6 +161,8 @@ class Store extends Base {
|
|
161
161
|
me.initialData = [...value]
|
162
162
|
}
|
163
163
|
|
164
|
+
me.isLoading = false;
|
165
|
+
|
164
166
|
me.add(value)
|
165
167
|
}
|
166
168
|
}
|
@@ -256,22 +258,9 @@ class Store extends Base {
|
|
256
258
|
*/
|
257
259
|
beforeSetData(value, oldValue) {
|
258
260
|
if (value) {
|
259
|
-
|
260
|
-
value = [value]
|
261
|
-
}
|
262
|
-
|
263
|
-
let me = this,
|
264
|
-
i = 0,
|
265
|
-
len = value.length,
|
266
|
-
item;
|
267
|
-
|
268
|
-
for (; i < len; i++) {
|
269
|
-
item = value[i]
|
261
|
+
this.isLoading = true;
|
270
262
|
|
271
|
-
|
272
|
-
value[i] = RecordFactory.createRecord(me.model, item)
|
273
|
-
}
|
274
|
-
}
|
263
|
+
value = this.createRecord(value)
|
275
264
|
}
|
276
265
|
|
277
266
|
return value
|
@@ -304,10 +293,34 @@ class Store extends Base {
|
|
304
293
|
}
|
305
294
|
|
306
295
|
/**
|
307
|
-
*
|
296
|
+
* Converts an object or array of objects into records
|
297
|
+
* @param {Object|Object[]} config
|
298
|
+
* @returns {Object|Object[]} Array in case an array was passed
|
308
299
|
*/
|
309
300
|
createRecord(config) {
|
310
|
-
|
301
|
+
let isArray = true;
|
302
|
+
|
303
|
+
if (config) {
|
304
|
+
if (!Array.isArray(config)) {
|
305
|
+
isArray = false;
|
306
|
+
config = [config]
|
307
|
+
}
|
308
|
+
|
309
|
+
let me = this,
|
310
|
+
i = 0,
|
311
|
+
len = config.length,
|
312
|
+
item;
|
313
|
+
|
314
|
+
for (; i < len; i++) {
|
315
|
+
item = config[i]
|
316
|
+
|
317
|
+
if (!RecordFactory.isRecord(item)) {
|
318
|
+
config[i] = RecordFactory.createRecord(me.model, item)
|
319
|
+
}
|
320
|
+
}
|
321
|
+
}
|
322
|
+
|
323
|
+
return isArray ? config : config[0]
|
311
324
|
}
|
312
325
|
|
313
326
|
/**
|
@@ -375,8 +388,7 @@ class Store extends Base {
|
|
375
388
|
onCollectionMutate(opts) {
|
376
389
|
let me = this;
|
377
390
|
|
378
|
-
if (me.configsApplied) {
|
379
|
-
// console.log('onCollectionMutate', opts);
|
391
|
+
if (me.configsApplied && !me.isLoading) {
|
380
392
|
me.fire('load', me.items)
|
381
393
|
}
|
382
394
|
}
|
package/src/form/field/Base.mjs
CHANGED
@@ -33,6 +33,10 @@ class Field extends Component {
|
|
33
33
|
* @member {String|null} formGroup_=null
|
34
34
|
*/
|
35
35
|
formGroup_: null,
|
36
|
+
/**
|
37
|
+
* @member {String|null} keys={}
|
38
|
+
*/
|
39
|
+
keys: {},
|
36
40
|
/**
|
37
41
|
* True indicates that a user has interacted with the form field
|
38
42
|
* @member {Boolean} isTouched_=false
|
package/src/grid/Scrollbar.mjs
CHANGED
@@ -53,7 +53,7 @@ class GridScrollbar extends Component {
|
|
53
53
|
ScrollSync.register({
|
54
54
|
fromId: me.parent.view.vdom.id,
|
55
55
|
toId : me.id,
|
56
|
-
twoWay: !Neo.config.
|
56
|
+
twoWay: !Neo.config.hasTouchEvents, // Syncing the scroller back to the view affects mobile scrolling
|
57
57
|
...params
|
58
58
|
})
|
59
59
|
} else {
|
package/src/grid/View.mjs
CHANGED
@@ -336,25 +336,6 @@ class GridView extends Component {
|
|
336
336
|
oldValue !== undefined && this.createViewData()
|
337
337
|
}
|
338
338
|
|
339
|
-
/**
|
340
|
-
* Triggered after the store config got changed
|
341
|
-
* @param {Neo.data.Store|null} value
|
342
|
-
* @param {Neo.data.Store|null} oldValue
|
343
|
-
* @protected
|
344
|
-
*/
|
345
|
-
afterSetStore(value, oldValue) {
|
346
|
-
if (value) {
|
347
|
-
let me = this;
|
348
|
-
|
349
|
-
value.on({
|
350
|
-
load : me.updateScrollHeight,
|
351
|
-
scope: me
|
352
|
-
});
|
353
|
-
|
354
|
-
value.getCount() > 0 && me.updateScrollHeight()
|
355
|
-
}
|
356
|
-
}
|
357
|
-
|
358
339
|
/**
|
359
340
|
* Triggered after the visibleColumns config got changed
|
360
341
|
* @param {Number[]} value
|
@@ -579,7 +560,7 @@ class GridView extends Component {
|
|
579
560
|
endIndex, i;
|
580
561
|
|
581
562
|
if (
|
582
|
-
|
563
|
+
store.isLoading ||
|
583
564
|
me.availableRows < 1 ||
|
584
565
|
me._containerWidth < 1 || // we are not checking me.containerWidth, since we want to ignore the config symbol
|
585
566
|
me.columnPositions.getCount() < 1 ||
|
@@ -599,6 +580,7 @@ class GridView extends Component {
|
|
599
580
|
|
600
581
|
me.parent.isLoading = false;
|
601
582
|
|
583
|
+
me.updateScrollHeight(true); // silent
|
602
584
|
me.update()
|
603
585
|
}
|
604
586
|
|
@@ -889,7 +871,6 @@ class GridView extends Component {
|
|
889
871
|
let me = this,
|
890
872
|
fieldNames = fields.map(field => field.name),
|
891
873
|
needsUpdate = false,
|
892
|
-
gridContainer = me.parent,
|
893
874
|
rowIndex = me.store.indexOf(record),
|
894
875
|
{selectionModel, vdom} = me,
|
895
876
|
cellId, cellNode, cellStyle, cellVdom, column, columnIndex;
|
@@ -960,16 +941,16 @@ class GridView extends Component {
|
|
960
941
|
}
|
961
942
|
|
962
943
|
/**
|
963
|
-
*
|
944
|
+
* @param {Boolean} silent=false
|
964
945
|
*/
|
965
|
-
updateScrollHeight() {
|
946
|
+
updateScrollHeight(silent=false) {
|
966
947
|
let me = this,
|
967
948
|
countRecords = me.store.getCount(),
|
968
949
|
{rowHeight} = me;
|
969
950
|
|
970
951
|
if (countRecords > 0 && rowHeight > 0) {
|
971
952
|
me.vdom.cn[0].height = `${(countRecords + 1) * rowHeight}px`;
|
972
|
-
me.update()
|
953
|
+
!silent && me.update()
|
973
954
|
}
|
974
955
|
}
|
975
956
|
|
@@ -23,7 +23,11 @@ class CellEditing extends BaseCellEditing {
|
|
23
23
|
/**
|
24
24
|
* @member {String[]} editorCls=['neo-grid-editor']
|
25
25
|
*/
|
26
|
-
editorCls: ['neo-grid-editor']
|
26
|
+
editorCls: ['neo-grid-editor'],
|
27
|
+
/**
|
28
|
+
* @member {Boolean} focusCells=true
|
29
|
+
*/
|
30
|
+
focusCells: true
|
27
31
|
}
|
28
32
|
}
|
29
33
|
|
package/src/main/DomEvents.mjs
CHANGED
@@ -21,7 +21,7 @@ const globalDomEvents = [
|
|
21
21
|
{name: 'wheel', handler: 'onWheel', options: {passive: false}}
|
22
22
|
];
|
23
23
|
|
24
|
-
// Will get applied to the document.body in case Neo.config.
|
24
|
+
// Will get applied to the document.body in case Neo.config.hasTouchEvents === true
|
25
25
|
const touchEvents = [
|
26
26
|
{name: 'touchcancel', handler: 'onTouchCancel'},
|
27
27
|
{name: 'touchend', handler: 'onTouchEnd'},
|
@@ -187,7 +187,7 @@ class DomEvents extends Base {
|
|
187
187
|
addGlobalDomListeners() {
|
188
188
|
let me = this;
|
189
189
|
|
190
|
-
[...globalDomEvents].concat(Neo.config.
|
190
|
+
[...globalDomEvents].concat(Neo.config.hasTouchEvents ? touchEvents : []).forEach(event => {
|
191
191
|
document.body.addEventListener(event.name, me[event.handler].bind(me), event.options)
|
192
192
|
});
|
193
193
|
}
|
@@ -514,7 +514,7 @@ class DomEvents extends Base {
|
|
514
514
|
if (
|
515
515
|
isInput &&
|
516
516
|
event.key === 'Tab' &&
|
517
|
-
me.testPathInclusion(event, ['neo-table-editor'], true)
|
517
|
+
me.testPathInclusion(event, ['neo-grid-editor', 'neo-table-editor'], true)
|
518
518
|
) {
|
519
519
|
event.preventDefault()
|
520
520
|
}
|
@@ -26,14 +26,16 @@ class DeltaUpdates extends Base {
|
|
26
26
|
len = attributes.length,
|
27
27
|
attribute;
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
if (node) {
|
30
|
+
for (; i < len; i++) {
|
31
|
+
attribute = attributes.item(i);
|
32
|
+
clone.setAttribute(attribute.nodeName, attribute.nodeValue)
|
33
|
+
}
|
33
34
|
|
34
|
-
|
35
|
+
clone.innerHTML= node.innerHTML;
|
35
36
|
|
36
|
-
|
37
|
+
node.parentNode.replaceChild(clone, node)
|
38
|
+
}
|
37
39
|
}
|
38
40
|
|
39
41
|
/**
|
@@ -41,7 +43,7 @@ class DeltaUpdates extends Base {
|
|
41
43
|
* @param {String} delta.id
|
42
44
|
*/
|
43
45
|
du_focusNode(delta) {
|
44
|
-
this.getElement(delta.id)
|
46
|
+
this.getElement(delta.id)?.focus()
|
45
47
|
}
|
46
48
|
|
47
49
|
/**
|
@@ -183,7 +185,7 @@ class DeltaUpdates extends Base {
|
|
183
185
|
let me = this,
|
184
186
|
node = me.getElement(delta.parentId);
|
185
187
|
|
186
|
-
node
|
188
|
+
node?.replaceChild(me.getElement(delta.toId), me.getElement(delta.fromId))
|
187
189
|
}
|
188
190
|
|
189
191
|
/**
|
@@ -195,7 +197,9 @@ class DeltaUpdates extends Base {
|
|
195
197
|
let me = this,
|
196
198
|
node = me.getElement(delta.id);
|
197
199
|
|
198
|
-
node
|
200
|
+
if (node) {
|
201
|
+
node.textContent = delta.value
|
202
|
+
}
|
199
203
|
}
|
200
204
|
|
201
205
|
/**
|
@@ -211,11 +215,7 @@ class DeltaUpdates extends Base {
|
|
211
215
|
let me = this,
|
212
216
|
node = me.getElementOrBody(delta.id);
|
213
217
|
|
214
|
-
if (
|
215
|
-
if (Neo.config.environment === 'development') {
|
216
|
-
console.warn('du_updateNode: node not found for id', delta.id)
|
217
|
-
}
|
218
|
-
} else {
|
218
|
+
if (node) {
|
219
219
|
Object.entries(delta).forEach(([prop, value]) => {
|
220
220
|
switch(prop) {
|
221
221
|
case 'attributes':
|
@@ -22,6 +22,22 @@ class BaseModel extends Model {
|
|
22
22
|
get dataFields() {
|
23
23
|
return this.view.parent.columns.map(column => column.dataField)
|
24
24
|
}
|
25
|
+
|
26
|
+
/**
|
27
|
+
* Checks if an event path contains a grid cell editor
|
28
|
+
* @param {Object} data
|
29
|
+
* @param {Object[]} data.path
|
30
|
+
* @returns {Boolean}
|
31
|
+
*/
|
32
|
+
hasEditorFocus({path}) {
|
33
|
+
for (const node of path) {
|
34
|
+
if (node.cls?.includes('neo-grid-editor')) {
|
35
|
+
return true
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
return false
|
40
|
+
}
|
25
41
|
}
|
26
42
|
|
27
43
|
export default Neo.setupClass(BaseModel);
|
@@ -54,28 +54,28 @@ class CellModel extends BaseModel {
|
|
54
54
|
* @param {Object} data
|
55
55
|
*/
|
56
56
|
onKeyDownDown(data) {
|
57
|
-
this.onNavKeyRow(1)
|
57
|
+
!this.hasEditorFocus(data) && this.onNavKeyRow(1)
|
58
58
|
}
|
59
59
|
|
60
60
|
/**
|
61
61
|
* @param {Object} data
|
62
62
|
*/
|
63
63
|
onKeyDownLeft(data) {
|
64
|
-
this.onNavKeyColumn(-1)
|
64
|
+
!this.hasEditorFocus(data) && this.onNavKeyColumn(-1)
|
65
65
|
}
|
66
66
|
|
67
67
|
/**
|
68
68
|
* @param {Object} data
|
69
69
|
*/
|
70
70
|
onKeyDownRight(data) {
|
71
|
-
this.onNavKeyColumn(1)
|
71
|
+
!this.hasEditorFocus(data) && this.onNavKeyColumn(1)
|
72
72
|
}
|
73
73
|
|
74
74
|
/**
|
75
75
|
* @param {Object} data
|
76
76
|
*/
|
77
77
|
onKeyDownUp(data) {
|
78
|
-
this.onNavKeyRow(-1)
|
78
|
+
!this.hasEditorFocus(data) && this.onNavKeyRow(-1)
|
79
79
|
}
|
80
80
|
|
81
81
|
/**
|
@@ -66,14 +66,14 @@ class ColumnModel extends BaseModel {
|
|
66
66
|
* @param {Object} data
|
67
67
|
*/
|
68
68
|
onKeyDownLeft(data) {
|
69
|
-
this.onNavKeyColumn(-1)
|
69
|
+
!this.hasEditorFocus(data) && this.onNavKeyColumn(-1)
|
70
70
|
}
|
71
71
|
|
72
72
|
/**
|
73
73
|
* @param {Object} data
|
74
74
|
*/
|
75
75
|
onKeyDownRight(data) {
|
76
|
-
this.onNavKeyColumn(1)
|
76
|
+
!this.hasEditorFocus(data) && this.onNavKeyColumn(1)
|
77
77
|
}
|
78
78
|
|
79
79
|
/**
|
@@ -55,14 +55,14 @@ class RowModel extends BaseModel {
|
|
55
55
|
* @param {Object} data
|
56
56
|
*/
|
57
57
|
onKeyDownDown(data) {
|
58
|
-
this.onNavKeyRow(1)
|
58
|
+
!this.hasEditorFocus(data) && this.onNavKeyRow(1)
|
59
59
|
}
|
60
60
|
|
61
61
|
/**
|
62
62
|
* @param {Object} data
|
63
63
|
*/
|
64
64
|
onKeyDownUp(data) {
|
65
|
-
this.onNavKeyRow(-1)
|
65
|
+
!this.hasEditorFocus(data) && this.onNavKeyRow(-1)
|
66
66
|
}
|
67
67
|
|
68
68
|
/**
|
@@ -29,7 +29,11 @@ class CellEditing extends Plugin {
|
|
29
29
|
/**
|
30
30
|
* @member {String[]} editorCls=['neo-table-editor']
|
31
31
|
*/
|
32
|
-
editorCls: ['neo-table-editor']
|
32
|
+
editorCls: ['neo-table-editor'],
|
33
|
+
/**
|
34
|
+
* @member {Boolean} focusCells=true
|
35
|
+
*/
|
36
|
+
focusCells: true
|
33
37
|
}
|
34
38
|
|
35
39
|
/**
|
@@ -110,7 +114,8 @@ class CellEditing extends Plugin {
|
|
110
114
|
cellNode = VdomUtil.find(view.vdom, cellId).vdom,
|
111
115
|
column = me.owner.headerToolbar.getColumn(dataField),
|
112
116
|
editor = me.editors[dataField],
|
113
|
-
value = record[dataField]
|
117
|
+
value = record[dataField],
|
118
|
+
keys;
|
114
119
|
|
115
120
|
if (me.mountedEditor) {
|
116
121
|
await me.unmountEditor();
|
@@ -133,15 +138,21 @@ class CellEditing extends Plugin {
|
|
133
138
|
value,
|
134
139
|
windowId,
|
135
140
|
|
136
|
-
keys: {
|
137
|
-
Enter : 'onEditorKeyEnter',
|
138
|
-
Escape: 'onEditorKeyEscape',
|
139
|
-
Tab : 'onEditorKeyTab',
|
140
|
-
scope : me
|
141
|
-
},
|
142
|
-
|
143
141
|
...column.editor
|
144
|
-
})
|
142
|
+
});
|
143
|
+
|
144
|
+
keys = {
|
145
|
+
Enter : 'onEditorKeyEnter',
|
146
|
+
Escape: 'onEditorKeyEscape',
|
147
|
+
Tab : 'onEditorKeyTab',
|
148
|
+
scope : me
|
149
|
+
};
|
150
|
+
|
151
|
+
if (editor.keys) {
|
152
|
+
editor.keys.add(keys)
|
153
|
+
} else {
|
154
|
+
editor.keys = keys
|
155
|
+
}
|
145
156
|
} else {
|
146
157
|
editor.originalConfig.value = value;
|
147
158
|
editor.setSilent({record, value})
|
@@ -249,14 +260,14 @@ class CellEditing extends Plugin {
|
|
249
260
|
* @returns {Promise<void>}
|
250
261
|
*/
|
251
262
|
async onTableKeyDown(data) {
|
252
|
-
let me
|
253
|
-
{target}
|
254
|
-
|
263
|
+
let me = this,
|
264
|
+
{target} = data,
|
265
|
+
{view} = me.owner,
|
255
266
|
dataField, record;
|
256
267
|
|
257
268
|
if (!me.mountedEditor && target.cls?.includes('neo-selected')) {
|
258
|
-
dataField =
|
259
|
-
record =
|
269
|
+
dataField = view.getCellDataField(target.id);
|
270
|
+
record = view.getRecord(target.id);
|
260
271
|
|
261
272
|
await me.mountEditor(record, dataField)
|
262
273
|
}
|
@@ -283,7 +294,7 @@ class CellEditing extends Plugin {
|
|
283
294
|
if (cellId) {
|
284
295
|
selectionModel?.deselect(cellId, true); // the cell might still count as selected => silent deselect first
|
285
296
|
selectionModel?.select(cellId);
|
286
|
-
me.owner.focus(cellId)
|
297
|
+
me.focusCells && me.owner.focus(cellId)
|
287
298
|
}
|
288
299
|
}
|
289
300
|
|
@@ -315,15 +326,15 @@ class CellEditing extends Plugin {
|
|
315
326
|
return
|
316
327
|
}
|
317
328
|
|
318
|
-
let me
|
319
|
-
record
|
320
|
-
|
321
|
-
rowIndex
|
329
|
+
let me = this,
|
330
|
+
record = me.mountedEditor.record,
|
331
|
+
{view} = me.owner,
|
332
|
+
rowIndex = view.store.indexOf(record);
|
322
333
|
|
323
334
|
me.mountedEditor = null;
|
324
335
|
|
325
|
-
|
326
|
-
await
|
336
|
+
view.getVdomRoot().cn[rowIndex] = view.createRow({record, rowIndex});
|
337
|
+
await view.promiseUpdate()
|
327
338
|
}
|
328
339
|
}
|
329
340
|
|