neo.mjs 6.13.0 → 6.15.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 (78) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/covid/neo-config.json +1 -1
  3. package/apps/covid/view/HeaderContainer.mjs +2 -2
  4. package/apps/form/view/pages/Page10.mjs +2 -2
  5. package/apps/portal/view/ViewportController.mjs +5 -4
  6. package/apps/portal/view/home/ContentBox.mjs +80 -0
  7. package/apps/portal/view/home/MainContainer.mjs +51 -15
  8. package/apps/portal/view/learn/ContentTreeList.mjs +10 -3
  9. package/apps/portal/view/learn/MainContainerController.mjs +37 -5
  10. package/apps/portal/view/learn/MainContainerModel.mjs +51 -7
  11. package/apps/portal/view/learn/PageContainer.mjs +21 -9
  12. package/apps/sharedcovid/neo-config.json +1 -1
  13. package/apps/sharedcovid/view/HeaderContainer.mjs +2 -2
  14. package/examples/ServiceWorker.mjs +2 -2
  15. package/examples/button/base/MainContainer.mjs +2 -2
  16. package/examples/button/split/MainContainer.mjs +2 -2
  17. package/examples/component/process/MainContainer.mjs +3 -3
  18. package/examples/component/process/realWorldExample/MainContainer.mjs +15 -15
  19. package/examples/component/toast/MainContainer.mjs +4 -4
  20. package/examples/dialog/DemoDialog.mjs +4 -4
  21. package/examples/fieldWithPrefix/MainContainer.mjs +4 -5
  22. package/examples/form/field/{select → combobox}/MainContainer.mjs +7 -10
  23. package/examples/form/field/{select → combobox}/MainModel.mjs +4 -4
  24. package/examples/form/field/{select → combobox}/MainStore.mjs +2 -2
  25. package/examples/form/field/{select → combobox}/app.mjs +1 -1
  26. package/examples/form/field/{select → combobox}/index.html +1 -1
  27. package/examples/form/field/{select → combobox}/neo-config.json +1 -1
  28. package/examples/tableFiltering/MainContainer.mjs +2 -2
  29. package/package.json +4 -4
  30. package/resources/data/deck/learnneo/pages/2023-10-14T19-25-08-153Z.md +16 -1
  31. package/resources/data/deck/learnneo/pages/ComponentsAndContainers.md +180 -0
  32. package/resources/data/deck/learnneo/pages/Config.md +11 -4
  33. package/resources/data/deck/learnneo/pages/DescribingTheUI.md +6 -0
  34. package/resources/data/deck/learnneo/pages/Earthquakes.md +36 -9
  35. package/resources/data/deck/learnneo/pages/Events.md +55 -43
  36. package/resources/data/deck/learnneo/pages/GuideEvents.md +9 -8
  37. package/resources/data/deck/learnneo/pages/References.md +14 -7
  38. package/resources/data/deck/learnneo/pages/TodoList.md +241 -0
  39. package/resources/data/deck/learnneo/pages/WhyNeo-Quick.md +6 -11
  40. package/resources/data/deck/learnneo/tree.json +2 -0
  41. package/resources/scss/src/apps/portal/home/ContentBox.scss +26 -0
  42. package/resources/scss/src/apps/portal/home/MainContainer.scss +4 -12
  43. package/resources/scss/src/apps/portal/learn/MainContainer.scss +0 -7
  44. package/resources/scss/src/apps/portal/learn/PageContainer.scss +35 -0
  45. package/resources/scss/src/apps/portal/learn/PageSectionsPanel.scss +8 -0
  46. package/resources/scss/src/form/field/{Select.scss → ComboBox.scss} +8 -8
  47. package/resources/scss/theme-dark/form/field/ComboBox.scss +9 -0
  48. package/resources/scss/theme-light/form/field/ComboBox.scss +9 -0
  49. package/resources/scss/theme-neo-light/form/field/ComboBox.scss +9 -0
  50. package/src/DefaultConfig.mjs +2 -2
  51. package/src/component/Base.mjs +16 -1
  52. package/src/container/Viewport.mjs +5 -2
  53. package/src/controller/Application.mjs +12 -1
  54. package/src/controller/Base.mjs +15 -4
  55. package/src/controller/Component.mjs +5 -1
  56. package/src/core/Observable.mjs +62 -22
  57. package/src/form/field/Base.mjs +21 -9
  58. package/src/form/field/Chip.mjs +3 -3
  59. package/src/form/field/Color.mjs +3 -3
  60. package/src/form/field/{Select.mjs → ComboBox.mjs} +179 -130
  61. package/src/form/field/Country.mjs +3 -3
  62. package/src/form/field/Text.mjs +7 -10
  63. package/src/form/field/_export.mjs +2 -2
  64. package/src/main/DomEvents.mjs +2 -1
  65. package/src/main/addon/MonacoEditor.mjs +2 -2
  66. package/src/main/addon/Navigator.mjs +27 -24
  67. package/src/selection/ListModel.mjs +13 -14
  68. package/src/selection/Model.mjs +10 -10
  69. package/src/toolbar/Paging.mjs +2 -2
  70. package/src/util/HashHistory.mjs +1 -0
  71. package/src/worker/App.mjs +5 -1
  72. package/src/worker/Manager.mjs +14 -7
  73. package/test/components/app.mjs +1 -1
  74. package/test/components/files/form/field/{Select.mjs → ComboBox.mjs} +9 -7
  75. package/test/components/siesta.js +1 -1
  76. package/resources/scss/theme-dark/form/field/Select.scss +0 -9
  77. package/resources/scss/theme-light/form/field/Select.scss +0 -9
  78. package/resources/scss/theme-neo-light/form/field/Select.scss +0 -9
@@ -1,10 +1,10 @@
1
1
  import Button from '../../../src/button/Base.mjs';
2
2
  import CheckBox from '../../../src/form/field/CheckBox.mjs';
3
+ import ComboBox from '../../../src/form/field/ComboBox.mjs';
3
4
  import Component from '../../../src/component/Base.mjs';
4
5
  import FormContainer from '../../../src/form/Container.mjs';
5
6
  import MainContainerController from './MainContainerController.mjs';
6
7
  import NumberField from '../../../src/form/field/Number.mjs';
7
- import SelectField from '../../../src/form/field/Select.mjs';
8
8
  import TextField from '../../../src/form/field/Text.mjs';
9
9
  import Viewport from '../../../src/container/Viewport.mjs';
10
10
 
@@ -51,19 +51,19 @@ class MainContainer extends Viewport {
51
51
  labelText: 'iconCls',
52
52
  name : 'iconCls'
53
53
  }, {
54
- module : SelectField,
54
+ module : ComboBox,
55
55
  labelText : 'position = tr',
56
56
  name : 'position',
57
57
  store : {data: [{name: 'tl'}, {name: 'tc'}, {name: 'tr'}, {name: 'bl'}, {name: 'bc'}, {name: 'br'}]},
58
58
  valueField: 'name'
59
59
  }, {
60
- module : SelectField,
60
+ module : ComboBox,
61
61
  labelText: 'slideDirection = right',
62
62
  name : 'slideDirection',
63
63
  store : {data: [{name: 'down'}, {name: 'up'}, {name: 'left'}, {name: 'right'}]},
64
64
  valueField: 'name'
65
65
  }, {
66
- module : SelectField,
66
+ module : ComboBox,
67
67
  labelText: 'ui = info',
68
68
  name : 'ui',
69
69
  store : {data: [{name: 'info'}, {name: 'danger'}, {name: 'success'}]},
@@ -1,6 +1,6 @@
1
- import Button from '../../src/button/Base.mjs';
2
- import Dialog from '../../src/dialog/Base.mjs';
3
- import SelectField from '../../src/form/field/Select.mjs';
1
+ import Button from '../../src/button/Base.mjs';
2
+ import ComboBox from '../../src/form/field/ComboBox.mjs';
3
+ import Dialog from '../../src/dialog/Base.mjs';
4
4
 
5
5
  /**
6
6
  * @class Neo.examples.dialog.DemoDialog
@@ -57,7 +57,7 @@ class DemoDialog extends Dialog {
57
57
  const me = this;
58
58
 
59
59
  me.items = [{
60
- module : SelectField,
60
+ module : ComboBox,
61
61
  labelText : 'Select',
62
62
  labelWidth: 80,
63
63
 
@@ -1,8 +1,7 @@
1
+ import ComboBox from '../../src/form/field/ComboBox.mjs';
1
2
  import ConfigurationViewport from '../ConfigurationViewport.mjs';
2
-
3
- import PrefixPlugin from '../../src/plugin/PrefixField.mjs';
4
- import SelectField from '../../src/form/field/Select.mjs';
5
- import TextField from '../../src/form/field/Text.mjs';
3
+ import PrefixPlugin from '../../src/plugin/PrefixField.mjs';
4
+ import TextField from '../../src/form/field/Text.mjs';
6
5
 
7
6
  /**
8
7
  * @class Neo.examples.fieldWithPrefix.MainContainer
@@ -50,7 +49,7 @@ class MainContainer extends ConfigurationViewport {
50
49
  value : '_',
51
50
  style : {marginTop: '10px'}
52
51
  }, {
53
- module: SelectField,
52
+ module: ComboBox,
54
53
  store : {
55
54
  model: {fields: [{name: 'id'}, {name: 'name'}, {name: 'value'}]},
56
55
  data : [
@@ -1,19 +1,18 @@
1
1
  import CheckBox from '../../../../src/form/field/CheckBox.mjs';
2
+ import ComboBox from '../../../../src/form/field/ComboBox.mjs';
2
3
  import ConfigurationViewport from '../../../ConfigurationViewport.mjs';
3
4
  import MainStore from './MainStore.mjs';
4
5
  import NumberField from '../../../../src/form/field/Number.mjs';
5
- import SelectField from '../../../../src/form/field/Select.mjs';
6
6
  import Radio from '../../../../src/form/field/Radio.mjs';
7
7
  import TextField from '../../../../src/form/field/Text.mjs';
8
8
 
9
9
  /**
10
- * @class Neo.examples.form.field.select.MainContainer
10
+ * @class Neo.examples.form.field.combobox.MainContainer
11
11
  * @extends Neo.examples.ConfigurationViewport
12
12
  */
13
13
  class MainContainer extends ConfigurationViewport {
14
14
  static config = {
15
- className : 'Neo.examples.form.field.select.MainContainer',
16
- autoMount : true,
15
+ className : 'Neo.examples.form.field.combobox.MainContainer',
17
16
  configItemLabelWidth : 160,
18
17
  exampleContainerConfig: {style: {position: 'relative'}}
19
18
  }
@@ -160,17 +159,15 @@ class MainContainer extends ConfigurationViewport {
160
159
 
161
160
  createExampleComponent() {
162
161
  return Neo.create({
163
- module : SelectField,
162
+ module : ComboBox,
164
163
  labelPosition: 'inline',
165
164
  labelText : 'US States',
166
165
  labelWidth : 80,
166
+ pickerConfig : {minHeight : '6em'},
167
167
  store : MainStore,
168
- value : 'Arizona', // or 'AZ'
168
+ value : 'AZ',
169
169
  valueField : 'abbreviation',
170
- width : '50%',
171
- pickerConfig : {
172
- minHeight : '6em'
173
- }
170
+ width : '50%'
174
171
  })
175
172
  }
176
173
  }
@@ -1,20 +1,20 @@
1
1
  import Model from '../../../../src/data/Model.mjs';
2
2
 
3
3
  /**
4
- * @class Neo.examples.form.field.select.MainModel
4
+ * @class Neo.examples.form.field.combobox.MainModel
5
5
  * @extends Neo.data.Model
6
6
  */
7
7
  class MainModel extends Model {
8
8
  static config = {
9
- className : 'Neo.examples.form.field.select.MainModel',
9
+ className : 'Neo.examples.form.field.combobox.MainModel',
10
10
  keyProperty: 'abbreviation',
11
11
 
12
12
  fields: [{
13
13
  name: 'abbreviation',
14
- type: 'string'
14
+ type: 'String'
15
15
  }, {
16
16
  name: 'name',
17
- type: 'string'
17
+ type: 'String'
18
18
  }]
19
19
  }
20
20
  }
@@ -2,12 +2,12 @@ import Store from '../../../../src/data/Store.mjs';
2
2
  import Model from './MainModel.mjs';
3
3
 
4
4
  /**
5
- * @class Neo.examples.form.field.select.MainStore
5
+ * @class Neo.examples.form.field.combobox.MainStore
6
6
  * @extends Neo.data.Store
7
7
  */
8
8
  class MainStore extends Store {
9
9
  static config = {
10
- className : 'Neo.examples.form.field.select.MainStore',
10
+ className : 'Neo.examples.form.field.combobox.MainStore',
11
11
  autoLoad : true,
12
12
  keyProperty: 'abbreviation',
13
13
  model : Model,
@@ -2,5 +2,5 @@ import MainContainer from './MainContainer.mjs';
2
2
 
3
3
  export const onStart = () => Neo.app({
4
4
  mainView: MainContainer,
5
- name : 'Neo.examples.form.field.select'
5
+ name : 'Neo.examples.form.field.combobox'
6
6
  });
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta name="viewport" content="width=device-width, initial-scale=1">
5
5
  <meta charset="UTF-8">
6
- <title>Neo SelectField</title>
6
+ <title>Neo ComboBox</title>
7
7
  </head>
8
8
  <body>
9
9
  <script src="../../../../src/MicroLoader.mjs" type="module"></script>
@@ -1,5 +1,5 @@
1
1
  {
2
- "appPath" : "examples/form/field/select/app.mjs",
2
+ "appPath" : "examples/form/field/combobox/app.mjs",
3
3
  "basePath" : "../../../../",
4
4
  "environment": "development",
5
5
  "mainPath" : "./Main.mjs"
@@ -1,11 +1,11 @@
1
1
  import BooleanContainer from '../../src/filter/BooleanContainer.mjs';
2
2
  import CellModel from '../../src/selection/table/CellModel.mjs';
3
3
  import CheckBox from '../../src/form/field/CheckBox.mjs';
4
+ import ComboBox from '../../src/form/field/ComboBox.mjs';
4
5
  import DateContainer from '../../src/filter/DateContainer.mjs';
5
6
  import DateUtil from '../../src/util/Date.mjs';
6
7
  import MainStore from './MainStore.mjs';
7
8
  import NumberContainer from '../../src/filter/NumberContainer.mjs';
8
- import SelectField from '../../src/form/field/Select.mjs';
9
9
  import TableContainer from '../../src/table/Container.mjs';
10
10
  import Viewport from '../../src/container/Viewport.mjs';
11
11
 
@@ -64,7 +64,7 @@ class MainContainer extends Viewport {
64
64
  text : 'Country',
65
65
 
66
66
  editorConfig: {
67
- module: SelectField,
67
+ module: ComboBox,
68
68
 
69
69
  store: {
70
70
  autoLoad : true,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  {
3
3
  "name": "neo.mjs",
4
- "version": "6.13.0",
4
+ "version": "6.15.0",
5
5
  "description": "The webworkers driven UI framework",
6
6
  "type": "module",
7
7
  "repository": {
@@ -53,13 +53,13 @@
53
53
  "envinfo": "^7.11.1",
54
54
  "fs-extra": "^11.2.0",
55
55
  "highlightjs-line-numbers.js": "^2.8.0",
56
- "inquirer": "^9.2.15",
56
+ "inquirer": "^9.2.16",
57
57
  "marked": "^12.0.1",
58
58
  "monaco-editor": "^0.47.0",
59
59
  "neo-jsdoc": "1.0.1",
60
60
  "neo-jsdoc-x": "1.0.5",
61
- "postcss": "^8.4.35",
62
- "sass": "^1.71.1",
61
+ "postcss": "^8.4.37",
62
+ "sass": "^1.72.0",
63
63
  "siesta-lite": "5.5.2",
64
64
  "url": "^0.11.3",
65
65
  "webpack": "^5.90.3",
@@ -1,3 +1,5 @@
1
+ ## Introduction
2
+
1
3
  The purpose of this tutorial is to let you see the structure of a Neo.mjs workspace,
2
4
  and the structure of an application.
3
5
 
@@ -5,7 +7,12 @@ If you wish, you can create a workspace by following the directions in the previ
5
7
 
6
8
  <img src="https://raw.githubusercontent.com/neomjs/pages/main/resources/images/apps/learnneo/NeoWorkspace.png" style="height: 400px;">
7
9
 
8
- As you can see, a Neo.mjs workspace is a conventional npm package. If you run
10
+ As you can see, a Neo.mjs workspace is a conventional npm package.
11
+
12
+
13
+ ## Browsing the workspace
14
+
15
+ If you run
9
16
  the script `npm run server-start` from the workspace, Neo.mjs launches a web
10
17
  server whose doc root is the workspace.
11
18
 
@@ -14,6 +21,8 @@ server whose doc root is the workspace.
14
21
  If you drill down into the `src` directory you'll see your applications.
15
22
  The `docs` directory holds the Neo.mjs API docs.
16
23
 
24
+ ## The structure of a simple app
25
+
17
26
  In order to discuss the structure of an app, we'll create a simple starter
18
27
  app vis this script, run from the workspace. The script prompts for various
19
28
  application settings.
@@ -29,6 +38,8 @@ These files are part of the typical structure of a Neo.mjs application. The file
29
38
  You will, however, edit the main container, and its associated "controller" and "model",
30
39
  as well as create new views classes, their controllers, and other application logic.
31
40
 
41
+ ## Some source code
42
+
32
43
  Now let's look at a source file. This is the contents of `MainView.mjs`.
33
44
 
34
45
  <pre data-javascript>
@@ -61,6 +72,8 @@ This view also has a "controller" and "model". We'll talk about those later, but
61
72
  a controller is where event handling and app logic goes, and a model is where you set up shared
62
73
  bindable data.
63
74
 
75
+ ## Adding a button to the view
76
+
64
77
  We'll go into a lot more depth about view, controllers, and models in other topics, but to let
65
78
  you see how a component is configured let's put a button in the container.
66
79
 
@@ -103,6 +116,8 @@ some value."
103
116
  In another topic you'll learn about the Neo.mjs config system and declaratively describing views,
104
117
  controllers, and other things.
105
118
 
119
+ ## A running example
120
+
106
121
  Here's a simplified running example. The `model` and `controller` are omitted, because they aren't
107
122
  actually used in the example, and the import root path is different to reflect the location of the
108
123
  Neo.mjs library relative to the examples.
@@ -0,0 +1,180 @@
1
+ ## Introduction
2
+
3
+ Neo.mjs views are made up of components and containers.
4
+
5
+ A component is a visual widget, such as a button, label, or text field. A container is a visual
6
+ collection of components.
7
+
8
+ `Neo.component.Base` is the base class for all components. It introduces some common features, such as
9
+ event handling, binding, and some life-cycle methods.
10
+
11
+ `Neo.container.Base` is the base class for all containers. Containers are also components.
12
+
13
+ ## Neo.container.Base
14
+
15
+ Containers are commonly used, although there are many specialized sub-classes, such as panels and toolbars.
16
+
17
+
18
+ Containers have two key properties:
19
+
20
+ - `items`, which are the components within the container, and
21
+ - `layout`, which describes how the items are arranged
22
+
23
+ ## Neo.component.Base
24
+
25
+ The component base class introduces common component features, but is rarely used itself because it's so
26
+ primitive. Components introduce various properties, such as `width`, `height`, `cls` (to specify CSS classes for the component).
27
+
28
+ Here's a container, with one child item.
29
+
30
+ <pre data-neo>
31
+ import Container from '../../../../src/container/Base.mjs';
32
+
33
+ class MainView extends Container {
34
+ static config = {
35
+ className: 'Example.view.MainView',
36
+ layout : {ntype:'vbox', align:'start'},
37
+ items : [{
38
+ ntype : 'component', // Or module:Component
39
+ style : {border: 'thin solid red;'}, // Styling is usually done via "cls"
40
+ height: 100,
41
+ width : 200
42
+ }]
43
+ }
44
+ }
45
+
46
+ Neo.setupClass(MainView);
47
+ </pre>
48
+
49
+ Components also have an `html`. The `html` property is rarely used, and goes against the abstract philosophy of Neo.mjs, but
50
+ sometimes it's handy as a placeholder as you stub out views.
51
+
52
+ <pre data-neo>
53
+ import Container from '../../../../src/container/Base.mjs';
54
+
55
+ class MainView extends Container {
56
+ static config = {
57
+ className: 'Example.view.MainView',
58
+ layout : {ntype:'vbox', align:'start'},
59
+ items : [{
60
+ ntype : 'component', // Or module:Component
61
+ style : {border: 'thin solid red;'}, // Styling is usually done via "cls"
62
+ html : 'This is a placeholder for a more sophisticated component we\'ll add later.',
63
+ height: 100,
64
+ width : 200
65
+ }]
66
+ }
67
+ }
68
+
69
+ Neo.setupClass(MainView);
70
+ </pre>
71
+
72
+
73
+ ## Layout
74
+
75
+ The `layout` config specifies how components are arranged within a container. Here are examples of
76
+ some commonly-used layouts.
77
+
78
+ ### Fit layout
79
+
80
+ Fix is used when there's a single child. The component is sized to fit the container.
81
+
82
+ <pre data-neo>
83
+ import Container from '../../../../src/container/Base.mjs';
84
+
85
+ class MainView extends Container {
86
+ static config = {
87
+ className: 'Example.view.MainView',
88
+ layout : 'fit', // If no configs are needed, simply use the ntype of the layout
89
+ items : [{
90
+ ntype: 'component',
91
+ style: {backgroundColor: 'lightgreen'}, // The camel-cased property converts to the hyphenated css style
92
+ }]
93
+ }
94
+ }
95
+
96
+ Neo.setupClass(MainView);
97
+ </pre>
98
+
99
+ ### Vbox and hbox
100
+
101
+ Items are arranged vertically or horizontally. On-axis and off-axis alignment can be specified.
102
+
103
+ <pre data-neo>
104
+ import Button from '../../../../src/button/Base.mjs';
105
+ import Container from '../../../../src/container/Base.mjs';
106
+
107
+ class MainView extends Container {
108
+ static config = {
109
+ className: 'Example.view.MainView',
110
+ layout : {ntype:'vbox', align:'start'}, // Change the ntype to 'hbox'
111
+ items : [{
112
+ module : Button,
113
+ iconCls: 'fa fa-home',
114
+ text : 'Home'
115
+ }, {
116
+ module : Button,
117
+ iconCls: 'fa fa-star',
118
+ text : 'Star'
119
+ }]
120
+ }
121
+ }
122
+
123
+ Neo.setupClass(MainView);
124
+ </pre>
125
+
126
+ ### Card
127
+
128
+ Having multiple child items, one of which is visible.
129
+
130
+ <pre data-neo>
131
+ import Button from '../../../../src/button/Base.mjs';
132
+ import Base from '../../../../src/container/Base.mjs';
133
+
134
+ class MainView extends Base {
135
+ static config = {
136
+ className: 'Example.view.MainView',
137
+ layout : 'vbox',
138
+ items : [{
139
+ ntype: 'toolbar',
140
+ dock : 'top',
141
+ items: [{
142
+ ntype: 'button',
143
+ text: 'Click me to cycle through the cards',
144
+ ui: 'ghost',
145
+ iconCls: 'fa fa-chevron-right',
146
+ iconPosition: 'right',
147
+ handler: data => {
148
+ const container = data.component.up('container').getReference('cardContainer');
149
+ container.layout.activeIndex = (container.layout.activeIndex +1) % container.items.length;
150
+ }
151
+ }]
152
+ }, {
153
+ ntype: 'container',
154
+ reference: 'cardContainer',
155
+ layout: 'card',
156
+ flex: 1,
157
+ items: [{
158
+ ntype : 'component',
159
+ style: {backgroundColor: 'lightsalmon'}, // The camel-cased property converts to the hyphated css style
160
+ }, {
161
+ ntype : 'component',
162
+ style: {backgroundColor: 'darkseagreen'} // https://drafts.csswg.org/css-color/#named-colors
163
+ }, {
164
+ ntype : 'component',
165
+ style: {backgroundColor: 'cornflowerblue'} // Who came up with these names?
166
+ }]
167
+ }]
168
+ }
169
+ }
170
+
171
+ Neo.setupClass(MainView);
172
+ </pre>
173
+
174
+
175
+
176
+
177
+ ## Reusing containers
178
+
179
+
180
+ ## Lifecycle methods
@@ -1,9 +1,13 @@
1
+ ## Introduction
2
+
1
3
  As you've probably noticed, Neo.mjs classes have a `static config` property.
2
4
 
3
5
  The config describes properties you can specify as you create an instance of the class.
4
6
  Any config in the class, or its ancestors, can be specified.
5
7
 
6
- In addition, Neo.mjs uses that information to set up propoerty lifecycle
8
+ ## Simple properties and lifecycle properties
9
+
10
+ In addition, Neo.mjs uses that information to set up property lifecycle
7
11
  methods.
8
12
 
9
13
  Here's an example of a new component class `Simple` with three config properties:
@@ -12,6 +16,9 @@ Here's an example of a new component class `Simple` with three config properties
12
16
  2. `foo` &mdash; an instance property
13
17
  2. `bar_` &mdash; another instance property
14
18
 
19
+ The `Simple` class introduces syntax. It doesn't have any content, so if you run the code you won't
20
+ see anything. We'll change that in the next example.
21
+
15
22
  <pre data-neo>
16
23
  import Component from '../../../../src/component/Base.mjs';
17
24
  import Container from '../../../../src/container/Base.mjs';
@@ -46,8 +53,7 @@ class MainView extends Container {
46
53
  Neo.setupClass(MainView);
47
54
  </pre>
48
55
 
49
- The `Simple` class doesn't have any content, so if you run the code you won't see anything. We'll
50
- change that in the next example.
56
+ ## Detecting when a value changes
51
57
 
52
58
  Note that the `bar` property is defined with an underscore at the end. That tags the property as
53
59
  a _lifecyle property_. A lifecycle property provides methods that are run as the property is
@@ -75,7 +81,6 @@ class Simple extends Component {
75
81
  }
76
82
  afterSetBar(value, oldValue){
77
83
  this.html = value;
78
- this.fire('barChange', {component: this, value, oldValue});
79
84
  }
80
85
 
81
86
  }
@@ -103,6 +108,8 @@ This time if you run the code you'll see "hi there" in the view. That's because
103
108
  configured with `bar: 'hi there'`, and since that's a lifecycle property the `afterSetBar()` method
104
109
  is run. That method updates the view with the passed value.
105
110
 
111
+ ## Firing an event when a value changes
112
+
106
113
  Typically, the _afterSet_ method is used to update a view or to fire an event.
107
114
 
108
115
  Look at this code: `afterSetBar()` fires an event, and the config in the `items[]` is listening to it.
@@ -1,3 +1,5 @@
1
+ ## Introduction
2
+
1
3
  A Neo.mjs view is comprised of components and containers. A component is a visual widget, like a button,
2
4
  and a container is a visual collection of components.
3
5
 
@@ -8,6 +10,8 @@ have a few key configs, including `text` and `iconCls`. The configs are properti
8
10
  use to describe the component you're creating> You can also access or set the properties dynamically.
9
11
 
10
12
 
13
+ ## A view with one component
14
+
11
15
  <pre data-neo>
12
16
  import Button from '../../../../src/button/Base.mjs';
13
17
  import Container from '../../../../src/container/Base.mjs';
@@ -42,6 +46,8 @@ Containers also have a `layout` property, which describes how the items are arra
42
46
 
43
47
  Let's put a second button in the container.
44
48
 
49
+ ## A view with two components
50
+
45
51
  <pre data-neo>
46
52
  import Button from '../../../../src/button/Base.mjs';
47
53
  import Container from '../../../../src/container/Base.mjs';
@@ -120,7 +120,7 @@ As you can see, `MicroLoader.mjs` runs `Main.mjs`, which in turn spawns the thre
120
120
  - `neomjs-app-worker` is where app logic is run
121
121
 
122
122
  Neo.mjs apps run in multiple webworkers, and each webworker is run in a separate parallel thread.
123
- Parallel processing &mdash; along wih the efficient way the `neomjs-vdom-worker` applies delta updates &mdash; is why Neo.mjs applications run so fast.
123
+ Parallel processing &mdash; along wih the efficient way the vdom worker applies delta updates &mdash; is why Neo.mjs applications run so fast.
124
124
 
125
125
  ##Commonly-used Scripts
126
126
 
@@ -294,7 +294,7 @@ layout: {
294
294
 
295
295
  ## Debugging
296
296
 
297
- At startup a Neo.mjs application launches three Web Workers:
297
+ At startup, a Neo.mjs application launches three Web Workers:
298
298
 
299
299
  - neomjs-app-worker
300
300
  - neomjs-data-worker
@@ -1153,7 +1153,7 @@ and each class is simpler than using complex source files that try to configure
1153
1153
 
1154
1154
  <!-- /lab -->
1155
1155
 
1156
- ### Google Maps Add-on
1156
+ ## Google Maps Add-on
1157
1157
 
1158
1158
  Neo.mjs has a Google Map component. This component is a little different than a button or table,
1159
1159
  becauase it's implemented as a _main thread add-on_.
@@ -1169,14 +1169,10 @@ to also provide a wrapper class so it can be used like any other component withi
1169
1169
  Maps is implemented: there's a main-thread add-on and a corresponding Neo.mjs component. The add-on is
1170
1170
  specified in _neo-config.json_, and the component is imported and used like any other component.
1171
1171
 
1172
- Ultimately, normal components are responsible for specifying how
1173
- they're rendered (which is usually handled by Neo.mjs).
1174
-
1175
1172
  How do you specify which main-thread add-ons you want? If you recall the script you used to create the starter
1176
1173
  app, it has a step that asks what add-ons you want. That results in populating the `mainThreadAddons` property
1177
- in `neo-config.json`. We didn't choose Google Maps when we ran the script, but we need it. That means we
1178
- need to edit `neo-config.json` and add it. Google Maps also requires an API key, which is also configured in
1179
- `neo-config.json`.
1174
+ in `neo-config.json`. We didn't choose Google Maps when we ran the script, but we need it, which means we'll
1175
+ need to edit `neo-config.json`. Google Maps also requires an API key, which is also configured there.
1180
1176
 
1181
1177
  The Google Maps component has a few key configs:
1182
1178
 
@@ -1193,6 +1189,20 @@ Marker store records are required to have these properties:
1193
1189
 
1194
1190
  <!-- lab -->
1195
1191
 
1192
+ <details>
1193
+ <summary>Get the code for the custom add-on</summary>
1194
+ At the time this tutorial was written, the Neo.mjs Google Maps addon was about to be updated to
1195
+ accomodate Google's "AdvancedMarker" class. Until that's ready, we're going to use a modified version of the add-on.
1196
+
1197
+ Download and unzip this file, and copy the two source files to the corresponding subdirectories in
1198
+ your workspace's `src` directory. Note that `src` already contains some files, so don't replace the whole
1199
+ directory, but instead, move the files to their individual locations.
1200
+
1201
+ <a href="https://s3.amazonaws.com/mjs.neo.learning.images/zip/src.zip">src.zip</a>
1202
+
1203
+ <img src="https://s3.amazonaws.com/mjs.neo.learning.images/earthquakes/CopyGoogleMapsFiles.png" width="30%%"></img>
1204
+ </details>
1205
+
1196
1206
  <details>
1197
1207
  <summary>Specify the main-thread add-on</summary>
1198
1208
 
@@ -1215,6 +1225,10 @@ Edit `apps/earthquakes/neo-config.json` and add entries for the Google Maps add-
1215
1225
  }
1216
1226
  </pre>
1217
1227
 
1228
+ It's unusual to need to edit `neo-config.json`. The app theme is specified there, and so are main thread add-ons.
1229
+ In our case, we're adding `WS/GoogleMaps` which in turn requires that we specify the map key. The `WS/`
1230
+ prefix tells Neo.mjs that the add-on is in our workspace, rather than an add-on provided by Neo.mjs.
1231
+
1218
1232
  Save and refresh, and you'll see a console log emanating from the plugin.
1219
1233
 
1220
1234
  <img style="width:80%" src="https://s3.amazonaws.com/mjs.neo.learning.images/earthquakes/GoogleMapsLoaded.png"></img>
@@ -1406,3 +1420,16 @@ Save, refresh, and confirm that you see the value logged when you click on a map
1406
1420
 
1407
1421
 
1408
1422
  <!-- /lab -->
1423
+
1424
+ ## Summary
1425
+
1426
+ Congratulations on completing the tutorial!
1427
+
1428
+ The goals was to give you hands-on coding a simple app to let you get a feel for syntax
1429
+ and to introduce some basic Neo.mjs concepts
1430
+
1431
+ - Declarative, abstract code
1432
+ - Class-based coding, and the ability to extend any class, such as `view/earthquakes/Table.mjs`
1433
+ - View models, to share properties and objects, such as the store shared by the table and map
1434
+ - Events, specified via `listeners:{}`
1435
+ - Controllers, to hold event listeners and other procedural logic