neo.mjs 6.5.0 → 6.5.2
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/form/view/pages/Page1.mjs +14 -0
- package/examples/ServiceWorker.mjs +2 -2
- package/package.json +1 -1
- package/src/DefaultConfig.mjs +2 -2
- package/src/core/Base.mjs +34 -0
- package/src/data/connection/WebSocket.mjs +4 -4
- package/src/form/Container.mjs +6 -3
- package/src/form/field/Base.mjs +7 -0
- package/src/form/field/Text.mjs +11 -0
- package/src/util/Function.mjs +78 -69
- package/src/util/Rectangle.mjs +2 -2
package/apps/ServiceWorker.mjs
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import Button from '../../../../src/button/Base.mjs';
|
1
2
|
import FormPageContainer from '../FormPageContainer.mjs';
|
2
3
|
import TextField from '../../../../src/form/field/Text.mjs';
|
3
4
|
|
@@ -31,8 +32,21 @@ class Page1 extends FormPageContainer {
|
|
31
32
|
name : 'status',
|
32
33
|
readOnly : true,
|
33
34
|
value : 'Active'
|
35
|
+
}, {
|
36
|
+
module : Button,
|
37
|
+
handler: Page1.buttonHandler,
|
38
|
+
style : {marginTop: '2em', maxWidth: '300px'},
|
39
|
+
text : 'Change values'
|
34
40
|
}]
|
35
41
|
}
|
42
|
+
|
43
|
+
static buttonHandler(data) {
|
44
|
+
let container = data.component.up();
|
45
|
+
|
46
|
+
container.items[0].value = Math.random();
|
47
|
+
container.items[1].value = Math.random();
|
48
|
+
container.items[2].value = Math.random()
|
49
|
+
}
|
36
50
|
}
|
37
51
|
|
38
52
|
Neo.applyClassConfig(Page1);
|
package/package.json
CHANGED
package/src/DefaultConfig.mjs
CHANGED
@@ -236,12 +236,12 @@ const DefaultConfig = {
|
|
236
236
|
useVdomWorker: true,
|
237
237
|
/**
|
238
238
|
* buildScripts/injectPackageVersion.mjs will update this value
|
239
|
-
* @default '6.5.
|
239
|
+
* @default '6.5.2'
|
240
240
|
* @memberOf! module:Neo
|
241
241
|
* @name config.version
|
242
242
|
* @type String
|
243
243
|
*/
|
244
|
-
version: '6.5.
|
244
|
+
version: '6.5.2'
|
245
245
|
};
|
246
246
|
|
247
247
|
Object.assign(DefaultConfig, {
|
package/src/core/Base.mjs
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import {debounce} from '../util/Function.mjs';
|
1
2
|
import IdGenerator from './IdGenerator.mjs'
|
2
3
|
|
3
4
|
const configSymbol = Symbol.for('configSymbol'),
|
@@ -17,6 +18,20 @@ class Base {
|
|
17
18
|
* @static
|
18
19
|
*/
|
19
20
|
static methodNameRegex = /\n.*\n\s+at\s+.*\.(\w+)\s+.*/
|
21
|
+
/**
|
22
|
+
* You can define methods which should get delayed
|
23
|
+
* @example
|
24
|
+
* delayable: {
|
25
|
+
* fireChangeEvent: {
|
26
|
+
* type : 'debounce',
|
27
|
+
* timer: 300
|
28
|
+
* }
|
29
|
+
* }
|
30
|
+
* @member {Object} delayable={}
|
31
|
+
* @protected
|
32
|
+
* @static
|
33
|
+
*/
|
34
|
+
static delayable = {}
|
20
35
|
/**
|
21
36
|
* True automatically applies the core.Observable mixin
|
22
37
|
* @member {Boolean} observable=false
|
@@ -126,6 +141,8 @@ class Base {
|
|
126
141
|
value : true
|
127
142
|
});
|
128
143
|
|
144
|
+
me.applyDelayable();
|
145
|
+
|
129
146
|
me.remote && setTimeout(me.initRemote.bind(me), 1)
|
130
147
|
}
|
131
148
|
|
@@ -157,6 +174,23 @@ class Base {
|
|
157
174
|
}
|
158
175
|
}
|
159
176
|
|
177
|
+
/**
|
178
|
+
* Adjusts all methods inside static delayable
|
179
|
+
*/
|
180
|
+
applyDelayable() {
|
181
|
+
let me = this;
|
182
|
+
|
183
|
+
Object.entries(me.constructor.delayable).forEach(([key, value]) => {
|
184
|
+
let map = {
|
185
|
+
debounce() {
|
186
|
+
me[key] = new debounce(me[key], me, value.timer)
|
187
|
+
}
|
188
|
+
};
|
189
|
+
|
190
|
+
map[value.type]?.()
|
191
|
+
})
|
192
|
+
}
|
193
|
+
|
160
194
|
/**
|
161
195
|
* Applying overwrites and adding overwrittenMethods to the class constructors
|
162
196
|
* @param {Object} cfg
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import Base
|
2
|
-
import
|
3
|
-
import Observable
|
1
|
+
import Base from '../../core/Base.mjs';
|
2
|
+
import {createInterceptor} from '../../util/Function.mjs';
|
3
|
+
import Observable from '../../core/Observable.mjs';
|
4
4
|
|
5
5
|
/**
|
6
6
|
* @class Neo.data.connection.WebSocket
|
@@ -120,7 +120,7 @@ class Socket extends Base {
|
|
120
120
|
onopen : me.onOpen .bind(me)
|
121
121
|
});
|
122
122
|
|
123
|
-
|
123
|
+
createInterceptor(value, 'send', me.beforeSend, me);
|
124
124
|
}
|
125
125
|
|
126
126
|
return value;
|
package/src/form/Container.mjs
CHANGED
@@ -33,7 +33,6 @@ class Container extends BaseContainer {
|
|
33
33
|
|
34
34
|
/**
|
35
35
|
* Helper function used by setValues() which wraps the leaves of a tree structure into a new property.
|
36
|
-
* The logic assumes that field config values must not be objects (separation between the key & value realm).
|
37
36
|
* @param {Object} values
|
38
37
|
* @param {String} configName
|
39
38
|
* @param {String[]} fieldPaths
|
@@ -313,11 +312,15 @@ class Container extends BaseContainer {
|
|
313
312
|
*/
|
314
313
|
async setValues(values={}, suspendEvents=false) {
|
315
314
|
let fields = await this.getFields(),
|
316
|
-
fieldPaths = []
|
315
|
+
fieldPaths = [],
|
316
|
+
path;
|
317
317
|
|
318
318
|
// Grouped CheckBoxes & Radios can have the same path
|
319
319
|
// => using NeoArray to ensure they only get added once
|
320
|
-
fields.map(field =>
|
320
|
+
fields.map(field => {
|
321
|
+
path = field.getPath();
|
322
|
+
path && NeoArray.add(fieldPaths, path)
|
323
|
+
});
|
321
324
|
|
322
325
|
values = Neo.clone(values, true);
|
323
326
|
|
package/src/form/field/Base.mjs
CHANGED
@@ -184,6 +184,13 @@ class Base extends Component {
|
|
184
184
|
let me = this,
|
185
185
|
path;
|
186
186
|
|
187
|
+
// fields could have formGroups, but no name.
|
188
|
+
// returning the namespace can confuse form.Container.adjustTreeLeaves(),
|
189
|
+
// since namespaces could be considered as field instances.
|
190
|
+
if (!me.name) {
|
191
|
+
return null
|
192
|
+
}
|
193
|
+
|
187
194
|
if (!me.path) {
|
188
195
|
path = me.formGroup ? me.formGroup.split('.') : [];
|
189
196
|
|
package/src/form/field/Text.mjs
CHANGED
@@ -17,6 +17,17 @@ class Text extends Base {
|
|
17
17
|
* @static
|
18
18
|
*/
|
19
19
|
static autoCapitalizeValues = ['characters', 'none', 'on', 'off', 'sentences', 'words']
|
20
|
+
/**
|
21
|
+
* @member {Object} delayable
|
22
|
+
* @protected
|
23
|
+
* @static
|
24
|
+
*/
|
25
|
+
static delayable = {
|
26
|
+
fireChangeEvent: {
|
27
|
+
type : 'debounce',
|
28
|
+
timer: 300
|
29
|
+
}
|
30
|
+
}
|
20
31
|
/**
|
21
32
|
* Valid values for labelPosition
|
22
33
|
* @member {String[]} labelPositions=['bottom','inline','left','right','top']
|
package/src/util/Function.mjs
CHANGED
@@ -1,84 +1,93 @@
|
|
1
|
-
import Base from '../core/Base.mjs';
|
2
|
-
|
3
1
|
/**
|
4
|
-
*
|
5
|
-
* @
|
2
|
+
* Append args instead of prepending them
|
3
|
+
* @param {Object} scope
|
4
|
+
* @returns {Function}
|
6
5
|
*/
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
className: 'Neo.util.Function'
|
6
|
+
export function bindAppend(scope) {
|
7
|
+
const fn = this,
|
8
|
+
args = [].slice.call(arguments).slice(1);
|
9
|
+
|
10
|
+
return function() {
|
11
|
+
return fn.apply(scope, [].slice.call(arguments).concat(args))
|
14
12
|
}
|
13
|
+
}
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
/**
|
16
|
+
* Intended for functions with 1 param where the interceptor can change the value
|
17
|
+
* @param {Object} target
|
18
|
+
* @param {String} targetMethodName
|
19
|
+
* @param {Function} interceptFunction
|
20
|
+
* @param {Object} scope=target
|
21
|
+
* @returns {Function}
|
22
|
+
*/
|
23
|
+
export function createInterceptor(target, targetMethodName, interceptFunction, scope) {
|
24
|
+
let targetMethod = target[targetMethodName];
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
return (target[targetMethodName] = function(value) {
|
27
|
+
return targetMethod.call(target, interceptFunction.call(scope || target, value))
|
28
|
+
})
|
29
|
+
}
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
let targetMethod = target[targetMethodName];
|
31
|
+
/**
|
32
|
+
* @param {Neo.core.Base} target
|
33
|
+
* @param {String} methodName
|
34
|
+
* @param {Function} fn
|
35
|
+
* @param {Object} scope
|
36
|
+
* @returns {Function}
|
37
|
+
*/
|
38
|
+
export function createSequence(target, methodName, fn, scope) {
|
39
|
+
let method = target[methodName] || Neo.emptyFn;
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
}
|
41
|
+
return (target[methodName] = function() {
|
42
|
+
method.apply(this, arguments);
|
43
|
+
return fn.apply(scope || this, arguments);
|
44
|
+
})
|
45
|
+
}
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
let method = target[methodName] || Neo.emptyFn;
|
47
|
+
/**
|
48
|
+
* @param {Function} func
|
49
|
+
* @param {Neo.core.Base} scope
|
50
|
+
* @param {Number} timeout
|
51
|
+
* @returns {Function}
|
52
|
+
*/
|
53
|
+
export function debounce(func, scope, timeout=300) {
|
54
|
+
let debounceTimer;
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
return function(...args) {
|
57
|
+
// leading edge => trigger the first call right away
|
58
|
+
if (!Neo.isNumber(debounceTimer)) {
|
59
|
+
// we need to check if the scope (instance) did not get destroyed yet
|
60
|
+
scope?.id && func.apply(scope, args);
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
* @param {Function} interceptFunction
|
67
|
-
* @param {Object} scope=target
|
68
|
-
* @param {*} preventedReturnValue=null The value to return in case the interceptFunction returns false
|
69
|
-
* @returns {Function}
|
70
|
-
*/
|
71
|
-
static intercept(target, targetMethodName, interceptFunction, scope, preventedReturnValue=null) {
|
72
|
-
let targetMethod = target[targetMethodName];
|
62
|
+
// we still want to start a timer, do delay the 2nd+ update
|
63
|
+
debounceTimer = setTimeout(() => {debounceTimer = null}, timeout)
|
64
|
+
} else {
|
65
|
+
clearTimeout(debounceTimer);
|
73
66
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
67
|
+
debounceTimer = setTimeout(() => {
|
68
|
+
// we need to check if the scope (instance) did not get destroyed yet
|
69
|
+
scope?.id && func.apply(scope, args);
|
70
|
+
debounceTimer = setTimeout(() => {debounceTimer = null}, timeout)
|
71
|
+
}, timeout)
|
72
|
+
}
|
79
73
|
}
|
80
74
|
}
|
81
75
|
|
82
|
-
|
76
|
+
/**
|
77
|
+
* The interceptor can prevent the targetMethod from getting executed in case it returns false.
|
78
|
+
* @param {Object} target
|
79
|
+
* @param {String} targetMethodName
|
80
|
+
* @param {Function} interceptFunction
|
81
|
+
* @param {Object} scope=target
|
82
|
+
* @param {*} preventedReturnValue=null The value to return in case the interceptFunction returns false
|
83
|
+
* @returns {Function}
|
84
|
+
*/
|
85
|
+
export function intercept(target, targetMethodName, interceptFunction, scope, preventedReturnValue=null) {
|
86
|
+
let targetMethod = target[targetMethodName];
|
83
87
|
|
84
|
-
|
88
|
+
return (target[targetMethodName] = function() {
|
89
|
+
return (interceptFunction.apply(scope || target, arguments) === false)
|
90
|
+
? preventedReturnValue
|
91
|
+
: targetMethod.apply(target, arguments)
|
92
|
+
})
|
93
|
+
}
|
package/src/util/Rectangle.mjs
CHANGED
@@ -451,11 +451,11 @@ export default class Rectangle extends DOMRect {
|
|
451
451
|
|
452
452
|
// Fall back to the other two zones.
|
453
453
|
zonesToTry.push({
|
454
|
-
zone : zone = (
|
454
|
+
zone : zone = (edges.theirEdgeZone + 1) % 4,
|
455
455
|
edgeAlign : `${oppositeEdge[zoneEdges[zone]]}-${zoneEdges[zone]}`
|
456
456
|
});
|
457
457
|
zonesToTry.push({
|
458
|
-
zone : zone = (
|
458
|
+
zone : zone = (edges.theirEdgeZone + 3) % 4,
|
459
459
|
edgeAlign : `${oppositeEdge[zoneEdges[zone]]}-${zoneEdges[zone]}`
|
460
460
|
});
|
461
461
|
}
|