neo.mjs 6.5.1 → 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.
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='6.5.1'
23
+ * @member {String} version='6.5.2'
24
24
  */
25
- version: '6.5.1'
25
+ version: '6.5.2'
26
26
  }
27
27
 
28
28
  /**
@@ -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);
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='6.5.1'
23
+ * @member {String} version='6.5.2'
24
24
  */
25
- version: '6.5.1'
25
+ version: '6.5.2'
26
26
  }
27
27
 
28
28
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "6.5.1",
3
+ "version": "6.5.2",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -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.1'
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.1'
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 from '../../core/Base.mjs';
2
- import NeoFunction from '../../util/Function.mjs';
3
- import Observable from '../../core/Observable.mjs';
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
- NeoFunction.createInterceptor(value, 'send', me.beforeSend, me);
123
+ createInterceptor(value, 'send', me.beforeSend, me);
124
124
  }
125
125
 
126
126
  return value;
@@ -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
@@ -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']
@@ -1,84 +1,93 @@
1
- import Base from '../core/Base.mjs';
2
-
3
1
  /**
4
- * @class Neo.util.Function
5
- * @extends Neo.core.Base
2
+ * Append args instead of prepending them
3
+ * @param {Object} scope
4
+ * @returns {Function}
6
5
  */
7
- class NeoFunction extends Base {
8
- static config = {
9
- /**
10
- * @member {String} className='Neo.util.Function'
11
- * @protected
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
- * Append args instead of prepending them
18
- * @param {Object} scope
19
- * @returns {Function}
20
- */
21
- static bindAppend(scope) {
22
- const fn = this,
23
- args = [].slice.call(arguments).slice(1);
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
- return function() {
26
- return fn.apply(scope, [].slice.call(arguments).concat(args));
27
- }
28
- }
26
+ return (target[targetMethodName] = function(value) {
27
+ return targetMethod.call(target, interceptFunction.call(scope || target, value))
28
+ })
29
+ }
29
30
 
30
- /**
31
- * Intended for functions with 1 param where the interceptor can change the value
32
- * @param {Object} target
33
- * @param {String} targetMethodName
34
- * @param {Function} interceptFunction
35
- * @param {Object} scope=target
36
- * @returns {Function}
37
- */
38
- static createInterceptor(target, targetMethodName, interceptFunction, scope) {
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
- return (target[targetMethodName] = function(value) {
42
- return targetMethod.call(target, interceptFunction.call(scope || target, value));
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
- * @param {Neo.core.Base} target
48
- * @param {String} methodName
49
- * @param {Function} fn
50
- * @param {Object} scope
51
- * @returns {Function}
52
- */
53
- static createSequence(target, methodName, fn, scope) {
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
- return (target[methodName] = function() {
57
- method.apply(this, arguments);
58
- return fn.apply(scope || this, arguments);
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
- * The interceptor can prevent the targetMethod from getting executed in case it returns false.
64
- * @param {Object} target
65
- * @param {String} targetMethodName
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
- return (target[targetMethodName] = function() {
75
- return (interceptFunction.apply(scope || target, arguments) === false)
76
- ? preventedReturnValue
77
- : targetMethod.apply(target, arguments);
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
- Neo.applyClassConfig(NeoFunction);
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
- export default NeoFunction;
88
+ return (target[targetMethodName] = function() {
89
+ return (interceptFunction.apply(scope || target, arguments) === false)
90
+ ? preventedReturnValue
91
+ : targetMethod.apply(target, arguments)
92
+ })
93
+ }
@@ -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 = (alignSpec.startZone + 1) % 4,
454
+ zone : zone = (edges.theirEdgeZone + 1) % 4,
455
455
  edgeAlign : `${oppositeEdge[zoneEdges[zone]]}-${zoneEdges[zone]}`
456
456
  });
457
457
  zonesToTry.push({
458
- zone : zone = (zone + 2) % 4,
458
+ zone : zone = (edges.theirEdgeZone + 3) % 4,
459
459
  edgeAlign : `${oppositeEdge[zoneEdges[zone]]}-${zoneEdges[zone]}`
460
460
  });
461
461
  }