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
@@ -1,9 +1,10 @@
1
- import Base from '../core/Base.mjs';
2
- import ComponentManager from './Component.mjs';
3
- import FocusManager from './Focus.mjs';
4
- import Logger from '../util/Logger.mjs';
5
- import NeoArray from '../util/Array.mjs';
6
- import VDomUtil from '../util/VDom.mjs';
1
+ import Base from '../core/Base.mjs';
2
+ import ComponentManager from './Component.mjs';
3
+ import FocusManager from './Focus.mjs';
4
+ import Logger from '../util/Logger.mjs';
5
+ import NeoArray from '../util/Array.mjs';
6
+ import {resolveCallback} from '../util/Function.mjs';
7
+ import VDomUtil from '../util/VDom.mjs';
7
8
 
8
9
  const eventConfigKeys = [
9
10
  'bubble',
@@ -192,10 +193,12 @@ class DomEvent extends Base {
192
193
  */
193
194
  generateListenerConfig(config, scope) {
194
195
  return {
196
+ bubble : config.bubble,
195
197
  delegate : config.delegate,
196
198
  eventName: config.eventName,
197
199
  id : scope.id,
198
200
  opts : config,
201
+ priority : config.priority,
199
202
  scope : config.scope || scope,
200
203
  vnodeId : config.vnodeId || scope.id
201
204
  };
@@ -217,6 +220,7 @@ class DomEvent extends Base {
217
220
 
218
221
  /**
219
222
  * @param {Object} config
223
+ * @param {Boolean} config.bubble
220
224
  * @param {String} config.delegate
221
225
  * @param {String} config.eventName
222
226
  * @param {String} config.id
@@ -264,9 +268,10 @@ class DomEvent extends Base {
264
268
 
265
269
  if (localEvents.length > 0) {
266
270
  Neo.worker.App.promiseMessage('main', {
267
- action : 'addDomListener',
268
- appName: component.appName,
269
- events : localEvents
271
+ action : 'addDomListener',
272
+ appName : component.appName,
273
+ events : localEvents,
274
+ windowId: component.windowId
270
275
  }).then(data => {
271
276
  // console.log('added domListener', data);
272
277
  }).catch(err => {
@@ -278,6 +283,7 @@ class DomEvent extends Base {
278
283
 
279
284
  /**
280
285
  * @param {Object} config
286
+ * @param {Boolean} config.bubble
281
287
  * @param {String} config.delegate
282
288
  * @param {String} config.eventName
283
289
  * @param {String} config.id
@@ -285,20 +291,23 @@ class DomEvent extends Base {
285
291
  * @param {Number} config.opts
286
292
  * @param {Number} config.originalConfig
287
293
  * @param {String} config.ownerId
288
- * @param {Number} config.priority
294
+ * @param {Number} config.priority=1
289
295
  * @param {Object} config.scope
290
296
  * @param {String} config.vnodeId
291
297
  * @returns {Boolean} true if the listener got registered successfully (false in case it was already there)
292
298
  */
293
299
  register(config) {
294
- let alreadyRegistered = false,
300
+ let me = this,
301
+ alreadyRegistered = false,
295
302
  {eventName, id, opts, scope} = config,
296
- listeners = this.items,
303
+ listeners = me.items,
297
304
  fnType = typeof opts,
298
305
  fn, listener, listenerConfig, listenerId;
299
306
 
300
- if (fnType === 'function' || fnType === 'string') {
307
+ if (fnType === 'function') {
301
308
  fn = opts
309
+ } else if (fnType === 'string') {
310
+ fn = resolveCallback(opts, scope).fn
302
311
  } else {
303
312
  fn = opts.fn;
304
313
  scope = opts.scope || scope
@@ -343,22 +352,23 @@ class DomEvent extends Base {
343
352
  mounted : !config.local && globalDomEvents.includes(eventName),
344
353
  originalConfig: config.originalConfig,
345
354
  ownerId : config.ownerId,
346
- priority : config.priority || 1,
355
+ priority : config.priority || opts.priority || 1,
347
356
  scope,
348
357
  vnodeId : config.vnodeId
349
358
  };
350
359
 
351
- this.map[listenerId] = listenerConfig;
360
+ me.map[listenerId] = listenerConfig;
352
361
 
353
362
  listeners[id][eventName].push(listenerConfig);
354
363
 
355
- listeners[id][eventName].sort((a, b) => a.priority > b.priority);
364
+ listeners[id][eventName].sort((a, b) => b.priority - a.priority);
356
365
 
357
366
  return true
358
367
  }
359
368
 
360
369
  /**
361
370
  * @param {Object} config
371
+ * @param {Boolean} config.bubble
362
372
  * @param {String} config.eventName
363
373
  * @param {String} config.id
364
374
  * @param {Object} config.opts
@@ -414,14 +424,16 @@ class DomEvent extends Base {
414
424
  Object.entries(domListener).forEach(([key, value]) => {
415
425
  if (!eventConfigKeys.includes(key)) {
416
426
  me.register({
427
+ bubble : domListener.bubble || value.bubble,
417
428
  delegate : domListener.delegate || value.delegate || '#' + component.id,
418
429
  eventName : key,
419
430
  id : component.id,
420
431
  opts : value,
421
432
  originalConfig: domListener,
422
433
  ownerId : component.id,
423
- scope : domListener.scope || component,
424
- vnodeId : domListener.vnodeId || value.vnodeId || component.id
434
+ priority : domListener.priority || value.priority || 1,
435
+ scope : domListener.scope || component,
436
+ vnodeId : domListener.vnodeId || value.vnodeId || component.id
425
437
  })
426
438
  }
427
439
  })
@@ -50,6 +50,27 @@ class View extends Component {
50
50
  {tag: 'tbody', cn: []}
51
51
  }
52
52
 
53
+ /**
54
+ * @param config
55
+ */
56
+ construct(config) {
57
+ super.construct(config);
58
+
59
+ let me = this;
60
+
61
+ me.addDomListeners([{
62
+ click : me.onCellClick,
63
+ dblclick: me.onCellDoubleClick,
64
+ delegate: '.neo-table-cell',
65
+ scope : me
66
+ }, {
67
+ click : me.onRowClick,
68
+ dblclick: me.onRowDoubleClick,
69
+ delegate: '.neo-table-row',
70
+ scope : me
71
+ }])
72
+ }
73
+
53
74
  /**
54
75
  * @param {Object} data
55
76
  * @param {String} [data.cellId]
@@ -246,6 +267,39 @@ class View extends Component {
246
267
  super.destroy(...args)
247
268
  }
248
269
 
270
+ /**
271
+ * @param {Object} data
272
+ * @param {String} eventName
273
+ */
274
+ fireCellEvent(data, eventName) {
275
+ let me = this,
276
+ {id} = data.target,
277
+ dataField = me.getCellDataField(id),
278
+ record = me.getRecord(id);
279
+
280
+ me.parent.fire(eventName, {id: me, data, dataField, record})
281
+ }
282
+
283
+ /**
284
+ * @param {Object} data
285
+ * @param {String} eventName
286
+ */
287
+ fireRowEvent(data, eventName) {
288
+ let me = this,
289
+ {id} = data.target,
290
+ record = me.getRecord(id);
291
+
292
+ me.parent.fire(eventName, {id: me, data, record})
293
+ }
294
+
295
+ /**
296
+ * @param {String} cellId
297
+ * @returns {String}
298
+ */
299
+ getCellDataField(cellId) {
300
+ return cellId.split('__')[2]
301
+ }
302
+
249
303
  /**
250
304
  * @param {Object} record
251
305
  * @param {String} dataField
@@ -341,6 +395,34 @@ class View extends Component {
341
395
  return ['neo-table-row']
342
396
  }
343
397
 
398
+ /**
399
+ * @param {Object} data
400
+ */
401
+ onCellClick(data) {
402
+ this.fireCellEvent(data, 'cellClick')
403
+ }
404
+
405
+ /**
406
+ * @param {Object} data
407
+ */
408
+ onCellDoubleClick(data) {
409
+ this.fireCellEvent(data, 'cellDoubleClick')
410
+ }
411
+
412
+ /**
413
+ * @param {Object} data
414
+ */
415
+ onRowClick(data) {
416
+ this.fireRowEvent(data, 'rowClick')
417
+ }
418
+
419
+ /**
420
+ * @param {Object} data
421
+ */
422
+ onRowDoubleClick(data) {
423
+ this.fireRowEvent(data, 'rowDoubleClick')
424
+ }
425
+
344
426
  /**
345
427
  * Gets triggered after changing the value of a record field.
346
428
  * E.g. myRecord.foo = 'bar';
@@ -123,6 +123,30 @@ export function intercept(target, targetMethodName, interceptFunction, scope, pr
123
123
  })
124
124
  }
125
125
 
126
+ /**
127
+ * Locate a callable function by name in the passed scope.
128
+ *
129
+ * If the name starts with 'up.', the parent Component chain is searched.
130
+ *
131
+ * This is used by manager.DomEvents & core.Observable.fire and by 'handler' function calls to resolve
132
+ * string function names in the Component's own hierarchy.
133
+ * @param {Function|String} fn A function, or the name of a function to find in the passed scope object/
134
+ * @param {Object} scope=this The scope to find the function in if it is specified as a string.
135
+ * @returns {Object}
136
+ */
137
+ export function resolveCallback(fn, scope=this) {
138
+ if (typeof fn === 'string') {
139
+ if (!scope[fn] && fn.startsWith('up.')) {
140
+ fn = fn.slice(3);
141
+ while (!scope[fn] && (scope = scope.parent));
142
+ }
143
+
144
+ fn = scope[fn]
145
+ }
146
+
147
+ return {fn, scope}
148
+ }
149
+
126
150
  /**
127
151
  * @param {Function} callback
128
152
  * @param {Neo.core.Base} scope
@@ -1,32 +0,0 @@
1
- In this topic you'll create an application that fetches data on earthquakes in Iceland,
2
- and show the information in two views: a table, and a map.
3
- You'll do this in a series of simple labs.
4
-
5
- What are the goals of this lengthy topic?
6
-
7
- - To give you hands-on coding a simple app
8
- - To introduce fundamental Neo concepts
9
-
10
- Most of these labs are copy-and-paste because we're focusing on _what_ the code is doing on rather than _how_.
11
-
12
- For this tutorial don't worry about syntax details. Other tutorials and guides will spend more and
13
- more time on syntax.e
14
-
15
- ## Key concepts
16
-
17
- A few key concepts we'll be discussing:
18
-
19
- - Creating a starter app
20
- - Configuring components
21
- - Debugging
22
- - Class-based coding
23
- - View models
24
- - Events
25
- - Controllers
26
-
27
- ## Advice
28
-
29
- A word of advice: Keep a high-level perspective, especially early on. We'll have plenty of time to get
30
- into the code, and we'll do most things multiple times. In other words, focus on what you're accomplishing,
31
- and don't worry about syntax details.
32
-
@@ -1,47 +0,0 @@
1
- In this lab, you'll generate a Neo.mjs workspace and run the starter app.
2
-
3
- <details>
4
- <summary>Wait!</summary>
5
- You may already have a workspace! If so, you can skip this lab. For example, if you followed the <a href="#/learn/Setup">Getting Started > Setup</a> topic, above, you should already have a workspace.
6
-
7
- If you don't have a workspace, then continue on to the next step.
8
- </details>
9
-
10
- <details>
11
- <summary>Use the command-line to generate the workspace</summary>
12
-
13
- Use a terminal window to navigate to some parent folder,
14
- then run
15
-
16
- npx neo-app@latest
17
-
18
- You'll be prompted for a workspace name, starter app name, etc &mdash; accept the default for everything.
19
- As the command finishes it starts a server and opens a browser window.
20
- </details>
21
-
22
- <details>
23
- <summary>Inspect the workspace</summary>
24
-
25
- The workspace contains a local copy of the API docs, an `apps` directory (where your apps are found),
26
- and some other directories.
27
- </details>
28
-
29
- <details>
30
- <summary>Start the server</summary>
31
- From the root of the `workspace` start the server via `npm run server-start`. That starts a server
32
- at port 8080 and opens a new browser window.
33
-
34
- <img src="https://s3.amazonaws.com/mjs.neo.learning.images/earthquakes/StartServer.png" style="width:80%"/>
35
-
36
- </details>
37
-
38
-
39
- <details>
40
- <summary>Run the starter app</summary>
41
-
42
- By default, an app named `myapp` was created. You can run it by entering the `apps` directory and
43
- clicking `myapp`. It's a folder containing an `index.html` along with the source code for the app.
44
-
45
- <img src="https://s3.amazonaws.com/mjs.neo.learning.images/earthquakes/RunTheStarterApp.png" style="width:80%"/>
46
-
47
- </details>
@@ -1,150 +0,0 @@
1
- In this lab you'll create a starter app and add a single component.
2
-
3
- <details>
4
-
5
- <summary>Use the command-line to create a starter app</summary>
6
-
7
- Use a terminal window to navigate to the workspace and run the following script. Use "Earthquakes"
8
- as the app name, and defaults for everything else.
9
-
10
- npm run create-app-minimal
11
-
12
- After the script runs yous should see these files in the `app/earthquakes` directory.
13
-
14
- `view/MainContainer.mjs`
15
- - `app.mjs`
16
- - `index.html`
17
- - `neo-config.json`
18
-
19
- If you look in `neo-config.json` you should see this content. Note the `mainThreadAddons` block
20
- &mdash; it reflects the add-ons you chose when you followed the instructions in the script.
21
- <pre>
22
- {
23
- "appPath": "../../apps/earthquakes/app.mjs",
24
- "basePath": "../../",
25
- "environment": "development",
26
- "mainPath": "../node_modules/neo.mjs/src/Main.mjs",
27
- "mainThreadAddons": [
28
- "DragDrop",
29
- "Stylesheet"
30
- ],
31
- "workerBasePath": "../../node_modules/neo.mjs/src/worker/"
32
- }</pre>
33
-
34
- You're free to edit `neo-config.json` if you were to change your mind later about the theme or need for other add-ons.
35
-
36
- If you refresh browser at <a href="http://localhost:8080/apps/" target="apps">http://localhost:8080/apps/</a>
37
- you'll see the new _earthquakes_ app listed, and if you run it you'll see... nothing! That's because the
38
- minimal starter app is the shell of an application without any view content. We'll add a little content
39
- later in the lab.
40
-
41
- <img style="width:80%" src="https://s3.amazonaws.com/mjs.neo.learning.images/earthquakes/EmptyEarthquakes.png"></img>
42
-
43
- </details>
44
-
45
- <details>
46
- <summary>Look at the main view source</summary>
47
-
48
- Use a code editor and look at `workspace/apps/earthquakes/src/view/MainView.mjs`. You'll see the
49
- following class definition:
50
-
51
- <pre data-javascript>
52
-
53
- import Base from '../../../node_modules/neo.mjs/src/container/Base.mjs';
54
- import Controller from './MainViewController.mjs';
55
- import ViewModel from './MainViewModel.mjs';
56
-
57
- class MainView extends Base {
58
- static config = {
59
- className: 'Earthquakes.view.MainView',
60
- ntype: 'earthquakes-main',
61
-
62
- controller: {module: Controller},
63
- model: {module: ViewModel},
64
-
65
- layout: {ntype: 'fit'},
66
- items: [],
67
- }
68
- }
69
-
70
- Neo.setupClass(MainView);
71
-
72
- export default MainView;
73
- </pre>
74
-
75
- As you can see, `MainView extends Base`, and `Base` is a _container_ (`Neo.container.Base`).
76
- A container is a component &mdash; it holds other components, specified in `items:[]`. There
77
- are no items in the starter app. The `layout` config specifies how the items are arranged.
78
-
79
- </details>
80
-
81
- <details>
82
- <summary>Add a component</summary>
83
-
84
- Let's add a button. To do that, add an import for the button base class, then configure it
85
- in the container's `items:[]`. If you were to read the API docs for buttons, you'd see
86
- that buttons have various configs, such as `text`, which is the button text, `iconCls`, which
87
- is typically a FontAwesome CSS class used to show an icon, and `handler`, which specifies
88
- which method to run when the button is clicked. We'll use `text`.
89
-
90
- <pre data-javascript>
91
-
92
- import Base from '../../../node_modules/neo.mjs/src/container/Base.mjs';
93
- import Button from '../../../node_modules/neo.mjs/src/button/Base.mjs';
94
- import Controller from './MainViewController.mjs';
95
- import ViewModel from './MainViewModel.mjs';
96
-
97
- class MainView extends Base {
98
- static config = {
99
- className: 'Earthquakes.view.MainView',
100
- ntype: 'earthquakes-main',
101
-
102
- controller: {module: Controller},
103
- model: {module: ViewModel},
104
-
105
- layout: {ntype: 'fit'},
106
- items: [{
107
- module: Button,
108
- text: 'Button!'
109
- }],
110
- }
111
- }
112
-
113
- Neo.setupClass(MainView);
114
-
115
- export default MainView;
116
- </pre>
117
-
118
-
119
- When you run the app you'll see the single button.
120
-
121
- <img src="https://s3.amazonaws.com/mjs.neo.learning.images/earthquakes/EarthquakesSingleFitButton.png" style="width:80%"/>
122
-
123
- The button takes up the full width. Buttons look different depending on the theme. We're using
124
- the _neo-theme-neo-light_ theme, which controls button height. Otherwise, child items a using the _fit_ layout
125
- take up the full window.
126
- </details>
127
-
128
-
129
- <details>
130
- <summary>Modify the layout</summary>
131
- The `layout` configures how child items are visually arranged. First, note that the config
132
- specifies `ntype`. We used `module` for the button config. An `ntype` is a class alias &mdash; if a class
133
- has already been imported, you can use the `ntype` rather than importing it again and using the `module`
134
- config. We haven't imported any layouts, but it turns out that `Neo.container.Base` _does_ import all the
135
- layout types, which means we're always free to use `ntype` with layouts. You're free to specify an `ntype`
136
- for the classes you define.
137
-
138
- Let's change the layout to arrange items vertically, with items aligned horizontally at the start.
139
-
140
- <pre data-javascript>
141
- layout: {
142
- ntype: 'vbox',
143
- align: 'start'
144
- }
145
- </pre>
146
-
147
- <img src="https://s3.amazonaws.com/mjs.neo.learning.images/earthquakes/EarthquakesSingleVoxStartButton.png" style="width:80%"/>
148
-
149
-
150
- </details>
@@ -1,136 +0,0 @@
1
- In this lab you'll get a little debugging practice by getting component references, changing properties,
2
- and runing methods.
3
-
4
- Remember that when using the debugger console you need to be in the _neo-app-worker_ context.
5
-
6
- <details>
7
- <summary>Use `Neo.manager.Component.items`</summary>
8
-
9
- While running the _earthquakes_ app, open Chrome devtools, choose the _neomjs-app-worker_ JavaScript
10
- context, and run this statement:
11
-
12
- Neo.manager.Component.items
13
-
14
- The `items` property is an array of all created components. The array may have a lot of entries, depending on
15
- the complexity of an app and how much you've done while running it. But it's an easy way to explore what's
16
- been created.
17
-
18
- </details>
19
-
20
- <details>
21
- <summary>Store as global variable</summary>
22
-
23
- Any time you have a object reference in the console &mdash; even if it's nested within an array or object &mdash;
24
- you can right click on the object and choose _Store as global_ variable. Chrome will create a variable named
25
- `temp1`, `temp2`, etc., that references the object. That can make it easier to inspect the object and run its methods..
26
-
27
-
28
- <img src="https://s3.amazonaws.com/mjs.neo.learning.images/earthquakes/StoreAsGlobal.png" style="width:80%"/>
29
-
30
- </details>
31
-
32
-
33
- <details>
34
- <summary>Use `Neo.find()` and `Neo.findFirst()`</summary>
35
-
36
- If you know what you're looking for, and don't want to bother inspecting everything in `Neo.manager.Component.items`,
37
- you can use `Neo.find()`, passing an object used to match against what you're searching for.
38
-
39
- `Neo.find()` returns an array of matching instances, and `Neo.findFirst()` returns the first matching item.
40
- Often you know there's only a single instance, so in practice `Neo.findFirst()` is more commonly used.
41
-
42
- You could find the button via Neo.find({ntype:'button'}) or Neo.find({text:'Button!'} (assuming you haven't changed
43
- the button's text.) You can even match a property you give the button. For example, if you configured it with a made-up
44
- property `foo:true`, you could find it via `Neo.findFirst({foo:true})`. The point is you can search for any properties
45
- you'd like.
46
-
47
- Try this out.
48
-
49
- `Neo.findFirst({text:'Button!'}).text = 'Foo!'
50
-
51
- You should see the button's text change immediately.
52
-
53
- </details>
54
-
55
-
56
- <details>
57
- <summary>Use `Shift-Ctrl-right-click`</summary>
58
-
59
- With your cursor over the button, press _Shift-Ctrl-right-click_. The console will log the button, its parent `MainView`
60
- and the subsequent parent `Viewport. The button reference shows up as `Base` because the button class name is `Neo.button.Base`.
61
-
62
- <img width="80%" src="https://s3.amazonaws.com/mjs.neo.learning.images/earthquakes/EarthquakesDemoShiftCtrl.png">
63
-
64
- Note that _Shift-Ctrl-right-click_ is only available during development &mdash; it isn't available in a build.
65
-
66
- </details>
67
-
68
-
69
- <details>
70
- <summary>Add a method</summary>
71
-
72
- As we mentioned, when debugging, if you a have a reference you can access or update its properties, or run
73
- its methods. Let's try that out by adding a method.
74
-
75
- Edit `apps/earthquakes/view/MainView.mjs` and add a method.
76
-
77
- <pre data-javascript>
78
-
79
- import Base from '../../../node_modules/neo.mjs/src/container/Base.mjs';
80
- import Button from '../../../node_modules/neo.mjs/src/button/Base.mjs';
81
- import Controller from './MainViewController.mjs';
82
- import ViewModel from './MainViewModel.mjs';
83
-
84
- class MainView extends Base {
85
- static config = {
86
- className: 'Earthquakes.view.MainView',
87
- ntype: 'earthquakes-main',
88
-
89
- controller: {module: Controller},
90
- model: {module: ViewModel},
91
-
92
- layout: {
93
- ntype: 'vbox',
94
- align: 'start'
95
- },
96
- items: [{
97
- module: Button,
98
- foo: true,
99
- text: 'Button!'
100
- }],
101
- }
102
- doFoo() {
103
- console.log('foo!');
104
- }
105
- }
106
-
107
- Neo.setupClass(MainView);
108
-
109
- export default MainView;
110
- </pre>
111
-
112
- Save your changes.
113
-
114
- As you can see, the code defined an instance method `doFoo()` that simply logs a message. We'll run the method via debugging techniques in the next step.
115
-
116
- </details>
117
-
118
- <details>
119
- <summary>Use `Neo.component.Manager.items` to run the method</summary>
120
-
121
- On the console run `Neo.component.Manager.items`. Expand the array and right-click on the entry for `MainView` and
122
- choose `Store object as global variable`. Then type `temp1.doFoo()` &mdash; you should see "foo!" being logged.
123
-
124
- Remember that you _must_ run console statement in the _neomjs-app-worker_ context, and every time your choose
125
- `Store object as global variable` it'll increment the name of the temp variable: `temp1`, `temp2`, etc.
126
- </details>
127
-
128
- <details>
129
- <summary>Use _Shift-Ctrl-right-click_ to run the method</summary>
130
-
131
- Now try the _Shift-Ctrl-right-click_ technique.
132
-
133
- With your cursor over the button, do a _Shift-Ctrl-right-click_ &mdash; you'll see the component hierarchy logged.
134
- As you did in the previous step, right-click on the entry for `MainView` and choose `Store object as global variable`.
135
- Then run `doFoo()` using that variable.
136
- </details>