neo.mjs 5.6.11 → 5.7.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.
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.6.11'
23
+ * @member {String} version='5.7.0'
24
24
  */
25
- version: '5.6.11'
25
+ version: '5.7.0'
26
26
  }
27
27
 
28
28
  /**
@@ -3,6 +3,6 @@
3
3
  "basePath" : "../../",
4
4
  "environment" : "development",
5
5
  "mainPath" : "./Main.mjs",
6
- "mainThreadAddons": ["AmCharts", "DragDrop", "MapboxGL", "Stylesheet"],
6
+ "mainThreadAddons": ["AmCharts", "DragDrop", "MapboxGL", "ScrollSync", "Stylesheet"],
7
7
  "themes" : ["neo-theme-dark", "neo-theme-light"]
8
8
  }
@@ -3,5 +3,5 @@
3
3
  "basePath" : "../../",
4
4
  "environment" : "development",
5
5
  "mainPath" : "./Main.mjs",
6
- "mainThreadAddons": ["DragDrop", "LocalStorage", "Stylesheet"]
6
+ "mainThreadAddons": ["DragDrop", "LocalStorage", "ScrollSync", "Stylesheet"]
7
7
  }
@@ -21,6 +21,10 @@ class FormPageContainer extends FormContainer {
21
21
  * @member {Object} layout={ntype:'vbox'}
22
22
  */
23
23
  layout: {ntype: 'vbox'},
24
+ /**
25
+ * @member {Object} style={overflow:'auto'}
26
+ */
27
+ style: {overflow: 'auto'},
24
28
  /**
25
29
  * @member {Object} _vdom
26
30
  */
@@ -18,7 +18,8 @@ class Page2 extends FormPageContainer {
18
18
  items: [{
19
19
  module : DateField,
20
20
  labelText: 'Birthday',
21
- name : 'birthday'
21
+ name : 'birthday',
22
+ style : {marginBottom: '800px', marginTop: '800px'}
22
23
  }]
23
24
  }
24
25
  }
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.6.11'
23
+ * @member {String} version='5.7.0'
24
24
  */
25
- version: '5.6.11'
25
+ version: '5.7.0'
26
26
  }
27
27
 
28
28
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "5.6.11",
3
+ "version": "5.7.0",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -57,7 +57,7 @@
57
57
  "neo-jsdoc-x": "^1.0.5",
58
58
  "postcss": "^8.4.23",
59
59
  "sass": "^1.62.1",
60
- "webpack": "^5.82.0",
60
+ "webpack": "^5.82.1",
61
61
  "webpack-cli": "^5.1.1",
62
62
  "webpack-dev-server": "4.15.0",
63
63
  "webpack-hook-plugin": "^1.0.7",
@@ -236,12 +236,12 @@ const DefaultConfig = {
236
236
  useVdomWorker: true,
237
237
  /**
238
238
  * buildScripts/injectPackageVersion.mjs will update this value
239
- * @default '5.6.11'
239
+ * @default '5.7.0'
240
240
  * @memberOf! module:Neo
241
241
  * @name config.version
242
242
  * @type String
243
243
  */
244
- version: '5.6.11'
244
+ version: '5.7.0'
245
245
  };
246
246
 
247
247
  Object.assign(DefaultConfig, {
package/src/Main.mjs CHANGED
@@ -431,14 +431,22 @@ class Main extends core.Base {
431
431
  }
432
432
 
433
433
  /**
434
- * Open a new popup window
434
+ * Open a new popup window and return if successfull
435
435
  * @param {Object} data
436
436
  * @param {String} data.url
437
437
  * @param {String} data.windowFeatures
438
438
  * @param {String} data.windowName
439
- */
439
+ * @return {Boolean}
440
+ */
440
441
  windowOpen(data) {
441
- this.openWindows[data.windowName] = window.open(data.url, data.windowName, data.windowFeatures);
442
+ let openedWindow = window.open(data.url, data.windowName, data.windowFeatures),
443
+ success = !!openedWindow;
444
+
445
+ if (success) {
446
+ this.openWindows[data.windowName] = openedWindow;
447
+ }
448
+
449
+ return success;
442
450
  }
443
451
 
444
452
  /**
@@ -270,9 +270,16 @@ class Picker extends Text {
270
270
  // avoid breaking selection model cls updates
271
271
  await Neo.timeout(30);
272
272
 
273
- me.pickerIsMounted && picker.unmount();
273
+ if (me.pickerIsMounted) {
274
+ picker.unmount();
275
+
276
+ me.pickerIsMounted = false;
274
277
 
275
- me.pickerIsMounted = false;
278
+ Neo.main.addon.ScrollSync.unregister({
279
+ sourceId: me.id,
280
+ targetId: picker.id
281
+ })
282
+ }
276
283
  }
277
284
 
278
285
  /**
@@ -372,6 +379,11 @@ class Picker extends Text {
372
379
  });
373
380
 
374
381
  picker.render(true);
382
+
383
+ Neo.main.addon.ScrollSync.register({
384
+ sourceId: me.id,
385
+ targetId: picker.id
386
+ })
375
387
  }
376
388
  }
377
389
 
@@ -637,7 +637,7 @@ class Select extends Picker {
637
637
  cls: ['neo-input-field-wrapper'],
638
638
  cn : [{
639
639
  tag : 'input',
640
- autocomplete: 'off',
640
+ autocomplete: 'no',
641
641
  autocorrect : 'off',
642
642
  cls : ['neo-textfield-input', 'neo-typeahead-input'],
643
643
  id : me.getInputHintId(),
@@ -258,12 +258,13 @@ class Text extends Base {
258
258
 
259
259
  /**
260
260
  * Triggered after the autoComplete config got changed
261
+ * Chrome ignores a value of "off", so we stick to a different value instead
261
262
  * @param {Boolean} value
262
263
  * @param {Boolean} oldValue
263
264
  * @protected
264
265
  */
265
266
  afterSetAutoComplete(value, oldValue) {
266
- this.changeInputElKey('autocomplete', value ? null : 'off');
267
+ this.changeInputElKey('autocomplete', value ? null : 'no');
267
268
  }
268
269
 
269
270
  /**
@@ -310,10 +310,13 @@ class DragDrop extends Base {
310
310
  }
311
311
 
312
312
  if (!me.dragProxyElement || me.alwaysFireDragMove) {
313
+ const originalEvent = event.detail.originalEvent;
313
314
  DomEvents.sendMessageToApp({
314
315
  ...me.getEventData(event),
315
316
  offsetX: me.offsetX,
316
317
  offsetY: me.offsetY,
318
+ screenX: originalEvent.screenX,
319
+ screenY: originalEvent.screenY,
317
320
  type : 'drag:move'
318
321
  });
319
322
  }
@@ -167,8 +167,6 @@ class GoogleMaps extends Base {
167
167
  let key = Neo.config.googleMapsApiKey,
168
168
  url = ' https://maps.googleapis.com/maps/api/js';
169
169
 
170
- window.foo = Neo.emptyFn;
171
-
172
170
  DomAccess.loadScript(`${url}?key=${key}&v=weekly&callback=Neo.emptyFn`).then(() => {
173
171
  console.log('GoogleMaps API loaded');
174
172
  })
@@ -1,6 +1,10 @@
1
- import Base from '../../core/Base.mjs';
1
+ import Base from '../../core/Base.mjs';
2
+ import DomEvents from '../DomEvents.mjs'
2
3
 
3
4
  /**
5
+ * This addon keeps the position of overlays in sync with an anchor element,
6
+ * when scrolling inside any parent node.
7
+ * A prominent use case is Neo.form.field.Picker.
4
8
  * @class Neo.main.addon.ScrollSync
5
9
  * @extends Neo.core.Base
6
10
  * @singleton
@@ -30,29 +34,113 @@ class ScrollSync extends Base {
30
34
  singleton: true
31
35
  }
32
36
 
37
+ /**
38
+ * @member {Object} sourceMap={}
39
+ * @protected
40
+ */
41
+ sourceMap = {}
42
+
43
+ /**
44
+ * @param {Object} config
45
+ */
46
+ construct(config = {}) {
47
+ super.construct(config);
48
+
49
+ document.addEventListener('scroll', this.onDocumentScroll.bind(this), true)
50
+ }
51
+
52
+ /**
53
+ * @param {Event} event
54
+ */
55
+ onDocumentScroll(event) {
56
+ let me = this,
57
+ scrollNode = event.target,
58
+ sourceRect, targetNode;
59
+
60
+ me.sourceMap[scrollNode.id]?.forEach(item => {
61
+ sourceRect = document.getElementById(item.sourceId).getBoundingClientRect();
62
+ targetNode = document.getElementById(item.targetId)
63
+
64
+ targetNode.style.left = `${sourceRect.x + item.deltaX}px`;
65
+ targetNode.style.top = `${sourceRect.y + item.deltaY}px`
66
+ })
67
+ }
68
+
33
69
  /**
34
70
  * @param {Object} data
35
71
  * @param {String} data.sourceId
36
72
  * @param {String} data.targetId
73
+ * @returns Promise<Boolean>
37
74
  */
38
- register(data) {
39
- console.log('register', data)
75
+ async register(data) {
76
+ // short delay to ensure the target node got mounted
77
+ await Neo.timeout(50)
78
+
79
+ let sourceId = data.sourceId,
80
+ sourceMap = this.sourceMap,
81
+ sourceNode = document.getElementById(sourceId),
82
+ sourceRect = sourceNode.getBoundingClientRect(),
83
+ parentNode = sourceNode.parentNode,
84
+ targetId = data.targetId,
85
+ targetRect = document.getElementById(targetId).getBoundingClientRect(),
86
+ deltaX = targetRect.x - sourceRect.x,
87
+ deltaY = targetRect.y - sourceRect.y,
88
+ overflowX, overflowY, parentId;
89
+
90
+ while (parentNode && parentNode.id) {
91
+ parentId = parentNode.id;
92
+
93
+ ({overflowX, overflowY} = getComputedStyle(parentNode))
94
+
95
+ if (overflowX === 'auto' || overflowX === 'scroll' || overflowY === 'auto' || overflowY === 'scroll') {
96
+ if (!sourceMap[parentId]) {
97
+ sourceMap[parentId] = []
98
+ }
99
+
100
+ sourceMap[parentId].push({deltaX, deltaY, sourceId, targetId})
101
+ }
102
+
103
+ parentNode = parentNode.parentNode
104
+ }
105
+
106
+ return true
40
107
  }
41
108
 
42
109
  /**
43
110
  * @param {Object} data
44
111
  * @param {String} data.sourceId
45
112
  * @param {String} data.targetId
113
+ * @returns {Boolean}
46
114
  */
47
115
  unregister(data) {
48
- console.log('unregister', data)
49
- }
50
- }
116
+ let sourceId = data.sourceId,
117
+ sourceMap = this.sourceMap,
118
+ sourceNode = document.getElementById(sourceId),
119
+ parentNode = sourceNode.parentNode,
120
+ parentId;
121
+
122
+ while (parentNode && parentNode.id) {
123
+ parentId = parentNode.id;
124
+
125
+ if (sourceMap[parentId]) {
126
+ [...sourceMap[parentId]].forEach((item, index) => {
127
+ if (item.sourceId === sourceId && item.targetId === data.targetId) {
128
+ sourceMap[parentId].splice(index, 1)
129
+ }
130
+ })
51
131
 
52
- Neo.applyClassConfig(ScrollSync);
132
+ if (sourceMap[parentId].length < 1) {
133
+ delete sourceMap[parentId]
134
+ }
135
+ }
53
136
 
54
- let instance = Neo.create(ScrollSync);
137
+ parentNode = parentNode.parentNode
138
+ }
139
+
140
+ return true
141
+ }
142
+ }
55
143
 
56
- Neo.applyToGlobalNs(instance);
144
+ let instance = Neo.applyClassConfig(ScrollSync);
57
145
 
58
146
  export default instance;