neo.mjs 6.0.2 → 6.0.4
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/examples/ServiceWorker.mjs +2 -2
- package/examples/treeSelectionModel/MainContainer.mjs +88 -62
- package/package.json +1 -1
- package/resources/scss/src/form/field/FileUpload.scss +25 -22
- package/src/DefaultConfig.mjs +2 -2
- package/src/Neo.mjs +47 -45
- package/src/core/Util.mjs +22 -25
- package/src/form/field/CheckBox.mjs +2 -0
- package/src/form/field/FileUpload.mjs +42 -12
- package/src/form/field/Text.mjs +20 -26
- package/src/tree/Accordion.mjs +110 -9
package/apps/ServiceWorker.mjs
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
import ConfigurationViewport from '../ConfigurationViewport.mjs';
|
2
2
|
|
3
|
-
import
|
4
|
-
import
|
5
|
-
import
|
6
|
-
import
|
3
|
+
import AccordionTree from '../../src/tree/Accordion.mjs';
|
4
|
+
import CheckBox from "../../src/form/field/CheckBox.mjs";
|
5
|
+
import NumberField from '../../src/form/field/Number.mjs';
|
6
|
+
import Panel from '../../src/container/Panel.mjs';
|
7
|
+
import Store from '../../src/data/Store.mjs';
|
8
|
+
// Do not remove the ViewController nor ViewModel
|
9
|
+
import ViewController from '../../src/controller/Component.mjs';
|
10
|
+
import ViewModel from '../../src/model/Component.mjs';
|
7
11
|
|
8
12
|
/**
|
9
13
|
* @class Neo.examples.treeSelectionModel.MainContainer
|
@@ -48,9 +52,9 @@ class MainContainer extends ConfigurationViewport {
|
|
48
52
|
labelText: 'height',
|
49
53
|
listeners: {change: me.onConfigChange.bind(me, 'height')},
|
50
54
|
maxValue : 1200,
|
51
|
-
minValue :
|
52
|
-
stepSize :
|
53
|
-
value :
|
55
|
+
minValue : 250,
|
56
|
+
stepSize : 50,
|
57
|
+
value : 650,
|
54
58
|
style : {marginTop: '10px'}
|
55
59
|
}, {
|
56
60
|
module : NumberField,
|
@@ -59,9 +63,9 @@ class MainContainer extends ConfigurationViewport {
|
|
59
63
|
listeners: {change: me.onConfigChange.bind(me, 'width')},
|
60
64
|
maxValue : 1200,
|
61
65
|
minValue : 200,
|
62
|
-
stepSize :
|
66
|
+
stepSize : 3,
|
63
67
|
style : {marginTop: '10px'},
|
64
|
-
value :
|
68
|
+
value : 400
|
65
69
|
}];
|
66
70
|
}
|
67
71
|
|
@@ -69,69 +73,91 @@ class MainContainer extends ConfigurationViewport {
|
|
69
73
|
* @returns {*}
|
70
74
|
*/
|
71
75
|
createExampleComponent() {
|
72
|
-
const
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
76
|
+
const me = this,
|
77
|
+
store = Neo.create(Store, {
|
78
|
+
keyProperty: 'id',
|
79
|
+
model : {
|
80
|
+
fields: [
|
81
|
+
{name: 'collapsed', type: 'Boolean'},
|
82
|
+
{name: 'content', type: 'String'},
|
83
|
+
{name: 'iconCls', type: 'String'},
|
84
|
+
{name: 'id', type: 'Integer'},
|
85
|
+
{name: 'isLeaf', type: 'Boolean'},
|
86
|
+
{name: 'name', type: 'String'},
|
87
|
+
{name: 'parentId', type: 'Integer'}
|
88
|
+
]
|
89
|
+
},
|
90
|
+
|
91
|
+
autoLoad: true,
|
92
|
+
url : '../../examples/treeSelectionModel/tree.json'
|
93
|
+
});
|
86
94
|
|
87
95
|
return Neo.ntype({
|
88
|
-
ntype
|
96
|
+
ntype: 'container',
|
97
|
+
|
98
|
+
model: {
|
99
|
+
data: {
|
100
|
+
selection: [{name: 'Please select something'}]
|
101
|
+
}
|
102
|
+
},
|
103
|
+
|
89
104
|
layout: {ntype: 'hbox', align: 'stretch'},
|
90
105
|
items : [{
|
91
|
-
// module: TextField,
|
92
|
-
// label: 'Test',
|
93
|
-
// plugin: {
|
94
|
-
// Plugin: {
|
95
|
-
// bold: true
|
96
|
-
// }
|
97
|
-
// }
|
98
|
-
// },{
|
99
106
|
module: AccordionTree,
|
100
|
-
store : store,
|
101
|
-
height: 800,
|
102
|
-
width : 400,
|
103
|
-
|
104
|
-
// ensure afterSetMounted runs only once
|
105
|
-
storeLoaded: false,
|
106
|
-
afterSetMounted() {
|
107
|
-
if (!this.storeLoaded) {
|
108
|
-
this.storeLoaded = true;
|
109
|
-
} else {
|
110
|
-
return;
|
111
|
-
}
|
112
107
|
|
113
|
-
|
108
|
+
bind: {selection: {twoWay: true, value: data => data.selection}},
|
114
109
|
|
115
|
-
|
116
|
-
url: '../../examples/treeSelectionModel/tree.json'
|
117
|
-
}).then(data => {
|
118
|
-
const items = data.json,
|
119
|
-
colorArray = ['red', 'yellow', 'green'],
|
120
|
-
iconArray = ['home', 'industry', 'user'];
|
110
|
+
store: store,
|
121
111
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
112
|
+
/**
|
113
|
+
* We are using data-binding.
|
114
|
+
* Here is an example for listener and controller
|
115
|
+
*/
|
116
|
+
// controller: {
|
117
|
+
// module: ViewController,
|
118
|
+
//
|
119
|
+
// onAccordionItemClick(record) {
|
120
|
+
// let viewport = Neo.get('neo-configuration-viewport-1'),
|
121
|
+
// outputEl = viewport.getReference('output');
|
122
|
+
//
|
123
|
+
// outputEl.html = record.name;
|
124
|
+
// }
|
125
|
+
// },
|
126
|
+
//
|
127
|
+
// listeners: {
|
128
|
+
// leafItemClick: 'onAccordionItemClick'
|
129
|
+
// }
|
130
130
|
|
131
|
-
|
132
|
-
|
133
|
-
|
131
|
+
listeners: {
|
132
|
+
selectPreFirstItem: () => Neo.log('listener selectPreFirstItem fired'),
|
133
|
+
selectPostLastItem: () => Neo.log('listener selectPostLastItem fired')
|
134
134
|
}
|
135
|
+
}, {
|
136
|
+
module: Panel,
|
137
|
+
height: 150,
|
138
|
+
width : '100%',
|
139
|
+
|
140
|
+
itemDefaults: {
|
141
|
+
style: {
|
142
|
+
padding: '10px'
|
143
|
+
}
|
144
|
+
},
|
145
|
+
|
146
|
+
headers: [{
|
147
|
+
dock : 'top',
|
148
|
+
style: {borderRightColor: 'transparent'},
|
149
|
+
|
150
|
+
items: [{
|
151
|
+
ntype: 'label',
|
152
|
+
text : 'Accordion Selection'
|
153
|
+
}]
|
154
|
+
}],
|
155
|
+
|
156
|
+
items: [{
|
157
|
+
ntype : 'component',
|
158
|
+
reference: 'output',
|
159
|
+
bind : {html: data => data.selection[0].name}
|
160
|
+
}]
|
135
161
|
}]
|
136
162
|
});
|
137
163
|
}
|
package/package.json
CHANGED
@@ -98,17 +98,39 @@
|
|
98
98
|
flex : 0 0 1.2rem;
|
99
99
|
}
|
100
100
|
|
101
|
-
//
|
102
|
-
&:not(.neo-
|
101
|
+
// When we have a file selected, the file input and label are hidden
|
102
|
+
&:not(.neo-field-empty) {
|
103
103
|
input[type="file"],label {
|
104
104
|
display : none;
|
105
105
|
}
|
106
106
|
}
|
107
107
|
|
108
|
-
&.neo-
|
108
|
+
&.neo-field-empty {
|
109
|
+
// The input field and its label are visible when no file is selected.
|
110
|
+
// It takes up the whole component, and is the only interactive item
|
111
|
+
:not(input[type="file"],label) {
|
112
|
+
display : none;
|
113
|
+
}
|
114
|
+
input::file-selector-button {
|
115
|
+
position : absolute;
|
116
|
+
border : 0 none;
|
117
|
+
margin : 0;
|
118
|
+
top : 0;
|
119
|
+
left : 0;
|
120
|
+
right : 0;
|
121
|
+
bottom : 0;
|
122
|
+
background-color : var(--fileuploadfield-background-color);
|
123
|
+
color : var(--fileuploadfield-color);
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
&.neo-invalid:not(.neo-field-empty) {
|
109
128
|
.neo-file-upload-error-message {
|
110
129
|
display : initial;
|
111
130
|
}
|
131
|
+
input[type="file"],label {
|
132
|
+
display : none;
|
133
|
+
}
|
112
134
|
}
|
113
135
|
}
|
114
136
|
|
@@ -230,25 +252,6 @@
|
|
230
252
|
}
|
231
253
|
}
|
232
254
|
|
233
|
-
.neo-file-upload-state-ready {
|
234
|
-
// Only the input field and its label is visible when in ready state
|
235
|
-
// It takes up the whole component, and is the only interactive item
|
236
|
-
:not(input[type="file"],label) {
|
237
|
-
display : none;
|
238
|
-
}
|
239
|
-
input::file-selector-button {
|
240
|
-
position : absolute;
|
241
|
-
border : 0 none;
|
242
|
-
margin : 0;
|
243
|
-
top : 0;
|
244
|
-
left : 0;
|
245
|
-
right : 0;
|
246
|
-
bottom : 0;
|
247
|
-
background-color : var(--fileuploadfield-background-color);
|
248
|
-
color : var(--fileuploadfield-color);
|
249
|
-
}
|
250
|
-
}
|
251
|
-
|
252
255
|
.neo-file-upload-body {
|
253
256
|
flex : 1 1 0%;
|
254
257
|
display : flex;
|
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.0.
|
239
|
+
* @default '6.0.4'
|
240
240
|
* @memberOf! module:Neo
|
241
241
|
* @name config.version
|
242
242
|
* @type String
|
243
243
|
*/
|
244
|
-
version: '6.0.
|
244
|
+
version: '6.0.4'
|
245
245
|
};
|
246
246
|
|
247
247
|
Object.assign(DefaultConfig, {
|
package/src/Neo.mjs
CHANGED
@@ -59,11 +59,11 @@ Neo = globalThis.Neo = Object.assign({
|
|
59
59
|
|
60
60
|
if (Object.hasOwn(ctor, 'classConfigApplied')) {
|
61
61
|
baseCfg = Neo.clone(ctor.config, true);
|
62
|
-
break
|
62
|
+
break
|
63
63
|
}
|
64
64
|
|
65
65
|
protos.unshift(proto);
|
66
|
-
proto = proto.__proto__
|
66
|
+
proto = proto.__proto__
|
67
67
|
}
|
68
68
|
|
69
69
|
config = baseCfg || {};
|
@@ -76,7 +76,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
76
76
|
cfg = ctor.config || {};
|
77
77
|
|
78
78
|
if (Neo.overwrites) {
|
79
|
-
ctor.applyOverwrites(cfg)
|
79
|
+
ctor.applyOverwrites(cfg)
|
80
80
|
}
|
81
81
|
|
82
82
|
Object.entries(cfg).forEach(([key, value]) => {
|
@@ -84,7 +84,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
84
84
|
delete cfg[key];
|
85
85
|
key = key.slice(0, -1);
|
86
86
|
cfg[key] = value;
|
87
|
-
autoGenerateGetSet(element, key)
|
87
|
+
autoGenerateGetSet(element, key)
|
88
88
|
}
|
89
89
|
|
90
90
|
// only apply properties which have no setters inside the prototype chain
|
@@ -94,7 +94,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
94
94
|
enumerable: true,
|
95
95
|
value,
|
96
96
|
writable : true
|
97
|
-
})
|
97
|
+
})
|
98
98
|
}
|
99
99
|
});
|
100
100
|
|
@@ -104,7 +104,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
104
104
|
// Running the docs app inside a workspace can pull in the same classes from different roots,
|
105
105
|
// so we want to check for different class names as well
|
106
106
|
if (Object.hasOwn(ntypeMap, ntype) && cfg.className !== ntypeMap[ntype]) {
|
107
|
-
throw new Error(`ntype conflict for '${ntype}' inside the classes:\n${ntypeMap[ntype]}\n${cfg.className}`)
|
107
|
+
throw new Error(`ntype conflict for '${ntype}' inside the classes:\n${ntypeMap[ntype]}\n${cfg.className}`)
|
108
108
|
}
|
109
109
|
|
110
110
|
ntypeMap[ntype] = cfg.className;
|
@@ -113,11 +113,11 @@ Neo = globalThis.Neo = Object.assign({
|
|
113
113
|
mixins = Object.hasOwn(config, 'mixins') && config.mixins || [];
|
114
114
|
|
115
115
|
if (ctor.observable) {
|
116
|
-
mixins.push('Neo.core.Observable')
|
116
|
+
mixins.push('Neo.core.Observable')
|
117
117
|
}
|
118
118
|
|
119
119
|
if (Object.hasOwn(cfg, 'mixins') && Array.isArray(cfg.mixins) && cfg.mixins.length > 0) {
|
120
|
-
mixins.push(...cfg.mixins)
|
120
|
+
mixins.push(...cfg.mixins)
|
121
121
|
}
|
122
122
|
|
123
123
|
if (mixins.length > 0) {
|
@@ -139,17 +139,17 @@ Neo = globalThis.Neo = Object.assign({
|
|
139
139
|
isClass : true
|
140
140
|
});
|
141
141
|
|
142
|
-
!config.singleton && this.applyToGlobalNs(cls)
|
142
|
+
!config.singleton && this.applyToGlobalNs(cls)
|
143
143
|
});
|
144
144
|
|
145
145
|
proto = cls.prototype || cls;
|
146
146
|
|
147
147
|
if (proto.singleton) {
|
148
148
|
cls = Neo.create(cls);
|
149
|
-
Neo.applyToGlobalNs(cls)
|
149
|
+
Neo.applyToGlobalNs(cls)
|
150
150
|
}
|
151
151
|
|
152
|
-
return cls
|
152
|
+
return cls
|
153
153
|
},
|
154
154
|
|
155
155
|
/**
|
@@ -177,10 +177,10 @@ Neo = globalThis.Neo = Object.assign({
|
|
177
177
|
Object.entries(config).forEach(([key, value]) => {
|
178
178
|
fnName = namespace[value];
|
179
179
|
target[key] = bind ? fnName.bind(namespace) : fnName;
|
180
|
-
})
|
180
|
+
})
|
181
181
|
}
|
182
182
|
|
183
|
-
return target
|
183
|
+
return target
|
184
184
|
},
|
185
185
|
|
186
186
|
/**
|
@@ -199,7 +199,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
199
199
|
nsArray = className.split('.');
|
200
200
|
key = nsArray.pop();
|
201
201
|
ns = Neo.ns(nsArray, true);
|
202
|
-
ns[key] = cls
|
202
|
+
ns[key] = cls
|
203
203
|
}
|
204
204
|
},
|
205
205
|
|
@@ -214,12 +214,12 @@ Neo = globalThis.Neo = Object.assign({
|
|
214
214
|
if (target && Neo.typeOf(defaults) === 'Object') {
|
215
215
|
Object.entries(defaults).forEach(([key, value]) => {
|
216
216
|
if (!Object.hasOwn(target, key)) {
|
217
|
-
target[key] = value
|
217
|
+
target[key] = value
|
218
218
|
}
|
219
|
-
})
|
219
|
+
})
|
220
220
|
}
|
221
221
|
|
222
|
-
return target
|
222
|
+
return target
|
223
223
|
},
|
224
224
|
|
225
225
|
/**
|
@@ -243,7 +243,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
243
243
|
out = {};
|
244
244
|
|
245
245
|
Object.entries(obj).forEach(([key, value]) => {
|
246
|
-
out[key] = !deep ? value : Neo.clone(value, deep, ignoreNeoInstances)
|
246
|
+
out[key] = !deep ? value : Neo.clone(value, deep, ignoreNeoInstances)
|
247
247
|
});
|
248
248
|
|
249
249
|
return out
|
@@ -263,7 +263,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
263
263
|
delete config._id;
|
264
264
|
delete config.id;
|
265
265
|
|
266
|
-
return Neo.create(instance.className, config)
|
266
|
+
return Neo.create(instance.className, config)
|
267
267
|
},
|
268
268
|
|
269
269
|
/**
|
@@ -305,7 +305,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
305
305
|
cls, instance;
|
306
306
|
|
307
307
|
if (type === 'NeoClass') {
|
308
|
-
cls = className
|
308
|
+
cls = className
|
309
309
|
} else {
|
310
310
|
if (type === 'Object') {
|
311
311
|
config = className;
|
@@ -313,17 +313,17 @@ Neo = globalThis.Neo = Object.assign({
|
|
313
313
|
if (!config.className && !config.module) {
|
314
314
|
// using console.error instead of throw to show the config object
|
315
315
|
console.error('Class created with object configuration missing className or module property', config);
|
316
|
-
return null
|
316
|
+
return null
|
317
317
|
}
|
318
318
|
|
319
319
|
className = config.className || config.module.prototype.className;
|
320
320
|
}
|
321
321
|
|
322
322
|
if (!exists(className)) {
|
323
|
-
throw new Error('Class ' + className + ' does not exist')
|
323
|
+
throw new Error('Class ' + className + ' does not exist')
|
324
324
|
}
|
325
325
|
|
326
|
-
cls = Neo.ns(className)
|
326
|
+
cls = Neo.ns(className)
|
327
327
|
}
|
328
328
|
|
329
329
|
instance = new cls();
|
@@ -333,7 +333,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
333
333
|
instance.onAfterConstructed();
|
334
334
|
instance.init();
|
335
335
|
|
336
|
-
return instance
|
336
|
+
return instance
|
337
337
|
},
|
338
338
|
|
339
339
|
/**
|
@@ -435,7 +435,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
435
435
|
return createArrayNs(true, current, prev);
|
436
436
|
}
|
437
437
|
|
438
|
-
prev[current] = {}
|
438
|
+
prev[current] = {}
|
439
439
|
}
|
440
440
|
|
441
441
|
if (prev) {
|
@@ -443,9 +443,9 @@ Neo = globalThis.Neo = Object.assign({
|
|
443
443
|
return createArrayNs(false, current, prev);
|
444
444
|
}
|
445
445
|
|
446
|
-
return prev[current]
|
446
|
+
return prev[current]
|
447
447
|
}
|
448
|
-
}, scope || globalThis)
|
448
|
+
}, scope || globalThis)
|
449
449
|
},
|
450
450
|
|
451
451
|
/**
|
@@ -474,16 +474,17 @@ Neo = globalThis.Neo = Object.assign({
|
|
474
474
|
if (!config.ntype) {
|
475
475
|
throw new Error('Class defined with object configuration missing ntype property. ' + config.ntype);
|
476
476
|
}
|
477
|
-
|
477
|
+
|
478
|
+
ntype = config.ntype
|
478
479
|
}
|
479
480
|
|
480
481
|
let className = Neo.ntypeMap[ntype];
|
481
482
|
|
482
483
|
if (!className) {
|
483
|
-
throw new Error('ntype ' + ntype + ' does not exist')
|
484
|
+
throw new Error('ntype ' + ntype + ' does not exist')
|
484
485
|
}
|
485
486
|
|
486
|
-
return Neo.create(className, config)
|
487
|
+
return Neo.create(className, config)
|
487
488
|
},
|
488
489
|
|
489
490
|
/**
|
@@ -492,7 +493,7 @@ Neo = globalThis.Neo = Object.assign({
|
|
492
493
|
*/
|
493
494
|
typeOf(item) {
|
494
495
|
if (item === null || item === undefined) {
|
495
|
-
return null
|
496
|
+
return null
|
496
497
|
}
|
497
498
|
|
498
499
|
return {
|
@@ -626,7 +627,7 @@ function autoGenerateGetSet(proto, key) {
|
|
626
627
|
delete me[configSymbol][key];
|
627
628
|
|
628
629
|
if (key !== 'items') {
|
629
|
-
value = Neo.clone(value, true, true)
|
630
|
+
value = Neo.clone(value, true, true)
|
630
631
|
}
|
631
632
|
|
632
633
|
// we do want to store the value before the beforeSet modification as well,
|
@@ -639,7 +640,7 @@ function autoGenerateGetSet(proto, key) {
|
|
639
640
|
// If they don't return a value, that means no change
|
640
641
|
if (value === undefined) {
|
641
642
|
me[_key] = oldValue;
|
642
|
-
return
|
643
|
+
return
|
643
644
|
}
|
644
645
|
|
645
646
|
me[_key] = value;
|
@@ -650,7 +651,7 @@ function autoGenerateGetSet(proto, key) {
|
|
650
651
|
!Neo.isEqual(value, oldValue)
|
651
652
|
) {
|
652
653
|
me[afterSet]?.(value, oldValue);
|
653
|
-
me.afterSetConfig?.(key, value, oldValue)
|
654
|
+
me.afterSetConfig?.(key, value, oldValue)
|
654
655
|
}
|
655
656
|
}
|
656
657
|
};
|
@@ -672,9 +673,9 @@ function createArrayNs(create, current, prev) {
|
|
672
673
|
arrItem, arrRoot;
|
673
674
|
|
674
675
|
if (create) {
|
675
|
-
prev[arrDetails[0]] = arrRoot = prev[arrDetails[0]] || []
|
676
|
+
prev[arrDetails[0]] = arrRoot = prev[arrDetails[0]] || []
|
676
677
|
} else {
|
677
|
-
arrRoot = prev[arrDetails[0]]
|
678
|
+
arrRoot = prev[arrDetails[0]]
|
678
679
|
}
|
679
680
|
|
680
681
|
if (!arrRoot) {
|
@@ -688,10 +689,10 @@ function createArrayNs(create, current, prev) {
|
|
688
689
|
arrRoot[arrItem] = arrRoot[arrItem] || {};
|
689
690
|
}
|
690
691
|
|
691
|
-
arrRoot = arrRoot[arrItem]
|
692
|
+
arrRoot = arrRoot[arrItem]
|
692
693
|
}
|
693
694
|
|
694
|
-
return arrRoot
|
695
|
+
return arrRoot
|
695
696
|
}
|
696
697
|
|
697
698
|
/**
|
@@ -704,9 +705,9 @@ function exists(className) {
|
|
704
705
|
try {
|
705
706
|
return !!className.split('.').reduce((prev, current) => {
|
706
707
|
return prev[current];
|
707
|
-
}, globalThis)
|
708
|
+
}, globalThis)
|
708
709
|
} catch(e) {
|
709
|
-
return false
|
710
|
+
return false
|
710
711
|
}
|
711
712
|
}
|
712
713
|
|
@@ -725,8 +726,9 @@ function mixinProperty(proto, mixinProto) {
|
|
725
726
|
if (proto[key]?._from) {
|
726
727
|
if (mixinProto.className === proto[key]._from) {
|
727
728
|
console.warn('Mixin set multiple times or already defined on a Base Class', proto.className, mixinProto.className, key);
|
728
|
-
return
|
729
|
+
return
|
729
730
|
}
|
731
|
+
|
730
732
|
throw new Error(
|
731
733
|
`${proto.className}: Multiple mixins defining same property (${mixinProto.className}, ${proto[key]._from}) => ${key}`
|
732
734
|
);
|
@@ -737,7 +739,7 @@ function mixinProperty(proto, mixinProto) {
|
|
737
739
|
Object.getOwnPropertyDescriptor(proto, key)._from = mixinProto.className;
|
738
740
|
|
739
741
|
if (typeof proto[key] === 'function') {
|
740
|
-
proto[key]._name = key
|
742
|
+
proto[key]._name = key
|
741
743
|
}
|
742
744
|
};
|
743
745
|
}
|
@@ -749,8 +751,8 @@ function mixinProperty(proto, mixinProto) {
|
|
749
751
|
*/
|
750
752
|
function mixReduce(mixinCls) {
|
751
753
|
return (prev, current, idx, arr) => {
|
752
|
-
return prev[current] = idx !== arr.length -1 ? prev[current] || {} : mixinCls
|
753
|
-
}
|
754
|
+
return prev[current] = idx !== arr.length -1 ? prev[current] || {} : mixinCls
|
755
|
+
}
|
754
756
|
}
|
755
757
|
|
756
758
|
/**
|
@@ -761,7 +763,7 @@ function mixReduce(mixinCls) {
|
|
761
763
|
function parseArrayFromString(str) {
|
762
764
|
return (extractArraysRegex.exec(str) || [null]).slice(1).reduce(
|
763
765
|
(fun, args) => [fun].concat(args.match(charsRegex))
|
764
|
-
)
|
766
|
+
)
|
765
767
|
}
|
766
768
|
|
767
769
|
Neo.config = Neo.config || {};
|
package/src/core/Util.mjs
CHANGED
@@ -42,7 +42,7 @@ class Util extends Base {
|
|
42
42
|
* @returns {Boolean|String} Returns false for non string inputs
|
43
43
|
*/
|
44
44
|
static capitalize(value) {
|
45
|
-
return
|
45
|
+
return value[0].toUpperCase() + value.slice(1)
|
46
46
|
}
|
47
47
|
|
48
48
|
/**
|
@@ -51,10 +51,6 @@ class Util extends Base {
|
|
51
51
|
* @returns {Object} The camelcase styles object
|
52
52
|
*/
|
53
53
|
static createStyleObject(string) {
|
54
|
-
if (!string) {
|
55
|
-
return null;
|
56
|
-
}
|
57
|
-
|
58
54
|
let parts;
|
59
55
|
|
60
56
|
// split(';') does fetch semicolons inside brackets
|
@@ -74,10 +70,11 @@ class Util extends Base {
|
|
74
70
|
parts[0] = parts[0].replace(/-([a-z])/g, (str, letter) => {
|
75
71
|
return letter.toUpperCase();
|
76
72
|
});
|
77
|
-
|
73
|
+
|
74
|
+
obj[parts[0]] = parts[1]
|
78
75
|
}
|
79
76
|
return obj;
|
80
|
-
}, {})
|
77
|
+
}, {})
|
81
78
|
}
|
82
79
|
|
83
80
|
/**
|
@@ -90,11 +87,11 @@ class Util extends Base {
|
|
90
87
|
|
91
88
|
Object.entries(styles).forEach(([key, value]) => {
|
92
89
|
if (value !== undefined && value !== null) {
|
93
|
-
style += Util.decamel(key) + ':' + value + ';'
|
90
|
+
style += Util.decamel(key) + ':' + value + ';'
|
94
91
|
}
|
95
92
|
});
|
96
93
|
|
97
|
-
return style
|
94
|
+
return style
|
98
95
|
}
|
99
96
|
|
100
97
|
/**
|
@@ -104,7 +101,7 @@ class Util extends Base {
|
|
104
101
|
* @returns {String} The lowercase output
|
105
102
|
*/
|
106
103
|
static decamel(value) {
|
107
|
-
return value.replace(Util.decamelRegEx, '$1-$2').toLowerCase()
|
104
|
+
return value.replace(Util.decamelRegEx, '$1-$2').toLowerCase()
|
108
105
|
}
|
109
106
|
|
110
107
|
/**
|
@@ -122,7 +119,7 @@ class Util extends Base {
|
|
122
119
|
* @returns {Boolean}
|
123
120
|
*/
|
124
121
|
static isBoolean(value) {
|
125
|
-
return typeof value === 'boolean'
|
122
|
+
return typeof value === 'boolean'
|
126
123
|
}
|
127
124
|
|
128
125
|
/**
|
@@ -131,7 +128,7 @@ class Util extends Base {
|
|
131
128
|
* @returns {Boolean}
|
132
129
|
*/
|
133
130
|
static isDefined(value) {
|
134
|
-
return typeof value !== 'undefined'
|
131
|
+
return typeof value !== 'undefined'
|
135
132
|
}
|
136
133
|
|
137
134
|
/**
|
@@ -141,26 +138,26 @@ class Util extends Base {
|
|
141
138
|
*/
|
142
139
|
static isEmpty(value) {
|
143
140
|
if (value === null || value === undefined) {
|
144
|
-
return true
|
141
|
+
return true
|
145
142
|
}
|
146
143
|
|
147
144
|
if (Array.isArray(value)) {
|
148
|
-
return value.length === 0
|
145
|
+
return value.length === 0
|
149
146
|
}
|
150
147
|
|
151
148
|
if (value instanceof Date) {
|
152
|
-
return false
|
149
|
+
return false
|
153
150
|
}
|
154
151
|
|
155
152
|
if (Util.isObject(value)) {
|
156
|
-
return Object.keys(value).length === 0
|
153
|
+
return Object.keys(value).length === 0
|
157
154
|
}
|
158
155
|
|
159
156
|
if (Util.isString(value)) {
|
160
|
-
return value === ''
|
157
|
+
return value === ''
|
161
158
|
}
|
162
159
|
|
163
|
-
return false
|
160
|
+
return false
|
164
161
|
}
|
165
162
|
|
166
163
|
/**
|
@@ -169,7 +166,7 @@ class Util extends Base {
|
|
169
166
|
* @returns {Boolean}
|
170
167
|
*/
|
171
168
|
static isFunction(value) {
|
172
|
-
return typeof value === 'function'
|
169
|
+
return typeof value === 'function'
|
173
170
|
}
|
174
171
|
|
175
172
|
/**
|
@@ -178,7 +175,7 @@ class Util extends Base {
|
|
178
175
|
* @returns {Boolean}
|
179
176
|
*/
|
180
177
|
static isNumber(value){
|
181
|
-
return typeof value === 'number' && isFinite(value)
|
178
|
+
return typeof value === 'number' && isFinite(value)
|
182
179
|
}
|
183
180
|
|
184
181
|
/**
|
@@ -187,7 +184,7 @@ class Util extends Base {
|
|
187
184
|
* @returns {Boolean}
|
188
185
|
*/
|
189
186
|
static isObject(value) {
|
190
|
-
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
187
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
191
188
|
}
|
192
189
|
|
193
190
|
/**
|
@@ -196,7 +193,7 @@ class Util extends Base {
|
|
196
193
|
* @returns {Boolean}
|
197
194
|
*/
|
198
195
|
static isString(value) {
|
199
|
-
return typeof value === 'string'
|
196
|
+
return typeof value === 'string'
|
200
197
|
}
|
201
198
|
|
202
199
|
/**
|
@@ -210,14 +207,14 @@ class Util extends Base {
|
|
210
207
|
let len;
|
211
208
|
|
212
209
|
if (!iterable || !(len = iterable.length)) {
|
213
|
-
return []
|
210
|
+
return []
|
214
211
|
}
|
215
212
|
|
216
213
|
if (typeof iterable === 'string') {
|
217
|
-
return iterable.split('')
|
214
|
+
return iterable.split('')
|
218
215
|
}
|
219
216
|
|
220
|
-
return Array.prototype.slice.call(iterable, start || 0, end || len)
|
217
|
+
return Array.prototype.slice.call(iterable, start || 0, end || len)
|
221
218
|
}
|
222
219
|
}
|
223
220
|
|
@@ -132,7 +132,7 @@ class FileUpload extends Base {
|
|
132
132
|
]
|
133
133
|
},
|
134
134
|
|
135
|
-
cls : [],
|
135
|
+
cls : ['neo-field-empty'],
|
136
136
|
|
137
137
|
/**
|
138
138
|
* An Object containing a default set of headers to be passed to the server on every HTTP request.
|
@@ -153,6 +153,7 @@ class FileUpload extends Base {
|
|
153
153
|
UPLOADING : 'scanning',
|
154
154
|
|
155
155
|
MALWARE_DETECTED : 'scan-failed',
|
156
|
+
UN_DOWNLOADABLE : 'not-downloadable',
|
156
157
|
AVAILABLE : 'not-downloadable',
|
157
158
|
DOWNLOADABLE : 'downloadable',
|
158
159
|
DELETED : 'deleted'
|
@@ -317,6 +318,7 @@ class FileUpload extends Base {
|
|
317
318
|
// UI strings which can be overridden for other languages
|
318
319
|
chooseFile : 'Choose file',
|
319
320
|
documentText : 'Document',
|
321
|
+
invalidFileFormat : 'invalid file format',
|
320
322
|
pleaseUseTheseTypes : 'Please use these file types',
|
321
323
|
fileSizeMoreThan : 'File size exceeds',
|
322
324
|
documentDeleteError : 'Document delete service error',
|
@@ -346,16 +348,19 @@ class FileUpload extends Base {
|
|
346
348
|
}
|
347
349
|
|
348
350
|
afterSetId(value, oldValue) {
|
349
|
-
const
|
350
|
-
labelEl = this.vdom.cn[4],
|
351
|
-
inputElId = `${this.id}-input`;
|
351
|
+
const inputElId = `${this.id}-input`;
|
352
352
|
|
353
|
-
this.getInputEl().id =
|
354
|
-
labelEl.html = this.chooseFile;
|
353
|
+
this.getInputEl().id = this.vdom.cn[4].for = inputElId;
|
355
354
|
|
356
355
|
// silent vdom update, the super call will trigger the engine
|
357
356
|
super.afterSetId?.(value, oldValue);
|
358
357
|
}
|
358
|
+
|
359
|
+
onConstructed() {
|
360
|
+
super.onConstructed(...arguments);
|
361
|
+
|
362
|
+
this.vdom.cn[4].html = this.chooseFile;
|
363
|
+
}
|
359
364
|
|
360
365
|
/**
|
361
366
|
* @returns {Object}
|
@@ -365,9 +370,15 @@ class FileUpload extends Base {
|
|
365
370
|
}
|
366
371
|
|
367
372
|
async clear() {
|
368
|
-
const
|
373
|
+
const
|
374
|
+
me = this,
|
375
|
+
{ cls } = me;
|
376
|
+
|
377
|
+
NeoArray.add(cls, 'neo-field-empty');
|
378
|
+
me.cls = cls;
|
369
379
|
|
370
380
|
me.vdom.cn[3] = {
|
381
|
+
id : `${me.id}-input`,
|
371
382
|
cls : 'neo-file-upload-input',
|
372
383
|
tag : 'input',
|
373
384
|
type : 'file',
|
@@ -375,6 +386,7 @@ class FileUpload extends Base {
|
|
375
386
|
};
|
376
387
|
me.state = 'ready';
|
377
388
|
me.error = '';
|
389
|
+
me.file = me.document = null;
|
378
390
|
|
379
391
|
// We have to wait for the DOM to have changed, and the input field to be visible
|
380
392
|
await new Promise(resolve => setTimeout(resolve, 100));
|
@@ -388,18 +400,29 @@ class FileUpload extends Base {
|
|
388
400
|
onInputValueChange({ files }) {
|
389
401
|
const
|
390
402
|
me = this,
|
391
|
-
{
|
403
|
+
{
|
404
|
+
types,
|
405
|
+
cls
|
406
|
+
} = me,
|
407
|
+
body = me.vdom.cn[1];
|
392
408
|
|
393
409
|
if (files.length) {
|
410
|
+
NeoArray.remove(cls, 'neo-field-empty');
|
411
|
+
me.cls = cls;
|
412
|
+
|
394
413
|
const
|
395
414
|
file = files.item(0),
|
396
415
|
pointPos = file.name.lastIndexOf('.'),
|
397
416
|
type = pointPos > -1 ? file.name.slice(pointPos + 1) : '';
|
398
417
|
|
399
418
|
if (me.types && !types[type]) {
|
419
|
+
body.cn[0].innerHTML = file.name;
|
420
|
+
body.cn[1].innerHTML = `${me.invalidFileFormat} (.${type}) ${me.formatSize(file.size)}`;
|
400
421
|
me.error = `${me.pleaseUseTheseTypes}: .${Object.keys(types).join(' .')}`;
|
401
422
|
}
|
402
423
|
else if (file.size > me.maxSize) {
|
424
|
+
body.cn[0].innerHTML = file.name;
|
425
|
+
body.cn[1].innerHTML = me.formatSize(file.size);
|
403
426
|
me.error = `${me.fileSizeMoreThan} ${String(me._maxSize).toUpperCase()}`;
|
404
427
|
}
|
405
428
|
// If it passes the type and maxSize check, upload it
|
@@ -424,6 +447,7 @@ class FileUpload extends Base {
|
|
424
447
|
headers = { ...me.headers };
|
425
448
|
|
426
449
|
// Show the action button
|
450
|
+
me.file = file;
|
427
451
|
me.state = 'starting';
|
428
452
|
|
429
453
|
// We have to wait for the DOM to have changed, and the action button to be visible
|
@@ -553,6 +577,9 @@ class FileUpload extends Base {
|
|
553
577
|
me.clear();
|
554
578
|
me.state = 'ready';
|
555
579
|
break;
|
580
|
+
case 'ready':
|
581
|
+
me.clear();
|
582
|
+
break;
|
556
583
|
}
|
557
584
|
}
|
558
585
|
|
@@ -629,9 +656,12 @@ class FileUpload extends Base {
|
|
629
656
|
afterSetDocument(document) {
|
630
657
|
if (document) {
|
631
658
|
const
|
632
|
-
me
|
659
|
+
me = this,
|
660
|
+
{ cls } = me;
|
661
|
+
|
662
|
+
NeoArray.remove(cls, 'neo-field-empty');
|
663
|
+
me.cls = cls;
|
633
664
|
|
634
|
-
me.preExistingDocument = true;
|
635
665
|
me.documentId = document.id;
|
636
666
|
me.fileSize = me.formatSize(document.size);
|
637
667
|
me.vdom.cn[1].cn[0].innerHTML = document.fileName;
|
@@ -680,8 +710,7 @@ class FileUpload extends Base {
|
|
680
710
|
status.innerHTML = me.fileSize;
|
681
711
|
break;
|
682
712
|
case 'not-downloadable':
|
683
|
-
status.innerHTML = me.
|
684
|
-
me.fileSize : `${me.successfullyUploaded} \u2022 ${me.fileSize}`;
|
713
|
+
status.innerHTML = me.document ? me.fileSize : `${me.successfullyUploaded} \u2022 ${me.fileSize}`;
|
685
714
|
break;
|
686
715
|
case 'deleted':
|
687
716
|
status.innerHTML = me.fileWasDeleted;
|
@@ -695,6 +724,7 @@ class FileUpload extends Base {
|
|
695
724
|
|
696
725
|
NeoArray.remove(cls, 'neo-file-upload-state-' + oldValue);
|
697
726
|
NeoArray.add(cls, 'neo-file-upload-state-' + value);
|
727
|
+
NeoArray[me.file || me.document ? 'remove' : 'add', 'neo-field-empty'];
|
698
728
|
me.cls = cls;
|
699
729
|
}
|
700
730
|
|
package/src/form/field/Text.mjs
CHANGED
@@ -23,7 +23,7 @@ class Text extends Base {
|
|
23
23
|
* @protected
|
24
24
|
* @static
|
25
25
|
*/
|
26
|
-
static labelPositions
|
26
|
+
static labelPositions = ['bottom', 'inline', 'left', 'right', 'top']
|
27
27
|
|
28
28
|
static config = {
|
29
29
|
/**
|
@@ -220,18 +220,14 @@ class Text extends Base {
|
|
220
220
|
* @member {Object} _vdom
|
221
221
|
*/
|
222
222
|
_vdom:
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
]
|
232
|
-
}
|
233
|
-
]
|
234
|
-
}
|
223
|
+
{cn: [
|
224
|
+
{tag: 'label', cls: [], style: {}},
|
225
|
+
{tag: 'label', cls: []},
|
226
|
+
{tag: 'input', cls: ['neo-textfield-input'], flag: 'neo-real-input', style: {}},
|
227
|
+
{cls: ['neo-textfield-error-wrapper'], removeDom: true, cn: [
|
228
|
+
{cls: ['neo-textfield-error']}
|
229
|
+
]}
|
230
|
+
]}
|
235
231
|
}
|
236
232
|
|
237
233
|
/**
|
@@ -250,10 +246,10 @@ class Text extends Base {
|
|
250
246
|
let me = this;
|
251
247
|
|
252
248
|
me.addDomListeners([
|
253
|
-
{input: me.onInputValueChange, scope: me},
|
249
|
+
{input : me.onInputValueChange, scope: me},
|
254
250
|
{mouseenter: me.onMouseEnter, scope: me},
|
255
251
|
{mouseleave: me.onMouseLeave, scope: me}
|
256
|
-
])
|
252
|
+
])
|
257
253
|
}
|
258
254
|
|
259
255
|
/**
|
@@ -263,13 +259,11 @@ class Text extends Base {
|
|
263
259
|
* @protected
|
264
260
|
*/
|
265
261
|
afterSetAppName(value, oldValue) {
|
266
|
-
let me = this;
|
267
|
-
|
268
262
|
super.afterSetAppName(value, oldValue);
|
269
263
|
|
270
|
-
value &&
|
264
|
+
value && this.triggers?.forEach(item => {
|
271
265
|
item.appName = value;
|
272
|
-
})
|
266
|
+
})
|
273
267
|
}
|
274
268
|
|
275
269
|
/**
|
@@ -279,7 +273,7 @@ class Text extends Base {
|
|
279
273
|
* @protected
|
280
274
|
*/
|
281
275
|
afterSetAutoCapitalize(value, oldValue) {
|
282
|
-
this.changeInputElKey('autocapitalize', value === 'off' || value === 'none' ? null : value)
|
276
|
+
this.changeInputElKey('autocapitalize', value === 'off' || value === 'none' ? null : value)
|
283
277
|
}
|
284
278
|
|
285
279
|
/**
|
@@ -290,7 +284,7 @@ class Text extends Base {
|
|
290
284
|
* @protected
|
291
285
|
*/
|
292
286
|
afterSetAutoComplete(value, oldValue) {
|
293
|
-
this.changeInputElKey('autocomplete', value ? null : 'no')
|
287
|
+
this.changeInputElKey('autocomplete', value ? null : 'no')
|
294
288
|
}
|
295
289
|
|
296
290
|
/**
|
@@ -306,9 +300,9 @@ class Text extends Base {
|
|
306
300
|
if (value) {
|
307
301
|
triggers = me.triggers || [];
|
308
302
|
triggers.unshift(ClearTrigger);
|
309
|
-
me.triggers = triggers
|
303
|
+
me.triggers = triggers
|
310
304
|
} else {
|
311
|
-
me.removeTrigger('clear')
|
305
|
+
me.removeTrigger('clear')
|
312
306
|
}
|
313
307
|
}
|
314
308
|
|
@@ -505,7 +499,7 @@ class Text extends Base {
|
|
505
499
|
|
506
500
|
!isEmpty && setTimeout(() => {
|
507
501
|
me.updateCenterBorderElWidth(false)
|
508
|
-
}, 20)
|
502
|
+
}, 20)
|
509
503
|
} else {
|
510
504
|
// changes from e.g. left to top
|
511
505
|
me.updateInputWidth()
|
@@ -980,7 +974,7 @@ class Text extends Base {
|
|
980
974
|
})
|
981
975
|
}
|
982
976
|
|
983
|
-
super.destroy(...args)
|
977
|
+
super.destroy(...args)
|
984
978
|
}
|
985
979
|
|
986
980
|
/**
|
@@ -1419,7 +1413,7 @@ class Text extends Base {
|
|
1419
1413
|
* @param {Boolean} silent=true
|
1420
1414
|
* @returns {Boolean} Returns true in case there are no client-side errors
|
1421
1415
|
*/
|
1422
|
-
validate(silent
|
1416
|
+
validate(silent=true) {
|
1423
1417
|
let me = this,
|
1424
1418
|
maxLength = me.maxLength,
|
1425
1419
|
minLength = me.minLength,
|
package/src/tree/Accordion.mjs
CHANGED
@@ -37,6 +37,18 @@ class AccordionTree extends TreeList {
|
|
37
37
|
* @member {Boolean} firstParentIsVisible=true
|
38
38
|
*/
|
39
39
|
firstParentIsVisible_: true,
|
40
|
+
/**
|
41
|
+
* Currently selected item, which is bindable
|
42
|
+
* @member {Record[|null} selection=null
|
43
|
+
*
|
44
|
+
* @example
|
45
|
+
* module: AccordionTree,
|
46
|
+
* bind : {selection: {twoWay: true, value: data => data.selection}}
|
47
|
+
*
|
48
|
+
* ntype: 'component',
|
49
|
+
* bind : {html: data => data.selection[0].name}
|
50
|
+
*/
|
51
|
+
selection_: null,
|
40
52
|
/**
|
41
53
|
* @member {Object} _vdom
|
42
54
|
*/
|
@@ -112,6 +124,25 @@ class AccordionTree extends TreeList {
|
|
112
124
|
return ClassSystemUtil.beforeSetInstance(value, TreeAccordionModel);
|
113
125
|
}
|
114
126
|
|
127
|
+
/**
|
128
|
+
* Remove all items from the accordion
|
129
|
+
* If you do not need to update the view after clearing, set `withUpdate = false`
|
130
|
+
*
|
131
|
+
* @param {Boolean} [withUpdate=true]
|
132
|
+
*/
|
133
|
+
clear(withUpdate = true) {
|
134
|
+
delete this.getVdomRoot().cn[0].cn
|
135
|
+
|
136
|
+
if (withUpdate) this.update();
|
137
|
+
}
|
138
|
+
|
139
|
+
/**
|
140
|
+
* Remove all items from the selection
|
141
|
+
*/
|
142
|
+
clearSelection() {
|
143
|
+
this.selectionModel.deselectAll();
|
144
|
+
}
|
145
|
+
|
115
146
|
/**
|
116
147
|
* @param {String} [parentId] The parent node
|
117
148
|
* @param {Object} [vdomRoot] The vdom template root for the current sub tree
|
@@ -133,12 +164,9 @@ class AccordionTree extends TreeList {
|
|
133
164
|
|
134
165
|
if (parentId !== null) {
|
135
166
|
vdomRoot.cn.push({
|
136
|
-
tag
|
137
|
-
cls
|
138
|
-
cn
|
139
|
-
style: {
|
140
|
-
paddingLeft: '15px'
|
141
|
-
}
|
167
|
+
tag: 'ul',
|
168
|
+
cls: ['neo-list'],
|
169
|
+
cn : []
|
142
170
|
});
|
143
171
|
|
144
172
|
tmpRoot = vdomRoot.cn[vdomRoot.cn.length - 1];
|
@@ -188,7 +216,6 @@ class AccordionTree extends TreeList {
|
|
188
216
|
}]
|
189
217
|
}],
|
190
218
|
style: {
|
191
|
-
padding : '10px',
|
192
219
|
position: item.isLeaf ? null : 'sticky',
|
193
220
|
top : item.isLeaf ? null : (level * 38) + 'px',
|
194
221
|
zIndex : item.isLeaf ? null : (20 / (level + 1)),
|
@@ -257,6 +284,7 @@ class AccordionTree extends TreeList {
|
|
257
284
|
|
258
285
|
/**
|
259
286
|
* Accordion gaining focus without selection => setSelection
|
287
|
+
*
|
260
288
|
* @param {Object} data
|
261
289
|
*/
|
262
290
|
onFocus(data) {
|
@@ -267,12 +295,85 @@ class AccordionTree extends TreeList {
|
|
267
295
|
if (!selection) selModel.selectRoot();
|
268
296
|
}
|
269
297
|
|
270
|
-
|
271
|
-
|
298
|
+
/**
|
299
|
+
* Called from SelectionModel select()
|
300
|
+
*
|
301
|
+
* @param {String[]} value
|
302
|
+
*/
|
303
|
+
onSelect(value) {
|
304
|
+
const me = this;
|
305
|
+
let records = [];
|
306
|
+
|
307
|
+
value.forEach((selectItemId) => {
|
308
|
+
let id = me.getItemRecordId(selectItemId),
|
309
|
+
record = me.store.get(id);
|
310
|
+
|
311
|
+
records.push(record);
|
312
|
+
});
|
313
|
+
|
314
|
+
me.selection = records;
|
315
|
+
}
|
316
|
+
|
317
|
+
/**
|
318
|
+
* After the store loaded, create the items for the list
|
319
|
+
*
|
320
|
+
* @param {Record[]} records
|
321
|
+
*/
|
322
|
+
onStoreLoad(records) {
|
323
|
+
let me = this,
|
324
|
+
listenerId;
|
325
|
+
|
326
|
+
me.clear(false);
|
327
|
+
|
328
|
+
if (!me.mounted && me.rendering) {
|
329
|
+
listenerId = me.on('mounted', () => {
|
330
|
+
me.un('mounted', listenerId);
|
331
|
+
me.createItems(null, me.getListItemsRoot(), 0);
|
332
|
+
me.timeout(0).then(() => {
|
333
|
+
me.update();
|
334
|
+
});
|
335
|
+
});
|
336
|
+
} else {
|
337
|
+
me.createItems(null, me.getListItemsRoot(), 0);
|
338
|
+
me.timeout(0).then(() => {
|
339
|
+
me.update();
|
340
|
+
});
|
341
|
+
}
|
272
342
|
}
|
273
343
|
|
274
344
|
onStoreRecordChange() {
|
275
345
|
}
|
346
|
+
|
347
|
+
/**
|
348
|
+
* Set the selection either bei record id or record.
|
349
|
+
* You can pass a record or a recordId as value
|
350
|
+
*
|
351
|
+
* @param {Record|Record[]|Number|Number[]|String|String[]} value
|
352
|
+
*/
|
353
|
+
setSelection(value) {
|
354
|
+
if (value === null) {
|
355
|
+
this.clearSelection();
|
356
|
+
return;
|
357
|
+
}
|
358
|
+
|
359
|
+
// In case you pass in an array use only the first item
|
360
|
+
if (Neo.isArray(value)) value = value[0];
|
361
|
+
|
362
|
+
const me = this;
|
363
|
+
let recordKeyProperty, elId;
|
364
|
+
|
365
|
+
if (Neo.isObject(value)) {
|
366
|
+
// Record
|
367
|
+
recordKeyProperty = value[me.getKeyProperty()];
|
368
|
+
} else {
|
369
|
+
// RecordId
|
370
|
+
recordKeyProperty = value;
|
371
|
+
}
|
372
|
+
|
373
|
+
elId = me.getItemId(recordKeyProperty);
|
374
|
+
|
375
|
+
me.selectionModel.selectAndScrollIntoView(elId);
|
376
|
+
}
|
276
377
|
}
|
277
378
|
|
278
379
|
Neo.applyClassConfig(AccordionTree);
|