neo.mjs 6.9.1 → 6.9.3

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.9.1'
23
+ * @member {String} version='6.9.3'
24
24
  */
25
- version: '6.9.1'
25
+ version: '6.9.3'
26
26
  }
27
27
 
28
28
  /**
@@ -20,7 +20,7 @@ class MainContainerController extends Component {
20
20
  '/contact': 'handleContactRoute',
21
21
  '/users/{userId}': { handler: 'handleUserRoute', preHandler: 'doPrehandling' },
22
22
  // '/users/{userId}' : {handler: 'handleUserRoute', preHandler: 'doPrehandling'}, //example
23
- // '/users/{userId}/posts/{postId}' : {handler:'handleUserPostsRoute', preHandler: 'doPrehandlingFalse'}, //example
23
+ //'/users/{userId}/posts/{postId}' : {handler:'handleUserPostsRoute', preHandler: 'doPrehandlingFalse'}, //example
24
24
  // default: 'doDefaultHandling' //optional - example
25
25
  },
26
26
 
@@ -46,7 +46,7 @@ class MainContainerController extends Component {
46
46
 
47
47
 
48
48
  doPrehandling(value, oldValue, params = null) {
49
- const userId = parseInt(params);
49
+ const userId = parseInt(params.userId);
50
50
  if (userId > 0 && userId === this.data.activeUser) {
51
51
  return true;
52
52
  }
@@ -132,7 +132,6 @@ class MainContainerController extends Component {
132
132
  * @param {Object} data
133
133
  */
134
134
  onSwitchButtonMetaReset(data) {
135
- const currentUser = this.data.activeUser;
136
135
  this.data.activeUser = 0;
137
136
  this.#setUsername();
138
137
  this.#removeMetaButtonSelection();
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='6.9.1'
23
+ * @member {String} version='6.9.3'
24
24
  */
25
- version: '6.9.1'
25
+ version: '6.9.3'
26
26
  }
27
27
 
28
28
  /**
@@ -69,13 +69,14 @@ class MainContainer extends Viewport {
69
69
  weight: -10000,
70
70
 
71
71
  // Embed a tooltip request into the DOM
72
- vdom : {
73
- data : {
74
- 'neo-tooltip' : 'The Label'
72
+ vdom: {
73
+ data: {
74
+ neoTooltip: 'The Label'
75
75
  }
76
76
  }
77
77
  },
78
78
  rowsPerPage: {
79
+ style : {margin: '0 .5em'},
79
80
  tooltip: 'Set the number of rows to display in a page',
80
81
  weight : -999
81
82
  }
@@ -23,10 +23,6 @@ class MainContainer extends ConfigurationViewport {
23
23
  cls : ['examples-container-accordion']
24
24
  }
25
25
 
26
- onConfigChange(config, opts) {
27
- this.exampleComponent.items[0][config] = opts.value;
28
- }
29
-
30
26
  createConfigurationComponents() {
31
27
  let me = this,
32
28
  treeList = me.exampleComponent.items[0];
@@ -74,6 +70,12 @@ class MainContainer extends ConfigurationViewport {
74
70
  stepSize : 3,
75
71
  style : {marginTop: '10px'},
76
72
  value : 400
73
+ }, {
74
+ ntype : 'button',
75
+ handler: me.onRemoveDomButtonClick.bind(me),
76
+ style : {marginTop: '20px'},
77
+ text : 'Remove DOM',
78
+ width : 100
77
79
  }];
78
80
  }
79
81
 
@@ -169,6 +171,23 @@ class MainContainer extends ConfigurationViewport {
169
171
  }]
170
172
  });
171
173
  }
174
+
175
+ /**
176
+ * @param {String} config
177
+ * @param {Object} opts
178
+ */
179
+ onConfigChange(config, opts) {
180
+ this.exampleComponent.items[0][config] = opts.value;
181
+ }
182
+
183
+ /**
184
+ *
185
+ * @param data
186
+ */
187
+ onRemoveDomButtonClick(data) {
188
+ let accordion = this.exampleComponent.items[0];
189
+ accordion.hidden = !accordion.hidden
190
+ }
172
191
  }
173
192
 
174
193
  Neo.applyClassConfig(MainContainer);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "6.9.1",
3
+ "version": "6.9.3",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -56,7 +56,7 @@
56
56
  "neo-jsdoc": "1.0.1",
57
57
  "neo-jsdoc-x": "1.0.5",
58
58
  "postcss": "^8.4.31",
59
- "sass": "^1.69.3",
59
+ "sass": "^1.69.4",
60
60
  "showdown": "^2.1.0",
61
61
  "webpack": "^5.89.0",
62
62
  "webpack-cli": "^5.1.4",
@@ -236,12 +236,12 @@ const DefaultConfig = {
236
236
  useVdomWorker: true,
237
237
  /**
238
238
  * buildScripts/injectPackageVersion.mjs will update this value
239
- * @default '6.9.1'
239
+ * @default '6.9.3'
240
240
  * @memberOf! module:Neo
241
241
  * @name config.version
242
242
  * @type String
243
243
  */
244
- version: '6.9.1'
244
+ version: '6.9.3'
245
245
  };
246
246
 
247
247
  Object.assign(DefaultConfig, {
@@ -98,7 +98,7 @@ class Filter extends Base {
98
98
  }
99
99
 
100
100
  afterSetDisabled(...args) {
101
- this.fireChangeEvent(...args);
101
+ this.fireChangeEvent(...args)
102
102
  }
103
103
 
104
104
  afterSetFilterBy(value, oldValue) {
@@ -106,28 +106,28 @@ class Filter extends Base {
106
106
  }
107
107
 
108
108
  afterSetIsUpdating(value, oldValue) {
109
- value === false && this.fireChangeEvent(value, oldValue);
109
+ value === false && this.fireChangeEvent(value, oldValue)
110
110
  }
111
111
 
112
112
  afterSetOperator(...args) {
113
- this.fireChangeEvent(...args);
113
+ this.fireChangeEvent(...args)
114
114
  }
115
115
 
116
116
  afterSetProperty(...args) {
117
- this.fireChangeEvent(...args);
117
+ this.fireChangeEvent(...args)
118
118
  }
119
119
 
120
120
  afterSetValue(...args) {
121
- this.fireChangeEvent(...args);
121
+ this.fireChangeEvent(...args)
122
122
  }
123
123
 
124
124
  beforeSetFilterBy(value, oldValue) {
125
125
  if (value && typeof value !== 'function') {
126
126
  Neo.logError('filterBy has to be a function', this);
127
- return oldValue;
127
+ return oldValue
128
128
  }
129
129
 
130
- return value;
130
+ return value
131
131
  }
132
132
 
133
133
  /**
@@ -138,7 +138,7 @@ class Filter extends Base {
138
138
  * @protected
139
139
  */
140
140
  beforeSetOperator(value, oldValue) {
141
- return this.beforeSetEnumValue(value, oldValue, 'operator');
141
+ return this.beforeSetEnumValue(value, oldValue, 'operator')
142
142
  }
143
143
 
144
144
  /**
@@ -152,10 +152,10 @@ class Filter extends Base {
152
152
  value = me.value;
153
153
 
154
154
  if (!me.filterBy) {
155
- return {operator, property, value};
155
+ return {operator, property, value}
156
156
  }
157
157
 
158
- return null;
158
+ return null
159
159
  }
160
160
 
161
161
  /**
@@ -170,7 +170,7 @@ class Filter extends Base {
170
170
  operator: me.operator,
171
171
  property: me.property,
172
172
  value : me.value
173
- });
173
+ })
174
174
  }
175
175
  }
176
176
 
@@ -187,7 +187,7 @@ class Filter extends Base {
187
187
  filterValue, recordValue;
188
188
 
189
189
  if (me._disabled) {
190
- return false;
190
+ return false
191
191
  }
192
192
 
193
193
  if (me._filterBy) {
@@ -196,11 +196,11 @@ class Filter extends Base {
196
196
  filteredItems,
197
197
  item,
198
198
  value: me._value
199
- });
199
+ })
200
200
  }
201
201
 
202
202
  if (me.includeEmptyValues && (me._value === null || Neo.isEmpty(me._value))) {
203
- return false;
203
+ return false
204
204
  }
205
205
 
206
206
  filterValue = me._value;
@@ -208,47 +208,56 @@ class Filter extends Base {
208
208
 
209
209
  if (filterValue instanceof Date && recordValue instanceof Date) {
210
210
  filterValue = filterValue.valueOf();
211
- recordValue = recordValue.valueOf();
211
+ recordValue = recordValue.valueOf()
212
212
  }
213
213
 
214
- return !Filter[me._operator](recordValue, filterValue);
214
+ return !Filter[me._operator](recordValue, filterValue)
215
215
  }
216
216
 
217
- static ['=='] (a, b) {return a == b;}
218
- static ['==='](a, b) {return a === b;}
219
- static ['!='] (a, b) {return a != b;}
220
- static ['!=='](a, b) {return a !== b;}
221
- static ['<'] (a, b) {return a < b;}
222
- static ['<='] (a, b) {return a <= b;}
223
- static ['>'] (a, b) {return a > b;}
224
- static ['>='] (a, b) {return a >= b;}
217
+ static ['=='] (a, b) {return a == b}
218
+ static ['==='](a, b) {return a === b}
219
+ static ['!='] (a, b) {return a != b}
220
+ static ['!=='](a, b) {return a !== b}
221
+ static ['<'] (a, b) {return a < b}
222
+ static ['<='] (a, b) {return a <= b}
223
+ static ['>'] (a, b) {return a > b}
224
+ static ['>='] (a, b) {return a >= b}
225
225
 
226
226
  static ['endsWith'](a, b) {
227
- return a?.toLowerCase().endsWith(b?.toLowerCase()) || false;
227
+ if (!Neo.isString(a)) {a = String(a)}
228
+ if (!Neo.isString(b)) {b = String(b)}
229
+
230
+ return a?.toLowerCase().endsWith(b?.toLowerCase()) || false
228
231
  }
229
232
 
230
233
  static ['excluded'](a, b) {
231
- return b.indexOf(a) < 0;
234
+ return b.indexOf(a) < 0
232
235
  }
233
236
 
234
237
  static ['included'](a, b) {
235
- return b.indexOf(a) > -1;
238
+ return b.indexOf(a) > -1
236
239
  }
237
240
 
238
241
  static ['isDefined'](a, b) {
239
- return a !== undefined;
242
+ return a !== undefined
240
243
  }
241
244
 
242
245
  static ['isUndefined'](a, b) {
243
- return a === undefined;
246
+ return a === undefined
244
247
  }
245
248
 
246
249
  static ['like'](a, b) {
247
- return a?.toLowerCase().includes(b?.toLowerCase()) || false;
250
+ if (!Neo.isString(a)) {a = String(a)}
251
+ if (!Neo.isString(b)) {b = String(b)}
252
+
253
+ return a?.toLowerCase().includes(b?.toLowerCase()) || false
248
254
  }
249
255
 
250
256
  static ['startsWith'](a, b) {
251
- return a?.toLowerCase().startsWith(b?.toLowerCase()) || false;
257
+ if (!Neo.isString(a)) {a = String(a)}
258
+ if (!Neo.isString(b)) {b = String(b)}
259
+
260
+ return a?.toLowerCase().startsWith(b?.toLowerCase()) || false
252
261
  }
253
262
  }
254
263
 
@@ -401,7 +401,7 @@ class Base extends Component {
401
401
  * @param {Boolean} [silent=false] true to update the vdom silently (useful for destroying multiple child items in a row)
402
402
  */
403
403
  destroy(updateParentVdom=false, silent=false) {
404
- this.items.forEach(item => {
404
+ this.items?.forEach(item => {
405
405
  item.destroy?.(false, true)
406
406
  });
407
407
 
@@ -502,8 +502,11 @@ class Base extends Component {
502
502
 
503
503
  if (config.items) {
504
504
  // If we are passed an object, merge the class's own items object into it
505
- me.items = Neo.typeOf(config.items) === 'Object' ?
506
- Neo.merge(Neo.clone(me.constructor.config.items), config.items) : config.items;
505
+ if (Neo.typeOf(config.items) === 'Object') {
506
+ me.items = Neo.merge(Neo.clone(me.constructor.config.items), config.items)
507
+ } else {
508
+ me._items = Neo.clone(config.items, true, true)
509
+ }
507
510
  delete config.items
508
511
  }
509
512
 
@@ -21,7 +21,7 @@ class Base extends CoreBase {
21
21
  /**
22
22
  * @member {Object} routes={}
23
23
  */
24
- routes: {},
24
+ routes_: {},
25
25
 
26
26
  /**
27
27
  * @member {Object} handleRoutes={}
@@ -42,20 +42,42 @@ class Base extends CoreBase {
42
42
  super.construct(config);
43
43
 
44
44
  const me = this;
45
+ HashHistory.on('change', me.onHashChange, me);
46
+ }
47
+
48
+ /**
49
+ * Triggered after the badgePosition config got changed
50
+ * @param {String} value
51
+ * @param {String} oldValue
52
+ * @protected
53
+ */
54
+ afterSetRoutes(value, oldValue){
55
+ const me = this;
56
+
57
+ const functionSort = (a,b) => {
58
+ const usedRegex = new RegExp("/", "g");
59
+ return a.match(usedRegex).length - b.match(usedRegex).length;
60
+ }
61
+ me.routes = Object.keys(value).sort(functionSort).reduce(
62
+ (obj, key) => {
63
+ obj[key] = value[key];
64
+ return obj;
65
+ },
66
+ {}
67
+ );
68
+
45
69
 
46
70
  me.handleRoutes = {};
47
71
  if (Object.keys(me.routes).length > 0) {
48
72
  Object.keys(me.routes).forEach(key => {
49
73
  if (key.toLowerCase() === 'default'){
50
- me.defaultRoute = me.routes[key];
74
+ me.defaultRoute = value[key];
51
75
  } else {
52
76
  me.handleRoutes[key] = new RegExp(key.replace(/{[^\s/]+}/g, '([\\w-]+)')+'$');
53
77
  }
54
78
 
55
79
  });
56
80
  }
57
-
58
- HashHistory.on('change', me.onHashChange, me);
59
81
  }
60
82
 
61
83
  /**
@@ -85,13 +107,26 @@ class Base extends CoreBase {
85
107
 
86
108
  const me = this;
87
109
  let hasRouteBeenFound = false;
88
- Object.keys(me.handleRoutes).every( key => {
110
+ Object.keys(me.handleRoutes).forEach( key => {
89
111
  let preHandler = undefined;
90
112
  let executeHandler = undefined;
91
113
  let responsePreHandler = undefined;
92
114
 
93
115
  const result = value.hashString.match(me.handleRoutes[key]);
94
116
  if (result){
117
+
118
+ const paramsRegex = /{[^\s/]+}/g;
119
+ const arrayParamIds = key.match(paramsRegex);
120
+ const arrayParamValues = result.splice(1,result.length - 1);
121
+ if (arrayParamIds && arrayParamIds.length !== arrayParamValues.length){
122
+ throw "Number of IDs and number of Values do not match";
123
+ }
124
+
125
+ const paramObject = {};
126
+ for(let i=0; arrayParamIds && i< arrayParamIds.length; i++){
127
+ paramObject[ arrayParamIds[i].substring(1,arrayParamIds[i].length -1)] = arrayParamValues[i];
128
+ }
129
+
95
130
  const target = me.routes[key];
96
131
  if (Neo.isString(target)){
97
132
  executeHandler = this.routes[key];
@@ -100,20 +135,20 @@ class Base extends CoreBase {
100
135
  if (Neo.isObject(target)){
101
136
  executeHandler = this.routes[key].handler;
102
137
  preHandler = this.routes[key].preHandler;
103
- responsePreHandler = preHandler ? me[preHandler]?.call(this, value, oldValue, result.splice(1,result.length - 1)) : true;
138
+ if (preHandler) {
139
+ responsePreHandler = me[preHandler]?.call(this, value, oldValue, paramObject);
140
+ } else {
141
+ responsePreHandler = true;
142
+ console.warn('No preHandler defined for routes -> todo it better');
143
+ }
104
144
  }
105
145
 
106
146
  hasRouteBeenFound = true;
107
147
 
108
148
  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');
149
+ this[executeHandler]?.call(this, value, oldValue, paramObject);
112
150
  }
113
- return false;
114
-
115
151
  }
116
- return true;
117
152
  });
118
153
 
119
154
  if (Object.keys(me.handleRoutes).length > 0 && !hasRouteBeenFound) {
@@ -134,6 +134,15 @@ class Component extends Base {
134
134
  return component || null
135
135
  }
136
136
 
137
+ /**
138
+ * Convenience shortcut for accessing model.Component based data.Stores
139
+ * @param {String} key
140
+ * @returns {Neo.data.Store}
141
+ */
142
+ getStore(key) {
143
+ return this.getModel().getStore(key)
144
+ }
145
+
137
146
  /**
138
147
  * Override this method inside your view controllers as a starting point in case you need references
139
148
  * (instead of using onConstructed() inside your controller)
@@ -285,7 +285,7 @@ class FileUpload extends Base {
285
285
  documentDeleteMethod: 'DELETE',
286
286
 
287
287
  /**
288
- * @member {String} state_=null
288
+ * @member {String} state_=ready
289
289
  */
290
290
  state_: 'ready',
291
291
 
@@ -729,7 +729,7 @@ class FileUpload extends Base {
729
729
  isChangeEventNeeded = true;
730
730
  }
731
731
 
732
- if (isChangeEventNeeded) {
732
+ if (isChangeEventNeeded && oldValue !== undefined) {
733
733
  me.fireChangeEvent(me.file)
734
734
  }
735
735
  me.validate();
@@ -39,9 +39,9 @@ class Select extends Picker {
39
39
  */
40
40
  displayField: 'name',
41
41
  /**
42
- * @member {String} filterOperator='like'
42
+ * @member {String} filterOperator_='like'
43
43
  */
44
- filterOperator: 'like',
44
+ filterOperator_: 'like',
45
45
  /**
46
46
  * True will only fire a change event, in case the TextField input value matches a record.
47
47
  * onFocusLeave() will try to select a hint record, if needed and possible.
@@ -109,9 +109,9 @@ class Select extends Picker {
109
109
  typeAhead_: true,
110
110
  /**
111
111
  * Set this config to false, in case typing into the input field should not filter list items
112
- * @member {Boolean} useFilter=true
112
+ * @member {Boolean} useFilter_=true
113
113
  */
114
- useFilter: true,
114
+ useFilter_: true,
115
115
  /**
116
116
  * This config should point to the store keyProperty or a different model field,
117
117
  * which you want to submit instead
@@ -661,12 +661,13 @@ class Select extends Picker {
661
661
  autocomplete: 'no',
662
662
  autocorrect : 'off',
663
663
  cls : ['neo-textfield-input', 'neo-typeahead-input'],
664
+ disabled : true,
664
665
  id : me.getInputHintId(),
665
666
  spellcheck : 'false'
666
667
  }, inputEl.vdom]
667
668
  }
668
669
  } else {
669
- VDomUtil.replaceVdomChild(vdom, inputEl.parentNode.id, inputEl.vdom);
670
+ VDomUtil.replaceVdomChild(vdom, inputEl.parentNode.id, inputEl.vdom)
670
671
  }
671
672
 
672
673
  !silent && me.update()
@@ -420,13 +420,11 @@ class DomEvents extends Base {
420
420
  onChange(event) {
421
421
  let me = this,
422
422
  target = event.target,
423
- tagName = target.tagName,
424
- value = target.value,
425
423
 
426
424
  data = {
427
425
  ...me.getEventData(event),
428
426
  valid: target.checkValidity(),
429
- value: tagName === 'INPUT' ? StringUtil.escapeHtml(value) : tagName === 'TEXTAREA' ? me.stripHtml(value) : value
427
+ value: target.value
430
428
  };
431
429
 
432
430
  // input and change events can pass a FileList for input type file
@@ -196,7 +196,9 @@ class DeltaUpdates extends Base {
196
196
  node = me.getElementOrBody(delta.id);
197
197
 
198
198
  if (!node) {
199
- console.warn('du_updateNode: node not found for id', delta.id)
199
+ if (Neo.config.environment === 'development') {
200
+ console.warn('du_updateNode: node not found for id', delta.id)
201
+ }
200
202
  } else {
201
203
  Object.entries(delta).forEach(([prop, value]) => {
202
204
  switch(prop) {
@@ -458,7 +458,7 @@ class Component extends Base {
458
458
  * Access the closest store inside the VM parent chain.
459
459
  * @param {String} key
460
460
  * @param {Neo.model.Component} originModel=this for internal usage only
461
- * @returns {*} value
461
+ * @returns {Neo.data.Store}
462
462
  */
463
463
  getStore(key, originModel=this) {
464
464
  let me = this,
@@ -237,7 +237,7 @@ class View extends Component {
237
237
  me.promiseUpdate().then(() => {
238
238
  if (selectedRows?.length > 0) {
239
239
  // this logic only works for selection.table.RowModel
240
- Neo.main.DomAccess.scrollToTableRow({id: selectedRows[0]});
240
+ Neo.main.DomAccess.scrollToTableRow({appName: me.appName, id: selectedRows[0]})
241
241
  }
242
242
  })
243
243
  }
@@ -6,9 +6,29 @@ project.configure({
6
6
  });
7
7
 
8
8
  project.plan(
9
- 'files/button/Base.mjs',
10
- 'files/component/DateSelector.mjs',
11
- 'files/form/field/Select.mjs'
9
+ {
10
+ group: 'button',
11
+ items: [
12
+ 'files/button/Base.mjs'
13
+ ]
14
+ },
15
+ {
16
+ group: 'component',
17
+ items: [
18
+ 'files/component/DateSelector.mjs'
19
+ ]
20
+ },
21
+ {
22
+ group: 'form',
23
+ items: [
24
+ {
25
+ group: 'field',
26
+ items: [
27
+ 'files/form/field/Select.mjs'
28
+ ]
29
+ }
30
+ ]
31
+ }
12
32
  );
13
33
 
14
34
  project.start();