neo.mjs 6.8.2 → 6.9.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.
- package/.github/PULL_REQUEST_TEMPLATE.md +1 -1
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/learnneo/app.mjs +6 -0
- package/apps/learnneo/index.html +11 -0
- package/apps/learnneo/model/Content.mjs +44 -0
- package/apps/learnneo/neo-config.json +6 -0
- package/apps/learnneo/store/Content.mjs +24 -0
- package/apps/learnneo/view/Viewport.mjs +34 -0
- package/apps/learnneo/view/ViewportController.mjs +19 -0
- package/apps/learnneo/view/home/ContentTreeList.mjs +41 -0
- package/apps/learnneo/view/home/MainContainer.mjs +51 -0
- package/apps/learnneo/view/home/MainContainerController.mjs +50 -0
- package/apps/route/app.mjs +6 -0
- package/apps/route/index.html +11 -0
- package/apps/route/neo-config.json +6 -0
- package/apps/route/view/ButtonBar.mjs +57 -0
- package/apps/route/view/CenterContainer.mjs +37 -0
- package/apps/route/view/FooterContainer.mjs +47 -0
- package/apps/route/view/HeaderContainer.mjs +47 -0
- package/apps/route/view/MainView.mjs +66 -0
- package/apps/route/view/MainViewController.mjs +210 -0
- package/apps/route/view/MetaContainer.mjs +52 -0
- package/apps/route/view/Viewport.mjs +15 -0
- package/apps/route/view/center/CardAdministration.mjs +36 -0
- package/apps/route/view/center/CardAdministrationDenied.mjs +26 -0
- package/apps/route/view/center/CardContact.mjs +29 -0
- package/apps/route/view/center/CardHome.mjs +26 -0
- package/apps/route/view/center/CardSection1.mjs +26 -0
- package/apps/route/view/center/CardSection2.mjs +27 -0
- package/examples/ConfigurationViewport.mjs +1 -1
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/form/field/select/MainContainer.mjs +7 -2
- package/examples/table/container/MainContainer.mjs +4 -2
- package/examples/table/container/MainModel.mjs +3 -0
- package/examples/table/container/MainStore.mjs +10 -10
- package/examples/todoList/version1/MainComponent.mjs +5 -5
- package/examples/toolbar/paging/view/MainContainer.mjs +31 -3
- package/package.json +1 -1
- package/resources/data/learnneo/content.json +27 -0
- package/resources/data/learnneo/pages/whyneo.md +76 -0
- package/resources/scss/src/apps/route/CenterContainer.scss +29 -0
- package/resources/scss/src/apps/route/HeaderContainer.scss +122 -0
- package/resources/scss/src/apps/route/MainView.scss +3 -0
- package/resources/scss/src/apps/route/MetaContainer.scss +44 -0
- package/resources/scss/src/apps/route/_all.scss +1 -0
- package/resources/scss/src/form/field/Picker.scss +0 -1
- package/src/DefaultConfig.mjs +2 -2
- package/src/Neo.mjs +15 -14
- package/src/button/Base.mjs +2 -2
- package/src/component/Base.mjs +41 -50
- package/src/container/Base.mjs +59 -2
- package/src/controller/Base.mjs +84 -4
- package/src/controller/Component.mjs +22 -7
- package/src/core/Observable.mjs +50 -9
- package/src/dialog/Base.mjs +1 -4
- package/src/form/field/FileUpload.mjs +11 -0
- package/src/form/field/Picker.mjs +0 -17
- package/src/form/field/Range.mjs +8 -0
- package/src/form/field/Text.mjs +29 -0
- package/src/form/field/trigger/Picker.mjs +7 -0
- package/src/main/DomEvents.mjs +9 -3
- package/src/manager/DomEvent.mjs +3 -0
- package/src/menu/List.mjs +1 -1
- package/src/table/View.mjs +78 -53
- package/src/toolbar/Paging.mjs +68 -76
- package/src/tooltip/Base.mjs +111 -11
package/src/controller/Base.mjs
CHANGED
@@ -16,7 +16,23 @@ class Base extends CoreBase {
|
|
16
16
|
* @member {String} ntype='controller'
|
17
17
|
* @protected
|
18
18
|
*/
|
19
|
-
ntype: 'controller'
|
19
|
+
ntype: 'controller',
|
20
|
+
|
21
|
+
/**
|
22
|
+
* @member {Object} routes={}
|
23
|
+
*/
|
24
|
+
routes: {},
|
25
|
+
|
26
|
+
/**
|
27
|
+
* @member {Object} handleRoutes={}
|
28
|
+
*/
|
29
|
+
handleRoutes: {},
|
30
|
+
|
31
|
+
/**
|
32
|
+
* @member {String} defaultRoute=undefined
|
33
|
+
*/
|
34
|
+
defaultRoute: null
|
35
|
+
|
20
36
|
}
|
21
37
|
|
22
38
|
/**
|
@@ -25,7 +41,21 @@ class Base extends CoreBase {
|
|
25
41
|
construct(config) {
|
26
42
|
super.construct(config);
|
27
43
|
|
28
|
-
|
44
|
+
const me = this;
|
45
|
+
|
46
|
+
me.handleRoutes = {};
|
47
|
+
if (Object.keys(me.routes).length > 0) {
|
48
|
+
Object.keys(me.routes).forEach(key => {
|
49
|
+
if (key.toLowerCase() === 'default'){
|
50
|
+
me.defaultRoute = me.routes[key];
|
51
|
+
} else {
|
52
|
+
me.handleRoutes[key] = new RegExp(key.replace(/{[^\s/]+}/g, '([\\w-]+)')+'$');
|
53
|
+
}
|
54
|
+
|
55
|
+
});
|
56
|
+
}
|
57
|
+
|
58
|
+
HashHistory.on('change', me.onHashChange, me);
|
29
59
|
}
|
30
60
|
|
31
61
|
/**
|
@@ -37,6 +67,15 @@ class Base extends CoreBase {
|
|
37
67
|
super.destroy(...args);
|
38
68
|
}
|
39
69
|
|
70
|
+
/**
|
71
|
+
* Placeholder method which gets triggered when an invalid route is called
|
72
|
+
* @param {Object} value
|
73
|
+
* @param {Object} oldValue
|
74
|
+
*/
|
75
|
+
onNoRouteFound(value, oldValue) {
|
76
|
+
|
77
|
+
}
|
78
|
+
|
40
79
|
/**
|
41
80
|
* Placeholder method which gets triggered when the hash inside the browser url changes
|
42
81
|
* @param {Object} value
|
@@ -44,6 +83,46 @@ class Base extends CoreBase {
|
|
44
83
|
*/
|
45
84
|
onHashChange(value, oldValue) {
|
46
85
|
|
86
|
+
const me = this;
|
87
|
+
let hasRouteBeenFound = false;
|
88
|
+
Object.keys(me.handleRoutes).every( key => {
|
89
|
+
let preHandler = undefined;
|
90
|
+
let executeHandler = undefined;
|
91
|
+
let responsePreHandler = undefined;
|
92
|
+
|
93
|
+
const result = value.hashString.match(me.handleRoutes[key]);
|
94
|
+
if (result){
|
95
|
+
const target = me.routes[key];
|
96
|
+
if (Neo.isString(target)){
|
97
|
+
executeHandler = this.routes[key];
|
98
|
+
responsePreHandler = true;
|
99
|
+
}
|
100
|
+
if (Neo.isObject(target)){
|
101
|
+
executeHandler = this.routes[key].handler;
|
102
|
+
preHandler = this.routes[key].preHandler;
|
103
|
+
responsePreHandler = preHandler ? me[preHandler]?.call(this, value, oldValue, result.splice(1,result.length - 1)) : true;
|
104
|
+
}
|
105
|
+
|
106
|
+
hasRouteBeenFound = true;
|
107
|
+
|
108
|
+
if (responsePreHandler) {
|
109
|
+
this[executeHandler]?.call(this, value, oldValue, result.splice(1,result.length - 1));
|
110
|
+
} else {
|
111
|
+
console.warn('No preHandler defined for routes -> todo it better');
|
112
|
+
}
|
113
|
+
return false;
|
114
|
+
|
115
|
+
}
|
116
|
+
return true;
|
117
|
+
});
|
118
|
+
|
119
|
+
if (Object.keys(me.handleRoutes).length > 0 && !hasRouteBeenFound) {
|
120
|
+
if (me.defaultRoute) {
|
121
|
+
this[me.defaultRoute]?.call(this, value, oldValue);
|
122
|
+
} else {
|
123
|
+
this.onNoRouteFound(value, oldValue);
|
124
|
+
}
|
125
|
+
}
|
47
126
|
}
|
48
127
|
|
49
128
|
/**
|
@@ -53,9 +132,10 @@ class Base extends CoreBase {
|
|
53
132
|
let currentHash = HashHistory.first();
|
54
133
|
|
55
134
|
currentHash && this.onHashChange(currentHash, null);
|
56
|
-
|
57
|
-
super.onConstructed();
|
58
135
|
}
|
136
|
+
|
137
|
+
|
138
|
+
|
59
139
|
}
|
60
140
|
|
61
141
|
Neo.applyClassConfig(Base);
|
@@ -69,10 +69,22 @@ class Component extends Base {
|
|
69
69
|
* @param {String} handlerName
|
70
70
|
* @returns {Neo.controller.Component|null}
|
71
71
|
*/
|
72
|
-
getHandlerScope(handlerName) {
|
72
|
+
getHandlerScope(handlerName, component) {
|
73
73
|
let me = this,
|
74
74
|
parent = me.parent;
|
75
75
|
|
76
|
+
if (component) {
|
77
|
+
// Look for ths function *name* first in the Component itself.
|
78
|
+
// If we find it, return true so calling code knows not to continue to search.
|
79
|
+
const handlerCb = component.resolveCallback(handlerName, component);
|
80
|
+
|
81
|
+
// Handler fn is resolved in the Component or its own parent chain.
|
82
|
+
// Return a status indicating that we do not need an erly binding
|
83
|
+
if (handlerCb.fn) {
|
84
|
+
return true;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
76
88
|
return Neo.isFunction(me[handlerName]) ?
|
77
89
|
me : parent ?
|
78
90
|
parent.getHandlerScope(handlerName) : null;
|
@@ -140,9 +152,12 @@ class Component extends Base {
|
|
140
152
|
eventHandler, handlerScope;
|
141
153
|
|
142
154
|
if (handler && typeof handler === 'string') {
|
143
|
-
handlerScope = me.getHandlerScope(handler);
|
155
|
+
handlerScope = me.getHandlerScope(handler, component);
|
144
156
|
|
145
|
-
|
157
|
+
// If the handler name was not resolved in the Component itself, bind it
|
158
|
+
if (handlerScope !== true) {
|
159
|
+
component.handler = handlerScope[handler].bind(component.handlerScope || handlerScope);
|
160
|
+
}
|
146
161
|
}
|
147
162
|
|
148
163
|
if (listeners) {
|
@@ -150,11 +165,11 @@ class Component extends Base {
|
|
150
165
|
if (key !== 'scope' && key !== 'delegate') {
|
151
166
|
if (Neo.isString(value)) {
|
152
167
|
eventHandler = value;
|
153
|
-
handlerScope = me.getHandlerScope(eventHandler);
|
168
|
+
handlerScope = me.getHandlerScope(eventHandler, component);
|
154
169
|
|
155
170
|
if (!handlerScope) {
|
156
171
|
Logger.logError('Unknown event handler for', eventHandler, component)
|
157
|
-
} else {
|
172
|
+
} else if (handlerScope !== true) {
|
158
173
|
listeners[key] = {};
|
159
174
|
listeners[key].fn = handlerScope[eventHandler].bind(handlerScope)
|
160
175
|
}
|
@@ -162,11 +177,11 @@ class Component extends Base {
|
|
162
177
|
value.forEach(listener => {
|
163
178
|
if (Neo.isObject(listener) && listener.hasOwnProperty('fn') && Neo.isString(listener.fn)) {
|
164
179
|
eventHandler = listener.fn;
|
165
|
-
handlerScope = me.getHandlerScope(eventHandler);
|
180
|
+
handlerScope = me.getHandlerScope(eventHandler, component);
|
166
181
|
|
167
182
|
if (!handlerScope) {
|
168
183
|
Logger.logError('Unknown event handler for', eventHandler, component)
|
169
|
-
} else {
|
184
|
+
} else if (handlerScope !== true) {
|
170
185
|
listener.fn = handlerScope[eventHandler].bind(handlerScope)
|
171
186
|
}
|
172
187
|
}
|
package/src/core/Observable.mjs
CHANGED
@@ -98,31 +98,50 @@ class Observable extends Base {
|
|
98
98
|
let me = this,
|
99
99
|
args = [].slice.call(arguments, 1),
|
100
100
|
listeners = me.listeners,
|
101
|
-
|
101
|
+
handler, handlers, i, len;
|
102
102
|
|
103
103
|
if (listeners && listeners[name]) {
|
104
|
-
|
105
|
-
len =
|
104
|
+
handlers = [...listeners[name]];
|
105
|
+
len = handlers.length;
|
106
106
|
|
107
107
|
for (i = 0; i < len; i++) {
|
108
|
-
|
108
|
+
handler = handlers[i];
|
109
109
|
|
110
|
-
|
111
|
-
|
112
|
-
|
110
|
+
// Resolve function name on the scope (oe me), or, if it starts with 'up.'
|
111
|
+
// look in the ownership hierarchy from me.
|
112
|
+
const cb = me.resolveCallback(handler.fn, handler.scope || me);
|
113
113
|
|
114
114
|
// remove the listener, in case the scope no longer exists
|
115
|
-
if (
|
115
|
+
if (cb.scope && !cb.scope.id) {
|
116
116
|
listeners[name].splice(i, 1);
|
117
117
|
} else {
|
118
118
|
if (!me.suspendEvents) {
|
119
|
-
|
119
|
+
// Object event format. Inject firer reference in as 'source'
|
120
|
+
if (args.length === 1 && typeof(args[0]) === 'object') {
|
121
|
+
args[0].source = me.id;
|
122
|
+
}
|
123
|
+
cb.fn.apply(cb.scope, handler.data ? args.concat(handler.data) : args);
|
120
124
|
}
|
121
125
|
}
|
122
126
|
}
|
123
127
|
}
|
124
128
|
}
|
125
129
|
|
130
|
+
/**
|
131
|
+
* Call the passed function, or a function by *name* which exists in the passed scope's
|
132
|
+
* or this component's ownership chain.
|
133
|
+
* @param {Function|String} fn A function, or the name of a function to find in the passed scope object/
|
134
|
+
* @param {Object} scope The scope to find the function in if it is specified as a string.
|
135
|
+
* @param {Array} args Arguments to pass to the callback.
|
136
|
+
*/
|
137
|
+
callback(fn, scope=this, args) {
|
138
|
+
if (fn) {
|
139
|
+
const handler = this.resolveCallback(fn, scope);
|
140
|
+
|
141
|
+
handler.fn.apply(handler.scope, args);
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
126
145
|
/**
|
127
146
|
* @param {Object} config
|
128
147
|
*/
|
@@ -240,6 +259,28 @@ class Observable extends Base {
|
|
240
259
|
|
241
260
|
// }
|
242
261
|
|
262
|
+
/**
|
263
|
+
* Locate a callable function by name in the passed scope.
|
264
|
+
*
|
265
|
+
* If the name starts with 'up.', the parent Component chain is searched.
|
266
|
+
*
|
267
|
+
* This is used by Observable.fire and by 'handler' function calls to resolve
|
268
|
+
* string function names in the Component's own hierarchy.
|
269
|
+
* @param {Function|String} fn A function, or the name of a function to find in the passed scope object/
|
270
|
+
* @param {Object} scope The scope to find the function in if it is specified as a string.
|
271
|
+
* @returns {Object}
|
272
|
+
*/
|
273
|
+
resolveCallback(fn, scope=this) {
|
274
|
+
if (typeof fn === 'string') {
|
275
|
+
if (!scope[fn] && fn.startsWith('up.')) {
|
276
|
+
fn = fn.slice(3);
|
277
|
+
while (!scope[fn] && (scope = scope.parent));
|
278
|
+
}
|
279
|
+
fn = scope[fn];
|
280
|
+
}
|
281
|
+
return { scope, fn };
|
282
|
+
}
|
283
|
+
|
243
284
|
/**
|
244
285
|
* Alias for removeListener
|
245
286
|
* @param {Object|String} name
|
package/src/dialog/Base.mjs
CHANGED
@@ -376,10 +376,7 @@ class Base extends Panel {
|
|
376
376
|
me.closeOrHide(false);
|
377
377
|
|
378
378
|
if (me.closeAction === 'hide') {
|
379
|
-
await Neo.applyDeltas(appName,
|
380
|
-
{id, cls: {remove: ['animated-hiding-showing']}},
|
381
|
-
{id, action: 'removeNode'}
|
382
|
-
])
|
379
|
+
await Neo.applyDeltas(appName, {id, action: 'removeNode'})
|
383
380
|
}
|
384
381
|
}
|
385
382
|
|
@@ -691,13 +691,17 @@ class FileUpload extends Base {
|
|
691
691
|
|
692
692
|
delete vdom.inert;
|
693
693
|
|
694
|
+
let isChangeEventNeeded;
|
695
|
+
|
694
696
|
switch (value) {
|
695
697
|
case 'ready':
|
696
698
|
anchor.tag = 'div';
|
697
699
|
anchor.href = '';
|
700
|
+
isChangeEventNeeded = true;
|
698
701
|
break;
|
699
702
|
case 'upload-failed':
|
700
703
|
status.innerHTML = `${me.uploadFailed}${isNaN(me.progress) ? '' : `... (${Math.round(me.progress * 100)}%)`}`;
|
704
|
+
isChangeEventNeeded = true;
|
701
705
|
break;
|
702
706
|
case 'processing':
|
703
707
|
status.innerHTML = `${me.scanning}... (${me.formatSize(me.uploadSize)})`;
|
@@ -706,6 +710,7 @@ class FileUpload extends Base {
|
|
706
710
|
case 'scan-failed':
|
707
711
|
status.innerHTML = `${me.malwareFoundInFile}. \u2022 ${me.fileSize}`;
|
708
712
|
me.error = me.pleaseCheck;
|
713
|
+
isChangeEventNeeded = true;
|
709
714
|
break;
|
710
715
|
case 'downloadable':
|
711
716
|
anchor.tag = 'a';
|
@@ -713,14 +718,20 @@ class FileUpload extends Base {
|
|
713
718
|
[me.documentIdParameter] : me.documentId
|
714
719
|
});
|
715
720
|
status.innerHTML = me.fileSize;
|
721
|
+
isChangeEventNeeded = true;
|
716
722
|
break;
|
717
723
|
case 'not-downloadable':
|
718
724
|
status.innerHTML = me.document ? me.fileSize : `${me.successfullyUploaded} \u2022 ${me.fileSize}`;
|
725
|
+
isChangeEventNeeded = true;
|
719
726
|
break;
|
720
727
|
case 'deleted':
|
721
728
|
status.innerHTML = me.fileWasDeleted;
|
729
|
+
isChangeEventNeeded = true;
|
722
730
|
}
|
723
731
|
|
732
|
+
if (isChangeEventNeeded) {
|
733
|
+
me.fireChangeEvent(me.file)
|
734
|
+
}
|
724
735
|
me.validate();
|
725
736
|
me.update();
|
726
737
|
|
@@ -32,10 +32,6 @@ class Picker extends Text {
|
|
32
32
|
* @protected
|
33
33
|
*/
|
34
34
|
clientRects: null,
|
35
|
-
/**
|
36
|
-
* @member {Boolean} editable_=true
|
37
|
-
*/
|
38
|
-
editable_: true,
|
39
35
|
/**
|
40
36
|
* Additional used keys for the selection model
|
41
37
|
* @member {Object} keys
|
@@ -110,19 +106,6 @@ class Picker extends Text {
|
|
110
106
|
})
|
111
107
|
}
|
112
108
|
|
113
|
-
/**
|
114
|
-
* Triggered after the editable config got changed
|
115
|
-
* @param {Boolean} value
|
116
|
-
* @param {Boolean} oldValue
|
117
|
-
* @protected
|
118
|
-
*/
|
119
|
-
afterSetEditable(value, oldValue) {
|
120
|
-
let cls = this.cls;
|
121
|
-
|
122
|
-
NeoArray.toggle(cls, 'neo-not-editable', !value);
|
123
|
-
this.cls = cls
|
124
|
-
}
|
125
|
-
|
126
109
|
/**
|
127
110
|
* Triggered after the mounted config got changed
|
128
111
|
* @param {Boolean} value
|
package/src/form/field/Range.mjs
CHANGED
@@ -5,6 +5,14 @@ import Number from './Number.mjs';
|
|
5
5
|
* @extends Neo.form.field.Number
|
6
6
|
*/
|
7
7
|
class Range extends Number {
|
8
|
+
/**
|
9
|
+
* Removing the debounce for range fields
|
10
|
+
* @member {Object} delayable
|
11
|
+
* @protected
|
12
|
+
* @static
|
13
|
+
*/
|
14
|
+
static delayable = {}
|
15
|
+
|
8
16
|
static config = {
|
9
17
|
/**
|
10
18
|
* @member {String} className='Neo.form.field.Range'
|
package/src/form/field/Text.mjs
CHANGED
@@ -75,6 +75,15 @@ class Text extends Base {
|
|
75
75
|
* @member {String[]|null} disabledChars_=null
|
76
76
|
*/
|
77
77
|
disabledChars_: null,
|
78
|
+
/**
|
79
|
+
* Setting `editable` to `false` means that the input field will be read-only
|
80
|
+
* but the field is still workable and may have its value changed by user interaction.
|
81
|
+
*
|
82
|
+
* For example picker fields such as `Date` and `Select` may still have their
|
83
|
+
* values changed by selecting from the picker using keyboard or pointer.
|
84
|
+
* @member {Boolean} editable_=true
|
85
|
+
*/
|
86
|
+
editable_: true,
|
78
87
|
/**
|
79
88
|
* Configure the value of empty fields. null or an empty string is recommended.
|
80
89
|
* @member {String|null} emptyValue=null
|
@@ -184,6 +193,10 @@ class Text extends Base {
|
|
184
193
|
*/
|
185
194
|
placeholderText_: null,
|
186
195
|
/**
|
196
|
+
* Setting `readOnly` means that the field may not be changed by user interaction.
|
197
|
+
*
|
198
|
+
* The input field will be read-only and other ways of changing the field's value
|
199
|
+
* (such as by operating pickers) will be disabled.
|
187
200
|
* @member {Boolean} readOnly_=false
|
188
201
|
*/
|
189
202
|
readOnly_: false,
|
@@ -342,6 +355,22 @@ class Text extends Base {
|
|
342
355
|
}
|
343
356
|
}
|
344
357
|
|
358
|
+
/**
|
359
|
+
* Triggered after the editable config got changed
|
360
|
+
* @param {Boolean} value
|
361
|
+
* @param {Boolean} oldValue
|
362
|
+
* @protected
|
363
|
+
*/
|
364
|
+
afterSetEditable(value, oldValue) {
|
365
|
+
const
|
366
|
+
me = this,
|
367
|
+
{ cls } = me;
|
368
|
+
|
369
|
+
NeoArray.toggle(cls, 'neo-not-editable', !value);
|
370
|
+
me.cls = cls
|
371
|
+
me.changeInputElKey('readonly', value ? false : true);
|
372
|
+
}
|
373
|
+
|
345
374
|
/**
|
346
375
|
* Triggered after the error config got changed
|
347
376
|
* @param {String|null} value
|
@@ -35,6 +35,13 @@ class Picker extends Base {
|
|
35
35
|
onTriggerClick(data) {
|
36
36
|
this.field.onPickerTriggerClick();
|
37
37
|
}
|
38
|
+
|
39
|
+
/**
|
40
|
+
* @returns {Boolean} true in case the trigger should be hidden
|
41
|
+
*/
|
42
|
+
getHiddenState() {
|
43
|
+
return !this.field.editable;
|
44
|
+
}
|
38
45
|
}
|
39
46
|
|
40
47
|
Neo.applyClassConfig(Picker);
|
package/src/main/DomEvents.mjs
CHANGED
@@ -262,12 +262,18 @@ class DomEvents extends Base {
|
|
262
262
|
path = event.path;
|
263
263
|
}
|
264
264
|
|
265
|
-
|
265
|
+
const result = {
|
266
266
|
path : path.map(e => this.getTargetData(e)),
|
267
267
|
target : this.getTargetData(event.target),
|
268
268
|
timeStamp: event.timeStamp,
|
269
269
|
type : event.type
|
270
|
+
};
|
271
|
+
|
272
|
+
if (event.relatedTarget) {
|
273
|
+
result.relatedTarget = this.getTargetData(event.relatedTarget);
|
270
274
|
}
|
275
|
+
|
276
|
+
return result;
|
271
277
|
}
|
272
278
|
|
273
279
|
/**
|
@@ -552,7 +558,7 @@ class DomEvents extends Base {
|
|
552
558
|
*/
|
553
559
|
onMouseEnter(event) {
|
554
560
|
let me = this,
|
555
|
-
appEvent = {...me.getMouseEventData(event), fromElementId: event.fromElement?.id || null};
|
561
|
+
appEvent = {...me.getMouseEventData(event), fromElementId: event.fromElement?.id || null, toElementId: event.toElement?.id || null};
|
556
562
|
|
557
563
|
me.sendMessageToApp(appEvent);
|
558
564
|
me.fire('mouseEnter', appEvent)
|
@@ -563,7 +569,7 @@ class DomEvents extends Base {
|
|
563
569
|
*/
|
564
570
|
onMouseLeave(event) {
|
565
571
|
let me = this,
|
566
|
-
appEvent = {...me.getMouseEventData(event), toElementId: event.toElement?.id || null};
|
572
|
+
appEvent = {...me.getMouseEventData(event), fromElementId: event.fromElement?.id || null, toElementId: event.toElement?.id || null};
|
567
573
|
|
568
574
|
me.sendMessageToApp(appEvent);
|
569
575
|
me.fire('mouseLeave', appEvent)
|
package/src/manager/DomEvent.mjs
CHANGED
@@ -127,6 +127,9 @@ class DomEvent extends Base {
|
|
127
127
|
data = Neo.clone(data, true, true);
|
128
128
|
|
129
129
|
data.component = component;
|
130
|
+
|
131
|
+
// Handler needs to know which actual target matched the delegate
|
132
|
+
data.currentTarget = delegationTargetId;
|
130
133
|
listener.fn.apply(listener.scope || globalThis, [data]);
|
131
134
|
|
132
135
|
if (!listener.bubble) {
|
package/src/menu/List.mjs
CHANGED