neo.mjs 8.43.1 → 9.0.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.
Files changed (48) 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 +5 -6
  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/layout/Base.mjs +3 -2
  31. package/src/layout/Cube.mjs +41 -37
  32. package/src/main/DomEvents.mjs +26 -1
  33. package/src/manager/DomEvent.mjs +21 -22
  34. package/src/selection/Model.mjs +14 -11
  35. package/src/selection/grid/BaseModel.mjs +155 -2
  36. package/src/selection/grid/CellColumnModel.mjs +7 -11
  37. package/src/selection/grid/CellColumnRowModel.mjs +7 -11
  38. package/src/selection/grid/CellModel.mjs +5 -4
  39. package/src/selection/grid/CellRowModel.mjs +22 -30
  40. package/src/selection/grid/ColumnModel.mjs +7 -11
  41. package/src/selection/grid/RowModel.mjs +21 -35
  42. package/src/state/Provider.mjs +3 -8
  43. package/src/tab/Container.mjs +17 -1
  44. package/src/table/Container.mjs +38 -91
  45. package/src/table/View.mjs +51 -3
  46. package/src/table/header/Button.mjs +7 -18
  47. package/src/util/Function.mjs +3 -1
  48. package/src/util/VDom.mjs +4 -4
@@ -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;
@@ -58,12 +58,6 @@ class Container extends BaseContainer {
58
58
  * @protected
59
59
  */
60
60
  scrollbarsCssApplied: false,
61
- /**
62
- * Will get removed in neo v9, assign selection models to table.View instead
63
- * @member {Neo.selection.Model} selectionModel_=null
64
- * @deprecated
65
- */
66
- selectionModel_: null,
67
61
  /**
68
62
  * @member {Boolean} showHeaderFilters_=false
69
63
  */
@@ -139,11 +133,10 @@ class Container extends BaseContainer {
139
133
  sortable : me.sortable,
140
134
  ...me.headerToolbarConfig
141
135
  }, {
142
- module : View,
143
- containerId : me.id,
144
- id : me.viewId,
145
- selectionModel: me.selectionModel, // todo: remove this line in neo v9
146
- store : me.store,
136
+ module : View,
137
+ containerId: me.id,
138
+ id : me.viewId,
139
+ store : me.store,
147
140
  ...me.viewConfig
148
141
  }];
149
142
 
@@ -195,19 +188,6 @@ class Container extends BaseContainer {
195
188
  }
196
189
  }
197
190
 
198
- /**
199
- * Triggered after the selectionModel config got changed
200
- * @param {Neo.selection.Model} value
201
- * @param {Neo.selection.Model} oldValue
202
- * @protected
203
- * @deprecated
204
- */
205
- afterSetSelectionModel(value, oldValue) {
206
- if (value && this.view) {
207
- this.view.selectionModel = value
208
- }
209
- }
210
-
211
191
  /**
212
192
  * Triggered after the showHeaderFilters config got changed
213
193
  * @param {Boolean} value
@@ -232,6 +212,29 @@ class Container extends BaseContainer {
232
212
  }
233
213
  }
234
214
 
215
+ /**
216
+ * Triggered after the store config got changed
217
+ * @param {Number} value
218
+ * @param {Number} oldValue
219
+ * @protected
220
+ */
221
+ afterSetStore(value, oldValue) {
222
+ let me = this,
223
+ listeners = {
224
+ filter: me.onStoreFilter,
225
+ load : me.onStoreLoad,
226
+ scope : me
227
+ };
228
+
229
+ value ?.on(listeners);
230
+ oldValue?.un(listeners);
231
+
232
+ // in case we dynamically change the store, the view needs to get the new reference
233
+ if (me.view) {
234
+ me.view.store = value
235
+ }
236
+ }
237
+
235
238
  /**
236
239
  * Triggered after the useCustomScrollbars config got changed
237
240
  * @param {Boolean} value
@@ -293,35 +296,13 @@ class Container extends BaseContainer {
293
296
 
294
297
  /**
295
298
  * Triggered before the store config gets changed.
296
- * @param {Neo.data.Store} value
297
- * @param {Neo.data.Store} oldValue
299
+ * @param {Object|Neo.data.Store|null} value
300
+ * @param {Neo.data.Store} oldValue
298
301
  * @protected
299
302
  */
300
303
  beforeSetStore(value, oldValue) {
301
- oldValue?.destroy();
302
-
303
304
  if (value) {
304
- let me = this,
305
-
306
- listeners = {
307
- filter : me.onStoreFilter,
308
- load : me.onStoreLoad,
309
- recordChange: me.onStoreRecordChange,
310
- scope : me
311
- };
312
-
313
- if (value instanceof Store) {
314
- value.on(listeners)
315
- } else {
316
- value = ClassSystemUtil.beforeSetInstance(value, Store, {
317
- listeners
318
- })
319
- }
320
-
321
- // in case we dynamically change the store, the view needs to get the new reference
322
- if (me.view) {
323
- me.view.store = value
324
- }
305
+ value = ClassSystemUtil.beforeSetInstance(value, Store)
325
306
  }
326
307
 
327
308
  return value
@@ -404,19 +385,6 @@ class Container extends BaseContainer {
404
385
  return columns
405
386
  }
406
387
 
407
- /**
408
- *
409
- */
410
- createViewData() {
411
- let me = this;
412
-
413
- me.view.createViewData();
414
-
415
- if (me.useCustomScrollbars && me.scrollbarsCssApplied === false) {
416
- me.applyCustomScrollbarsCss()
417
- }
418
- }
419
-
420
388
  /**
421
389
  * @override
422
390
  * @returns {*}
@@ -458,50 +426,29 @@ class Container extends BaseContainer {
458
426
 
459
427
  me.store.sort(opts);
460
428
  me.removeSortingCss(opts.property);
461
- me.onStoreLoad(me.store.items)
429
+ opts.direction && me.view.onStoreLoad()
462
430
  }
463
431
 
464
432
  /**
465
433
  *
466
434
  */
467
435
  onStoreFilter() {
468
- this.onStoreLoad(this.store.items)
436
+ this.onStoreLoad()
469
437
  }
470
438
 
471
439
  /**
472
- * @param {Object[]} data
473
440
  * @protected
474
441
  */
475
- onStoreLoad(data) {
442
+ onStoreLoad() {
476
443
  let me = this;
477
444
 
478
- if (me.rendered) {
479
- me.createViewData();
480
-
481
- if (me.store.sorters.length < 1) {
482
- me.removeSortingCss()
483
- }
484
- } else {
485
- me.on('rendered', () => {
486
- me.timeout(50).then(() => {
487
- me.createViewData()
488
- })
489
- }, me, {once: true})
445
+ if (me.useCustomScrollbars && me.scrollbarsCssApplied === false) {
446
+ me.applyCustomScrollbarsCss()
490
447
  }
491
- }
492
448
 
493
- /**
494
- * Gets triggered after changing the value of a record field.
495
- * E.g. myRecord.foo = 'bar';
496
- * @param {Object} opts
497
- * @param {String} opts.field The name of the field which got changed
498
- * @param {Neo.data.Model} opts.model The model instance of the changed record
499
- * @param {*} opts.oldValue
500
- * @param {Object} opts.record
501
- * @param {*} opts.value
502
- */
503
- onStoreRecordChange(opts) {
504
- this.view.onStoreRecordChange(opts)
449
+ if (me.store.sorters?.length < 1) {
450
+ me.removeSortingCss()
451
+ }
505
452
  }
506
453
 
507
454
  /**
@@ -56,9 +56,9 @@ class View extends Component {
56
56
  */
57
57
  selectedRecordField: 'annotations.selected',
58
58
  /**
59
- * @member {Neo.data.Store|null} store=null
59
+ * @member {Neo.data.Store|null} store_=null
60
60
  */
61
- store: null,
61
+ store_: null,
62
62
  /**
63
63
  * @member {Boolean} useRowRecordIds=true
64
64
  */
@@ -112,6 +112,25 @@ class View extends Component {
112
112
  this.rendered && value.register(this)
113
113
  }
114
114
 
115
+ /**
116
+ * Triggered after the store config got changed
117
+ * @param {Number} value
118
+ * @param {Number} oldValue
119
+ * @protected
120
+ */
121
+ afterSetStore(value, oldValue) {
122
+ let me = this,
123
+ listeners = {
124
+ filter : me.onStoreFilter,
125
+ load : me.onStoreLoad,
126
+ recordChange: me.onStoreRecordChange,
127
+ scope : me
128
+ };
129
+
130
+ oldValue?.un(listeners);
131
+ value ?.on(listeners);
132
+ }
133
+
115
134
  /**
116
135
  * @param {Object} data
117
136
  * @param {String} [data.cellId]
@@ -145,6 +164,8 @@ class View extends Component {
145
164
  fieldValue = ''
146
165
  }
147
166
 
167
+ me.bindCallback(column.renderer, 'renderer', column.rendererScope || tableContainer, column);
168
+
148
169
  rendererOutput = column.renderer.call(column.rendererScope || tableContainer, {
149
170
  column,
150
171
  columnIndex,
@@ -523,6 +544,33 @@ class View extends Component {
523
544
  this.fireRowEvent(data, 'rowDoubleClick')
524
545
  }
525
546
 
547
+ /**
548
+ *
549
+ */
550
+ onStoreFilter() {
551
+ this.onStoreLoad()
552
+ }
553
+
554
+ /**
555
+ * @param {Object[]} data
556
+ * @protected
557
+ */
558
+ onStoreLoad(data) {
559
+ let me = this;
560
+
561
+ me.createViewData();
562
+
563
+ if (me.mounted) {
564
+ me.timeout(50).then(() => {
565
+ Neo.main.DomAccess.scrollTo({
566
+ direction: 'top',
567
+ id : me.vdom.id,
568
+ value : 0
569
+ })
570
+ })
571
+ }
572
+ }
573
+
526
574
  /**
527
575
  * Gets triggered after changing the value of a record field.
528
576
  * E.g. myRecord.foo = 'bar';
@@ -531,7 +579,7 @@ class View extends Component {
531
579
  * @param {Neo.data.Model} opts.model The model instance of the changed record
532
580
  * @param {Object} opts.record
533
581
  */
534
- onStoreRecordChange({fields, model, record}) {
582
+ onStoreRecordChange({fields, record}) {
535
583
  let me = this,
536
584
  fieldNames = fields.map(field => field.name),
537
585
  needsUpdate = false,
@@ -197,25 +197,11 @@ class Button extends BaseButton {
197
197
  * @param {Boolean} oldValue
198
198
  * @protected
199
199
  */
200
- afterSetSortable(value, oldValue) {
200
+ afterSetSortable(value, oldValue) {
201
201
  let me = this,
202
202
  {cls} = me;
203
203
 
204
- if (value === true) {
205
- NeoArray.remove(cls, 'neo-sort-hidden');
206
-
207
- me.addDomListeners({
208
- click: me.onButtonClick,
209
- scope: me
210
- })
211
- } else {
212
- NeoArray.add(cls, 'neo-sort-hidden');
213
-
214
- me.removeDomListeners({
215
- click: me.onButtonClick,
216
- scope: me
217
- })
218
- }
204
+ NeoArray.toggle(cls, 'neo-sort-hidden', !value);
219
205
 
220
206
  me.cls = cls;
221
207
  me.update()
@@ -354,9 +340,10 @@ class Button extends BaseButton {
354
340
  }
355
341
 
356
342
  /**
343
+ * @param {Object} data
357
344
  * @protected
358
345
  */
359
- onButtonClick() {
346
+ onClick(data) {
360
347
  let me = this,
361
348
  map;
362
349
 
@@ -374,7 +361,9 @@ class Button extends BaseButton {
374
361
  }
375
362
  }
376
363
 
377
- me.isSorted = map[me.isSorted + '']
364
+ me.isSorted = map[me.isSorted + ''];
365
+
366
+ super.onClick(data)
378
367
  }
379
368
 
380
369
  /**
@@ -135,10 +135,12 @@ export function intercept(target, targetMethodName, interceptFunction, scope, pr
135
135
  * @returns {Object}
136
136
  */
137
137
  export function resolveCallback(fn, scope=this) {
138
- if (typeof fn === 'string') {
138
+ if (Neo.isString(fn)) {
139
139
  if (!scope[fn] && fn.startsWith('up.')) {
140
140
  fn = fn.slice(3);
141
141
  while (!scope[fn] && (scope = scope.parent));
142
+ } else {
143
+ scope = scope.getController?.()?.getHandlerScope(fn, null) || scope
142
144
  }
143
145
 
144
146
  fn = scope[fn]
package/src/util/VDom.mjs CHANGED
@@ -393,10 +393,10 @@ class VDom extends Base {
393
393
  }
394
394
 
395
395
  if (childNodes) {
396
- cn = childNodes.map(item => VDom.getVdom(item));
397
- cn = cn.filter(item => item.removeDom !== true);
398
- i = 0;
399
- len = cn?.length || 0;
396
+ cn = childNodes.map(item => VDom.getVdom(item));
397
+ cn = cn.filter(item => item.removeDom !== true);
398
+ i = 0;
399
+ len = cn?.length || 0;
400
400
 
401
401
  for (; i < len; i++) {
402
402
  if (vnode.childNodes) {