neo.mjs 5.10.2 → 5.10.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/buildScripts/createClass.mjs +10 -2
- package/examples/ConfigurationViewport.mjs +6 -2
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/component/process/MainContainer.mjs +90 -0
- package/examples/component/process/app.mjs +6 -0
- package/examples/component/process/index.html +11 -0
- package/examples/component/process/neo-config.json +6 -0
- package/examples/component/process/realWorldExample/MainContainer.mjs +334 -0
- package/examples/component/process/realWorldExample/RangeHeader.jpg +0 -0
- package/examples/component/process/realWorldExample/app.mjs +6 -0
- package/examples/component/process/realWorldExample/index.html +11 -0
- package/examples/component/process/realWorldExample/neo-config.json +6 -0
- package/examples/component/toast/MainContainer.mjs +9 -6
- package/examples/component/toast/MainContainerController.mjs +5 -5
- package/examples/component/toast/neo-config.json +1 -1
- package/examples/container/accordion/MainContainer.mjs +123 -0
- package/examples/container/accordion/app.mjs +6 -0
- package/examples/container/accordion/index.html +11 -0
- package/examples/container/accordion/neo-config.json +6 -0
- package/package.json +1 -1
- package/resources/scss/src/component/Process.scss +2 -4
- package/resources/scss/src/container/Accordion.scss +25 -0
- package/resources/scss/src/container/AccordionItem.scss +83 -0
- package/resources/scss/src/form/field/CheckBox.scss +1 -0
- package/resources/scss/src/form/field/Range.scss +1 -0
- package/resources/scss/theme-dark/component/Process.scss +8 -8
- package/resources/scss/theme-dark/container/Accordion.scss +13 -0
- package/resources/scss/theme-dark/container/AccordionItem.scss +23 -0
- package/resources/scss/theme-light/component/Process.scss +7 -7
- package/resources/scss/theme-light/container/Accordion.scss +13 -0
- package/resources/scss/theme-light/container/AccordionItem.scss +23 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/component/Process.mjs +11 -7
- package/src/component/Splitter.mjs +5 -4
- package/src/component/Toast.mjs +2 -1
- package/src/container/Accordion.mjs +130 -0
- package/src/container/AccordionItem.mjs +178 -0
- package/src/form/Container.mjs +42 -25
- package/src/form/field/CheckBox.mjs +7 -2
- package/src/form/field/Number.mjs +49 -37
- package/src/form/field/Range.mjs +31 -4
- package/src/form/field/Text.mjs +6 -1
- package/src/manager/Toast.mjs +5 -1
@@ -0,0 +1,130 @@
|
|
1
|
+
import AccordionItem from './AccordionItem.mjs';
|
2
|
+
import NeoArray from '../util/Array.mjs';
|
3
|
+
import Panel from './Panel.mjs';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* @class Neo.container.Accordion
|
7
|
+
* @extends Neo.container.Panel
|
8
|
+
*/
|
9
|
+
class Accordion extends Panel {
|
10
|
+
static config = {
|
11
|
+
/**
|
12
|
+
* @member {String} className='Neo.container.Accordion'
|
13
|
+
* @protected
|
14
|
+
*/
|
15
|
+
className: 'Neo.container.Accordion',
|
16
|
+
/**
|
17
|
+
* @member {String} ntype='accordion'
|
18
|
+
* @protected
|
19
|
+
*/
|
20
|
+
ntype: 'accordion',
|
21
|
+
/**
|
22
|
+
* @member {String[]} baseCls=['neo-accordion']
|
23
|
+
*/
|
24
|
+
baseCls: ['neo-accordion'],
|
25
|
+
/**
|
26
|
+
* Add zero based numbers, which accordion items you want initially expanded
|
27
|
+
* @member {Number[]} initialOpen=[]
|
28
|
+
*/
|
29
|
+
initialOpen_: [],
|
30
|
+
/**
|
31
|
+
* @member {Object} itemDefaults={ntype:'accordionitem'}
|
32
|
+
*/
|
33
|
+
itemDefaults: {ntype: 'accordionitem'},
|
34
|
+
/**
|
35
|
+
* @member {Object[]} items=[]
|
36
|
+
*/
|
37
|
+
items: [],
|
38
|
+
/**
|
39
|
+
* Max number of accordion items, which can be expanded at the same time
|
40
|
+
* @member {Number} maxExpandedItems=1
|
41
|
+
*/
|
42
|
+
maxExpandedItems: 1,
|
43
|
+
/**
|
44
|
+
* Keep track of currently open items
|
45
|
+
* @member {String[]} expandedItems=[]
|
46
|
+
* @private
|
47
|
+
*/
|
48
|
+
expandedItems_: [],
|
49
|
+
/**
|
50
|
+
* Creates a top header
|
51
|
+
* @memeber {String|null} title=null
|
52
|
+
*/
|
53
|
+
title_: null
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* @param {Number[]} value
|
58
|
+
* @param {Number[]} oldValue
|
59
|
+
*/
|
60
|
+
afterSetInitialOpen(value, oldValue) {
|
61
|
+
const me = this,
|
62
|
+
items = me.items,
|
63
|
+
expandedItems = me.expandedItems;
|
64
|
+
|
65
|
+
value.forEach((itemNo) => {
|
66
|
+
const id = Neo.getId(me.itemDefaults.ntype),
|
67
|
+
item = items[itemNo];
|
68
|
+
|
69
|
+
item.expanded = true;
|
70
|
+
item.id = id;
|
71
|
+
NeoArray.add(expandedItems, id);
|
72
|
+
});
|
73
|
+
|
74
|
+
me.expandedItems = expandedItems;
|
75
|
+
}
|
76
|
+
|
77
|
+
/**
|
78
|
+
* After changes to title config, we add a header
|
79
|
+
* @param {String|null} value
|
80
|
+
* @param {String|null} oldValue
|
81
|
+
*/
|
82
|
+
afterSetTitle(value, oldValue) {
|
83
|
+
const me = this,
|
84
|
+
titleEl = me.down({flag: 'titleEl'});
|
85
|
+
|
86
|
+
if (value && !titleEl) {
|
87
|
+
me.headers = [{
|
88
|
+
baseCls: 'neo-accordion-title',
|
89
|
+
cls : ['neo-accordion-title'],
|
90
|
+
dock : 'top',
|
91
|
+
text : value
|
92
|
+
}];
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* Called by accordion items.
|
98
|
+
* Checks for maxExpandedItems
|
99
|
+
* @param {Object} data
|
100
|
+
* @param {Boolean} data.expanded newState
|
101
|
+
* @param {Neo.container.AccordionItem} data.target accordion item
|
102
|
+
* @protected
|
103
|
+
*/
|
104
|
+
childExpandChange(data) {
|
105
|
+
const me = this,
|
106
|
+
maxExpandedItems = me.maxExpandedItems,
|
107
|
+
expandedItems = me.expandedItems,
|
108
|
+
curNoOpenItems = expandedItems.length,
|
109
|
+
target = data.target,
|
110
|
+
targetId = target.id,
|
111
|
+
expanded = data.expanded;
|
112
|
+
|
113
|
+
if (expanded
|
114
|
+
&& maxExpandedItems !== 0
|
115
|
+
&& curNoOpenItems === maxExpandedItems
|
116
|
+
) {
|
117
|
+
Neo.get(expandedItems[0]).expanded = false;
|
118
|
+
NeoArray.remove(expandedItems, expandedItems[0]);
|
119
|
+
}
|
120
|
+
|
121
|
+
target.expanded = expanded;
|
122
|
+
NeoArray.toggle(expandedItems, targetId);
|
123
|
+
|
124
|
+
me.expandedItems = expandedItems;
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
Neo.applyClassConfig(Accordion);
|
129
|
+
|
130
|
+
export default Accordion;
|
@@ -0,0 +1,178 @@
|
|
1
|
+
import Base from './Base.mjs';
|
2
|
+
import Toolbar from '../toolbar/Base.mjs';
|
3
|
+
import NeoArray from '../util/Array.mjs';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* @class Neo.container.AccordionItem
|
7
|
+
* @extends Neo.container.Base
|
8
|
+
*/
|
9
|
+
class AccordionContainer extends Base {
|
10
|
+
static config = {
|
11
|
+
/**
|
12
|
+
* @member {String} className='Neo.container.AccordionItem'
|
13
|
+
* @protected
|
14
|
+
*/
|
15
|
+
className: 'Neo.container.AccordionItem',
|
16
|
+
/**
|
17
|
+
* @member {String} ntype='accordionitem'
|
18
|
+
* @protected
|
19
|
+
*/
|
20
|
+
ntype: 'accordionitem',
|
21
|
+
/**
|
22
|
+
* @member {String[]} baseCls=['neo-accordion-component']
|
23
|
+
*/
|
24
|
+
baseCls: ['neo-accordion-item'],
|
25
|
+
|
26
|
+
/**
|
27
|
+
* Additional cls for the arrow, in case you need to customize it
|
28
|
+
* @member {String[]|String|null} arrowCls=null
|
29
|
+
*/
|
30
|
+
arrowCls: null,
|
31
|
+
/**
|
32
|
+
* Expand or collapse (true/false) this value
|
33
|
+
* @member {Boolean} expanded=false
|
34
|
+
*/
|
35
|
+
expanded_: false,
|
36
|
+
/**
|
37
|
+
* cls for the icon in front of the title
|
38
|
+
* May be empty. 'fa' is preset,
|
39
|
+
* so if you use fontawesome you do not have to add it.
|
40
|
+
*
|
41
|
+
* @member {String[]|String|null} iconCls=null
|
42
|
+
*/
|
43
|
+
iconCls_: null,
|
44
|
+
/**
|
45
|
+
* Title for Headerbar
|
46
|
+
* @member {String|null} title=null
|
47
|
+
*/
|
48
|
+
title_: null
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Runs after afterSetTitle, so that the title component does not exist prior.
|
53
|
+
* @protected
|
54
|
+
*/
|
55
|
+
createItems() {
|
56
|
+
const me = this,
|
57
|
+
items = me.items,
|
58
|
+
title = me.title;
|
59
|
+
let iconCls = me.iconCls || ['no-icon'],
|
60
|
+
arrowCls = me.arrowCls || 'fa-caret-down',
|
61
|
+
header, content;
|
62
|
+
|
63
|
+
if (!Neo.isArray(iconCls)) {
|
64
|
+
iconCls = iconCls.split(' ');
|
65
|
+
}
|
66
|
+
if (!Neo.isArray(arrowCls)) {
|
67
|
+
arrowCls = arrowCls.split(' ');
|
68
|
+
}
|
69
|
+
|
70
|
+
header = Neo.create({
|
71
|
+
module: Toolbar,
|
72
|
+
items : [{
|
73
|
+
flag : 'iconEl',
|
74
|
+
ntype : 'component',
|
75
|
+
baseCls: ['neo-accordion-header-icon'],
|
76
|
+
cls : ['fa', ...iconCls],
|
77
|
+
}, {
|
78
|
+
flag : 'titleEl',
|
79
|
+
ntype : 'component',
|
80
|
+
baseCls: ['neo-accordion-header-title'],
|
81
|
+
html : title
|
82
|
+
}, {
|
83
|
+
ntype : 'component',
|
84
|
+
baseCls: ['neo-accordion-header-arrow'],
|
85
|
+
cls : ['fa', ...arrowCls]
|
86
|
+
}]
|
87
|
+
});
|
88
|
+
content = {
|
89
|
+
ntype : 'container',
|
90
|
+
flag : 'content',
|
91
|
+
baseCls: ['neo-accordion-content', 'neo-container'],
|
92
|
+
items : items
|
93
|
+
};
|
94
|
+
|
95
|
+
me.items = [header, content];
|
96
|
+
|
97
|
+
super.createItems();
|
98
|
+
|
99
|
+
me.addDomListeners([
|
100
|
+
{click: me.onExpandClick, delegate: 'neo-accordion-header-arrow'}
|
101
|
+
]);
|
102
|
+
}
|
103
|
+
|
104
|
+
/**
|
105
|
+
* After changing expanded, we expand/collapse via CSS
|
106
|
+
* @param {Boolean} isExpanded
|
107
|
+
*/
|
108
|
+
afterSetExpanded(isExpanded) {
|
109
|
+
const me = this,
|
110
|
+
cls = me.cls,
|
111
|
+
fn = isExpanded ? 'add' : 'remove';
|
112
|
+
|
113
|
+
NeoArray[fn](cls, 'neo-expanded');
|
114
|
+
me.cls = cls;
|
115
|
+
|
116
|
+
// Ensure scrollbars are not flipping in and out
|
117
|
+
Neo.timeout(450).then(() => {
|
118
|
+
NeoArray[fn](cls, 'neo-scrollable');
|
119
|
+
me.cls = cls;
|
120
|
+
})
|
121
|
+
}
|
122
|
+
|
123
|
+
/**
|
124
|
+
* The initial title is set before the component is created,
|
125
|
+
* so we have to check if it exists.
|
126
|
+
*
|
127
|
+
* @param {String[]|String} newValue
|
128
|
+
* @param {String[]} oldValue
|
129
|
+
*/
|
130
|
+
afterSetIconCls(newValue, oldValue) {
|
131
|
+
let iconEl = this.down({flag: 'iconEl'});
|
132
|
+
|
133
|
+
if (iconEl) {
|
134
|
+
let cls = iconEl.cls;
|
135
|
+
|
136
|
+
if (!Neo.isArray(newValue)) newValue = newValue.split(' ');
|
137
|
+
|
138
|
+
NeoArray.remove(cls, oldValue);
|
139
|
+
NeoArray.add(cls, newValue);
|
140
|
+
iconEl.cls = cls;
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
/**
|
145
|
+
* The initial title is set before the component is created,
|
146
|
+
* so we have to check if it exists.
|
147
|
+
*
|
148
|
+
* @param {String} newValue
|
149
|
+
*/
|
150
|
+
afterSetTitle(newValue) {
|
151
|
+
let titleEl = this.down({flag: 'titleEl'});
|
152
|
+
|
153
|
+
if (titleEl) titleEl.html = newValue;
|
154
|
+
}
|
155
|
+
|
156
|
+
/**
|
157
|
+
* If the parent is an AccordionContainer, we run the parent function.
|
158
|
+
* Otherwise we set this.expanded to the new value.
|
159
|
+
*/
|
160
|
+
onExpandClick() {
|
161
|
+
const me = this,
|
162
|
+
currentState = me.expanded;
|
163
|
+
let parent = me.up('accordion');
|
164
|
+
|
165
|
+
if (parent.ntype === 'accordion') {
|
166
|
+
parent.childExpandChange({
|
167
|
+
expanded: !currentState,
|
168
|
+
target : me
|
169
|
+
});
|
170
|
+
} else {
|
171
|
+
me.expanded = !currentState;
|
172
|
+
}
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
Neo.applyClassConfig(AccordionContainer);
|
177
|
+
|
178
|
+
export default AccordionContainer;
|
package/src/form/Container.mjs
CHANGED
@@ -198,46 +198,63 @@ class Container extends BaseContainer {
|
|
198
198
|
}
|
199
199
|
|
200
200
|
/**
|
201
|
-
* Set field
|
202
|
-
* @param {Object}
|
201
|
+
* Set field configs by field name or field id
|
202
|
+
* @param {Object} configs={}
|
203
203
|
* @param {Boolean} suspendEvents=false
|
204
204
|
*/
|
205
|
-
async
|
205
|
+
async setConfigs(configs={}, suspendEvents=false) {
|
206
206
|
let me = this,
|
207
207
|
fields = await me.getFields(),
|
208
|
-
isCheckBox, isRadio, path, value;
|
208
|
+
fieldConfigs, isCheckBox, isRadio, path, value;
|
209
209
|
|
210
210
|
fields.forEach(item => {
|
211
|
-
|
212
|
-
|
213
|
-
|
211
|
+
path = me.getFieldPath(item);
|
212
|
+
fieldConfigs = Neo.nsWithArrays(path, false, configs);
|
213
|
+
|
214
|
+
if (fieldConfigs) {
|
215
|
+
if (suspendEvents) {
|
216
|
+
item.suspendEvents = true;
|
217
|
+
}
|
218
|
+
|
219
|
+
isCheckBox = Neo.form.field?.CheckBox && item instanceof Neo.form.field.CheckBox;
|
220
|
+
value = fieldConfigs.value;
|
214
221
|
|
215
|
-
|
216
|
-
|
217
|
-
|
222
|
+
if (isCheckBox) {
|
223
|
+
if (Neo.typeOf(value) === 'Array') {
|
224
|
+
if (value.includes(item.value)) {
|
225
|
+
fieldConfigs.checked = true
|
226
|
+
}
|
227
|
+
} else {
|
228
|
+
fieldConfigs.checked = item.value === value
|
229
|
+
}
|
230
|
+
} else if (value !== undefined) {
|
231
|
+
isRadio = Neo.form.field?.Radio && item instanceof Neo.form.field.Radio;
|
218
232
|
|
219
|
-
|
220
|
-
|
221
|
-
if (value.includes(item.value)) {
|
222
|
-
item.checked = true
|
233
|
+
if (isRadio) {
|
234
|
+
fieldConfigs.checked = item.value === value
|
223
235
|
}
|
224
|
-
} else {
|
225
|
-
item.checked = item.value === value
|
226
236
|
}
|
227
|
-
} else if (value !== undefined) {
|
228
|
-
isRadio = Neo.form.field?.Radio && item instanceof Neo.form.field.Radio;
|
229
237
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
item.
|
238
|
+
item.set(fieldConfigs)
|
239
|
+
|
240
|
+
if (suspendEvents) {
|
241
|
+
delete item.suspendEvents;
|
234
242
|
}
|
235
243
|
}
|
244
|
+
})
|
245
|
+
}
|
236
246
|
|
237
|
-
|
238
|
-
|
239
|
-
|
247
|
+
/**
|
248
|
+
* Set field values by field name or field id
|
249
|
+
* @param {Object} values={}
|
250
|
+
* @param {Boolean} suspendEvents=false
|
251
|
+
*/
|
252
|
+
async setValues(values={}, suspendEvents=false) {
|
253
|
+
Object.entries(values).forEach(([key, value]) => {
|
254
|
+
values[key] = {value}
|
240
255
|
})
|
256
|
+
|
257
|
+
await this.setConfigs(values, suspendEvents)
|
241
258
|
}
|
242
259
|
|
243
260
|
/**
|
@@ -81,7 +81,7 @@ class CheckBox extends Base {
|
|
81
81
|
labelCls_: [],
|
82
82
|
/**
|
83
83
|
* Edge-case config in case we want to render leading content with their own selectors like:
|
84
|
-
* <span class="my-label-id-cls">E10</span>
|
84
|
+
* <span class="my-label-id-cls">E10</span> · Firstname
|
85
85
|
* @member {String|null} labelId_=null
|
86
86
|
*/
|
87
87
|
labelId_: null,
|
@@ -90,6 +90,11 @@ class CheckBox extends Base {
|
|
90
90
|
* @member {String[]} labelIdCls_=[]
|
91
91
|
*/
|
92
92
|
labelIdCls_: [],
|
93
|
+
/**
|
94
|
+
* Separator between labelId & labelText
|
95
|
+
* @member {String} labelIdSeparator_=' · '
|
96
|
+
*/
|
97
|
+
labelIdSeparator_: ' · ',
|
93
98
|
/**
|
94
99
|
* Valid values: 'left', 'top'
|
95
100
|
* @member {String} labelPosition_='left'
|
@@ -310,7 +315,7 @@ class CheckBox extends Base {
|
|
310
315
|
let me = this;
|
311
316
|
|
312
317
|
if (me.labelId) {
|
313
|
-
value = `<span class="${me.labelIdCls.join(',')}">${me.labelId}</span
|
318
|
+
value = `<span class="${me.labelIdCls.join(',')}">${me.labelId}</span>${me.labelIdSeparator + value}`
|
314
319
|
}
|
315
320
|
|
316
321
|
me.vdom.cn[0].cn[0].innerHTML = value;
|
@@ -148,7 +148,7 @@ class Number extends Text {
|
|
148
148
|
|
149
149
|
me.changeInputElKey('step', value);
|
150
150
|
|
151
|
-
stepSizeString = String(
|
151
|
+
stepSizeString = String(value);
|
152
152
|
|
153
153
|
me.stepSizeDigits = stepSizeString.includes('.') ? stepSizeString.split('.')[1].length : 0;
|
154
154
|
|
@@ -157,16 +157,44 @@ class Number extends Text {
|
|
157
157
|
|
158
158
|
if (modulo !== 0) { // find the closest valid value
|
159
159
|
if (modulo / value > 0.5) {
|
160
|
-
if
|
161
|
-
|
160
|
+
if (val + value - modulo < me.maxValue) {
|
161
|
+
me.value = val + value - modulo;
|
162
|
+
} else if (val - modulo > me.minValue) {
|
163
|
+
me.value = val - modulo;
|
164
|
+
}
|
162
165
|
} else {
|
163
|
-
if
|
164
|
-
|
166
|
+
if (val - modulo > me.minValue) {
|
167
|
+
me.value = val - modulo;
|
168
|
+
} else if (val + value - modulo < me.maxValue) {
|
169
|
+
me.value = val + value - modulo;
|
170
|
+
}
|
165
171
|
}
|
166
172
|
}
|
167
173
|
}
|
168
174
|
}
|
169
175
|
|
176
|
+
/**
|
177
|
+
* Triggered after the triggerPosition config got changed
|
178
|
+
* @param {String} value
|
179
|
+
* @param {String} oldValue
|
180
|
+
* @protected
|
181
|
+
*/
|
182
|
+
afterSetTriggerPosition(value, oldValue) {
|
183
|
+
oldValue && this.updateTriggers();
|
184
|
+
}
|
185
|
+
|
186
|
+
/**
|
187
|
+
* Triggered after the useSpinButtons config got changed
|
188
|
+
* @param {Boolean} value
|
189
|
+
* @param {Boolean} oldValue
|
190
|
+
* @protected
|
191
|
+
*/
|
192
|
+
afterSetUseSpinButtons(value, oldValue) {
|
193
|
+
if (typeof oldValue === 'boolean') {
|
194
|
+
this.updateTriggers();
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
170
198
|
/**
|
171
199
|
* Triggered before the maxLength config gets changed
|
172
200
|
* @param {Number|null} value
|
@@ -195,28 +223,6 @@ class Number extends Text {
|
|
195
223
|
return null;
|
196
224
|
}
|
197
225
|
|
198
|
-
/**
|
199
|
-
* Triggered after the triggerPosition config got changed
|
200
|
-
* @param {String} value
|
201
|
-
* @param {String} oldValue
|
202
|
-
* @protected
|
203
|
-
*/
|
204
|
-
afterSetTriggerPosition(value, oldValue) {
|
205
|
-
oldValue && this.updateTriggers();
|
206
|
-
}
|
207
|
-
|
208
|
-
/**
|
209
|
-
* Triggered after the useSpinButtons config got changed
|
210
|
-
* @param {Boolean} value
|
211
|
-
* @param {Boolean} oldValue
|
212
|
-
* @protected
|
213
|
-
*/
|
214
|
-
afterSetUseSpinButtons(value, oldValue) {
|
215
|
-
if (typeof oldValue === 'boolean') {
|
216
|
-
this.updateTriggers();
|
217
|
-
}
|
218
|
-
}
|
219
|
-
|
220
226
|
/**
|
221
227
|
* Triggered before the triggerPosition config gets changed
|
222
228
|
* @param {String} value
|
@@ -229,18 +235,24 @@ class Number extends Text {
|
|
229
235
|
|
230
236
|
/**
|
231
237
|
* Triggered before the value config gets changed
|
232
|
-
* @param {Number} value
|
238
|
+
* @param {Number|String} value
|
233
239
|
* @param {Number} oldValue
|
234
240
|
* @protected
|
235
241
|
*/
|
236
242
|
beforeSetValue(value, oldValue) {
|
237
|
-
if (
|
238
|
-
return
|
239
|
-
}
|
240
|
-
|
243
|
+
if (value === null || value === '') {
|
244
|
+
return null;
|
245
|
+
}
|
246
|
+
|
247
|
+
if (!Neo.isNumber(value)) {
|
248
|
+
value = +value;
|
249
|
+
}
|
250
|
+
|
251
|
+
if (this.stepSizeDigits > 0) {
|
252
|
+
value = +value.toFixed(this.stepSizeDigits);
|
241
253
|
}
|
242
254
|
|
243
|
-
return value
|
255
|
+
return value;
|
244
256
|
}
|
245
257
|
|
246
258
|
/**
|
@@ -366,7 +378,7 @@ class Number extends Text {
|
|
366
378
|
}
|
367
379
|
|
368
380
|
me.removeTrigger('spindown', true, triggers);
|
369
|
-
me.removeTrigger('spinup',
|
381
|
+
me.removeTrigger('spinup', true, triggers);
|
370
382
|
} else {
|
371
383
|
if (!me.hasTrigger('spindown')) {
|
372
384
|
triggers.push(SpinDownTrigger);
|
@@ -379,8 +391,8 @@ class Number extends Text {
|
|
379
391
|
me.removeTrigger('spinupdown', true, triggers);
|
380
392
|
}
|
381
393
|
} else {
|
382
|
-
me.removeTrigger('spindown',
|
383
|
-
me.removeTrigger('spinup',
|
394
|
+
me.removeTrigger('spindown', true, triggers);
|
395
|
+
me.removeTrigger('spinup', true, triggers);
|
384
396
|
me.removeTrigger('spinupdown', true, triggers);
|
385
397
|
}
|
386
398
|
|
@@ -392,7 +404,7 @@ class Number extends Text {
|
|
392
404
|
* @param {Boolean} silent=true
|
393
405
|
* @returns {Boolean} Returns true in case there are no client-side errors
|
394
406
|
*/
|
395
|
-
validate(silent=true) {
|
407
|
+
validate(silent = true) {
|
396
408
|
let me = this,
|
397
409
|
value = me.value,
|
398
410
|
isNumber = Neo.isNumber(value),
|
package/src/form/field/Range.mjs
CHANGED
@@ -30,6 +30,11 @@ class Range extends Number {
|
|
30
30
|
* @member {String} inputType='range'
|
31
31
|
*/
|
32
32
|
inputType: 'range',
|
33
|
+
/**
|
34
|
+
* If true, shows the result of the slider in the label
|
35
|
+
* @member {Boolean} showResultInLabel=false
|
36
|
+
*/
|
37
|
+
showResultInLabel: false,
|
33
38
|
/**
|
34
39
|
* @member {Array} tickmarks_=[]
|
35
40
|
*/
|
@@ -37,7 +42,7 @@ class Range extends Number {
|
|
37
42
|
/**
|
38
43
|
* @member {Boolean} useInputEvent=false
|
39
44
|
*/
|
40
|
-
useInputEvent
|
45
|
+
useInputEvent: false,
|
41
46
|
/**
|
42
47
|
* Disables the field.Number buttons
|
43
48
|
* @member {Boolean} useInputEvent=false
|
@@ -57,14 +62,16 @@ class Range extends Number {
|
|
57
62
|
if (me.useInputEvent) {
|
58
63
|
me.addDomListeners({
|
59
64
|
input: {
|
60
|
-
fn
|
61
|
-
id
|
62
|
-
scope
|
65
|
+
fn : me.onInputValueChange,
|
66
|
+
id : me.vdom.cn[2].id,
|
67
|
+
scope: me
|
63
68
|
}
|
64
69
|
});
|
65
70
|
}
|
66
71
|
|
67
72
|
inputEl.cls = ['neo-rangefield-input']; // replace neo-textfield-input
|
73
|
+
|
74
|
+
me.addValueToLabel();
|
68
75
|
}
|
69
76
|
|
70
77
|
/**
|
@@ -76,6 +83,26 @@ class Range extends Number {
|
|
76
83
|
afterSetTickmarks(value, oldValue) {
|
77
84
|
// todo
|
78
85
|
}
|
86
|
+
|
87
|
+
/**
|
88
|
+
* Override the NumberField implementation
|
89
|
+
* @param {Object} data
|
90
|
+
*/
|
91
|
+
afterSetValue(value, oldValue) {
|
92
|
+
this.addValueToLabel();
|
93
|
+
super.afterSetValue(value, oldValue);
|
94
|
+
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* Update label with value
|
98
|
+
*/
|
99
|
+
addValueToLabel() {
|
100
|
+
const me = this;
|
101
|
+
|
102
|
+
if (me.showResultInLabel) {
|
103
|
+
me.getLabelEl().innerHTML = `[${me.value}] ` + me.labelText;
|
104
|
+
}
|
105
|
+
}
|
79
106
|
}
|
80
107
|
|
81
108
|
Neo.applyClassConfig(Range);
|
package/src/form/field/Text.mjs
CHANGED
@@ -141,6 +141,11 @@ class Text extends Base {
|
|
141
141
|
* @member {String[]} labelIdCls_=[]
|
142
142
|
*/
|
143
143
|
labelIdCls_: [],
|
144
|
+
/**
|
145
|
+
* Separator between labelId & labelText
|
146
|
+
* @member {String} labelIdSeparator_=' · '
|
147
|
+
*/
|
148
|
+
labelIdSeparator_: ' · ',
|
144
149
|
/**
|
145
150
|
* @member {String} labelOptionalText_=' (Optional)'
|
146
151
|
*/
|
@@ -514,7 +519,7 @@ class Text extends Base {
|
|
514
519
|
isEmpty = me.isEmpty();
|
515
520
|
|
516
521
|
if (me.labelId) {
|
517
|
-
value = `<span class="${me.labelIdCls.join(',')}">${me.labelId}</span
|
522
|
+
value = `<span class="${me.labelIdCls.join(',')}">${me.labelId}</span>${me.labelIdSeparator + value}`
|
518
523
|
}
|
519
524
|
|
520
525
|
me.getLabelEl().innerHTML = value;
|
package/src/manager/Toast.mjs
CHANGED
@@ -204,7 +204,11 @@ class Toast extends Base {
|
|
204
204
|
component.style = moveObj;
|
205
205
|
component.update();
|
206
206
|
|
207
|
-
|
207
|
+
// Sometimes the index is already reduced
|
208
|
+
// so the last index might not be available
|
209
|
+
if(rects[index]) {
|
210
|
+
acc = acc + rects[index].height;
|
211
|
+
}
|
208
212
|
}
|
209
213
|
}
|
210
214
|
}
|