neo.mjs 7.0.6 → 7.1.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 (73) hide show
  1. package/README.md +2 -2
  2. package/apps/ServiceWorker.mjs +2 -2
  3. package/apps/portal/index.html +1 -1
  4. package/apps/portal/model/Content.mjs +3 -2
  5. package/apps/portal/view/home/FooterContainer.mjs +1 -1
  6. package/apps/portal/view/home/parts/Features.mjs +5 -5
  7. package/examples/ServiceWorker.mjs +2 -2
  8. package/examples/todoList/version2/MainContainer.mjs +38 -48
  9. package/examples/todoList/version2/TodoList.mjs +6 -39
  10. package/examples/todoList/version2/TodoListModel.mjs +1 -1
  11. package/package.json +7 -7
  12. package/resources/data/deck/learnneo/pages/Welcome.md +0 -4
  13. package/resources/data/deck/learnneo/pages/guides/Forms.md +1 -0
  14. package/resources/data/deck/learnneo/pages/guides/InstanceLifecycle.md +1 -0
  15. package/resources/data/deck/learnneo/pages/guides/Layouts.md +1 -0
  16. package/resources/data/deck/learnneo/pages/guides/Mixins.md +1 -0
  17. package/resources/data/deck/learnneo/pages/guides/MultiWindow.md +1 -0
  18. package/resources/data/deck/learnneo/pages/guides/Tables.md +1 -0
  19. package/resources/data/deck/learnneo/pages/guides/events/DomEvents.md +263 -0
  20. package/resources/data/deck/learnneo/pages/{TodoList.md → tutorials/TodoList.md} +23 -33
  21. package/resources/data/deck/learnneo/tree.json +45 -48
  22. package/src/DefaultConfig.mjs +2 -2
  23. package/src/code/LivePreview.mjs +28 -1
  24. package/src/collection/Base.mjs +1 -0
  25. package/src/controller/Component.mjs +10 -10
  26. package/src/core/Observable.mjs +4 -27
  27. package/src/grid/View.mjs +82 -0
  28. package/src/list/Base.mjs +16 -0
  29. package/src/main/addon/DragDrop.mjs +3 -2
  30. package/src/manager/DomEvent.mjs +30 -18
  31. package/src/table/View.mjs +82 -0
  32. package/src/util/Function.mjs +24 -0
  33. package/resources/data/deck/learnneo/pages/2023-10-08T20-37-30-658Z.md +0 -0
  34. package/resources/data/deck/learnneo/pages/2023-10-08T22-22-11-013Z.md +0 -0
  35. package/resources/data/deck/learnneo/pages/Earthquakes-01-goals.md +0 -32
  36. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-01-generate-a-workspace.md +0 -47
  37. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-02-generate-the-starter-app.md +0 -150
  38. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-03-debugging.md +0 -136
  39. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-04-fetch-data.md +0 -146
  40. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-05-refactor-the-table.md +0 -146
  41. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-06-use-a-view-model.md +0 -301
  42. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-07-use-the-google-maps-addon.md +0 -175
  43. package/resources/data/deck/learnneo/pages/Earthquakes-Lab-08-events.md +0 -38
  44. package/resources/data/deck/learnneo/pages/TestLivePreview.md +0 -32
  45. package/resources/data/deck/learnneo/pages/WhatAboutHTML.md +0 -1
  46. package/resources/data/deck/learnneo/pages/stylesheet.md +0 -57
  47. /package/resources/data/deck/learnneo/pages/{WhyNeo-Effort.md → benefits/Effort.md} +0 -0
  48. /package/resources/data/deck/learnneo/pages/{WhyNeo-Features.md → benefits/Features.md} +0 -0
  49. /package/resources/data/deck/learnneo/pages/{WhyNeo-Intro.md → benefits/Introduction.md} +0 -0
  50. /package/resources/data/deck/learnneo/pages/{WhyNeo-Multi-Window.md → benefits/Multi-Window.md} +0 -0
  51. /package/resources/data/deck/learnneo/pages/{WhyNeo-Quick.md → benefits/Quick.md} +0 -0
  52. /package/resources/data/deck/learnneo/pages/{WhyNeo-Speed.md → benefits/Speed.md} +0 -0
  53. /package/resources/data/deck/learnneo/pages/{ComponentModels.md → gettingstarted/ComponentModels.md} +0 -0
  54. /package/resources/data/deck/learnneo/pages/{Config.md → gettingstarted/Config.md} +0 -0
  55. /package/resources/data/deck/learnneo/pages/{DescribingTheUI.md → gettingstarted/DescribingTheUI.md} +0 -0
  56. /package/resources/data/deck/learnneo/pages/{Events.md → gettingstarted/Events.md} +0 -0
  57. /package/resources/data/deck/learnneo/pages/{Extending.md → gettingstarted/Extending.md} +0 -0
  58. /package/resources/data/deck/learnneo/pages/{References.md → gettingstarted/References.md} +0 -0
  59. /package/resources/data/deck/learnneo/pages/{Setup.md → gettingstarted/Setup.md} +0 -0
  60. /package/resources/data/deck/learnneo/pages/{2023-10-14T19-25-08-153Z.md → gettingstarted/Workspaces.md} +0 -0
  61. /package/resources/data/deck/learnneo/pages/{ComponentsAndContainers.md → guides/ComponentsAndContainers.md} +0 -0
  62. /package/resources/data/deck/learnneo/pages/{CustomComponents.md → guides/CustomComponents.md} +0 -0
  63. /package/resources/data/deck/learnneo/pages/{MainThreadAddonExample.md → guides/MainThreadAddonExample.md} +0 -0
  64. /package/resources/data/deck/learnneo/pages/{MainThreadAddonIntro.md → guides/MainThreadAddonIntro.md} +0 -0
  65. /package/resources/data/deck/learnneo/pages/{GuideViewModels.md → guides/ViewModels.md} +0 -0
  66. /package/resources/data/deck/learnneo/pages/{GuideEvents.md → guides/events/CustomEvents.md} +0 -0
  67. /package/resources/data/deck/learnneo/pages/{2023-10-08T20-20-37-336Z.md → javascript/ClassFeatures.md} +0 -0
  68. /package/resources/data/deck/learnneo/pages/{2023-10-07T19-18-28-517Z.md → javascript/Classes.md} +0 -0
  69. /package/resources/data/deck/learnneo/pages/{2023-10-31T13-59-37-550Z.md → javascript/NewNode.md} +0 -0
  70. /package/resources/data/deck/learnneo/pages/{2023-10-08T20-20-07-934Z.md → javascript/Overrides.md} +0 -0
  71. /package/resources/data/deck/learnneo/pages/{2023-10-08T21-58-25-809Z.md → javascript/Super.md} +0 -0
  72. /package/resources/data/deck/learnneo/pages/{Earthquakes.md → tutorials/Earthquakes.md} +0 -0
  73. /package/resources/data/deck/learnneo/pages/{RSP.md → tutorials/RSP.md} +0 -0
@@ -175,64 +175,54 @@ class MainContainer extends Container {
175
175
  className: 'Neo.examples.todoList.version2.MainContainer',
176
176
  style : {padding: '20px'},
177
177
 
178
- // custom configs
179
- idCounter: 3,
180
- store : null
181
- }
182
-
183
- construct(config) {
184
- super.construct(config);
185
-
186
- let me = this;
187
-
188
- me.store = Neo.create({
189
- module: TodoListStore
190
- });
191
-
192
- me.items = [{
178
+ items: [{
193
179
  module : List,
194
180
  displayField : 'text',
195
181
  flex : 1,
196
- store : me.store,
182
+ reference : 'todo-list',
183
+ store : TodoListStore,
197
184
  style : {padding: '5px'},
198
185
  useCheckBoxes: true
199
186
  }, {
200
187
  module: Toolbar,
201
- flex : 'none',
202
188
  dock : 'bottom',
189
+ flex : 'none',
203
190
  items : [{
204
191
  module : TextField,
205
192
  flex : 1,
206
193
  labelPosition: 'inline',
207
194
  labelText : 'Item Text',
208
- reference : 'addItemField'
195
+ reference : 'add-item-field'
209
196
  }, '->', {
210
- handler : me.onAddButtonClick,
211
- handlerScope: me,
212
- scope : me,
213
- style : {height: '27px', marginLeft: '1em'},
214
- text : 'Add Item'
197
+ handler: 'up.onAddButtonClick',
198
+ style : {height: '27px', marginLeft: '1em'},
199
+ text : 'Add Item'
215
200
  }]
216
- }];
201
+ }]
217
202
  }
218
203
 
219
- onAddButtonClick() {
204
+ idCounter = 0
205
+
206
+ /**
207
+ *
208
+ */
209
+ onConstructed() {
210
+ super.onConstructed();
211
+ this.idCounter = this.getReference('todo-list').store.getCount()
212
+ }
213
+
214
+ onAddButtonClick(data) {
220
215
  let me = this,
221
- field = me.down({reference: 'addItemField'}),
222
- data;
216
+ field = me.getReference('add-item-field');
223
217
 
224
218
  if (field.value) {
225
219
  me.idCounter++;
226
220
 
227
- data = me.store.data;
228
-
229
- data.push({
221
+ me.getReference('todo-list').store.add({
230
222
  id : me.idCounter,
231
223
  done: false,
232
224
  text: field.value
233
- });
234
-
235
- me.store.data = data
225
+ })
236
226
  }
237
227
  }
238
228
  }
@@ -1,50 +1,47 @@
1
1
  {"data": [
2
- {"name": "Welcome!", "parentId": null, "isLeaf": true, "id": "Welcome" },
3
- {"name": "Benefits", "parentId": null, "isLeaf": false, "id": "WhyNeo"},
4
- {"name": "Introduction ", "parentId": "WhyNeo", "isLeaf": true, "id": "WhyNeo-Intro"},
5
- {"name": "Off the Main Thread", "parentId": "WhyNeo", "isLeaf": true, "id": "benefits.Multi-Threading"},
6
- {"name": "Extreme Speed", "parentId": "WhyNeo", "isLeaf": true, "id": "WhyNeo-Speed"},
7
- {"name": "Multi-Window Applications", "parentId": "WhyNeo", "isLeaf": true, "id": "WhyNeo-Multi-Window"},
8
- {"name": "Quick Application Development", "parentId": "WhyNeo", "isLeaf": true, "id": "WhyNeo-Quick"},
9
- {"name": "Complexity and Effort", "parentId": "WhyNeo", "isLeaf": true, "id": "WhyNeo-Effort"},
10
- {"name": "Forms Engine", "parentId": "WhyNeo", "isLeaf": true, "id": "benefits.FormsEngine"},
11
- {"name": "Features and Benefits Summary", "parentId": "WhyNeo", "isLeaf": true, "id": "WhyNeo-Features"},
12
- {"name": "Getting Started", "parentId": null, "isLeaf": false, "id": "GettingStarted", "collapsed": true},
13
- {"name": "Setup", "parentId": "GettingStarted", "isLeaf": true, "id": "Setup"},
14
- {"name": "Workspaces and Applications", "parentId": "GettingStarted", "isLeaf": true, "id": "2023-10-14T19-25-08-153Z"},
15
- {"name": "Describing a View", "parentId": "GettingStarted", "isLeaf": true, "id": "DescribingTheUI"},
16
- {"name": "Events", "parentId": "GettingStarted", "isLeaf": true, "id": "Events"},
17
- {"name": "Component References", "parentId": "GettingStarted", "isLeaf": true, "id": "References"},
18
- {"name": "Extending Classes", "parentId": "GettingStarted", "isLeaf": true, "id": "Extending"},
19
- {"name": "Config", "parentId": "GettingStarted", "isLeaf": true, "id": "Config"},
20
- {"name": "Shared Bindable Data", "parentId": "GettingStarted", "isLeaf": true, "id": "ComponentModels"},
21
- {"name": "Tutorials", "parentId": null, "isLeaf": false, "expanded": false, "id": "Tutorials", "collapsed": true},
22
- {"name": "Rock Scissors Paper", "parentId": "Tutorials", "isLeaf": true, "expanded": false, "id": "RSP", "hidden": true},
23
- {"name": "Earthquakes", "parentId": "Tutorials", "isLeaf": true, "expanded": false, "id": "Earthquakes", "collapsed": true},
24
- {"name": "Todo List", "parentId": "Tutorials", "isLeaf": true, "expanded": false, "id": "TodoList"},
25
- {"name": "Guides", "parentId": null, "isLeaf": false, "expanded": false, "id": "InDepth", "collapsed": true},
26
- {"name": "Config", "parentId": "InDepth", "isLeaf": false, "id": "Config"},
27
- {"name": "Instance Lifecycle", "parentId": "InDepth", "isLeaf": false, "id": "InstanceLifecycle", "hidden": true},
28
- {"name": "User Input (Forms)", "parentId": "InDepth", "isLeaf": false, "id": "Forms", "hidden": true},
29
- {"name": "Component and Container Basics", "parentId": "InDepth", "isLeaf": true, "id": "ComponentsAndContainers"},
30
- {"name": "Layouts", "parentId": "InDepth", "isLeaf": false, "id": "Layouts", "hidden": true},
31
- {"name": "View Models", "parentId": "InDepth", "isLeaf": true, "id": "GuideViewModels"},
32
- {"name": "Custom Components", "parentId": "InDepth", "isLeaf": true, "id": "CustomComponents", "hidden": true},
33
- {"name": "Events", "parentId": "InDepth", "isLeaf": true, "expanded": false, "id": "GuideEvents"},
34
- {"name": "Tables (Stores)", "parentId": "InDepth", "isLeaf": false, "id": "Tables", "hidden": true},
35
- {"name": "Shared Bindable Data (Component Models)", "parentId": "InDepth", "isLeaf": false, "id": "InDepthComponentModels", "hidden": true},
36
- {"name": "Multi-Window Applications", "parentId": "InDepth", "isLeaf": false, "id": "MultiWindow", "hidden": true},
37
- {"name": "Main Thread Addons", "parentId": "InDepth", "isLeaf": false, "id": "MainThreadAddons", "hidden": true},
38
- {"name": "Introduction", "parentId": "MainThreadAddons", "isLeaf": true, "id": "MainThreadAddonIntro"},
39
- {"name": "Example", "parentId": "MainThreadAddons", "isLeaf": true, "id": "MainThreadAddonExample"},
40
- {"name": "Mixins", "parentId": "InDepth", "isLeaf": false, "id": "Mixins", "hidden": true},
41
- {"name": "JavaScript Classes", "parentId": null, "isLeaf": false, "id": "JavaScriptClasses", "hidden": true},
42
- {"name": "Classes, Properties, and Methods", "parentId": "JavaScriptClasses", "isLeaf": true, "id": "2023-10-07T19-18-28-517Z"},
43
- {"name": "Overriding Methods", "parentId": "JavaScriptClasses", "isLeaf": true, "id": "2023-10-08T20-20-07-934Z"},
44
- {"name": "Other JavaScript Class Features", "parentId": "JavaScriptClasses", "isLeaf": true, "id": "2023-10-08T20-20-37-336Z"},
45
- {"name": "Super", "parentId": "JavaScriptClasses", "isLeaf": true, "id": "2023-10-08T21-58-25-809Z"},
46
- {"name": "New Node", "parentId": "JavaScriptClasses", "isLeaf": true, "id": "2023-10-31T13-59-37-550Z"},
47
- {"name": "Appendix", "parentId": null, "id": "appendix", "hidden": true, "collapsed": true},
48
- {"name": "Stylesheet", "parentId": "appendix", "isLeaf": true, "id": "stylesheet"},
49
- {"name": "Test", "parentId": "appendix", "isLeaf": true, "id": "TestLivePreview"}
2
+ {"name": "Welcome!", "parentId": null, "id": "Welcome" },
3
+ {"name": "Benefits", "parentId": null, "isLeaf": false, "id": "Benefits"},
4
+ {"name": "Introduction ", "parentId": "Benefits", "id": "benefits.Introduction"},
5
+ {"name": "Off the Main Thread", "parentId": "Benefits", "id": "benefits.Multi-Threading"},
6
+ {"name": "Extreme Speed", "parentId": "Benefits", "id": "benefits.Speed"},
7
+ {"name": "Multi-Window Applications", "parentId": "Benefits", "id": "benefits.Multi-Window"},
8
+ {"name": "Quick Application Development", "parentId": "Benefits", "id": "benefits.Quick"},
9
+ {"name": "Complexity and Effort", "parentId": "Benefits", "id": "benefits.Effort"},
10
+ {"name": "Forms Engine", "parentId": "Benefits", "id": "benefits.FormsEngine"},
11
+ {"name": "Features and Benefits Summary", "parentId": "Benefits", "id": "benefits.Features"},
12
+ {"name": "Getting Started", "parentId": null, "isLeaf": false, "id": "GettingStarted", "collapsed": true},
13
+ {"name": "Setup", "parentId": "GettingStarted", "id": "gettingstarted.Setup"},
14
+ {"name": "Workspaces and Applications", "parentId": "GettingStarted", "id": "gettingstarted.Workspaces"},
15
+ {"name": "Describing a View", "parentId": "GettingStarted", "id": "gettingstarted.DescribingTheUI"},
16
+ {"name": "Events", "parentId": "GettingStarted", "id": "gettingstarted.Events"},
17
+ {"name": "Component References", "parentId": "GettingStarted", "id": "gettingstarted.References"},
18
+ {"name": "Extending Classes", "parentId": "GettingStarted", "id": "gettingstarted.Extending"},
19
+ {"name": "Config", "parentId": "GettingStarted", "id": "gettingstarted.Config"},
20
+ {"name": "Shared Bindable Data", "parentId": "GettingStarted", "id": "gettingstarted.ComponentModels"},
21
+ {"name": "Tutorials", "parentId": null, "isLeaf": false, "id": "Tutorials", "collapsed": true},
22
+ {"name": "Rock Scissors Paper", "parentId": "Tutorials", "id": "tutorials.RSP", "hidden": true},
23
+ {"name": "Earthquakes", "parentId": "Tutorials", "id": "tutorials.Earthquakes"},
24
+ {"name": "Todo List", "parentId": "Tutorials", "id": "tutorials.TodoList"},
25
+ {"name": "Guides", "parentId": null, "isLeaf": false, "id": "InDepth", "collapsed": true},
26
+ {"name": "Instance Lifecycle", "parentId": "InDepth", "id": "guides.InstanceLifecycle", "hidden": true},
27
+ {"name": "User Input (Forms)", "parentId": "InDepth", "id": "guides.Forms", "hidden": true},
28
+ {"name": "Component and Container Basics", "parentId": "InDepth", "id": "guides.ComponentsAndContainers"},
29
+ {"name": "Layouts", "parentId": "InDepth", "isLeaf": false, "id": "guides.Layouts", "hidden": true},
30
+ {"name": "Shared Bindable Data (Component Models)", "parentId": "InDepth", "id": "guides.ViewModels"},
31
+ {"name": "Custom Components", "parentId": "InDepth", "id": "guides.CustomComponents", "hidden": true},
32
+ {"name": "Events", "parentId": "InDepth", "isLeaf": false, "id": "GuideEvents"},
33
+ {"name": "Custom Events", "parentId": "GuideEvents", "id": "guides.events.CustomEvents"},
34
+ {"name": "DOM Events", "parentId": "GuideEvents", "id": "guides.events.DomEvents"},
35
+ {"name": "Tables (Stores)", "parentId": "InDepth", "id": "guides.Tables", "hidden": true},
36
+ {"name": "Multi-Window Applications", "parentId": "InDepth", "id": "guides.MultiWindow", "hidden": true},
37
+ {"name": "Main Thread Addons", "parentId": "InDepth", "isLeaf": false, "id": "MainThreadAddons", "hidden": true},
38
+ {"name": "Introduction", "parentId": "MainThreadAddons", "id": "guides.MainThreadAddonIntro"},
39
+ {"name": "Example", "parentId": "MainThreadAddons", "id": "guides.MainThreadAddonExample"},
40
+ {"name": "Mixins", "parentId": "InDepth", "id": "guides.Mixins", "hidden": true},
41
+ {"name": "JavaScript Classes", "parentId": null, "isLeaf": false, "id": "JavaScript", "hidden": true},
42
+ {"name": "Classes, Properties, and Methods", "parentId": "JavaScript", "id": "javascript.Classes"},
43
+ {"name": "Overriding Methods", "parentId": "JavaScript", "id": "javascript.Overrides"},
44
+ {"name": "Other JavaScript Class Features", "parentId": "JavaScript", "id": "javascript.ClassFeatures"},
45
+ {"name": "Super", "parentId": "JavaScript", "id": "javascript.Super"},
46
+ {"name": "New Node", "parentId": "JavaScript", "id": "javascript.NewNode"}
50
47
  ]}
@@ -262,12 +262,12 @@ const DefaultConfig = {
262
262
  useVdomWorker: true,
263
263
  /**
264
264
  * buildScripts/injectPackageVersion.mjs will update this value
265
- * @default '7.0.6'
265
+ * @default '7.1.0'
266
266
  * @memberOf! module:Neo
267
267
  * @name config.version
268
268
  * @type String
269
269
  */
270
- version: '7.0.6'
270
+ version: '7.1.0'
271
271
  };
272
272
 
273
273
  Object.assign(DefaultConfig, {
@@ -4,6 +4,7 @@ import TabContainer from '../tab/Container.mjs';
4
4
 
5
5
  const
6
6
  classDeclarationRegex = /class\s+([a-zA-Z$_][a-zA-Z0-9$_]*)\s*(?:extends\s+[a-zA-Z$_][a-zA-Z0-9$_]*)?\s*{[\s\S]*?}/g,
7
+ classNameRegex = /className\s*:\s*['"]([^'"]+)['"]/g,
7
8
  exportRegex = /export\s+(?:default\s+)?(?:const|let|var|class|function|async\s+function|generator\s+function|async\s+generator\s+function|(\{[\s\S]*?\}))/g,
8
9
  importRegex = /import\s+([\w-]+)\s+from\s+['"]([^'"]+)['"]/;
9
10
 
@@ -294,6 +295,18 @@ class LivePreview extends Container {
294
295
 
295
296
  container.removeAll();
296
297
 
298
+ // We must ensure that classes inside the editor won't get cached, since this disables run-time changes
299
+ // See: https://github.com/neomjs/neo/issues/5863
300
+ me.findClassNames(codeString).forEach(item => {
301
+ let nsArray = item.split('.'),
302
+ className = nsArray.pop(),
303
+ ns = Neo.ns(nsArray);
304
+
305
+ if (ns) {
306
+ delete ns[className]
307
+ }
308
+ });
309
+
297
310
  try {
298
311
  new Function('container', codeString)(container);
299
312
  } catch (error) {
@@ -304,6 +317,21 @@ class LivePreview extends Container {
304
317
  }
305
318
  }
306
319
 
320
+ /**
321
+ * @param {String} sourceCode
322
+ * @returns {String[]}
323
+ */
324
+ findClassNames(sourceCode) {
325
+ let classNames = [],
326
+ match;
327
+
328
+ while ((match = classNameRegex.exec(sourceCode)) !== null) {
329
+ classNames.push(match[1])
330
+ }
331
+
332
+ return classNames
333
+ }
334
+
307
335
  /**
308
336
  * @param {String} sourceCode
309
337
  * @returns {String|null}
@@ -312,7 +340,6 @@ class LivePreview extends Container {
312
340
  let lastClassName = null,
313
341
  match;
314
342
 
315
- // Iterate through all matches of the regular expression
316
343
  while ((match = classDeclarationRegex.exec(sourceCode)) !== null) {
317
344
  // Update the last class name found
318
345
  lastClassName = match[1]
@@ -76,6 +76,7 @@ class Base extends CoreBase {
76
76
  /**
77
77
  * A map containing the key & reference of each collection item for faster access
78
78
  * @member {Map} map_=null
79
+ * @protected
79
80
  */
80
81
  map_: null,
81
82
  /**
@@ -1,5 +1,6 @@
1
- import Base from './Base.mjs';
2
- import Logger from '../util/Logger.mjs';
1
+ import Base from './Base.mjs';
2
+ import {resolveCallback} from '../util/Function.mjs';
3
+ import Logger from '../util/Logger.mjs';
3
4
 
4
5
  /**
5
6
  * @class Neo.controller.Component
@@ -71,7 +72,7 @@ class Component extends Base {
71
72
 
72
73
  /**
73
74
  * @param {String} handlerName
74
- * @param {Neo.component.Base} component
75
+ * @param {Neo.component.Base} [component]
75
76
  * @returns {Neo.controller.Component|Boolean|null}
76
77
  */
77
78
  getHandlerScope(handlerName, component) {
@@ -81,7 +82,7 @@ class Component extends Base {
81
82
  if (component) {
82
83
  // Look for ths function *name* first in the Component itself.
83
84
  // If we find it, return true so calling code knows not to continue to search.
84
- const handlerCb = component.resolveCallback(handlerName, component);
85
+ const handlerCb = resolveCallback(handlerName, component);
85
86
 
86
87
  // Handler fn is resolved in the Component or its own parent chain.
87
88
  // Return a status indicating that we do not need an early binding
@@ -91,8 +92,7 @@ class Component extends Base {
91
92
  }
92
93
 
93
94
  return Neo.isFunction(me[handlerName]) ?
94
- me : parent ?
95
- parent.getHandlerScope(handlerName) : null
95
+ me : parent?.getHandlerScope(handlerName) || null
96
96
  }
97
97
 
98
98
  /**
@@ -114,7 +114,7 @@ class Component extends Base {
114
114
  {parent} = me;
115
115
 
116
116
  if (parent) {
117
- return parent;
117
+ return parent
118
118
  }
119
119
 
120
120
  return me.component.parent?.getController() || null
@@ -238,9 +238,9 @@ class Component extends Base {
238
238
  if (eventHandler) {
239
239
  scope = me.getHandlerScope(eventHandler);
240
240
 
241
- if (!scope) {
242
- Logger.logError('Unknown domEvent handler for', eventHandler, component)
243
- } else {
241
+ // There can be string based listeners like 'up.onClick', which will resolved inside manager.DomEvents
242
+ // => Do nothing in case there is no match inside the controller hierarchy.
243
+ if (scope) {
244
244
  domListener[key] = scope[eventHandler].bind(scope)
245
245
  }
246
246
  }
@@ -1,4 +1,5 @@
1
- import Base from './Base.mjs';
1
+ import Base from './Base.mjs';
2
+ import {resolveCallback} from '../util/Function.mjs';
2
3
 
3
4
  /**
4
5
  * @class Neo.core.Observable
@@ -136,7 +137,7 @@ class Observable extends Base {
136
137
  */
137
138
  callback(fn, scope=this, args) {
138
139
  if (fn) {
139
- const handler = this.resolveCallback(fn, scope);
140
+ const handler = resolveCallback(fn, scope);
140
141
  handler.fn.apply(handler.scope, args)
141
142
  }
142
143
  }
@@ -172,7 +173,7 @@ class Observable extends Base {
172
173
 
173
174
  // Resolve function name on the scope (or me), or, if it starts with 'up.'
174
175
  // look in the ownership hierarchy from me.
175
- const cb = me.resolveCallback(handler.fn, handler.scope || me);
176
+ const cb = resolveCallback(handler.fn, handler.scope || me);
176
177
 
177
178
  // remove the listener if the scope no longer exists
178
179
  if (cb.scope && !cb.scope.id) {
@@ -338,30 +339,6 @@ class Observable extends Base {
338
339
 
339
340
  // }
340
341
 
341
- /**
342
- * Locate a callable function by name in the passed scope.
343
- *
344
- * If the name starts with 'up.', the parent Component chain is searched.
345
- *
346
- * This is used by Observable.fire and by 'handler' function calls to resolve
347
- * string function names in the Component's own hierarchy.
348
- * @param {Function|String} fn A function, or the name of a function to find in the passed scope object/
349
- * @param {Object} scope The scope to find the function in if it is specified as a string.
350
- * @returns {Object}
351
- */
352
- resolveCallback(fn, scope=this) {
353
- if (typeof fn === 'string') {
354
- if (!scope[fn] && fn.startsWith('up.')) {
355
- fn = fn.slice(3);
356
- while (!scope[fn] && (scope = scope.parent));
357
- }
358
-
359
- fn = scope[fn]
360
- }
361
-
362
- return {fn, scope}
363
- }
364
-
365
342
  /**
366
343
  * Alias for removeListener
367
344
  * @param {Object|String} name
package/src/grid/View.mjs CHANGED
@@ -23,6 +23,27 @@ class View extends Component {
23
23
  baseCls: ['neo-grid-view']
24
24
  }
25
25
 
26
+ /**
27
+ * @param config
28
+ */
29
+ construct(config) {
30
+ super.construct(config);
31
+
32
+ let me = this;
33
+
34
+ me.addDomListeners([{
35
+ click : me.onCellClick,
36
+ dblclick: me.onCellDoubleClick,
37
+ delegate: '.neo-grid-cell',
38
+ scope : me
39
+ }, {
40
+ click : me.onRowClick,
41
+ dblclick: me.onRowDoubleClick,
42
+ delegate: '.neo-grid-row',
43
+ scope : me
44
+ }])
45
+ }
46
+
26
47
  /**
27
48
  * @param {Array} inputData
28
49
  */
@@ -169,6 +190,39 @@ class View extends Component {
169
190
  super.destroy(updateParentVdom, silent)
170
191
  }
171
192
 
193
+ /**
194
+ * @param {Object} data
195
+ * @param {String} eventName
196
+ */
197
+ fireCellEvent(data, eventName) {
198
+ let me = this,
199
+ {id} = data.target,
200
+ dataField = me.getCellDataField(id),
201
+ record = me.getRecord(id);
202
+
203
+ me.parent.fire(eventName, {id: me, data, dataField, record})
204
+ }
205
+
206
+ /**
207
+ * @param {Object} data
208
+ * @param {String} eventName
209
+ */
210
+ fireRowEvent(data, eventName) {
211
+ let me = this,
212
+ {id} = data.target,
213
+ record = me.getRecord(id);
214
+
215
+ me.parent.fire(eventName, {id: me, data, record})
216
+ }
217
+
218
+ /**
219
+ * @param {String} cellId
220
+ * @returns {String}
221
+ */
222
+ getCellDataField(cellId) {
223
+ return cellId.split('__')[2]
224
+ }
225
+
172
226
  /**
173
227
  * @param {Object} record
174
228
  * @param {String} field
@@ -232,6 +286,34 @@ class View extends Component {
232
286
  return ['neo-grid-row']
233
287
  }
234
288
 
289
+ /**
290
+ * @param {Object} data
291
+ */
292
+ onCellClick(data) {
293
+ this.fireCellEvent(data, 'cellClick')
294
+ }
295
+
296
+ /**
297
+ * @param {Object} data
298
+ */
299
+ onCellDoubleClick(data) {
300
+ this.fireCellEvent(data, 'cellDoubleClick')
301
+ }
302
+
303
+ /**
304
+ * @param {Object} data
305
+ */
306
+ onRowClick(data) {
307
+ this.fireRowEvent(data, 'rowClick')
308
+ }
309
+
310
+ /**
311
+ * @param {Object} data
312
+ */
313
+ onRowDoubleClick(data) {
314
+ this.fireRowEvent(data, 'rowDoubleClick')
315
+ }
316
+
235
317
  /**
236
318
  * Gets triggered after changing the value of a record field.
237
319
  * E.g. myRecord.foo = 'bar';
package/src/list/Base.mjs CHANGED
@@ -409,6 +409,22 @@ class Base extends Component {
409
409
  me.cls = cls
410
410
  }
411
411
 
412
+ /**
413
+ * Triggered after the windowId config got changed
414
+ * @param {Number} value
415
+ * @param {Number} oldValue
416
+ * @protected
417
+ */
418
+ afterSetWindowId(value, oldValue) {
419
+ super.afterSetWindowId(value, oldValue);
420
+
421
+ let {navigator} = this;
422
+
423
+ if (navigator) {
424
+ navigator.windowId = value
425
+ }
426
+ }
427
+
412
428
  /**
413
429
  * Triggered before the selectionModel config gets changed.
414
430
  * @param {Neo.selection.Model} value
@@ -153,8 +153,8 @@ class DragDrop extends Base {
153
153
 
154
154
  Promise.all(imports).then(modules => {
155
155
  // create the Mouse- and / or TouchSensor
156
- Neo.create({
157
- module: modules[0].default
156
+ modules.forEach(module => {
157
+ Neo.create({module: module.default})
158
158
  })
159
159
  })
160
160
  }
@@ -461,6 +461,7 @@ class DragDrop extends Base {
461
461
  node;
462
462
 
463
463
  delete data.appName;
464
+ delete data.windowId;
464
465
 
465
466
  if (data.boundaryContainerId) {
466
467
  node = DomAccess.getElementOrBody(data.boundaryContainerId);