neo.mjs 6.15.3 → 6.15.5
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.
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/portal/view/Viewport.mjs +73 -10
- package/apps/portal/view/ViewportModel.mjs +29 -0
- package/apps/portal/view/learn/MainContainer.mjs +7 -10
- package/apps/portal/view/learn/MainContainerController.mjs +1 -1
- package/apps/portal/view/learn/PageSectionsContainer.mjs +51 -0
- package/examples/ServiceWorker.mjs +2 -2
- package/package.json +4 -4
- package/resources/data/deck/learnneo/pages/2023-10-14T19-25-08-153Z.md +0 -2
- package/resources/data/deck/learnneo/pages/ComponentsAndContainers.md +44 -11
- package/resources/data/deck/learnneo/pages/Config.md +0 -2
- package/resources/data/deck/learnneo/pages/CustomComponents.md +45 -0
- package/resources/data/deck/learnneo/pages/DescribingTheUI.md +0 -2
- package/resources/data/deck/learnneo/pages/Earthquakes.md +0 -2
- package/resources/data/deck/learnneo/pages/Events.md +0 -2
- package/resources/data/deck/learnneo/pages/Extending.md +0 -1
- package/resources/data/deck/learnneo/pages/References.md +0 -2
- package/resources/data/deck/learnneo/pages/Setup.md +0 -2
- package/resources/data/deck/learnneo/pages/TestLivePreview.md +1 -2
- package/resources/data/deck/learnneo/pages/Welcome.md +60 -0
- package/resources/data/deck/learnneo/pages/WhyNeo-Multi-Threaded.md +2 -0
- package/resources/data/deck/learnneo/pages/WhyNeo-Multi-Window.md +3 -3
- package/resources/data/deck/learnneo/pages/WhyNeo-Speed.md +34 -12
- package/resources/data/deck/learnneo/tree.json +3 -2
- package/resources/scss/src/apps/portal/learn/ContentView.scss +25 -20
- package/resources/scss/src/apps/portal/learn/LivePreview.scss +27 -6
- package/resources/scss/src/apps/portal/learn/MainContainer.scss +3 -33
- package/resources/scss/src/apps/portal/learn/PageContainer.scss +11 -6
- package/resources/scss/src/apps/portal/learn/PageSectionsContainer.scss +14 -0
- package/resources/scss/src/apps/portal/learn/PageSectionsList.scss +5 -6
- package/resources/scss/src/component/wrapper/MonacoEditor.scss +3 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/component/Base.mjs +0 -1
- package/src/component/wrapper/MonacoEditor.mjs +5 -0
- package/src/core/Base.mjs +24 -4
- package/src/form/field/ComboBox.mjs +2 -0
- package/src/list/Base.mjs +12 -5
- package/src/main/addon/IntersectionObserver.mjs +29 -5
- package/src/main/addon/Navigator.mjs +207 -155
- package/test/components/app.mjs +1 -0
- package/test/components/files/component/Base.mjs +88 -0
- package/test/components/siesta.js +1 -0
- package/apps/portal/view/learn/PageSectionsPanel.mjs +0 -59
- package/resources/scss/src/apps/portal/learn/PageSectionsPanel.scss +0 -40
package/apps/ServiceWorker.mjs
CHANGED
@@ -1,13 +1,23 @@
|
|
1
1
|
import BaseViewport from '../../../src/container/Viewport.mjs';
|
2
2
|
import Container from '../../../src/container/Base.mjs';
|
3
3
|
import HeaderToolbar from './HeaderToolbar.mjs';
|
4
|
+
import NeoArray from '../../../src/util/Array.mjs';
|
4
5
|
import ViewportController from './ViewportController.mjs';
|
6
|
+
import ViewportModel from './ViewportModel.mjs';
|
5
7
|
|
6
8
|
/**
|
7
9
|
* @class Portal.view.Viewport
|
8
10
|
* @extends Neo.container.Viewport
|
9
11
|
*/
|
10
12
|
class Viewport extends BaseViewport {
|
13
|
+
/**
|
14
|
+
* Valid values for size
|
15
|
+
* @member {String[]} sizes=['large','medium','small','x-small',null]
|
16
|
+
* @protected
|
17
|
+
* @static
|
18
|
+
*/
|
19
|
+
static sizes = ['large', 'medium', 'small', 'x-small', null]
|
20
|
+
|
11
21
|
static config = {
|
12
22
|
/**
|
13
23
|
* @member {String} className='Portal.view.Viewport'
|
@@ -35,23 +45,76 @@ class Viewport extends BaseViewport {
|
|
35
45
|
{module: () => import('./blog/Container.mjs')},
|
36
46
|
{module: () => import('../../../docs/app/view/MainContainer.mjs')}
|
37
47
|
]
|
38
|
-
}]
|
48
|
+
}],
|
49
|
+
/**
|
50
|
+
* @member {Neo.model.Component} model=ViewportModel
|
51
|
+
*/
|
52
|
+
model: ViewportModel,
|
53
|
+
/**
|
54
|
+
* Values are: large, medium, small, xSmall
|
55
|
+
* @member {String|null} size_=null
|
56
|
+
*/
|
57
|
+
size_: null
|
58
|
+
}
|
59
|
+
|
60
|
+
/**
|
61
|
+
* @param {Object} config
|
62
|
+
*/
|
63
|
+
construct(config) {
|
64
|
+
super.construct(config);
|
65
|
+
this.addDomListeners([{resize: this.onResize, scope: this}])
|
39
66
|
}
|
40
67
|
|
41
68
|
/**
|
42
|
-
*
|
69
|
+
* Triggered after the size config got changed
|
70
|
+
* @param {String|null} value
|
71
|
+
* @param {String|null} oldValue
|
72
|
+
* @protected
|
43
73
|
*/
|
44
|
-
|
45
|
-
|
74
|
+
afterSetSize(value, oldValue) {
|
75
|
+
if (value) {
|
76
|
+
let me = this,
|
77
|
+
cls = me.cls;
|
46
78
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
search = searchString ? JSON.parse(`{"${decodeURI(searchString.replace(/&/g, "\",\"").replace(/=/g, "\":\""))}"}`) : {};
|
79
|
+
NeoArray.remove(cls, 'portal-size-' + oldValue);
|
80
|
+
NeoArray.add( cls, 'portal-size-' + value);
|
81
|
+
me.cls = cls;
|
51
82
|
|
52
|
-
|
83
|
+
me.model.setData({size: value})
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
/**
|
88
|
+
* Triggered before the size config gets changed
|
89
|
+
* @param {String|null} value
|
90
|
+
* @param {String|null} oldValue
|
91
|
+
* @returns {String|null}
|
92
|
+
* @protected
|
93
|
+
*/
|
94
|
+
beforeSetSize(value, oldValue) {
|
95
|
+
return this.beforeSetEnumValue(value, oldValue, 'size')
|
96
|
+
}
|
97
|
+
|
98
|
+
/**
|
99
|
+
* @param {Number} width
|
100
|
+
* @returns {String}
|
101
|
+
*/
|
102
|
+
getSize(width) {
|
103
|
+
if (width <= 640) {return 'x-small'}
|
104
|
+
if (width <= 1024) {return 'small'}
|
105
|
+
if (width <= 1296) {return 'medium'}
|
106
|
+
return 'large'
|
107
|
+
}
|
108
|
+
|
109
|
+
/**
|
110
|
+
* @param {Object} data
|
111
|
+
*/
|
112
|
+
onResize(data) {
|
113
|
+
let me = this;
|
53
114
|
|
54
|
-
|
115
|
+
if (me.id === data.id) {
|
116
|
+
me.size = me.getSize(data.borderBoxSize.inlineSize)
|
117
|
+
}
|
55
118
|
}
|
56
119
|
}
|
57
120
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import Component from '../../../src/model/Component.mjs';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @class Portal.view.ViewportModel
|
5
|
+
* @extends Neo.model.Component
|
6
|
+
*/
|
7
|
+
class ViewportModel extends Component {
|
8
|
+
static config = {
|
9
|
+
/**
|
10
|
+
* @member {String} className='Portal.view.ViewportModel'
|
11
|
+
* @protected
|
12
|
+
*/
|
13
|
+
className: 'Portal.view.ViewportModel',
|
14
|
+
/**
|
15
|
+
* @member {Object} data
|
16
|
+
*/
|
17
|
+
data: {
|
18
|
+
/**
|
19
|
+
* Values are: large, medium, small, xSmall, null
|
20
|
+
* @member {String|null} size
|
21
|
+
*/
|
22
|
+
size: null
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
Neo.setupClass(ViewportModel);
|
28
|
+
|
29
|
+
export default ViewportModel;
|
@@ -3,7 +3,7 @@ import ContentTreeList from './ContentTreeList.mjs';
|
|
3
3
|
import MainContainerController from './MainContainerController.mjs';
|
4
4
|
import MainContainerModel from './MainContainerModel.mjs';
|
5
5
|
import PageContainer from './PageContainer.mjs';
|
6
|
-
import
|
6
|
+
import PageSectionsContainer from './PageSectionsContainer.mjs';
|
7
7
|
import Splitter from '../../../../src/component/Splitter.mjs';
|
8
8
|
|
9
9
|
/**
|
@@ -30,6 +30,7 @@ class MainContainer extends Container {
|
|
30
30
|
*/
|
31
31
|
items: [{
|
32
32
|
module : Container,
|
33
|
+
bind : {hidden: data => data.size === 'x-small'},
|
33
34
|
cls : ['sidenav-container'],
|
34
35
|
layout : 'fit',
|
35
36
|
minWidth: 350,
|
@@ -41,20 +42,16 @@ class MainContainer extends Container {
|
|
41
42
|
}]
|
42
43
|
}, {
|
43
44
|
module : Splitter,
|
45
|
+
bind : {hidden: data => data.size === 'x-small'},
|
44
46
|
cls : ['main-content-splitter'],
|
45
47
|
resizeTarget: 'previous',
|
46
48
|
size : 3
|
47
49
|
}, {
|
48
50
|
module: PageContainer
|
49
|
-
},
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
// size : 3
|
54
|
-
// },
|
55
|
-
{
|
56
|
-
module : PageSectionsPanel,
|
57
|
-
reference: 'page-sections-panel',
|
51
|
+
}, {
|
52
|
+
module : PageSectionsContainer,
|
53
|
+
bind : {hidden: data => data.size !== 'large'},
|
54
|
+
reference: 'page-sections-container',
|
58
55
|
width : 250
|
59
56
|
}],
|
60
57
|
/**
|
@@ -184,7 +184,7 @@ class MainContainerController extends Controller {
|
|
184
184
|
* @param {Object} data
|
185
185
|
*/
|
186
186
|
onIntersect(data) {
|
187
|
-
let panel = this.getReference('page-sections-
|
187
|
+
let panel = this.getReference('page-sections-container'),
|
188
188
|
list = panel.list,
|
189
189
|
recordId = parseInt(data.data.recordId);
|
190
190
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import Container from '../../../../src/container/Base.mjs';
|
2
|
+
import PageSectionsList from './PageSectionsList.mjs';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @class Portal.view.learn.PageSectionsContainer
|
6
|
+
* @extends Neo.container.Base
|
7
|
+
*/
|
8
|
+
class PageSectionsContainer extends Container {
|
9
|
+
static config = {
|
10
|
+
/**
|
11
|
+
* @member {String} className='Portal.view.learn.PageSectionsContainer'
|
12
|
+
* @protected
|
13
|
+
*/
|
14
|
+
className: 'Portal.view.learn.PageSectionsContainer',
|
15
|
+
/**
|
16
|
+
* @member {String[]} cls=['portal-page-sections-container']
|
17
|
+
*/
|
18
|
+
cls: ['portal-page-sections-container'],
|
19
|
+
/**
|
20
|
+
* @member {Object[]} items
|
21
|
+
*/
|
22
|
+
items: [{
|
23
|
+
vdom:
|
24
|
+
{cn: [
|
25
|
+
{tag: 'h3', html: 'On this page'}
|
26
|
+
]}
|
27
|
+
|
28
|
+
}, {
|
29
|
+
module : PageSectionsList,
|
30
|
+
reference: 'list'
|
31
|
+
}],
|
32
|
+
/**
|
33
|
+
* @member {Object} layout={ntype:'vbox'}
|
34
|
+
*/
|
35
|
+
layout: {
|
36
|
+
ntype: 'vbox'
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Convenience shortcut
|
42
|
+
* @member {Portal.view.learn.PageSectionsList} list
|
43
|
+
*/
|
44
|
+
get list() {
|
45
|
+
return this.getReference('list')
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
Neo.setupClass(PageSectionsContainer);
|
50
|
+
|
51
|
+
export default PageSectionsContainer;
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
{
|
3
3
|
"name": "neo.mjs",
|
4
|
-
"version": "6.15.
|
4
|
+
"version": "6.15.5",
|
5
5
|
"description": "The webworkers driven UI framework",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
@@ -44,16 +44,16 @@
|
|
44
44
|
},
|
45
45
|
"homepage": "https://neomjs.github.io/pages/",
|
46
46
|
"devDependencies": {
|
47
|
-
"@fortawesome/fontawesome-free": "^6.5.
|
47
|
+
"@fortawesome/fontawesome-free": "^6.5.2",
|
48
48
|
"autoprefixer": "^10.4.19",
|
49
49
|
"chalk": "^5.3.0",
|
50
50
|
"clean-webpack-plugin": "^4.0.0",
|
51
51
|
"commander": "^12.0.0",
|
52
|
-
"cssnano": "^6.1.
|
52
|
+
"cssnano": "^6.1.2",
|
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.
|
56
|
+
"inquirer": "^9.2.17",
|
57
57
|
"marked": "^12.0.1",
|
58
58
|
"monaco-editor": "^0.47.0",
|
59
59
|
"neo-jsdoc": "1.0.1",
|
@@ -1,5 +1,3 @@
|
|
1
|
-
## Introduction
|
2
|
-
|
3
1
|
Neo.mjs views are made up of components and containers.
|
4
2
|
|
5
3
|
A component is a visual widget, such as a button, label, or text field. A container is a visual
|
@@ -88,7 +86,7 @@ class MainView extends Container {
|
|
88
86
|
layout : 'fit', // If no configs are needed, simply use the ntype of the layout
|
89
87
|
items : [{
|
90
88
|
ntype: 'component',
|
91
|
-
style: {backgroundColor: 'lightgreen'}, // The camel-cased property converts to the hyphenated css style
|
89
|
+
style: {backgroundColor: 'lightgreen'}, // The camel-cased backgroundColor property converts to the hyphenated css style
|
92
90
|
}]
|
93
91
|
}
|
94
92
|
}
|
@@ -98,7 +96,7 @@ Neo.setupClass(MainView);
|
|
98
96
|
|
99
97
|
### Vbox and hbox
|
100
98
|
|
101
|
-
|
99
|
+
With `vbox` and `hbox`, items are arranged vertically or horizontally.
|
102
100
|
|
103
101
|
<pre data-neo>
|
104
102
|
import Button from '../../../../src/button/Base.mjs';
|
@@ -125,7 +123,7 @@ Neo.setupClass(MainView);
|
|
125
123
|
|
126
124
|
### Card
|
127
125
|
|
128
|
-
|
126
|
+
A card container has multiple child items, one of which is visible.
|
129
127
|
|
130
128
|
<pre data-neo>
|
131
129
|
import Button from '../../../../src/button/Base.mjs';
|
@@ -146,7 +144,7 @@ class MainView extends Base {
|
|
146
144
|
iconPosition: 'right',
|
147
145
|
handler: data => {
|
148
146
|
const container = data.component.up('container').getReference('cardContainer');
|
149
|
-
container.layout.activeIndex = (container.layout.activeIndex +1) % container.items.length;
|
147
|
+
container.layout.activeIndex = (container.layout.activeIndex + 1) % container.items.length;
|
150
148
|
}
|
151
149
|
}]
|
152
150
|
}, {
|
@@ -156,13 +154,13 @@ class MainView extends Base {
|
|
156
154
|
flex: 1,
|
157
155
|
items: [{
|
158
156
|
ntype : 'component',
|
159
|
-
style: {backgroundColor: 'lightsalmon'}
|
157
|
+
style: {backgroundColor: 'lightsalmon'} // https://drafts.csswg.org/css-color/#named-colors
|
160
158
|
}, {
|
161
159
|
ntype : 'component',
|
162
|
-
style: {backgroundColor: 'darkseagreen'} //
|
160
|
+
style: {backgroundColor: 'darkseagreen'} // Who came up with these names?
|
163
161
|
}, {
|
164
162
|
ntype : 'component',
|
165
|
-
style: {backgroundColor: 'cornflowerblue'}
|
163
|
+
style: {backgroundColor: 'cornflowerblue'}
|
166
164
|
}]
|
167
165
|
}]
|
168
166
|
}
|
@@ -174,7 +172,42 @@ Neo.setupClass(MainView);
|
|
174
172
|
|
175
173
|
|
176
174
|
|
177
|
-
## Reusing
|
175
|
+
## Reusing components
|
176
|
+
|
177
|
+
Neo.mjs is class-based, and thus, any component or container can be defined as its own class, and reused like any
|
178
|
+
other component in the framework.
|
179
|
+
|
180
|
+
<pre data-neo>
|
181
|
+
import Button from '../../../../src/button/Base.mjs';
|
182
|
+
// In practice this would be some handy reusable component
|
183
|
+
class MySpecialButton extends Button {
|
184
|
+
static config = {
|
185
|
+
className: 'Example.view.MySpecialButton',
|
186
|
+
iconCls: 'far fa-face-grin-wide',
|
187
|
+
ui: 'ghost'
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
191
|
+
Neo.setupClass(MySpecialButton);
|
192
|
+
|
193
|
+
|
194
|
+
import Container from '../../../../src/container/Base.mjs';
|
195
|
+
|
196
|
+
class MainView extends Container {
|
197
|
+
static config = {
|
198
|
+
className: 'Example.view.MainView',
|
199
|
+
layout : {ntype:'vbox', align:'start'},
|
200
|
+
items : [{
|
201
|
+
module : Button,
|
202
|
+
iconCls: 'fa fa-home',
|
203
|
+
text : 'A framework button'
|
204
|
+
}, {
|
205
|
+
module : MySpecialButton,
|
206
|
+
text : 'My special button'
|
207
|
+
}]
|
208
|
+
}
|
209
|
+
}
|
178
210
|
|
211
|
+
Neo.setupClass(MainView);
|
212
|
+
</pre>
|
179
213
|
|
180
|
-
## Lifecycle methods
|
@@ -0,0 +1,45 @@
|
|
1
|
+
## Introduction
|
2
|
+
|
3
|
+
Neo.mjs is class-based, which means you're free to extend any component (or any other Neo.mjs class).
|
4
|
+
|
5
|
+
|
6
|
+
## Overriding ancestor configs
|
7
|
+
|
8
|
+
## Introducing new configs
|
9
|
+
|
10
|
+
## Lifecycle config properties
|
11
|
+
|
12
|
+
<pre data-neo>
|
13
|
+
import Button from '../../../../src/button/Base.mjs';
|
14
|
+
// In practice this would be some handy reusable component
|
15
|
+
class MySpecialButton extends Button {
|
16
|
+
static config = {
|
17
|
+
className: 'Example.view.MySpecialButton',
|
18
|
+
iconCls: 'far fa-face-grin-wide',
|
19
|
+
ui: 'ghost'
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
Neo.setupClass(MySpecialButton);
|
24
|
+
|
25
|
+
|
26
|
+
import Container from '../../../../src/container/Base.mjs';
|
27
|
+
|
28
|
+
class MainView extends Container {
|
29
|
+
static config = {
|
30
|
+
className: 'Example.view.MainView',
|
31
|
+
layout : {ntype:'vbox', align:'start'},
|
32
|
+
items : [{
|
33
|
+
module : Button,
|
34
|
+
iconCls: 'fa fa-home',
|
35
|
+
text : 'A framework button'
|
36
|
+
}, {
|
37
|
+
module : MySpecialButton,
|
38
|
+
text : 'My special button'
|
39
|
+
}]
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
Neo.setupClass(MainView);
|
44
|
+
</pre>
|
45
|
+
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
In theory, a Neo.mjs app could be defined in a single `.mjs` source file. But that would be very hard to
|
3
2
|
maintain, and any reusable configs would have to be duplicated. Instead, each of your views and reusable
|
4
3
|
widgets will be defined as its own class. The result is simpler views which are inherently reusable and easier
|
@@ -1,7 +1,6 @@
|
|
1
1
|
To code a live preview, enclose the code in a `pre` tag with the `data-neo` attribute.
|
2
2
|
|
3
|
-
<
|
4
|
-
</pre>
|
3
|
+
<code><pre data-neo>...</pre> <</code>
|
5
4
|
|
6
5
|
Imports are relative to the portal app running within the framework. That means
|
7
6
|
Neo.mjs imports should be coded to go up four levels, then look into the `src`
|
@@ -0,0 +1,60 @@
|
|
1
|
+
Welcome to Neo.mjs! This set of topics contains information to help you use Neo.mjs.
|
2
|
+
|
3
|
+
|
4
|
+
## Topics
|
5
|
+
|
6
|
+
### Why Neo?
|
7
|
+
|
8
|
+
Describes technical and business reasons for using Neo.mjs
|
9
|
+
|
10
|
+
### Getting Started
|
11
|
+
|
12
|
+
Install instructions, along with fundamental concepts that are good to understand before diving into Neo.mjs.
|
13
|
+
|
14
|
+
### Tutorials
|
15
|
+
|
16
|
+
Hands-on tutorials where you'll code a few simple Neo.mjs applications.
|
17
|
+
|
18
|
+
### Guides
|
19
|
+
|
20
|
+
These are in-depth discussions of various topics.
|
21
|
+
|
22
|
+
### Appendix
|
23
|
+
|
24
|
+
You can ignore this! It just holds a site style sheet and other miscellanea.
|
25
|
+
|
26
|
+
## Using these topics
|
27
|
+
|
28
|
+
As you can see, the topics table of contents is on the left. Topic sections and sub-sections are shown on the right.
|
29
|
+
|
30
|
+
Topics sometimes contain "disclosure" widgets, which are just <details> tags. These are used in cases
|
31
|
+
where we want to present high-level points and reveal details when the disclosure is expanded.
|
32
|
+
|
33
|
+
<details>
|
34
|
+
<summary>This is a disclosure widget</summary>
|
35
|
+
<p style="background-color:lightgreen;padding:8px">This is a fascinating piece of information which is revealed when the widget is expanded.</p>
|
36
|
+
</details>
|
37
|
+
|
38
|
+
Topics also sometimes contain runnable examples. These are shown as tab panels with Source and Preview tabs.
|
39
|
+
|
40
|
+
You can also launch the preview in a window by going to the Preview tab, then clicking on the little window
|
41
|
+
icon on the right <span class="far fa-xs fa-window-maximize"></span>. This web site is a Neo.mjs application,
|
42
|
+
and the ability to launch browser windows — all integrated within a single app — is a unique feature of Neo.mjs!
|
43
|
+
|
44
|
+
<pre data-neo>
|
45
|
+
import Button from '../../../../src/button/Base.mjs';
|
46
|
+
import Container from '../../../../src/container/Base.mjs';
|
47
|
+
|
48
|
+
class MainView extends Container {
|
49
|
+
static config = {
|
50
|
+
className: 'Example.view.MainView',
|
51
|
+
layout : {ntype:'vbox', align:'start'},
|
52
|
+
items : [{
|
53
|
+
module : Button,
|
54
|
+
text : 'Button'
|
55
|
+
}]
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
Neo.setupClass(MainView);
|
60
|
+
</pre>
|
@@ -6,6 +6,8 @@ to the main browser thread, resulting in:
|
|
6
6
|
3. A <b>data</b> web-worker were HTTP and socket calls are run
|
7
7
|
4. A <b>view</b> web-worker that manages delta updates
|
8
8
|
|
9
|
+
<img src="https://s3.amazonaws.com/mjs.neo.learning.images/why/IndexHtmlFlow.png" width="120%"></img>
|
10
|
+
|
9
11
|
The benefits of using web workers is that each runs in parallel its own thread. In a typical framework
|
10
12
|
all code is run in the main thread, so processes compete for CPU cycles.
|
11
13
|
|
@@ -8,11 +8,11 @@ across windows, running seamlessly as a single application.
|
|
8
8
|
|
9
9
|
<details>
|
10
10
|
<summary><h3>Example</h3></summary>
|
11
|
-
An easy way to show this is by looking at a code preview example.
|
11
|
+
An easy way to show this is by looking at a code preview example. In the example below, click Preview,
|
12
12
|
then click on the new window icon on the right side of the toolbar. This launches a new window
|
13
13
|
running the code. Even though it's running in a new window, it's still part of the app.
|
14
|
-
(In this case, the app is the
|
15
|
-
share events,
|
14
|
+
(In this case, the app is the web site you're looking at now.) That means both the code in both windows
|
15
|
+
seamlessly share events, data, etc. — the code doesn't care that some code is running in a
|
16
16
|
separate window.
|
17
17
|
<pre data-neo>
|
18
18
|
import Button from '../../../../src/button/Base.mjs';
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
The Neo.mjs web-worker processes are automatically run in parallel, on separate CPU cores.
|
2
2
|
|
3
3
|
By contrast, other JavaScript frameworks run in a single thread, so all business logic,
|
4
4
|
data handling, and DOM rendering compete for CPU resources.
|
@@ -12,16 +12,38 @@ If the default four threads aren't enough, you're free to launch additional web-
|
|
12
12
|
to run other specialized logic.
|
13
13
|
|
14
14
|
|
15
|
-
|
16
|
-
<summary>Example</summary>
|
17
|
-
Look at this example. It's complex. As you pan left and right, and zoom in and out, the upper-right
|
18
|
-
shows you the number of delta updates being applied. If you move really quickly, you might reach 20,000
|
19
|
-
or 30,000 delta updates per second. We've seen some examples that go over 40,000 updates per second —
|
20
|
-
but we've never actually hit the limit.
|
15
|
+
### Example
|
21
16
|
|
22
|
-
|
17
|
+
Look at this example. It's the `Neo.component.Helix` component. Besides looking cool, it illustrates how quickly Neo.mjs can update a complex user interface.
|
23
18
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
19
|
+
Click on Preview, then use your mouse or trackpad to pan and zoom — the helix zooms and spirals accordingly, very very rapidly.
|
20
|
+
If you move quickly, you might reach 20,000 or 30,000 delta updates per second. We've seen some examples that go over 40,000 updates per
|
21
|
+
second — but we've never actually hit the limit.
|
22
|
+
|
23
|
+
<pre data-neo>
|
24
|
+
import Base from '../../../../src/container/Base.mjs';
|
25
|
+
import Helix from '../../../../src/component/Helix.mjs';
|
26
|
+
class Foo extends Base {
|
27
|
+
static config = {
|
28
|
+
className: 'Foo',
|
29
|
+
layout: 'fit',
|
30
|
+
items: [{
|
31
|
+
module: Helix,
|
32
|
+
imageField : 'image',
|
33
|
+
imageSource: '../../../../resources/examples/',
|
34
|
+
store: {
|
35
|
+
autoLoad: true,
|
36
|
+
model: {
|
37
|
+
fields: [ { name: 'image' , type: 'String' } ],
|
38
|
+
},
|
39
|
+
url: '../../../../resources/examples/data/ai_contacts.json'
|
40
|
+
}
|
41
|
+
}]
|
42
|
+
}
|
43
|
+
}
|
44
|
+
Neo.setupClass(Foo);
|
45
|
+
</pre>
|
46
|
+
|
47
|
+
|
48
|
+
If you're interested, there's <a href="../../examples/component/helix/index.html" target="_blank">a more full-featured helix example</a> that includes showing delta updates,
|
49
|
+
along with some other control. Look at the upper-right corner to see delta updates.
|