neo.mjs 8.43.1 → 9.0.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.
Files changed (46) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/colors/view/ViewportController.mjs +2 -6
  3. package/apps/portal/index.html +1 -1
  4. package/apps/portal/view/ViewportController.mjs +3 -3
  5. package/apps/portal/view/home/FooterContainer.mjs +1 -1
  6. package/apps/portal/view/learn/ContentComponent.mjs +5 -5
  7. package/apps/portal/view/learn/MainContainerController.mjs +0 -23
  8. package/apps/sharedcovid/view/MainContainerController.mjs +4 -13
  9. package/examples/ServiceWorker.mjs +2 -2
  10. package/examples/button/base/MainContainer.mjs +9 -1
  11. package/examples/component/multiWindowCoronaGallery/ViewportController.mjs +4 -11
  12. package/examples/component/multiWindowHelix/ViewportController.mjs +1 -7
  13. package/package.json +5 -5
  14. package/src/DefaultConfig.mjs +2 -2
  15. package/src/button/Base.mjs +28 -7
  16. package/src/component/Base.mjs +43 -86
  17. package/src/component/wrapper/AmChart.mjs +4 -3
  18. package/src/container/Base.mjs +15 -3
  19. package/src/controller/Component.mjs +4 -106
  20. package/src/core/Base.mjs +15 -2
  21. package/src/core/Observable.mjs +9 -11
  22. package/src/data/Model.mjs +9 -0
  23. package/src/data/RecordFactory.mjs +1 -1
  24. package/src/form/field/Text.mjs +3 -1
  25. package/src/grid/Container.mjs +2 -4
  26. package/src/grid/View.mjs +37 -45
  27. package/src/grid/column/AnimatedChange.mjs +1 -1
  28. package/src/grid/column/Component.mjs +14 -5
  29. package/src/grid/header/Button.mjs +6 -17
  30. package/src/main/DomEvents.mjs +26 -1
  31. package/src/manager/DomEvent.mjs +21 -22
  32. package/src/selection/Model.mjs +14 -11
  33. package/src/selection/grid/BaseModel.mjs +155 -2
  34. package/src/selection/grid/CellColumnModel.mjs +7 -11
  35. package/src/selection/grid/CellColumnRowModel.mjs +7 -11
  36. package/src/selection/grid/CellModel.mjs +5 -4
  37. package/src/selection/grid/CellRowModel.mjs +22 -30
  38. package/src/selection/grid/ColumnModel.mjs +7 -11
  39. package/src/selection/grid/RowModel.mjs +21 -35
  40. package/src/state/Provider.mjs +3 -8
  41. package/src/tab/Container.mjs +17 -1
  42. package/src/table/Container.mjs +34 -67
  43. package/src/table/View.mjs +51 -3
  44. package/src/table/header/Button.mjs +7 -18
  45. package/src/util/Function.mjs +3 -1
  46. package/src/util/VDom.mjs +4 -4
@@ -94,17 +94,19 @@ class Model extends Base {
94
94
  * @param {String} [selectedCls]
95
95
  */
96
96
  deselect(item, silent, itemCollection=this.items, selectedCls) {
97
+ let me = this,
98
+ {view} = me,
99
+ node;
100
+
97
101
  // We hold vdom ids for now, so all incoming selections must be converted.
98
102
  item = item.isRecord ? view.getItemId(item) : Neo.isObject(item) ? item.id : item;
99
103
 
100
104
  if (itemCollection.includes(item)) {
101
- let me = this,
102
- {view} = me,
103
- node = view.getVdomChild(item);
105
+ node = view.getVdomChild(item);
104
106
 
105
107
  if (node) {
106
108
  node.cls = NeoArray.remove(node.cls || [], selectedCls || me.selectedCls);
107
- node['aria-selected'] = false
109
+ delete node['aria-selected']
108
110
  }
109
111
 
110
112
  NeoArray.remove(itemCollection, item);
@@ -119,9 +121,8 @@ class Model extends Base {
119
121
  selection: itemCollection
120
122
  })
121
123
  }
122
- }
123
- else if (!silent) {
124
- this.fire('noChange')
124
+ } else if (!silent) {
125
+ me.fire('noChange')
125
126
  }
126
127
  }
127
128
 
@@ -146,8 +147,7 @@ class Model extends Base {
146
147
  me.fire('selectionChange', {
147
148
  selection: this.items
148
149
  })
149
- }
150
- else if (!silent) {
150
+ } else if (!silent) {
151
151
  me.fire('noChange')
152
152
  }
153
153
  }
@@ -225,12 +225,15 @@ class Model extends Base {
225
225
  * @param {String} [selectedCls]
226
226
  */
227
227
  select(items, itemCollection=this.items, selectedCls) {
228
+ if (!Array.isArray(items)) {
229
+ items = [items]
230
+ }
231
+
228
232
  let me = this,
229
233
  {view} = me;
230
234
 
231
235
  // We hold vdom ids for now, so all incoming selections must be converted.
232
- items = (items = Array.isArray(items) ?
233
- items: [items]).map(item => item.isRecord ? view.getItemId(item) : Neo.isObject(item) ? item.id : item);
236
+ items = items.map(item => item.isRecord ? view.getItemId(item) : Neo.isObject(item) ? item.id : item);
234
237
 
235
238
  if (!Neo.isEqual(itemCollection, items)) {
236
239
  if (me.singleSelect && itemCollection === me.items) {
@@ -1,4 +1,5 @@
1
- import Model from '../Model.mjs';
1
+ import Model from '../Model.mjs';
2
+ import NeoArray from '../../util/Array.mjs';
2
3
 
3
4
  /**
4
5
  * Abstract base class for all grid related selection models
@@ -12,7 +13,18 @@ class BaseModel extends Model {
12
13
  * @member {String} className='Neo.selection.grid.BaseModel'
13
14
  * @protected
14
15
  */
15
- className: 'Neo.selection.grid.BaseModel'
16
+ className: 'Neo.selection.grid.BaseModel',
17
+ /**
18
+ * Storing the column dataFields
19
+ * @member {String[]} selectedColumns=[]
20
+ */
21
+ selectedColumns: [],
22
+ /**
23
+ * Storing the record ids
24
+ * @member {Number[]|String[]} selectedRows=[]
25
+ * @protected
26
+ */
27
+ selectedRows: []
16
28
  }
17
29
 
18
30
  /**
@@ -23,6 +35,83 @@ class BaseModel extends Model {
23
35
  return this.view.parent.columns.items.map(column => column.dataField)
24
36
  }
25
37
 
38
+ /**
39
+ * @param {Boolean} [silent=false] true to prevent a vdom update
40
+ */
41
+ deselectAllRows(silent=false) {
42
+ let me = this,
43
+ items = [...me.selectedRows],
44
+ {view} = me;
45
+
46
+ if (items.length) {
47
+ items.forEach(item => {
48
+ me.deselectRow(item, true)
49
+ });
50
+
51
+ if (!silent && items.length > 0) {
52
+ view.update()
53
+ }
54
+
55
+ me.fire('selectionChange', {
56
+ selection: me.selectedRows
57
+ })
58
+ } else if (!silent) {
59
+ me.fire('noChange')
60
+ }
61
+ }
62
+
63
+ /**
64
+ * @param {Number|String} recordId
65
+ * @param {Boolean} [silent=false]
66
+ */
67
+ deselectRow(recordId, silent=false) {
68
+ let me = this,
69
+ {view} = me,
70
+ {store} = view,
71
+ record = store.get(recordId),
72
+ rowId = view.getRowId(store.indexOf(record)),
73
+ node = view.getVdomChild(rowId);
74
+
75
+ if (node) {
76
+ node.cls = NeoArray.remove(node.cls || [], me.selectedCls);
77
+ delete node['aria-selected']
78
+ }
79
+
80
+ me.selectedRows = [recordId];
81
+
82
+ !silent && view.update()
83
+ }
84
+
85
+ /**
86
+ * Get the record for a given event path
87
+ * @param {Object[]} path
88
+ * @returns {Number|String|null}
89
+ */
90
+ getRecord(path) {
91
+ let node, rowIndex;
92
+
93
+ for (node of path) {
94
+ if (node.aria.rowindex) {
95
+ rowIndex = parseInt(node.aria.rowindex);
96
+
97
+ // aria-rowindex is 1 based & also includes the header
98
+ rowIndex -= 2;
99
+
100
+ return this.view.store.getAt(rowIndex)
101
+ }
102
+ }
103
+
104
+ return null
105
+ }
106
+
107
+ /**
108
+ * @param {Record} record
109
+ * @returns {Boolean}
110
+ */
111
+ hasAnnotations(record) {
112
+ return !!Object.getOwnPropertyDescriptor(record.__proto__, this.view.selectedRecordField)
113
+ }
114
+
26
115
  /**
27
116
  * Checks if an event path contains a grid cell editor
28
117
  * @param {Object} data
@@ -38,6 +127,70 @@ class BaseModel extends Model {
38
127
 
39
128
  return false
40
129
  }
130
+
131
+ /**
132
+ * @param {String} dataField
133
+ * @returns {Boolean} true in case the column is selected
134
+ */
135
+ isSelectedColumn(dataField) {
136
+ return this.selectedColumns.includes(dataField)
137
+ }
138
+
139
+ /**
140
+ * @param {Number|String} recordId
141
+ * @returns {Boolean} true in case the row is selected
142
+ */
143
+ isSelectedRow(recordId) {
144
+ return this.selectedRows.includes(recordId)
145
+ }
146
+
147
+ /**
148
+ * @param {Number|String} recordId
149
+ * @param {Boolean} [silent=false]
150
+ */
151
+ selectRow(recordId, silent=false) {
152
+ let me = this,
153
+ {view} = me,
154
+ {store} = view,
155
+ record = store.get(recordId),
156
+ rowId = view.getRowId(store.indexOf(record)),
157
+ node = view.getVdomChild(rowId);
158
+
159
+ if (me.singleSelect) {
160
+ me.deselectAllRows(true)
161
+ }
162
+
163
+ if (node) {
164
+ node.cls = NeoArray.add(node.cls || [], me.selectedCls);
165
+ node['aria-selected'] = true
166
+ }
167
+
168
+ me.selectedRows = [recordId];
169
+
170
+ !silent && view.update()
171
+ }
172
+
173
+ /**
174
+ * @param {Number|String} recordId
175
+ * @param {Boolean} [silent=false]
176
+ */
177
+ toggleRowSelection(recordId, silent=false) {
178
+ this[this.isSelectedRow(recordId) ? 'deselectRow' : 'selectRow'](recordId, silent)
179
+ }
180
+
181
+ /**
182
+ *
183
+ */
184
+ unregister() {
185
+ let me = this,
186
+ countRows = me.selectedRows.length;
187
+
188
+ me.selectedRows = [];
189
+
190
+ countRows > 0 && me.view.createViewData();
191
+
192
+ super.unregister()
193
+ }
41
194
  }
42
195
 
43
196
  export default Neo.setupClass(BaseModel);
@@ -25,24 +25,20 @@ class CellColumnModel extends CellModel {
25
25
  * @member {String} selectedColumnCellCls='selected-column-cell'
26
26
  * @protected
27
27
  */
28
- selectedColumnCellCls: 'selected-column-cell',
29
- /**
30
- * Storing the column dataFields
31
- * @member {String[]} selectedColumns=[]
32
- */
33
- selectedColumns: []
28
+ selectedColumnCellCls: 'selected-column-cell'
34
29
  }
35
30
 
36
31
  /**
37
32
  * @param {Object} data
38
33
  */
39
34
  onCellClick(data) {
40
- let me = this,
41
- {view} = me,
42
- cellId = data.data.currentTarget;
35
+ let me = this,
36
+ {view} = me,
37
+ cellId = data.data.currentTarget,
38
+ dataField = cellId && view.getDataField(cellId);
43
39
 
44
- if (cellId) {
45
- me.selectedColumns = [view.getDataField(cellId)];
40
+ if (dataField) {
41
+ me.selectedColumns = me.isSelected(cellId) ? [] : [dataField];
46
42
  view.createViewData(true)
47
43
  }
48
44
 
@@ -25,24 +25,20 @@ class CellColumnRowModel extends CellRowModel {
25
25
  * @member {String} selectedColumnCellCls='selected-column-cell'
26
26
  * @protected
27
27
  */
28
- selectedColumnCellCls: 'selected-column-cell',
29
- /**
30
- * Storing the column dataFields
31
- * @member {String[]} selectedColumns=[]
32
- */
33
- selectedColumns: []
28
+ selectedColumnCellCls: 'selected-column-cell'
34
29
  }
35
30
 
36
31
  /**
37
32
  * @param {Object} data
38
33
  */
39
34
  onCellClick(data) {
40
- let me = this,
41
- {view} = me,
42
- cellId = data.data.currentTarget;
35
+ let me = this,
36
+ {view} = me,
37
+ cellId = data.data.currentTarget,
38
+ dataField = cellId && view.getDataField(cellId);
43
39
 
44
- if (cellId) {
45
- me.selectedColumns = [view.getDataField(cellId)];
40
+ if (dataField) {
41
+ me.selectedColumns = me.isSelected(cellId) ? [] : [dataField];
46
42
  view.createViewData(true)
47
43
  }
48
44
 
@@ -102,7 +102,7 @@ class CellModel extends BaseModel {
102
102
  newIndex += dataFields.length
103
103
  }
104
104
 
105
- me.select(view.getCellId(record, dataFields[newIndex]));
105
+ me.select(view.getCellId(store.indexOf(record), dataFields[newIndex]));
106
106
 
107
107
  view.parent.scrollByColumns(currentIndex, step)
108
108
  }
@@ -114,6 +114,7 @@ class CellModel extends BaseModel {
114
114
  let me = this,
115
115
  {view} = me,
116
116
  {store} = view,
117
+ countRecords = store.getCount(),
117
118
  currentIndex = 0,
118
119
  dataField, newIndex;
119
120
 
@@ -124,13 +125,13 @@ class CellModel extends BaseModel {
124
125
  dataField = me.dataFields[0]
125
126
  }
126
127
 
127
- newIndex = (currentIndex + step) % store.getCount();
128
+ newIndex = (currentIndex + step) % countRecords;
128
129
 
129
130
  while (newIndex < 0) {
130
- newIndex += store.getCount()
131
+ newIndex += countRecords
131
132
  }
132
133
 
133
- me.select(view.getCellId(store.getAt(newIndex), dataField));
134
+ me.select(view.getCellId(newIndex, dataField));
134
135
  view.scrollByRows(currentIndex, step)
135
136
  }
136
137
 
@@ -20,13 +20,7 @@ class CellRowModel extends CellModel {
20
20
  * @member {String} cls='neo-selection-cellrowmodel'
21
21
  * @protected
22
22
  */
23
- cls: 'neo-selection-cellrowmodel',
24
- /**
25
- * Storing the node ids
26
- * @member {String[]} selectedRows=[]
27
- * @protected
28
- */
29
- selectedRows: []
23
+ cls: 'neo-selection-cellrowmodel'
30
24
  }
31
25
 
32
26
  /**
@@ -35,12 +29,15 @@ class CellRowModel extends CellModel {
35
29
  onCellClick(data) {
36
30
  let me = this,
37
31
  {view} = me,
38
- record = view.getRecord(data.data.currentTarget),
39
- rowId = view.getRowId(record);
32
+ cellId = data.data.currentTarget,
33
+ record = me.getRecord(data.data.path);
40
34
 
41
- if (rowId) {
42
- me.selectedRows = [rowId];
43
- view.createViewData(true)
35
+ if (record) {
36
+ if (me.hasAnnotations(record)) {
37
+ me.updateAnnotations(record)
38
+ } else {
39
+ me[me.isSelected(cellId) ? 'deselectRow' : 'selectRow'](record[view.store.getKeyProperty()], true)
40
+ }
44
41
  }
45
42
 
46
43
  super.onCellClick(data)
@@ -54,35 +51,30 @@ class CellRowModel extends CellModel {
54
51
  {view} = me,
55
52
  {store} = view,
56
53
  countRecords = store.getCount(),
57
- rowId = me.selectedRows[0] || view.getRowId(store.getAt(0)),
58
- record = view.getRecord(rowId),
54
+ keyProperty = store.getKeyProperty(),
55
+ recordId = me.selectedRows[0] || store.getAt(0)[keyProperty],
56
+ record = store.get(recordId),
59
57
  index = store.indexOf(record),
60
- newIndex = (index + step) % countRecords,
61
- id;
58
+ newIndex = (index + step) % countRecords;
62
59
 
63
60
  while (newIndex < 0) {
64
61
  newIndex += countRecords
65
62
  }
66
63
 
67
- id = view.getRowId(store.getAt(newIndex));
64
+ record = store.getAt(newIndex);
68
65
 
69
- if (id) {
70
- me.selectedRows = [id];
71
- view.createViewData(true)
66
+ if (me.hasAnnotations(record)) {
67
+ me.updateAnnotations(record)
68
+ } else {
69
+ recordId = record[keyProperty];
70
+
71
+ if (recordId) {
72
+ me.selectRow(recordId, true) // silent
73
+ }
72
74
  }
73
75
 
74
76
  super.onNavKeyRow(step)
75
77
  }
76
-
77
- /**
78
- *
79
- */
80
- unregister() {
81
- this.selectedRows = [];
82
- this.view.createViewData();
83
-
84
- super.unregister()
85
- }
86
78
  }
87
79
 
88
80
  export default Neo.setupClass(CellRowModel);
@@ -20,12 +20,7 @@ class ColumnModel extends BaseModel {
20
20
  * @member {String} cls='neo-selection-columnmodel'
21
21
  * @protected
22
22
  */
23
- cls: 'neo-selection-columnmodel',
24
- /**
25
- * Storing the column dataFields
26
- * @member {String[]} selectedColumns=[]
27
- */
28
- selectedColumns: []
23
+ cls: 'neo-selection-columnmodel'
29
24
  }
30
25
 
31
26
  /**
@@ -59,12 +54,13 @@ class ColumnModel extends BaseModel {
59
54
  * @param {Object} data
60
55
  */
61
56
  onCellClick(data) {
62
- let me = this,
63
- {view} = me,
64
- cellId = data.data.currentTarget;
57
+ let me = this,
58
+ {view} = me,
59
+ cellId = data.data.currentTarget,
60
+ dataField = cellId && view.getDataField(cellId);
65
61
 
66
- if (cellId) {
67
- me.selectedColumns = [view.getDataField(cellId)];
62
+ if (dataField) {
63
+ me.selectedColumns = me.isSelectedColumn(dataField) ? [] : [dataField];
68
64
  view.createViewData()
69
65
  }
70
66
  }
@@ -43,14 +43,6 @@ class RowModel extends BaseModel {
43
43
  super.destroy(...args)
44
44
  }
45
45
 
46
- /**
47
- * @param {Record} record
48
- * @returns {Boolean}
49
- */
50
- hasAnnotations(record) {
51
- return !!Object.getOwnPropertyDescriptor(record.__proto__, this.view.selectedRecordField)
52
- }
53
-
54
46
  /**
55
47
  * @param {Object} data
56
48
  */
@@ -73,14 +65,11 @@ class RowModel extends BaseModel {
73
65
  {view} = me,
74
66
  {store} = view,
75
67
  countRecords = store.getCount(),
76
- currentIndex = 0,
77
- newIndex, record, rowId;
78
-
79
- if (me.hasSelection()) {
80
- currentIndex = store.indexOf(view.getRecordByRowId(me.items[0]))
81
- }
82
-
83
- newIndex = (currentIndex + step) % countRecords;
68
+ keyProperty = store.getKeyProperty(),
69
+ recordId = me.selectedRows[0] || store.getAt(0)[keyProperty],
70
+ record = store.get(recordId),
71
+ index = store.indexOf(record),
72
+ newIndex = (index + step) % countRecords;
84
73
 
85
74
  while (newIndex < 0) {
86
75
  newIndex += countRecords
@@ -91,12 +80,12 @@ class RowModel extends BaseModel {
91
80
  if (me.hasAnnotations(record)) {
92
81
  me.updateAnnotations(record)
93
82
  } else {
94
- rowId = view.getRowId(record);
83
+ recordId = record[keyProperty];
95
84
 
96
- if (rowId) {
97
- me.select(rowId);
85
+ if (recordId) {
86
+ me.selectRow(recordId);
98
87
 
99
- view.scrollByRows(currentIndex, step);
88
+ view.scrollByRows(index, step);
100
89
  view.fire('select', {record})
101
90
  }
102
91
  }
@@ -105,25 +94,21 @@ class RowModel extends BaseModel {
105
94
  /**
106
95
  * @param {Object} data
107
96
  */
108
- onRowClick(data) {
97
+ onRowClick({data}) {
109
98
  let me = this,
110
- id = data.data.currentTarget,
111
99
  {view} = me,
112
- isSelected, record;
113
-
114
- if (id) {
115
- record = view.getRecord(id);
100
+ record = me.getRecord(data.path),
101
+ recordId;
116
102
 
103
+ if (record) {
117
104
  if (me.hasAnnotations(record)) {
118
105
  me.updateAnnotations(record)
119
106
  } else {
120
- me.toggleSelection(id);
121
-
122
- isSelected = me.isSelected(id);
107
+ recordId = record[view.store.getKeyProperty()];
123
108
 
124
- !isSelected && view.onDeselect?.(record);
109
+ me.toggleRowSelection(recordId);
125
110
 
126
- view.fire(isSelected ? 'select' : 'deselect', {record})
111
+ view.fire(me.isSelectedRow(recordId) ? 'select' : 'deselect', {record})
127
112
  }
128
113
  }
129
114
  }
@@ -162,17 +147,18 @@ class RowModel extends BaseModel {
162
147
  updateAnnotations(record) {
163
148
  let me = this,
164
149
  {view} = me,
165
- rowId = view.getRowId(record),
166
- isSelected = me.isSelected(rowId),
150
+ {store} = view,
151
+ recordId = record[store.getKeyProperty()],
152
+ isSelected = me.isSelectedRow(recordId),
167
153
  annotationsField = view.selectedRecordField;
168
154
 
169
155
  if (me.singleSelect) {
170
156
  if (isSelected) {
171
157
  record[annotationsField] = false
172
158
  } else {
173
- me.items.forEach(rowId => {
159
+ me.selectedRows.forEach(recordId => {
174
160
  // We can use setSilent(), since the last change will trigger a view update
175
- view.getRecordByRowId(rowId).setSilent({[annotationsField]: false})
161
+ store.get(recordId).setSilent({[annotationsField]: false})
176
162
  });
177
163
 
178
164
  record[annotationsField] = true
@@ -155,17 +155,12 @@ class Provider extends Base {
155
155
  */
156
156
  beforeSetStores(value, oldValue) {
157
157
  if (value) {
158
- let me = this,
159
- controller = me.getController();
158
+ let me = this;
160
159
 
161
160
  Object.entries(value).forEach(([key, storeValue]) => {
162
- controller?.parseConfig(storeValue);
163
-
164
161
  // support mapping string based listeners into the stateProvider instance
165
- Object.entries(storeValue.listeners || {}).forEach(([listenerKey,listener]) => {
166
- if (Neo.isString(listener) && Neo.isFunction(me[listener])) {
167
- storeValue.listeners[listenerKey] = me[listener].bind(me)
168
- }
162
+ Object.entries(storeValue.listeners || {}).forEach(([listenerKey, listener]) => {
163
+ me.bindCallback(listener, listenerKey, me, storeValue.listeners)
169
164
  })
170
165
 
171
166
  value[key] = ClassSystemUtil.beforeSetInstance(storeValue)
@@ -281,7 +281,23 @@ class Container extends BaseContainer {
281
281
  items : tabComponents,
282
282
  layout : {ntype: 'card', activeIndex: me.activeIndex, removeInactiveCards: me.removeInactiveCards},
283
283
  useActiveTabIndicator: me.useActiveTabIndicator,
284
- ...me.contentContainer
284
+ ...me.contentContainer,
285
+
286
+ insert(index, item, silent) {
287
+ if (item?.isTab) {
288
+ me.insert(index, item, silent)
289
+ } else {
290
+ super.insert(index, item, silent)
291
+ }
292
+ },
293
+
294
+ remove(component, destroyItem, silent) {
295
+ if (component?.isTab) {
296
+ me.remove(component, destroyItem, silent)
297
+ } else {
298
+ super.remove(component, destroyItem, silent)
299
+ }
300
+ }
285
301
  }];
286
302
 
287
303
  me.itemDefaults = null;