neo.mjs 8.28.1 → 8.29.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.
- 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/GridContainer.mjs +11 -3
- package/examples/grid/bigData/MainModel.mjs +3 -1
- package/examples/grid/bigData/MainStore.mjs +2 -1
- package/examples/grid/nestedRecordFields/Viewport.mjs +8 -26
- package/package.json +1 -1
- package/resources/scss/src/grid/column/AnimatedChange.scss +15 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/core/Observable.mjs +7 -2
- package/src/draggable/grid/header/toolbar/SortZone.mjs +1 -3
- package/src/grid/Container.mjs +51 -26
- package/src/grid/View.mjs +66 -46
- package/src/grid/column/AnimatedChange.mjs +78 -0
- package/src/grid/column/Base.mjs +81 -0
- package/src/grid/column/Component.mjs +79 -0
- package/src/grid/column/Index.mjs +42 -0
- package/src/grid/column/_export.mjs +6 -0
- package/src/grid/header/Button.mjs +3 -40
- package/src/selection/grid/BaseModel.mjs +1 -1
package/apps/ServiceWorker.mjs
CHANGED
package/apps/portal/index.html
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import BaseGridContainer from '../../../src/grid/Container.mjs';
|
2
|
+
import Button from '../../../src/button/Base.mjs';
|
2
3
|
import MainStore from './MainStore.mjs';
|
3
4
|
|
4
5
|
/**
|
@@ -45,11 +46,18 @@ class GridContainer extends BaseGridContainer {
|
|
45
46
|
* @protected
|
46
47
|
*/
|
47
48
|
afterSetAmountColumns(value, oldValue) {
|
48
|
-
let i =
|
49
|
+
let i = 6,
|
49
50
|
columns = [
|
50
|
-
{dataField: 'id', text: '#', width: 60
|
51
|
+
{type: 'index', dataField: 'id', text: '#', width: 60},
|
51
52
|
{cellAlign: 'left', dataField: 'firstname', defaultSortDirection: 'ASC', text: 'Firstname', width: 150},
|
52
|
-
{cellAlign: 'left', dataField: 'lastname', defaultSortDirection: 'ASC', text: 'Lastname', width: 150}
|
53
|
+
{cellAlign: 'left', dataField: 'lastname', defaultSortDirection: 'ASC', text: 'Lastname', width: 150},
|
54
|
+
{cellAlign: 'left', dataField: 'countAction', text: 'Increase Counter', width: 150, component: ({record}) => ({
|
55
|
+
module: Button,
|
56
|
+
handler() {record.counter++},
|
57
|
+
text : record.firstname + ' ++',
|
58
|
+
width : 130
|
59
|
+
})},
|
60
|
+
{type: 'animatedChange', dataField: 'counter', text: 'Counter'}
|
53
61
|
];
|
54
62
|
|
55
63
|
for (; i <= value; i++) {
|
@@ -24,9 +24,11 @@ class MainModel extends Model {
|
|
24
24
|
* @protected
|
25
25
|
*/
|
26
26
|
afterSetAmountColumns(value, oldValue) {
|
27
|
-
let i =
|
27
|
+
let i = 6,
|
28
28
|
fields = [
|
29
29
|
{name: 'id', type: 'Int'},
|
30
|
+
{name: 'countAction'},
|
31
|
+
{name: 'counter', type: 'Int'},
|
30
32
|
{name: 'firstname', type: 'String'},
|
31
33
|
{name: 'lastname', type: 'String'}
|
32
34
|
];
|
@@ -113,9 +113,10 @@ class MainStore extends Store {
|
|
113
113
|
column, record;
|
114
114
|
|
115
115
|
for (; row < amountRows; row++) {
|
116
|
-
column =
|
116
|
+
column = 5;
|
117
117
|
record = {
|
118
118
|
id : row + 1,
|
119
|
+
counter : Math.round(Math.random() * 100),
|
119
120
|
firstname: me.firstnames[Math.floor(Math.random() * amountFirstnames)],
|
120
121
|
lastname : me.lastnames[ Math.floor(Math.random() * amountLastnames)]
|
121
122
|
};
|
@@ -43,7 +43,7 @@ class Viewport extends BaseViewport {
|
|
43
43
|
}]
|
44
44
|
}, {
|
45
45
|
module : GridContainer,
|
46
|
-
bind : {store
|
46
|
+
bind : {store: 'stores.mainStore'},
|
47
47
|
reference: 'grid',
|
48
48
|
|
49
49
|
columnDefaults: {
|
@@ -55,7 +55,11 @@ class Viewport extends BaseViewport {
|
|
55
55
|
{dataField: 'user.lastname', text: 'Lastname'},
|
56
56
|
{dataField: 'githubId', text: 'Github Id'},
|
57
57
|
{dataField: 'country', text: 'Country', renderer: 'up.countryRenderer'},
|
58
|
-
{dataField: 'edit', text: 'Edit Action',
|
58
|
+
{dataField: 'edit', text: 'Edit Action', component: {
|
59
|
+
module : Button,
|
60
|
+
handler: 'up.editButtonHandler',
|
61
|
+
text : 'Edit'
|
62
|
+
}}
|
59
63
|
],
|
60
64
|
|
61
65
|
viewConfig: {
|
@@ -72,8 +76,8 @@ class Viewport extends BaseViewport {
|
|
72
76
|
/**
|
73
77
|
* @param {Object} data
|
74
78
|
*/
|
75
|
-
countryRenderer({record}) {
|
76
|
-
let countryStore =
|
79
|
+
countryRenderer({gridContainer, record}) {
|
80
|
+
let countryStore = gridContainer.getStateProvider().getStore('countries');
|
77
81
|
|
78
82
|
if (countryStore.getCount() > 0) {
|
79
83
|
return countryStore.get(record.country).name
|
@@ -111,28 +115,6 @@ class Viewport extends BaseViewport {
|
|
111
115
|
}
|
112
116
|
}
|
113
117
|
|
114
|
-
/**
|
115
|
-
* @param {Object} data
|
116
|
-
*/
|
117
|
-
editRenderer({column, gridContainer, record, rowIndex}) {
|
118
|
-
let me = this,
|
119
|
-
{appName, windowId} = me,
|
120
|
-
widgetId = `${column.id}-widget-${rowIndex}`,
|
121
|
-
button = (column.widgetMap || (column.widgetMap = {}))[widgetId] || (column.widgetMap[widgetId] = Neo.create({
|
122
|
-
module : Button,
|
123
|
-
appName,
|
124
|
-
handler : 'up.editButtonHandler',
|
125
|
-
parentId: gridContainer.id,
|
126
|
-
record,
|
127
|
-
text : 'Edit',
|
128
|
-
windowId
|
129
|
-
}));
|
130
|
-
|
131
|
-
me.view.updateDepth = -1;
|
132
|
-
|
133
|
-
return button.createVdomReference()
|
134
|
-
}
|
135
|
-
|
136
118
|
/**
|
137
119
|
* @param {Object} data
|
138
120
|
*/
|
package/package.json
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
@keyframes grid-animated-cell {
|
2
|
+
50% {background-color:var(--button-ripple-background-color);}
|
3
|
+
}
|
4
|
+
|
5
|
+
.neo-grid-container {
|
6
|
+
.neo-grid-row, .neo-grid-row.neo-even {
|
7
|
+
.neo-grid-cell {
|
8
|
+
&.neo-animated {
|
9
|
+
animation-name : grid-animated-cell;
|
10
|
+
animation-duration : .4s;
|
11
|
+
animation-timing-function: ease-in-out;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}
|
15
|
+
}
|
package/src/DefaultConfig.mjs
CHANGED
@@ -263,12 +263,12 @@ const DefaultConfig = {
|
|
263
263
|
useVdomWorker: true,
|
264
264
|
/**
|
265
265
|
* buildScripts/injectPackageVersion.mjs will update this value
|
266
|
-
* @default '8.
|
266
|
+
* @default '8.29.0'
|
267
267
|
* @memberOf! module:Neo
|
268
268
|
* @name config.version
|
269
269
|
* @type String
|
270
270
|
*/
|
271
|
-
version: '8.
|
271
|
+
version: '8.29.0'
|
272
272
|
};
|
273
273
|
|
274
274
|
Object.assign(DefaultConfig, {
|
package/src/core/Observable.mjs
CHANGED
@@ -67,6 +67,11 @@ class Observable extends Base {
|
|
67
67
|
delete name.once
|
68
68
|
}
|
69
69
|
|
70
|
+
if (name.hasOwnProperty('order')) {
|
71
|
+
order = name.order;
|
72
|
+
delete name.order
|
73
|
+
}
|
74
|
+
|
70
75
|
if (name.hasOwnProperty('scope')) {
|
71
76
|
scope = name.scope;
|
72
77
|
delete name.scope
|
@@ -74,9 +79,9 @@ class Observable extends Base {
|
|
74
79
|
|
75
80
|
Object.entries(name).forEach(([key, value]) => {
|
76
81
|
if (Neo.isObject(value)) {
|
77
|
-
me.addListener(key, {delay, once, scope, ...value})
|
82
|
+
me.addListener(key, {delay, once, order, scope, ...value})
|
78
83
|
} else {
|
79
|
-
me.addListener(key, {delay, fn: value, once, scope})
|
84
|
+
me.addListener(key, {delay, fn: value, once, order, scope})
|
80
85
|
}
|
81
86
|
})
|
82
87
|
} else if (optsType === 'object') {
|
@@ -115,9 +115,7 @@ class SortZone extends BaseSortZone {
|
|
115
115
|
*/
|
116
116
|
moveTo(fromIndex, toIndex) {
|
117
117
|
super.moveTo(fromIndex, toIndex);
|
118
|
-
|
119
|
-
// It is crucial to use _columns to not get a shallow copy
|
120
|
-
NeoArray.move(this.owner.parent._columns, fromIndex, toIndex);
|
118
|
+
this.owner.parent.columns.move(fromIndex, toIndex)
|
121
119
|
}
|
122
120
|
|
123
121
|
/**
|
package/src/grid/Container.mjs
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
import BaseContainer from '../container/Base.mjs';
|
2
2
|
import ClassSystemUtil from '../util/ClassSystem.mjs';
|
3
|
+
import Collection from '../collection/Base.mjs';
|
3
4
|
import GridView from './View.mjs';
|
4
5
|
import ScrollManager from './ScrollManager.mjs';
|
5
6
|
import Store from '../data/Store.mjs';
|
6
7
|
import VerticalScrollbar from './VerticalScrollbar.mjs';
|
8
|
+
import * as column from './column/_export.mjs';
|
7
9
|
import * as header from './header/_export.mjs';
|
8
10
|
|
9
11
|
/**
|
@@ -11,6 +13,17 @@ import * as header from './header/_export.mjs';
|
|
11
13
|
* @extends Neo.container.Base
|
12
14
|
*/
|
13
15
|
class GridContainer extends BaseContainer {
|
16
|
+
/**
|
17
|
+
* @member {Object} columnTypes
|
18
|
+
* @protected
|
19
|
+
* @static
|
20
|
+
*/
|
21
|
+
static columnTypes = {
|
22
|
+
animatedChange: column.AnimatedChange,
|
23
|
+
column : column.Base,
|
24
|
+
component : column.Component,
|
25
|
+
index : column.Index
|
26
|
+
}
|
14
27
|
/**
|
15
28
|
* @member {Object} delayable
|
16
29
|
* @protected
|
@@ -182,7 +195,7 @@ class GridContainer extends BaseContainer {
|
|
182
195
|
|
183
196
|
me.vdom.id = me.getWrapperId();
|
184
197
|
|
185
|
-
me.createColumns(me.columns);
|
198
|
+
me._columns = me.createColumns(me.columns);
|
186
199
|
|
187
200
|
me.addDomListeners({
|
188
201
|
resize: me.onResize,
|
@@ -235,19 +248,15 @@ class GridContainer extends BaseContainer {
|
|
235
248
|
|
236
249
|
/**
|
237
250
|
* Triggered after the columns config got changed
|
238
|
-
* @param {
|
239
|
-
* @param {Object[]|null} oldValue
|
251
|
+
* @param {Neo.collection.Base|null} value
|
252
|
+
* @param {Object[]|Neo.collection.Base|null} oldValue
|
240
253
|
* @protected
|
241
254
|
*/
|
242
255
|
async afterSetColumns(value, oldValue) {
|
243
|
-
if (oldValue?.
|
244
|
-
let me
|
245
|
-
{headerToolbar} = me;
|
256
|
+
if (oldValue?.getCount?.() > 0) {
|
257
|
+
let me = this;
|
246
258
|
|
247
|
-
|
248
|
-
headerToolbar.items = value;
|
249
|
-
headerToolbar.createItems()
|
250
|
-
}
|
259
|
+
me.headerToolbar?.createItems()
|
251
260
|
|
252
261
|
await me.timeout(50);
|
253
262
|
|
@@ -413,41 +422,57 @@ class GridContainer extends BaseContainer {
|
|
413
422
|
createColumns(columns) {
|
414
423
|
let me = this,
|
415
424
|
{columnDefaults} = me,
|
425
|
+
headerButtons = [],
|
416
426
|
sorters = me.store?.sorters,
|
417
|
-
renderer;
|
418
|
-
|
419
|
-
if (!columns || !columns.length) {
|
420
|
-
Neo.logError('Attempting to create a grid.Container without defined columns', me.id);
|
421
|
-
}
|
427
|
+
columnClass, renderer;
|
422
428
|
|
423
|
-
columns
|
429
|
+
columns?.forEach((column, index) => {
|
424
430
|
renderer = column.renderer;
|
425
431
|
|
426
432
|
columnDefaults && Neo.assignDefaults(column, columnDefaults);
|
427
433
|
|
428
|
-
if (column.dock && !column.width) {
|
429
|
-
Neo.logError('Attempting to create a docked column without a defined width', column, me.id);
|
430
|
-
}
|
431
|
-
|
432
434
|
if (renderer && Neo.isString(renderer) && me[renderer]) {
|
433
435
|
column.renderer = me[renderer]
|
434
436
|
}
|
435
437
|
|
436
|
-
if (sorters?.[0]) {
|
437
|
-
|
438
|
-
column.isSorted = sorters[0].direction
|
439
|
-
}
|
438
|
+
if (sorters?.[0] && column.dataField === sorters[0].property) {
|
439
|
+
column.isSorted = sorters[0].direction
|
440
440
|
}
|
441
441
|
|
442
442
|
column.listeners = {
|
443
443
|
sort : me.onSortColumn,
|
444
444
|
scope: me
|
445
|
+
};
|
446
|
+
|
447
|
+
headerButtons.push(column);
|
448
|
+
|
449
|
+
if (column.component && !column.type) {
|
450
|
+
column.type = 'component'
|
445
451
|
}
|
452
|
+
|
453
|
+
columnClass = me.constructor.columnTypes[column.type || 'column'];
|
454
|
+
delete column.type;
|
455
|
+
|
456
|
+
columns[index] = Neo.create(columnClass, {
|
457
|
+
parent : me,
|
458
|
+
windowId: me.windowId,
|
459
|
+
...column
|
460
|
+
})
|
446
461
|
});
|
447
462
|
|
448
|
-
me.items[0].items =
|
463
|
+
me.items[0].items = headerButtons;
|
449
464
|
|
450
|
-
|
465
|
+
if (Neo.typeOf(me._columns) === 'NeoInstance') {
|
466
|
+
me._columns.clear();
|
467
|
+
me._columns.add(columns);
|
468
|
+
|
469
|
+
return me._columns
|
470
|
+
}
|
471
|
+
|
472
|
+
return Neo.create(Collection, {
|
473
|
+
keyProperty: 'dataField',
|
474
|
+
items : columns
|
475
|
+
})
|
451
476
|
}
|
452
477
|
|
453
478
|
/**
|
package/src/grid/View.mjs
CHANGED
@@ -388,7 +388,7 @@ class GridView extends Component {
|
|
388
388
|
fieldValue = ''
|
389
389
|
}
|
390
390
|
|
391
|
-
rendererOutput = column.renderer.call(column.rendererScope ||
|
391
|
+
rendererOutput = column.renderer.call(column.rendererScope || column, {
|
392
392
|
column,
|
393
393
|
columnIndex,
|
394
394
|
dataField,
|
@@ -512,7 +512,7 @@ class GridView extends Component {
|
|
512
512
|
let me = this,
|
513
513
|
{mountedColumns, selectedRows} = me,
|
514
514
|
gridContainer = me.parent,
|
515
|
-
columns
|
515
|
+
{columns} = gridContainer,
|
516
516
|
id = me.getRowId(record, rowIndex),
|
517
517
|
rowCls = me.getRowClass(record, rowIndex),
|
518
518
|
config, column, columnPosition, gridRow, i;
|
@@ -544,7 +544,7 @@ class GridView extends Component {
|
|
544
544
|
};
|
545
545
|
|
546
546
|
for (i=mountedColumns[0]; i <= mountedColumns[1]; i++) {
|
547
|
-
column = columns
|
547
|
+
column = columns.getAt(i);
|
548
548
|
config = me.applyRendererOutput({column, columnIndex: i, record, rowIndex});
|
549
549
|
|
550
550
|
if (column.dock) {
|
@@ -661,17 +661,11 @@ class GridView extends Component {
|
|
661
661
|
* @returns {Object|Number|null}
|
662
662
|
*/
|
663
663
|
getColumn(field, returnIndex=false) {
|
664
|
-
let columns = this.parent
|
665
|
-
|
666
|
-
len = columns.length,
|
667
|
-
column;
|
664
|
+
let {columns} = this.parent,
|
665
|
+
column = columns.get(field);
|
668
666
|
|
669
|
-
|
670
|
-
column
|
671
|
-
|
672
|
-
if (column.dataField === field) {
|
673
|
-
return returnIndex ? i : column
|
674
|
-
}
|
667
|
+
if (column) {
|
668
|
+
return returnIndex ? columns.indexOf(column) : column
|
675
669
|
}
|
676
670
|
|
677
671
|
return null
|
@@ -856,51 +850,42 @@ class GridView extends Component {
|
|
856
850
|
}
|
857
851
|
|
858
852
|
/**
|
859
|
-
*
|
860
|
-
*
|
861
|
-
* @param {
|
862
|
-
* @param {Object
|
863
|
-
* @param {Neo.data.Model} opts.model The model instance of the changed record
|
864
|
-
* @param {Object} opts.record
|
853
|
+
* @param {Object} data
|
854
|
+
* @param {Object[]} data.fields Each field object contains the keys: name, oldValue, value
|
855
|
+
* @param {Neo.data.Model} data.model The model instance of the changed record
|
856
|
+
* @param {Object} data.record
|
865
857
|
*/
|
866
858
|
onStoreRecordChange({fields, record}) {
|
867
|
-
let me
|
868
|
-
fieldNames
|
869
|
-
needsUpdate
|
870
|
-
rowIndex
|
871
|
-
{selectionModel
|
872
|
-
|
859
|
+
let me = this,
|
860
|
+
fieldNames = fields.map(field => field.name),
|
861
|
+
needsUpdate = false,
|
862
|
+
rowIndex = me.store.indexOf(record),
|
863
|
+
{selectionModel} = me,
|
864
|
+
column, needsCellUpdate;
|
873
865
|
|
874
866
|
if (fieldNames.includes(me.colspanField)) {
|
875
867
|
me.vdom.cn[rowIndex] = me.createRow({record, rowIndex});
|
876
868
|
me.update()
|
877
869
|
} else {
|
870
|
+
for (column of me.parent.columns.items) {
|
871
|
+
if (
|
872
|
+
column instanceof Neo.grid.column.Component &&
|
873
|
+
Neo.typeOf(column.component === 'Function') &&
|
874
|
+
!fieldNames.includes(column.dataField)
|
875
|
+
) {
|
876
|
+
needsCellUpdate = me.updateCellNode(record, column.dataField);
|
877
|
+
needsUpdate = needsUpdate || needsCellUpdate
|
878
|
+
}
|
879
|
+
}
|
880
|
+
|
878
881
|
fields.forEach(field => {
|
879
882
|
if (field.name === me.selectedRecordField) {
|
880
883
|
if (selectionModel.ntype === 'selection-grid-rowmodel') {
|
881
884
|
selectionModel[field.value ? 'select' : 'deselect'](me.getRowId(record))
|
882
885
|
}
|
883
886
|
} else {
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
// The vdom might not exist yet => nothing to do in this case
|
888
|
-
if (cellNode?.vdom) {
|
889
|
-
cellStyle = cellNode.vdom.style;
|
890
|
-
column = me.getColumn(field.name);
|
891
|
-
columnIndex = cellNode.index;
|
892
|
-
cellVdom = me.applyRendererOutput({cellId, column, columnIndex, record, rowIndex});
|
893
|
-
needsUpdate = true;
|
894
|
-
|
895
|
-
// The cell-positioning logic happens outside applyRendererOutput()
|
896
|
-
// We need to preserve these styles
|
897
|
-
Object.assign(cellVdom.style, {
|
898
|
-
left : cellStyle.left,
|
899
|
-
width: cellStyle.width
|
900
|
-
});
|
901
|
-
|
902
|
-
cellNode.parentNode.cn[columnIndex] = cellVdom
|
903
|
-
}
|
887
|
+
needsCellUpdate = me.updateCellNode(record, field.name);
|
888
|
+
needsUpdate = needsUpdate || needsCellUpdate
|
904
889
|
}
|
905
890
|
})
|
906
891
|
}
|
@@ -957,6 +942,41 @@ class GridView extends Component {
|
|
957
942
|
}
|
958
943
|
}
|
959
944
|
|
945
|
+
/**
|
946
|
+
* Update the cell vdom silently
|
947
|
+
* @param {Record} record
|
948
|
+
* @param {String} dataField
|
949
|
+
* @returns {Boolean} true in case the view needs an update
|
950
|
+
*/
|
951
|
+
updateCellNode(record, dataField) {
|
952
|
+
let me = this,
|
953
|
+
cellId = me.getCellId(record, dataField),
|
954
|
+
cellNode = VDomUtil.find(me.vdom, cellId),
|
955
|
+
needsUpdate = false,
|
956
|
+
rowIndex = me.store.indexOf(record),
|
957
|
+
cellStyle, cellVdom, column, columnIndex;
|
958
|
+
|
959
|
+
// The vdom might not exist yet => nothing to do in this case
|
960
|
+
if (cellNode?.vdom) {
|
961
|
+
cellStyle = cellNode.vdom.style;
|
962
|
+
column = me.getColumn(dataField);
|
963
|
+
columnIndex = cellNode.index;
|
964
|
+
cellVdom = me.applyRendererOutput({cellId, column, columnIndex, record, rowIndex});
|
965
|
+
needsUpdate = true;
|
966
|
+
|
967
|
+
// The cell-positioning logic happens outside applyRendererOutput()
|
968
|
+
// We need to preserve these styles
|
969
|
+
Object.assign(cellVdom.style, {
|
970
|
+
left : cellStyle.left,
|
971
|
+
width: cellStyle.width
|
972
|
+
});
|
973
|
+
|
974
|
+
cellNode.parentNode.cn[columnIndex] = cellVdom
|
975
|
+
}
|
976
|
+
|
977
|
+
return needsUpdate
|
978
|
+
}
|
979
|
+
|
960
980
|
/**
|
961
981
|
*
|
962
982
|
*/
|
@@ -1013,7 +1033,7 @@ class GridView extends Component {
|
|
1013
1033
|
endIndex = Math.min(countRecords, endIndex + bufferRowRange);
|
1014
1034
|
|
1015
1035
|
me.mountedRows[0] = startIndex; // update the array inline
|
1016
|
-
me.mountedRows[1] = endIndex
|
1036
|
+
me.mountedRows[1] = endIndex
|
1017
1037
|
}
|
1018
1038
|
|
1019
1039
|
/**
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import Column from './Base.mjs';
|
2
|
+
import NeoArray from '../../util/Array.mjs';
|
3
|
+
import VdomUtil from '../../util/VDom.mjs';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* @class Neo.grid.column.AnimatedChange
|
7
|
+
* @extends Neo.grid.column.Base
|
8
|
+
*/
|
9
|
+
class AnimatedChange extends Column {
|
10
|
+
static config = {
|
11
|
+
/**
|
12
|
+
* @member {String} className='Neo.grid.column.AnimatedChange'
|
13
|
+
* @protected
|
14
|
+
*/
|
15
|
+
className: 'Neo.grid.column.AnimatedChange',
|
16
|
+
/**
|
17
|
+
* @member {String} animationCls='neo-animated'
|
18
|
+
*/
|
19
|
+
animationCls: 'neo-animated',
|
20
|
+
/**
|
21
|
+
* @member {String} type='animatedChange'
|
22
|
+
* @protected
|
23
|
+
*/
|
24
|
+
type: 'animatedChange'
|
25
|
+
}
|
26
|
+
|
27
|
+
/**
|
28
|
+
* @param {Object} config
|
29
|
+
*/
|
30
|
+
construct(config) {
|
31
|
+
super.construct(config);
|
32
|
+
|
33
|
+
let me = this;
|
34
|
+
|
35
|
+
me.parent.store.on({
|
36
|
+
recordChange: me.onRecordChange,
|
37
|
+
scope : me
|
38
|
+
})
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Override as needed for dynamic record-based animation classes
|
43
|
+
* @param {Record} record
|
44
|
+
* @returns {String}
|
45
|
+
*/
|
46
|
+
getAnimationCls(record) {
|
47
|
+
return this.animationCls
|
48
|
+
}
|
49
|
+
|
50
|
+
/**
|
51
|
+
* @param {Object} data
|
52
|
+
* @param {Object[]} data.fields Each field object contains the keys: name, oldValue, value
|
53
|
+
* @param {Neo.data.Model} data.model The model instance of the changed record
|
54
|
+
* @param {Object} data.record
|
55
|
+
*/
|
56
|
+
onRecordChange({fields, record}) {
|
57
|
+
let me = this,
|
58
|
+
{view} = me.parent,
|
59
|
+
cellId, field, node;
|
60
|
+
|
61
|
+
for (field of fields) {
|
62
|
+
if (field.name === me.dataField) {
|
63
|
+
cellId = view.getCellId(record, me.dataField);
|
64
|
+
node = VdomUtil.find(view.vdom, cellId)?.vdom;
|
65
|
+
|
66
|
+
NeoArray.add(node.cls, me.getAnimationCls(record));
|
67
|
+
|
68
|
+
// This will trigger a 2nd view update, after grid.View: onStoreRecordChange()
|
69
|
+
// It is crucial to restart the keyframe based animation
|
70
|
+
// => The previous update call will remove the last animationCls
|
71
|
+
view.update();
|
72
|
+
break
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
export default Neo.setupClass(AnimatedChange);
|
@@ -0,0 +1,81 @@
|
|
1
|
+
import Base from '../../core/Base.mjs';
|
2
|
+
import {resolveCallback} from '../../util/Function.mjs';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @class Neo.grid.column.Base
|
6
|
+
* @extends Neo.core.Base
|
7
|
+
*/
|
8
|
+
class Column extends Base {
|
9
|
+
static config = {
|
10
|
+
/**
|
11
|
+
* @member {String} className='Neo.grid.column.Base'
|
12
|
+
* @protected
|
13
|
+
*/
|
14
|
+
className: 'Neo.grid.column.Base',
|
15
|
+
/**
|
16
|
+
* @member {String|null} dataField=null
|
17
|
+
*/
|
18
|
+
dataField: null,
|
19
|
+
/**
|
20
|
+
* @member {Neo.grid.Container|null} parent=null
|
21
|
+
*/
|
22
|
+
parent: null,
|
23
|
+
/**
|
24
|
+
* @member {Function|String|null} renderer_='cellRenderer'
|
25
|
+
*/
|
26
|
+
renderer_: 'cellRenderer',
|
27
|
+
/**
|
28
|
+
* Scope to execute the column renderer.
|
29
|
+
* Defaults to the column instance
|
30
|
+
* @member {Neo.core.Base|null} rendererScope=null
|
31
|
+
*/
|
32
|
+
rendererScope: null,
|
33
|
+
/**
|
34
|
+
* @member {String} type='column'
|
35
|
+
* @protected
|
36
|
+
*/
|
37
|
+
type: 'column',
|
38
|
+
/**
|
39
|
+
* @member {Number|null} windowId_=null
|
40
|
+
*/
|
41
|
+
windowId_: null
|
42
|
+
}
|
43
|
+
|
44
|
+
/**
|
45
|
+
* Triggered after the windowId config got changed
|
46
|
+
* @param {Number} value
|
47
|
+
* @param {Number|null} oldValue
|
48
|
+
* @protected
|
49
|
+
*/
|
50
|
+
afterSetWindowId(value, oldValue) {
|
51
|
+
value && Neo.currentWorker.insertThemeFiles(value, this.__proto__)
|
52
|
+
}
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Triggered before the renderer config gets changed
|
56
|
+
* @param {Function|String|null} value
|
57
|
+
* @param {Function|String|null} oldValue
|
58
|
+
* @protected
|
59
|
+
*/
|
60
|
+
beforeSetRenderer(value, oldValue) {
|
61
|
+
return resolveCallback(value, this).fn
|
62
|
+
}
|
63
|
+
|
64
|
+
/**
|
65
|
+
* @param {Object} data
|
66
|
+
* @param {Neo.button.Base} data.column
|
67
|
+
* @param {Number} data.columnIndex
|
68
|
+
* @param {String} data.dataField
|
69
|
+
* @param {Neo.grid.Container} data.gridContainer
|
70
|
+
* @param {Object} data.record
|
71
|
+
* @param {Number} data.rowIndex
|
72
|
+
* @param {Neo.data.Store} data.store
|
73
|
+
* @param {Number|String} data.value
|
74
|
+
* @returns {*}
|
75
|
+
*/
|
76
|
+
cellRenderer(data) {
|
77
|
+
return data.value
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
export default Neo.setupClass(Column);
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import Button from '../../button/Base.mjs';
|
2
|
+
import Column from './Base.mjs';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @class Neo.grid.column.Component
|
6
|
+
* @extends Neo.grid.column.Base
|
7
|
+
*/
|
8
|
+
class Component extends Column {
|
9
|
+
static config = {
|
10
|
+
/**
|
11
|
+
* @member {String} className='Neo.grid.column.Component'
|
12
|
+
* @protected
|
13
|
+
*/
|
14
|
+
className: 'Neo.grid.column.Component',
|
15
|
+
/**
|
16
|
+
* @member {Function|Object|null} component=null
|
17
|
+
*/
|
18
|
+
component: null,
|
19
|
+
/**
|
20
|
+
* @member {String} type='component'
|
21
|
+
* @protected
|
22
|
+
*/
|
23
|
+
type: 'component'
|
24
|
+
}
|
25
|
+
|
26
|
+
/**
|
27
|
+
* @member {Map} map=new Map()
|
28
|
+
* @protected
|
29
|
+
*/
|
30
|
+
map = new Map()
|
31
|
+
|
32
|
+
/**
|
33
|
+
* @param {Object} data
|
34
|
+
* @param {Neo.button.Base} data.column
|
35
|
+
* @param {Number} data.columnIndex
|
36
|
+
* @param {String} data.dataField
|
37
|
+
* @param {Neo.grid.Container} data.gridContainer
|
38
|
+
* @param {Object} data.record
|
39
|
+
* @param {Number} data.rowIndex
|
40
|
+
* @param {Neo.data.Store} data.store
|
41
|
+
* @param {Number|String} data.value
|
42
|
+
* @returns {*}
|
43
|
+
*/
|
44
|
+
cellRenderer(data) {
|
45
|
+
let {gridContainer, rowIndex} = data,
|
46
|
+
{appName, view, windowId} = gridContainer,
|
47
|
+
me = this,
|
48
|
+
id = `${me.id}-component-${rowIndex % (view.availableRows + 2 * view.bufferRowRange)}`,
|
49
|
+
component = me.map.get(id),
|
50
|
+
componentConfig = me.component;
|
51
|
+
|
52
|
+
if (Neo.typeOf(componentConfig) === 'Function') {
|
53
|
+
componentConfig = componentConfig(data)
|
54
|
+
}
|
55
|
+
|
56
|
+
if (component) {
|
57
|
+
delete componentConfig.className;
|
58
|
+
delete componentConfig.module;
|
59
|
+
delete componentConfig.ntype;
|
60
|
+
|
61
|
+
component.set(componentConfig)
|
62
|
+
} else {
|
63
|
+
component = Neo.create({
|
64
|
+
...componentConfig,
|
65
|
+
appName,
|
66
|
+
id,
|
67
|
+
windowId
|
68
|
+
});
|
69
|
+
|
70
|
+
me.map.set(id, component)
|
71
|
+
}
|
72
|
+
|
73
|
+
view.updateDepth = -1;
|
74
|
+
|
75
|
+
return component.createVdomReference()
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
export default Neo.setupClass(Component);
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import Column from './Base.mjs';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @class Neo.grid.column.Index
|
5
|
+
* @extends Neo.grid.column.Base
|
6
|
+
*/
|
7
|
+
class Index extends Column {
|
8
|
+
static config = {
|
9
|
+
/**
|
10
|
+
* @member {String} className='Neo.grid.column.Index'
|
11
|
+
* @protected
|
12
|
+
*/
|
13
|
+
className: 'Neo.grid.column.Index',
|
14
|
+
/**
|
15
|
+
* @member {String} type='index'
|
16
|
+
* @protected
|
17
|
+
*/
|
18
|
+
type: 'index',
|
19
|
+
/**
|
20
|
+
* @member {Boolean} zeroBased=false
|
21
|
+
*/
|
22
|
+
zeroBased: false
|
23
|
+
}
|
24
|
+
|
25
|
+
/**
|
26
|
+
* @param {Object} data
|
27
|
+
* @param {Neo.button.Base} data.column
|
28
|
+
* @param {Number} data.columnIndex
|
29
|
+
* @param {String} data.dataField
|
30
|
+
* @param {Neo.grid.Container} data.gridContainer
|
31
|
+
* @param {Object} data.record
|
32
|
+
* @param {Number} data.rowIndex
|
33
|
+
* @param {Neo.data.Store} data.store
|
34
|
+
* @param {Number|String} data.value
|
35
|
+
* @returns {*}
|
36
|
+
*/
|
37
|
+
cellRenderer({rowIndex}) {
|
38
|
+
return rowIndex + (this.zeroBased ? 0 : 1)
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
export default Neo.setupClass(Index);
|
@@ -1,7 +1,6 @@
|
|
1
|
-
import BaseButton
|
2
|
-
import NeoArray
|
3
|
-
import TextField
|
4
|
-
import {resolveCallback} from '../../util/Function.mjs';
|
1
|
+
import BaseButton from '../../button/Base.mjs';
|
2
|
+
import NeoArray from '../../util/Array.mjs';
|
3
|
+
import TextField from '../../form/field/Text.mjs';
|
5
4
|
|
6
5
|
/**
|
7
6
|
* @class Neo.grid.header.Button
|
@@ -72,16 +71,6 @@ class Button extends BaseButton {
|
|
72
71
|
* @protected
|
73
72
|
*/
|
74
73
|
isSorted_: null,
|
75
|
-
/**
|
76
|
-
* @member {Function|String|null} renderer_='cellRenderer'
|
77
|
-
*/
|
78
|
-
renderer_: 'cellRenderer',
|
79
|
-
/**
|
80
|
-
* Scope to execute the column renderer.
|
81
|
-
* Defaults to the matching grid.Container
|
82
|
-
* @member {Neo.core.Base|null} rendererScope=null
|
83
|
-
*/
|
84
|
-
rendererScope: null,
|
85
74
|
/**
|
86
75
|
* @member {String} role='columnheader'
|
87
76
|
*/
|
@@ -217,32 +206,6 @@ class Button extends BaseButton {
|
|
217
206
|
return this.beforeSetEnumValue(value, oldValue, 'cellAlign', 'cellAlignValues')
|
218
207
|
}
|
219
208
|
|
220
|
-
/**
|
221
|
-
* Triggered before the renderer config gets changed
|
222
|
-
* @param {Function|String|null} value
|
223
|
-
* @param {Function|String|null} oldValue
|
224
|
-
* @protected
|
225
|
-
*/
|
226
|
-
beforeSetRenderer(value, oldValue) {
|
227
|
-
return resolveCallback(value, this).fn
|
228
|
-
}
|
229
|
-
|
230
|
-
/**
|
231
|
-
* @param {Object} data
|
232
|
-
* @param {Neo.button.Base} data.column
|
233
|
-
* @param {Number} data.columnIndex
|
234
|
-
* @param {String} data.dataField
|
235
|
-
* @param {Neo.grid.Container} data.gridContainer
|
236
|
-
* @param {Object} data.record
|
237
|
-
* @param {Number} data.rowIndex
|
238
|
-
* @param {Neo.data.Store} data.store
|
239
|
-
* @param {Number|String} data.value
|
240
|
-
* @returns {*}
|
241
|
-
*/
|
242
|
-
cellRenderer(data) {
|
243
|
-
return data.value
|
244
|
-
}
|
245
|
-
|
246
209
|
/**
|
247
210
|
*
|
248
211
|
*/
|