neo.mjs 6.2.1 → 6.3.1
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/popover/MainContainer.mjs +58 -0
- package/examples/{treeSelectionModel → popover}/app.mjs +1 -1
- package/examples/popover/neo-config.json +13 -0
- package/examples/{treeSelectionModel → popover}/tree.json +1 -1
- package/examples/{treeSelectionModel → treeAccordion}/MainContainer.mjs +12 -4
- package/examples/treeAccordion/app.mjs +6 -0
- package/examples/treeAccordion/index.html +11 -0
- package/examples/{treeSelectionModel → treeAccordion}/neo-config.json +1 -1
- package/examples/treeAccordion/tree.json +112 -0
- package/package.json +1 -1
- package/resources/scss/src/examples/popover/MainContainer.scss +111 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/form/Container.mjs +45 -33
- package/src/form/field/Base.mjs +34 -19
- package/src/form/field/CheckBox.mjs +30 -2
- package/src/form/field/Radio.mjs +15 -3
- package/src/main/addon/Popover.mjs +75 -0
- package/src/main/addon/PrefixField.mjs +149 -0
- package/src/plugin/Popover.mjs +194 -0
- package/src/tree/Accordion.mjs +70 -17
- /package/examples/{treeSelectionModel → popover}/index.html +0 -0
- /package/resources/scss/src/examples/{treeSelectionModel → treeAccordion}/MainContainer.scss +0 -0
package/apps/ServiceWorker.mjs
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
import ConfigurationViewport from '../ConfigurationViewport.mjs';
|
2
|
+
|
3
|
+
import Component from '../../src/component/Base.mjs';
|
4
|
+
import PopoverPlugin from '../../src/plugin/Popover.mjs';
|
5
|
+
import Button from '../../src/button/Base.mjs';
|
6
|
+
|
7
|
+
/**
|
8
|
+
* @class Neo.examples.popover.MainContainer
|
9
|
+
* @extends Neo.examples.ConfigurationViewport
|
10
|
+
*/
|
11
|
+
class MainContainer extends ConfigurationViewport {
|
12
|
+
static config = {
|
13
|
+
className : 'Neo.examples.popover.MainContainer',
|
14
|
+
autoMount : true,
|
15
|
+
configItemLabelWidth: 100,
|
16
|
+
configItemWidth : 230,
|
17
|
+
layout : {ntype: 'hbox', align: 'stretch'},
|
18
|
+
cls : ['examples-container-accordion']
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
/**
|
23
|
+
* @returns {*}
|
24
|
+
*/
|
25
|
+
createExampleComponent() {
|
26
|
+
return Neo.ntype({
|
27
|
+
ntype : 'container',
|
28
|
+
height: '30%',
|
29
|
+
layout: {ntype: 'vbox', align: 'center', pack: 'center'},
|
30
|
+
items : [{
|
31
|
+
module: Component,
|
32
|
+
height: 10
|
33
|
+
}, {
|
34
|
+
module : Button,
|
35
|
+
width : 200,
|
36
|
+
text : 'Click Me',
|
37
|
+
plugins: [{
|
38
|
+
module: PopoverPlugin,
|
39
|
+
align : 'bc-tc',
|
40
|
+
items : [{
|
41
|
+
ntype : 'panel',
|
42
|
+
headers: [{
|
43
|
+
dock: 'top',
|
44
|
+
html: 'HEADER'
|
45
|
+
}],
|
46
|
+
items : [{
|
47
|
+
html: 'This is a comment about the button'
|
48
|
+
}]
|
49
|
+
}]
|
50
|
+
}]
|
51
|
+
}]
|
52
|
+
});
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
Neo.applyClassConfig(MainContainer);
|
57
|
+
|
58
|
+
export default MainContainer;
|
@@ -0,0 +1,13 @@
|
|
1
|
+
{
|
2
|
+
"appPath" : "examples/popover/app.mjs",
|
3
|
+
"basePath" : "../../",
|
4
|
+
"environment": "development",
|
5
|
+
"mainPath" : "./Main.mjs",
|
6
|
+
"themes" : ["neo-theme-dark", "neo-theme-light"],
|
7
|
+
"mainThreadAddons": [
|
8
|
+
"DragDrop",
|
9
|
+
"ScrollSync",
|
10
|
+
"Stylesheet",
|
11
|
+
"Popover"
|
12
|
+
]
|
13
|
+
}
|
@@ -10,12 +10,12 @@ import ViewController from '../../src/controller/Component.mjs';
|
|
10
10
|
import ViewModel from '../../src/model/Component.mjs';
|
11
11
|
|
12
12
|
/**
|
13
|
-
* @class Neo.examples.
|
13
|
+
* @class Neo.examples.treeAccordion.MainContainer
|
14
14
|
* @extends Neo.examples.ConfigurationViewport
|
15
15
|
*/
|
16
16
|
class MainContainer extends ConfigurationViewport {
|
17
17
|
static config = {
|
18
|
-
className : 'Neo.examples.
|
18
|
+
className : 'Neo.examples.treeAccordion.MainContainer',
|
19
19
|
autoMount : true,
|
20
20
|
configItemLabelWidth: 100,
|
21
21
|
configItemWidth : 230,
|
@@ -46,6 +46,14 @@ class MainContainer extends ConfigurationViewport {
|
|
46
46
|
listeners : {change: me.onConfigChange.bind(me, 'firstParentIsVisible')},
|
47
47
|
style : {marginTop: '10px'},
|
48
48
|
valueLabelText: 'firstParentIsVisible'
|
49
|
+
}, {
|
50
|
+
module : CheckBox,
|
51
|
+
checked : treeList.showIcon,
|
52
|
+
hideLabel : true,
|
53
|
+
hideValueLabel: false,
|
54
|
+
listeners : {change: me.onConfigChange.bind(me, 'showIcon')},
|
55
|
+
style : {marginTop: '10px'},
|
56
|
+
valueLabelText: 'showIcon'
|
49
57
|
}, {
|
50
58
|
module : NumberField,
|
51
59
|
clearable: true,
|
@@ -89,7 +97,7 @@ class MainContainer extends ConfigurationViewport {
|
|
89
97
|
},
|
90
98
|
|
91
99
|
autoLoad: true,
|
92
|
-
url : '../../examples/
|
100
|
+
url : '../../examples/treeAccordion/tree.json'
|
93
101
|
});
|
94
102
|
|
95
103
|
return Neo.ntype({
|
@@ -135,7 +143,7 @@ class MainContainer extends ConfigurationViewport {
|
|
135
143
|
}, {
|
136
144
|
module: Panel,
|
137
145
|
height: 150,
|
138
|
-
|
146
|
+
flex : 1,
|
139
147
|
|
140
148
|
itemDefaults: {
|
141
149
|
style: {
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<!DOCTYPE HTML>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
<title>Neo Tree</title>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<script src="../../src/MicroLoader.mjs" type="module"></script>
|
10
|
+
</body>
|
11
|
+
</html>
|
@@ -0,0 +1,112 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"id": 1,
|
4
|
+
"name": "ROOT",
|
5
|
+
"parentId": null,
|
6
|
+
"collapsed": false,
|
7
|
+
"isLeaf": false
|
8
|
+
},
|
9
|
+
{
|
10
|
+
"id": 2,
|
11
|
+
"name": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr,",
|
12
|
+
"parentId": 1,
|
13
|
+
"isLeaf": true,
|
14
|
+
"content": "Textfeld",
|
15
|
+
"iconCls": "fa fa-t color-blue"
|
16
|
+
},
|
17
|
+
{
|
18
|
+
"id": 3,
|
19
|
+
"name": "Sed diam nonumy",
|
20
|
+
"parentId": 1,
|
21
|
+
"isLeaf": true,
|
22
|
+
"content": "Textfeld",
|
23
|
+
"iconCls": "fa fa-t color-blue"
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"id": 4,
|
27
|
+
"name": "Eirmod",
|
28
|
+
"parentId": 1,
|
29
|
+
"isLeaf": true,
|
30
|
+
"content": "Textfeld",
|
31
|
+
"iconCls": "fa fa-t color-blue"
|
32
|
+
},
|
33
|
+
{
|
34
|
+
"id": 5,
|
35
|
+
"name": "Tempor",
|
36
|
+
"parentId": 1,
|
37
|
+
"isLeaf": true,
|
38
|
+
"content": "Textfeld",
|
39
|
+
"iconCls": "fa fa-t color-blue"
|
40
|
+
},
|
41
|
+
{
|
42
|
+
"id": 6,
|
43
|
+
"name": "Invidunt ut labore",
|
44
|
+
"parentId": 1,
|
45
|
+
"isLeaf": true,
|
46
|
+
"content": "Textfeld",
|
47
|
+
"iconCls": "fa fa-t color-blue"
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"id": 7,
|
51
|
+
"name": "Dolore magna aliquyam",
|
52
|
+
"parentId": null,
|
53
|
+
"collapsed": false,
|
54
|
+
"isLeaf": false
|
55
|
+
},
|
56
|
+
{
|
57
|
+
"id": 8,
|
58
|
+
"name": "V01 . At vero eos et accusam",
|
59
|
+
"parentId": 7,
|
60
|
+
"collapsed": false,
|
61
|
+
"isLeaf": false,
|
62
|
+
"content": "Auswählliste",
|
63
|
+
"iconCls": "fa fa-chevron-down color-red"
|
64
|
+
},
|
65
|
+
{
|
66
|
+
"id": 9,
|
67
|
+
"name": "Justo 1",
|
68
|
+
"parentId": 8,
|
69
|
+
"isLeaf": true,
|
70
|
+
"content": "Child",
|
71
|
+
"iconCls": "fa-regular fa-square-check color-green"
|
72
|
+
},
|
73
|
+
{
|
74
|
+
"id": 10,
|
75
|
+
"name": "Justo 2",
|
76
|
+
"parentId": 8,
|
77
|
+
"isLeaf": true,
|
78
|
+
"content": "Child",
|
79
|
+
"iconCls": "fa-regular fa-square-check color-green"
|
80
|
+
},
|
81
|
+
{
|
82
|
+
"id": 11,
|
83
|
+
"name": "Rebum",
|
84
|
+
"parentId": null,
|
85
|
+
"collapsed": false,
|
86
|
+
"isLeaf": false
|
87
|
+
},
|
88
|
+
{
|
89
|
+
"id": 12,
|
90
|
+
"name": "F0801 - Stet ",
|
91
|
+
"parentId": 11,
|
92
|
+
"isLeaf": true,
|
93
|
+
"content": "Datumfeld",
|
94
|
+
"iconCls": "fa-solid fa-calendar-days color-yellow"
|
95
|
+
},
|
96
|
+
{
|
97
|
+
"id": 13,
|
98
|
+
"name": "F0802 - Kasd",
|
99
|
+
"parentId": 11,
|
100
|
+
"isLeaf": true,
|
101
|
+
"content": "Datumfeld",
|
102
|
+
"iconCls": "fa-solid fa-calendar-days color-yellow"
|
103
|
+
},
|
104
|
+
{
|
105
|
+
"id": 14,
|
106
|
+
"name": "E30 - Gubergren",
|
107
|
+
"parentId": 11,
|
108
|
+
"isLeaf": true,
|
109
|
+
"content": "Mehrfachauswahl",
|
110
|
+
"iconCls": "fa-regular fa-square-check color-green"
|
111
|
+
}
|
112
|
+
]
|
package/package.json
CHANGED
@@ -0,0 +1,111 @@
|
|
1
|
+
[popover] {
|
2
|
+
inset: unset;
|
3
|
+
border-radius: 5px;
|
4
|
+
box-shadow: 2px 2px 7px #111;
|
5
|
+
background-color: #222;
|
6
|
+
|
7
|
+
//&.neo-popover[popover] {
|
8
|
+
// display: revert;
|
9
|
+
//}
|
10
|
+
|
11
|
+
&.bc-tc {
|
12
|
+
position-fallback: --bc-tc;
|
13
|
+
translate: -50%;
|
14
|
+
margin: .5rem 0;
|
15
|
+
}
|
16
|
+
&.tc-bc {
|
17
|
+
position-fallback: --tc-bc;
|
18
|
+
translate: -50%;
|
19
|
+
margin: .5rem 0;
|
20
|
+
}
|
21
|
+
&.tl-tr {
|
22
|
+
position-fallback: --tl-tr;
|
23
|
+
margin: 0 .5rem;
|
24
|
+
}
|
25
|
+
&.tr-tl {
|
26
|
+
position-fallback: --tl-tr;
|
27
|
+
margin: 0 .5rem;
|
28
|
+
}
|
29
|
+
&.cl-cr {
|
30
|
+
position-fallback: --cl-cr;
|
31
|
+
margin: 0 .25rem;
|
32
|
+
translate: 0 -50%;
|
33
|
+
}
|
34
|
+
&.cr-cl {
|
35
|
+
position-fallback: --cr-cl;
|
36
|
+
margin: 0 .25rem;
|
37
|
+
translate: 0 -50%;
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
@position-fallback --bc-tc {
|
42
|
+
@try {
|
43
|
+
bottom: anchor(top);
|
44
|
+
left: anchor(center);
|
45
|
+
}
|
46
|
+
|
47
|
+
@try {
|
48
|
+
top: anchor(bottom);
|
49
|
+
left: anchor(center);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
@position-fallback --tc-bc {
|
54
|
+
@try {
|
55
|
+
top: anchor(bottom);
|
56
|
+
left: anchor(center);
|
57
|
+
}
|
58
|
+
|
59
|
+
@try {
|
60
|
+
bottom: anchor(top);
|
61
|
+
left: anchor(center);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
@position-fallback --tl-tr {
|
66
|
+
@try {
|
67
|
+
top: anchor(top);
|
68
|
+
left: anchor(right);
|
69
|
+
}
|
70
|
+
|
71
|
+
@try {
|
72
|
+
top: anchor(top);
|
73
|
+
right: anchor(left);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
@position-fallback --tr-tl {
|
78
|
+
@try {
|
79
|
+
top: anchor(top);
|
80
|
+
right: anchor(left);
|
81
|
+
}
|
82
|
+
|
83
|
+
@try {
|
84
|
+
top: anchor(top);
|
85
|
+
left: anchor(right);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
@position-fallback --cr-cl {
|
90
|
+
@try {
|
91
|
+
top: anchor(center);
|
92
|
+
right: anchor(left);
|
93
|
+
}
|
94
|
+
|
95
|
+
@try {
|
96
|
+
top: anchor(center);
|
97
|
+
left: anchor(right);
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
@position-fallback --cl-cr {
|
102
|
+
@try {
|
103
|
+
top: anchor(center);
|
104
|
+
left: anchor(right);
|
105
|
+
}
|
106
|
+
|
107
|
+
@try {
|
108
|
+
top: anchor(center);
|
109
|
+
right: anchor(left);
|
110
|
+
}
|
111
|
+
}
|
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.
|
239
|
+
* @default '6.3.1'
|
240
240
|
* @memberOf! module:Neo
|
241
241
|
* @name config.version
|
242
242
|
* @type String
|
243
243
|
*/
|
244
|
-
version: '6.
|
244
|
+
version: '6.3.1'
|
245
245
|
};
|
246
246
|
|
247
247
|
Object.assign(DefaultConfig, {
|
package/src/form/Container.mjs
CHANGED
@@ -123,8 +123,8 @@ class Container extends BaseContainer {
|
|
123
123
|
|
124
124
|
await this.loadModules();
|
125
125
|
|
126
|
-
ComponentManager.getChildComponents(this).forEach(
|
127
|
-
|
126
|
+
ComponentManager.getChildComponents(this).forEach(field => {
|
127
|
+
field instanceof BaseField && fields.push(field)
|
128
128
|
});
|
129
129
|
|
130
130
|
return fields
|
@@ -135,40 +135,52 @@ class Container extends BaseContainer {
|
|
135
135
|
*/
|
136
136
|
async getValues() {
|
137
137
|
let fields = await this.getFields(),
|
138
|
+
Radio = Neo.form.field.Radio,
|
138
139
|
values = {},
|
139
|
-
|
140
|
+
fieldName, key, ns, nsArray, value;
|
140
141
|
|
141
|
-
fields.forEach(
|
142
|
-
value =
|
142
|
+
fields.forEach(field => {
|
143
|
+
value = field.getValue();
|
143
144
|
|
144
|
-
if (
|
145
|
-
|
145
|
+
if (field.name) {
|
146
|
+
fieldName = field.name;
|
146
147
|
|
147
|
-
if (
|
148
|
-
|
148
|
+
if (field.formGroup) {
|
149
|
+
fieldName = field.formGroup + '.' + fieldName;
|
149
150
|
}
|
150
151
|
|
151
|
-
nsArray =
|
152
|
+
nsArray = fieldName.split('.');
|
152
153
|
key = nsArray.pop();
|
153
154
|
ns = Neo.nsWithArrays(nsArray, true, values);
|
154
155
|
} else {
|
155
|
-
key =
|
156
|
+
key = field.id;
|
156
157
|
ns = values
|
157
158
|
}
|
158
159
|
|
160
|
+
// Ensuring that Radios will not return arrays
|
161
|
+
if (Radio && field instanceof Radio) {
|
162
|
+
// Only overwrite an existing value with a checked value
|
163
|
+
if (Object.hasOwn(ns, key)) {
|
164
|
+
if (value !== field.uncheckedValue) {
|
165
|
+
ns[key] = value
|
166
|
+
}
|
167
|
+
} else {
|
168
|
+
ns[key] = value
|
169
|
+
}
|
170
|
+
}
|
159
171
|
/*
|
160
172
|
* CheckBoxes need custom logic
|
161
173
|
* => we only want to pass the uncheckedValue in case the field does not belong to a group
|
162
174
|
* (multiple fields using the same name)
|
163
175
|
*/
|
164
|
-
if (Object.hasOwn(ns, key) && value !== undefined) {
|
165
|
-
if (ns[key] ===
|
176
|
+
else if (Object.hasOwn(ns, key) && value !== undefined) {
|
177
|
+
if (ns[key] === field.uncheckedValue) {
|
166
178
|
ns[key] = []
|
167
179
|
} else if (!Array.isArray(ns[key])) {
|
168
180
|
ns[key] = [ns[key]]
|
169
181
|
}
|
170
182
|
|
171
|
-
value !==
|
183
|
+
value !== field.uncheckedValue && ns[key].unshift(value)
|
172
184
|
} else if (value !== undefined) {
|
173
185
|
ns[key] = value
|
174
186
|
}
|
@@ -223,11 +235,11 @@ class Container extends BaseContainer {
|
|
223
235
|
fields = await me.getFields(),
|
224
236
|
path, value;
|
225
237
|
|
226
|
-
fields.forEach(
|
227
|
-
path = me.getFieldPath(
|
238
|
+
fields.forEach(field => {
|
239
|
+
path = me.getFieldPath(field);
|
228
240
|
value = Neo.nsWithArrays(path, false, values);
|
229
241
|
|
230
|
-
|
242
|
+
field.reset(path ? value : null)
|
231
243
|
})
|
232
244
|
}
|
233
245
|
|
@@ -241,38 +253,38 @@ class Container extends BaseContainer {
|
|
241
253
|
fields = await me.getFields(),
|
242
254
|
fieldConfigs, isCheckBox, isRadio, path, value;
|
243
255
|
|
244
|
-
fields.forEach(
|
245
|
-
path = me.getFieldPath(
|
256
|
+
fields.forEach(field => {
|
257
|
+
path = me.getFieldPath(field);
|
246
258
|
fieldConfigs = Neo.nsWithArrays(path, false, configs);
|
247
259
|
|
248
260
|
if (fieldConfigs) {
|
249
261
|
if (suspendEvents) {
|
250
|
-
|
262
|
+
field.suspendEvents = true
|
251
263
|
}
|
252
264
|
|
253
|
-
isCheckBox = Neo.form.field?.CheckBox &&
|
265
|
+
isCheckBox = Neo.form.field?.CheckBox && field instanceof Neo.form.field.CheckBox;
|
266
|
+
isRadio = Neo.form.field?.Radio && field instanceof Neo.form.field.Radio;
|
254
267
|
value = fieldConfigs.value;
|
255
268
|
|
256
|
-
if (
|
269
|
+
if (isRadio) {
|
270
|
+
fieldConfigs.checked = field.value === value;
|
271
|
+
delete fieldConfigs.value
|
272
|
+
} else if (isCheckBox) {
|
257
273
|
if (Neo.typeOf(value) === 'Array') {
|
258
|
-
if (value.includes(
|
274
|
+
if (value.includes(field.value)) {
|
259
275
|
fieldConfigs.checked = true
|
260
276
|
}
|
261
277
|
} else {
|
262
|
-
fieldConfigs.checked =
|
278
|
+
fieldConfigs.checked = field.value === value
|
263
279
|
}
|
264
|
-
} else if (value !== undefined) {
|
265
|
-
isRadio = Neo.form.field?.Radio && item instanceof Neo.form.field.Radio;
|
266
280
|
|
267
|
-
|
268
|
-
fieldConfigs.checked = item.value === value
|
269
|
-
}
|
281
|
+
delete fieldConfigs.value
|
270
282
|
}
|
271
283
|
|
272
|
-
|
284
|
+
field.set(fieldConfigs)
|
273
285
|
|
274
286
|
if (suspendEvents) {
|
275
|
-
delete
|
287
|
+
delete field.suspendEvents
|
276
288
|
}
|
277
289
|
}
|
278
290
|
})
|
@@ -299,8 +311,8 @@ class Container extends BaseContainer {
|
|
299
311
|
fields = await this.getFields(),
|
300
312
|
validField;
|
301
313
|
|
302
|
-
fields.forEach(
|
303
|
-
validField =
|
314
|
+
fields.forEach(field => {
|
315
|
+
validField = field.validate?.(false);
|
304
316
|
|
305
317
|
if (!validField) {
|
306
318
|
isValid = false
|
package/src/form/field/Base.mjs
CHANGED
@@ -76,9 +76,7 @@ class Base extends Component {
|
|
76
76
|
* @param {*} oldValue
|
77
77
|
*/
|
78
78
|
afterSetValue(value, oldValue) {
|
79
|
-
|
80
|
-
this.fireChangeEvent(value, oldValue)
|
81
|
-
}
|
79
|
+
oldValue !== undefined && this.fireChangeEvent(value, oldValue)
|
82
80
|
}
|
83
81
|
|
84
82
|
/**
|
@@ -134,27 +132,42 @@ class Base extends Component {
|
|
134
132
|
*/
|
135
133
|
fireChangeEvent(value, oldValue) {
|
136
134
|
let me = this,
|
137
|
-
FormContainer = Neo.form?.Container
|
135
|
+
FormContainer = Neo.form?.Container,
|
136
|
+
opts = {component: me, oldValue, value};
|
138
137
|
|
139
|
-
me.
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
138
|
+
if (Neo.isFunction(me.getGroupValue)) {
|
139
|
+
opts.groupValue = me.getGroupValue()
|
140
|
+
}
|
141
|
+
|
142
|
+
me.fire('change', opts);
|
144
143
|
|
145
144
|
if (!me.suspendEvents) {
|
146
145
|
ComponentManager.getParents(me).forEach(parent => {
|
147
146
|
if (FormContainer && parent instanceof FormContainer) {
|
148
|
-
parent.fire('fieldChange',
|
149
|
-
component: me,
|
150
|
-
oldValue,
|
151
|
-
value
|
152
|
-
})
|
147
|
+
parent.fire('fieldChange', opts)
|
153
148
|
}
|
154
149
|
})
|
155
150
|
}
|
156
151
|
}
|
157
152
|
|
153
|
+
/**
|
154
|
+
* Forms in neo can be nested. This method will return the closest parent which is a form.Container or null.
|
155
|
+
* @returns {Neo.form.Container|null}
|
156
|
+
*/
|
157
|
+
getClosestForm() {
|
158
|
+
let me = this,
|
159
|
+
FormContainer = Neo.form?.Container,
|
160
|
+
parent;
|
161
|
+
|
162
|
+
for (parent of ComponentManager.getParents(me)) {
|
163
|
+
if (FormContainer && parent instanceof FormContainer) {
|
164
|
+
return parent
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
return null
|
169
|
+
}
|
170
|
+
|
158
171
|
/**
|
159
172
|
* Override this method as needed
|
160
173
|
* @returns {Object|null}
|
@@ -213,15 +226,17 @@ class Base extends Component {
|
|
213
226
|
super.onFocusLeave?.(data);
|
214
227
|
|
215
228
|
let me = this,
|
216
|
-
FormContainer = Neo.form?.Container
|
229
|
+
FormContainer = Neo.form?.Container,
|
230
|
+
opts = {...data, component: me, value: me.getValue()};
|
231
|
+
|
232
|
+
if (Neo.isFunction(me.getGroupValue)) {
|
233
|
+
opts.groupValue = me.getGroupValue()
|
234
|
+
}
|
217
235
|
|
218
236
|
if (!me.suspendEvents) {
|
219
237
|
ComponentManager.getParents(me).forEach(parent => {
|
220
238
|
if (FormContainer && parent instanceof FormContainer) {
|
221
|
-
parent.fire('fieldFocusLeave',
|
222
|
-
...data,
|
223
|
-
component: me
|
224
|
-
})
|
239
|
+
parent.fire('fieldFocusLeave', opts)
|
225
240
|
}
|
226
241
|
})
|
227
242
|
}
|
@@ -194,7 +194,7 @@ class CheckBox extends Base {
|
|
194
194
|
me.update();
|
195
195
|
|
196
196
|
if (oldValue !== undefined) {
|
197
|
-
me.fireChangeEvent(me.getValue(),
|
197
|
+
me.fireChangeEvent(me.getValue(), me.getOldValue())
|
198
198
|
}
|
199
199
|
}
|
200
200
|
|
@@ -433,6 +433,23 @@ class CheckBox extends Base {
|
|
433
433
|
return true
|
434
434
|
}
|
435
435
|
|
436
|
+
/**
|
437
|
+
* @returns {String[]}
|
438
|
+
*/
|
439
|
+
getGroupValue() {
|
440
|
+
let form = this.getClosestForm(),
|
441
|
+
fields = ComponentManager.find({path: this.getPath()}),
|
442
|
+
value = [];
|
443
|
+
|
444
|
+
fields.forEach(field => {
|
445
|
+
if (field.checked && field.getClosestForm() === form) {
|
446
|
+
NeoArray.add(value, field.value)
|
447
|
+
}
|
448
|
+
});
|
449
|
+
|
450
|
+
return value
|
451
|
+
}
|
452
|
+
|
436
453
|
/**
|
437
454
|
* @returns {String}
|
438
455
|
*/
|
@@ -462,6 +479,17 @@ class CheckBox extends Base {
|
|
462
479
|
}
|
463
480
|
|
464
481
|
/**
|
482
|
+
* Counterpart to getValue(), returning the uncheckedValue if checked
|
483
|
+
* @returns {String|null}
|
484
|
+
*/
|
485
|
+
getOldValue() {
|
486
|
+
let me = this;
|
487
|
+
|
488
|
+
return me.checked ? me.uncheckedValue : me.value
|
489
|
+
}
|
490
|
+
|
491
|
+
/**
|
492
|
+
* Returns this.value if checked, otherwise this.uncheckedValue
|
465
493
|
* @returns {String|null}
|
466
494
|
*/
|
467
495
|
getValue() {
|
@@ -482,7 +510,7 @@ class CheckBox extends Base {
|
|
482
510
|
*/
|
483
511
|
isValid() {
|
484
512
|
this.validate(true); // silent
|
485
|
-
|
513
|
+
|
486
514
|
return this.error ? false : super.isValid()
|
487
515
|
}
|
488
516
|
|
package/src/form/field/Radio.mjs
CHANGED
@@ -45,10 +45,22 @@ class Radio extends CheckBox {
|
|
45
45
|
}
|
46
46
|
|
47
47
|
/**
|
48
|
-
*
|
48
|
+
* Radios should only fire change & fieldChange events if checked.
|
49
|
+
* If there was just 1 radio, you can not uncheck it.
|
50
|
+
* @param {*} value
|
51
|
+
* @param {*} oldValue
|
49
52
|
*/
|
50
|
-
|
51
|
-
|
53
|
+
fireChangeEvent(value, oldValue) {
|
54
|
+
this.checked && super.fireChangeEvent(value, oldValue)
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
* @returns {String[]}
|
59
|
+
*/
|
60
|
+
getGroupValue() {
|
61
|
+
let value = super.getGroupValue();
|
62
|
+
|
63
|
+
return value.length > 0 ? value[0] : []
|
52
64
|
}
|
53
65
|
|
54
66
|
/**
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import Base from '../../core/Base.mjs';
|
2
|
+
import DomAccess from '../DomAccess.mjs'
|
3
|
+
/**
|
4
|
+
* Addon for Popover
|
5
|
+
* @class Neo.main.addon.Popover
|
6
|
+
* @extends Neo.core.Base
|
7
|
+
* @singleton
|
8
|
+
*/
|
9
|
+
class Popover extends Base {
|
10
|
+
static config = {
|
11
|
+
/**
|
12
|
+
* @member {String} className='Neo.main.addon.Popover'
|
13
|
+
* @protected
|
14
|
+
*/
|
15
|
+
className: 'Neo.main.addon.Popover',
|
16
|
+
/**
|
17
|
+
* Remote method access for other workers
|
18
|
+
* @member {Object} remote={app: [//...]}
|
19
|
+
* @protected
|
20
|
+
*/
|
21
|
+
remote: {
|
22
|
+
app: [
|
23
|
+
'hide',
|
24
|
+
'show',
|
25
|
+
'toggle'
|
26
|
+
]
|
27
|
+
},
|
28
|
+
/**
|
29
|
+
* @member {Boolean} singleton=true
|
30
|
+
* @protected
|
31
|
+
*/
|
32
|
+
singleton: true
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
* @param {Object} data
|
37
|
+
* @param {String} data.id
|
38
|
+
* @returns {Boolean}
|
39
|
+
*/
|
40
|
+
hide(data) {
|
41
|
+
this.getPopover(data.id).hidePopover();
|
42
|
+
return true;
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
* @param {Object} data
|
47
|
+
* @param {String} data.id
|
48
|
+
* @returns {Boolean}
|
49
|
+
*/
|
50
|
+
show(data) {
|
51
|
+
this.getPopover(data.id).showPopover();
|
52
|
+
return true;
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* @param {Object} data
|
57
|
+
* @param {String} data.id
|
58
|
+
* @returns {Boolean}
|
59
|
+
*/
|
60
|
+
toggle(data) {
|
61
|
+
this.getPopover(data.id).togglePopover();
|
62
|
+
return true;
|
63
|
+
}
|
64
|
+
|
65
|
+
getPopover(parentId) {
|
66
|
+
const parent = document.getElementById(parentId),
|
67
|
+
popover = document.getElementById(parent.getAttribute('popovertarget'));
|
68
|
+
|
69
|
+
return popover;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
let instance = Neo.applyClassConfig(Popover);
|
74
|
+
|
75
|
+
export default instance;
|
@@ -0,0 +1,149 @@
|
|
1
|
+
import Base from '../../core/Base.mjs';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Helper class to include Google's Material Web Components into your neo.mjs app
|
5
|
+
* https://www.amcharts.com/docs/v4/
|
6
|
+
* @class Neo.main.addon.PrefixField
|
7
|
+
* @extends Neo.core.Base
|
8
|
+
* @singleton
|
9
|
+
*/
|
10
|
+
class PrefixField extends Base {
|
11
|
+
static config = {
|
12
|
+
/**
|
13
|
+
* @member {String} className='Neo.main.addon.PrefixField'
|
14
|
+
* @protected
|
15
|
+
*/
|
16
|
+
className: 'Neo.main.addon.PrefixField',
|
17
|
+
/**
|
18
|
+
* @member {Boolean} singleton=true
|
19
|
+
* @protected
|
20
|
+
*/
|
21
|
+
singleton: true,
|
22
|
+
/**
|
23
|
+
* Remote method access for other workers
|
24
|
+
* @member {Object} remote
|
25
|
+
* @protected
|
26
|
+
*/
|
27
|
+
remote: {
|
28
|
+
app: [
|
29
|
+
'initialize',
|
30
|
+
'destroy',
|
31
|
+
'updateAccept',
|
32
|
+
'updatePattern',
|
33
|
+
'updateSlots',
|
34
|
+
]
|
35
|
+
},
|
36
|
+
|
37
|
+
/**
|
38
|
+
* regex to calculate if entered value is acceptable
|
39
|
+
* Preset to numbers only
|
40
|
+
*
|
41
|
+
* @member {regex|null} accept
|
42
|
+
*/
|
43
|
+
accept_: null,
|
44
|
+
/**
|
45
|
+
* @member {String} pattern=null
|
46
|
+
*/
|
47
|
+
pattern_: null,
|
48
|
+
/**
|
49
|
+
* Only add a String. A Set will be automatically created
|
50
|
+
* @member {String|Set|null} slots=null
|
51
|
+
*/
|
52
|
+
slots_: null
|
53
|
+
}
|
54
|
+
|
55
|
+
destroy() {
|
56
|
+
|
57
|
+
}
|
58
|
+
|
59
|
+
elIds = new Map();
|
60
|
+
|
61
|
+
prev;
|
62
|
+
|
63
|
+
back = false;
|
64
|
+
|
65
|
+
/**
|
66
|
+
*
|
67
|
+
* @param {Object} data
|
68
|
+
* @param {String} data.elId
|
69
|
+
* @param {String} data.pattern
|
70
|
+
* @param {String} data.slots
|
71
|
+
* @param {String} data.accept
|
72
|
+
*/
|
73
|
+
initialize(data) {
|
74
|
+
const me = this;
|
75
|
+
|
76
|
+
me.elId = data.elId;
|
77
|
+
|
78
|
+
const el = me.el = document.getElementById(data.elId),
|
79
|
+
pattern = me.pattern = data.pattern,
|
80
|
+
slots = me.slots = new Set(data.slots || "_");
|
81
|
+
|
82
|
+
me.accept = data.accept;
|
83
|
+
me.prev = (j => Array.from(pattern, (c, i) => slots.has(c) ? j = i + 1 : j))(0);
|
84
|
+
me.first = [...pattern].findIndex(c => slots.has(c));
|
85
|
+
|
86
|
+
me.addListeners();
|
87
|
+
me.addCss();
|
88
|
+
}
|
89
|
+
|
90
|
+
addCss() {
|
91
|
+
this.el.classList.add('tiny-prefix-field-input');
|
92
|
+
}
|
93
|
+
|
94
|
+
addListeners() {
|
95
|
+
const me = this,
|
96
|
+
el = me.el,
|
97
|
+
formatFn = me.format.bind(me);
|
98
|
+
|
99
|
+
el.addEventListener("keypress", me.onKeyDown.bind(me));
|
100
|
+
el.addEventListener("input", formatFn);
|
101
|
+
el.addEventListener("focusin", formatFn);
|
102
|
+
el.addEventListener("focusout", me.onBlur.bind(me));
|
103
|
+
}
|
104
|
+
|
105
|
+
onBlur() {
|
106
|
+
const pattern = this.pattern,
|
107
|
+
el = this.el;
|
108
|
+
|
109
|
+
return el.value === pattern && (el.value = "");
|
110
|
+
}
|
111
|
+
|
112
|
+
onKeyDown(event) {
|
113
|
+
this.back = (event.key === "Backspace");
|
114
|
+
}
|
115
|
+
|
116
|
+
clean(input) {
|
117
|
+
const el = this.el,
|
118
|
+
accept = new RegExp(this.accept || "\\d", "g"),
|
119
|
+
pattern = this.pattern,
|
120
|
+
slots = this.slots;
|
121
|
+
|
122
|
+
input = input.match(accept) || [];
|
123
|
+
|
124
|
+
return Array.from(pattern, c =>
|
125
|
+
input[0] === c || slots.has(c) ? input.shift() || c : c
|
126
|
+
);
|
127
|
+
}
|
128
|
+
|
129
|
+
format() {
|
130
|
+
const me = this,
|
131
|
+
el = this.el,
|
132
|
+
prev = this.prev,
|
133
|
+
clean = this.clean.bind(this);
|
134
|
+
console.log(el.selectionStart, el.selectionEnd);
|
135
|
+
const [i, j] = [el.selectionStart, el.selectionEnd].map(i => {
|
136
|
+
i = clean(el.value.slice(0, i)).findIndex(c => me.slots.has(c));
|
137
|
+
return i < 0 ? prev[prev.length - 1] : me.back ? prev[i - 1] || me.first : i;
|
138
|
+
});
|
139
|
+
|
140
|
+
el.value = clean(el.value).join``;
|
141
|
+
el.setSelectionRange(i, j);
|
142
|
+
|
143
|
+
this.back = false;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
let instance = Neo.applyClassConfig(PrefixField);
|
148
|
+
|
149
|
+
export default instance;
|
@@ -0,0 +1,194 @@
|
|
1
|
+
import Base from './Base.mjs';
|
2
|
+
import Container from '../container/Base.mjs'
|
3
|
+
import NeoArray from "../util/Array.mjs";
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Popover usable as tooltip
|
7
|
+
* @class Neo.plugin.Popover
|
8
|
+
* @extends Neo.plugin.Base
|
9
|
+
*
|
10
|
+
* @example
|
11
|
+
*
|
12
|
+
* module : Button,
|
13
|
+
* width : 200,
|
14
|
+
* text : 'Click Me',
|
15
|
+
* plugins: [{
|
16
|
+
* module: PopoverPlugin,
|
17
|
+
* align : 'bc-tc',
|
18
|
+
* items : [{
|
19
|
+
* ntype : 'panel',
|
20
|
+
* headers: [{
|
21
|
+
* dock: 'top',
|
22
|
+
* html: 'HEADER'
|
23
|
+
* }],
|
24
|
+
* items : [{
|
25
|
+
* html: 'This is a comment about the button'
|
26
|
+
* }]
|
27
|
+
* }]
|
28
|
+
* }]
|
29
|
+
*/
|
30
|
+
class Popover extends Base {
|
31
|
+
/**
|
32
|
+
* Valid values for align
|
33
|
+
* @member {String[]} alignValues=['bc-tc','tc-bc','tl-tr','tr-tl','cl-cr','cr-cl',null]
|
34
|
+
* @protected
|
35
|
+
* @static
|
36
|
+
*
|
37
|
+
* todo add more
|
38
|
+
*/
|
39
|
+
static alignValues = ['bc-tc', 'tc-bc', 'tl-tr', 'tr-tl', 'cl-cr', 'cr-cl', null]
|
40
|
+
|
41
|
+
static config = {
|
42
|
+
/**
|
43
|
+
* @member {String} className='Neo.plugin.Popover'
|
44
|
+
* @protected
|
45
|
+
*/
|
46
|
+
className: 'Neo.plugin.Popover',
|
47
|
+
/**
|
48
|
+
* @member {String} ntype='popover'
|
49
|
+
* @protected
|
50
|
+
*/
|
51
|
+
ntype: 'plugin-popover',
|
52
|
+
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Define popover to popovertarget alignment
|
56
|
+
* Defaults to bottom center of popover is aligned to top center of owner
|
57
|
+
* @type {string} align='bc-tc'
|
58
|
+
*/
|
59
|
+
align_: 'bc-tc',
|
60
|
+
/**
|
61
|
+
* Custom cls to add to the owner component
|
62
|
+
* @member {String} ownerCls='neo-prefixfield'
|
63
|
+
*/
|
64
|
+
popovertargetCls: 'neo-popover-target',
|
65
|
+
/**
|
66
|
+
* Custom cls to add to the owner component
|
67
|
+
* @member {String} ownerCls='neo-prefixfield'
|
68
|
+
*/
|
69
|
+
popoverBaseCls: 'neo-popover',
|
70
|
+
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* @param {Object} config
|
74
|
+
*/
|
75
|
+
construct(config) {
|
76
|
+
let me = this;
|
77
|
+
|
78
|
+
super.construct(config);
|
79
|
+
|
80
|
+
me.popoverId = Neo.getId('popover');
|
81
|
+
|
82
|
+
// prepare owner
|
83
|
+
me.preparePopoverTarget();
|
84
|
+
me.addPopover();
|
85
|
+
|
86
|
+
me.addListeners();
|
87
|
+
}
|
88
|
+
|
89
|
+
/**
|
90
|
+
* Add listeners
|
91
|
+
* @protected
|
92
|
+
*/
|
93
|
+
addListeners() {
|
94
|
+
const me = this;
|
95
|
+
|
96
|
+
me.owner.addDomListeners([
|
97
|
+
{mouseover: me.onTargetMouseOver, scope: me},
|
98
|
+
{mouseout: me.onTargetMouseOut, scope: me}
|
99
|
+
]);
|
100
|
+
}
|
101
|
+
|
102
|
+
/**
|
103
|
+
* Create the popover and add it to the parent component of the owner
|
104
|
+
* @protected
|
105
|
+
*/
|
106
|
+
addPopover() {
|
107
|
+
const me = this,
|
108
|
+
owner = me.owner,
|
109
|
+
parent = Neo.get(me.owner.parentId),
|
110
|
+
popover = {
|
111
|
+
module: Container,
|
112
|
+
id : me.popoverId,
|
113
|
+
|
114
|
+
baseCls: [me.popoverBaseCls],
|
115
|
+
cls : [me.align],
|
116
|
+
|
117
|
+
layout: 'base',
|
118
|
+
items : me.items || [],
|
119
|
+
|
120
|
+
vdom: {
|
121
|
+
// Possible Values are auto, manual.
|
122
|
+
popover: 'auto',
|
123
|
+
anchor : owner.id
|
124
|
+
}
|
125
|
+
};
|
126
|
+
|
127
|
+
parent.add(popover);
|
128
|
+
}
|
129
|
+
|
130
|
+
/**
|
131
|
+
* Checks if the new value for "align" is valid
|
132
|
+
* @param {String|null} value
|
133
|
+
* @param {String|null} oldValue
|
134
|
+
* @protected
|
135
|
+
* @returns {String|null} value
|
136
|
+
*/
|
137
|
+
beforeSetAlign(value, oldValue) {
|
138
|
+
return this.testInputValue(value, oldValue, 'alignValues', 'align');
|
139
|
+
}
|
140
|
+
|
141
|
+
/**
|
142
|
+
* @event mouseout
|
143
|
+
* @param {Object} data
|
144
|
+
* @protected
|
145
|
+
*/
|
146
|
+
onTargetMouseOut(data) {
|
147
|
+
Neo.main.addon.Popover.hide({id: data.component.id});
|
148
|
+
}
|
149
|
+
|
150
|
+
/**
|
151
|
+
* @event mouseover
|
152
|
+
* @param {Object} data
|
153
|
+
* @protected
|
154
|
+
*/
|
155
|
+
onTargetMouseOver(data) {
|
156
|
+
Neo.main.addon.Popover.show({id: data.component.id});
|
157
|
+
}
|
158
|
+
|
159
|
+
/**
|
160
|
+
* @protected
|
161
|
+
*/
|
162
|
+
preparePopoverTarget() {
|
163
|
+
const me = this,
|
164
|
+
target = me.owner,
|
165
|
+
targetVdom = target.vdom;
|
166
|
+
|
167
|
+
target.addCls(me.popovertargetCls);
|
168
|
+
targetVdom.popovertarget = me.popoverId;
|
169
|
+
}
|
170
|
+
|
171
|
+
/**
|
172
|
+
* Checks if the new value for propertyName is valid
|
173
|
+
* @param {String|null} value
|
174
|
+
* @param {String|null} oldValue
|
175
|
+
* @param {String} validValuesName
|
176
|
+
* @param {String} propertyName
|
177
|
+
* @protected
|
178
|
+
* @returns {String|null} value
|
179
|
+
*/
|
180
|
+
testInputValue(value, oldValue, validValuesName, propertyName) {
|
181
|
+
const validValues = this.getStaticConfig(validValuesName);
|
182
|
+
|
183
|
+
if (!NeoArray.hasItem(validValues, value)) {
|
184
|
+
Neo.logError(this.id + ' -> layout: supported values for "' + propertyName + '" are', validValues);
|
185
|
+
return oldValue;
|
186
|
+
}
|
187
|
+
|
188
|
+
return value;
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
192
|
+
Neo.applyClassConfig(Popover);
|
193
|
+
|
194
|
+
export default Popover;
|
package/src/tree/Accordion.mjs
CHANGED
@@ -7,6 +7,20 @@ import VDomUtil from "../util/VDom.mjs";
|
|
7
7
|
/**
|
8
8
|
* @class Neo.tree.Accordion
|
9
9
|
* @extends Neo.tree.List
|
10
|
+
*
|
11
|
+
* Accordion Store expects the following fields
|
12
|
+
*
|
13
|
+
* [
|
14
|
+
* iconCls, // can be defined in fields:icon
|
15
|
+
* content, // can be defined in fields:text
|
16
|
+
* name, // can be defined in fields:header
|
17
|
+
*
|
18
|
+
* collapsed, // collapsed state for non-leaf-items
|
19
|
+
* isLeaf, // defines it item is leaf-item
|
20
|
+
* id, // defines item id
|
21
|
+
* parentId // leaf or sub-items need a parentId
|
22
|
+
* ]
|
23
|
+
*
|
10
24
|
*/
|
11
25
|
class AccordionTree extends TreeList {
|
12
26
|
static config = {
|
@@ -25,19 +39,24 @@ class AccordionTree extends TreeList {
|
|
25
39
|
*/
|
26
40
|
baseCls: ['neo-tree-list'],
|
27
41
|
/**
|
28
|
-
*
|
42
|
+
* Set to false to hide the initial root item
|
43
|
+
* @member {Boolean} firstParentIsVisible=true
|
29
44
|
*/
|
30
|
-
|
45
|
+
firstParentIsVisible_: true,
|
46
|
+
/**
|
47
|
+
* Define the field names for the store to show header, text and icon
|
48
|
+
* @member {Object} fields={header:'name',icon:'iconCls',text:'content'}
|
49
|
+
*/
|
50
|
+
fields: {
|
51
|
+
header: 'name',
|
52
|
+
icon : 'iconCls',
|
53
|
+
text : 'content'
|
54
|
+
},
|
31
55
|
/**
|
32
56
|
* Set to false will auto expand root parent items and disallow collapsing
|
33
57
|
* @member {Boolean} rootParentIsCollapsible=false
|
34
58
|
*/
|
35
59
|
rootParentsAreCollapsible_: false,
|
36
|
-
/**
|
37
|
-
* Set to false to hide the initial root item
|
38
|
-
* @member {Boolean} firstParentIsVisible=true
|
39
|
-
*/
|
40
|
-
firstParentIsVisible_: true,
|
41
60
|
/**
|
42
61
|
* Currently selected item, which is bindable
|
43
62
|
* @member {Record[]|null} selection=null
|
@@ -50,6 +69,15 @@ class AccordionTree extends TreeList {
|
|
50
69
|
* bind : {html: data => data.selection[0].name}
|
51
70
|
*/
|
52
71
|
selection_: null,
|
72
|
+
/**
|
73
|
+
* Set to false will hide the icons for all leaf items
|
74
|
+
* @member {Boolean} showIcon=true
|
75
|
+
*/
|
76
|
+
showIcon_: true,
|
77
|
+
/**
|
78
|
+
* @member {Boolean} showCollapseExpandAllIcons=true
|
79
|
+
*/
|
80
|
+
showCollapseExpandAllIcons: false,
|
53
81
|
/**
|
54
82
|
* @member {Object} _vdom
|
55
83
|
*/
|
@@ -114,6 +142,31 @@ class AccordionTree extends TreeList {
|
|
114
142
|
}
|
115
143
|
}
|
116
144
|
|
145
|
+
/**
|
146
|
+
* Called when changing showIcon
|
147
|
+
* Changes the display of the icons
|
148
|
+
*
|
149
|
+
* @param {Boolean} value
|
150
|
+
* @param {Boolean} oldValue
|
151
|
+
*/
|
152
|
+
afterSetShowIcon(value, oldValue) {
|
153
|
+
const me = this,
|
154
|
+
store = me.store,
|
155
|
+
hide = !value;
|
156
|
+
|
157
|
+
store.items.forEach((record) => {
|
158
|
+
const itemId = me.getItemId(record[me.getKeyProperty()]),
|
159
|
+
vdom = me.getVdomChild(itemId),
|
160
|
+
itemVdom = VDomUtil.getByFlag(vdom, 'icon');
|
161
|
+
|
162
|
+
if (record.isLeaf) {
|
163
|
+
itemVdom.removeDom = hide;
|
164
|
+
}
|
165
|
+
})
|
166
|
+
|
167
|
+
me.update()
|
168
|
+
}
|
169
|
+
|
117
170
|
/**
|
118
171
|
* Triggered before the selectionModel config gets changed.
|
119
172
|
* @param {Neo.selection.Model} value
|
@@ -211,10 +264,11 @@ class AccordionTree extends TreeList {
|
|
211
264
|
cls,
|
212
265
|
id,
|
213
266
|
cn : [{
|
267
|
+
flag : 'icon',
|
214
268
|
tag : 'span',
|
215
|
-
cls : ['neo-accordion-item-icon', item.
|
216
|
-
id : id + '
|
217
|
-
removeDom: !item.isLeaf
|
269
|
+
cls : ['neo-accordion-item-icon', item[me.fields.icon]],
|
270
|
+
id : id + '__icon',
|
271
|
+
removeDom: (!item.isLeaf || !me.showIcon)
|
218
272
|
}, {
|
219
273
|
cls : [itemCls + '-content'],
|
220
274
|
id : id + '__item-content',
|
@@ -224,13 +278,13 @@ class AccordionTree extends TreeList {
|
|
224
278
|
tag : 'span',
|
225
279
|
cls : [itemCls + '-content-header'],
|
226
280
|
id : id + '__item-content-header',
|
227
|
-
innerHTML: item.
|
281
|
+
innerHTML: item[me.fields.header]
|
228
282
|
}, {
|
229
283
|
flag : 'content',
|
230
284
|
tag : 'span',
|
231
285
|
cls : [itemCls + '-content-text'],
|
232
286
|
id : id + '__item-content-text',
|
233
|
-
innerHTML: item.
|
287
|
+
innerHTML: item[me.fields.text]
|
234
288
|
}]
|
235
289
|
}],
|
236
290
|
style: {
|
@@ -273,7 +327,6 @@ class AccordionTree extends TreeList {
|
|
273
327
|
const me = this,
|
274
328
|
selectionModel = me.selectionModel,
|
275
329
|
itemId = item.id,
|
276
|
-
// ! todo make it String
|
277
330
|
id = Number(itemId.split('__')[1]),
|
278
331
|
record = me.store.get(id);
|
279
332
|
|
@@ -354,11 +407,11 @@ class AccordionTree extends TreeList {
|
|
354
407
|
|
355
408
|
/**
|
356
409
|
* Update a record
|
357
|
-
* @param {Object}
|
358
|
-
* @param {Object[]}
|
359
|
-
* @param {Number}
|
410
|
+
* @param {Object} data
|
411
|
+
* @param {Object[]} data.fields
|
412
|
+
* @param {Number} data.index
|
360
413
|
* @param {Neo.data.Model} data.model
|
361
|
-
* @param {Record}
|
414
|
+
* @param {Record} data.record
|
362
415
|
*/
|
363
416
|
onStoreRecordChange(data) {
|
364
417
|
let me = this,
|
File without changes
|
/package/resources/scss/src/examples/{treeSelectionModel → treeAccordion}/MainContainer.scss
RENAMED
File without changes
|