x4js 1.5.5 → 1.5.7
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/README.md +8 -1
- package/lib/README.md +8 -1
- package/lib/changelog.txt +12 -0
- package/lib/cjs/calendar.js +7 -2
- package/lib/cjs/combobox.js +111 -21
- package/lib/cjs/label.js +2 -2
- package/lib/cjs/listview.js +3 -1
- package/lib/cjs/messagebox.js +27 -0
- package/lib/cjs/popup.js +2 -2
- package/lib/cjs/tools.js +1 -1
- package/lib/cjs/version.js +1 -1
- package/lib/esm/calendar.js +7 -2
- package/lib/esm/combobox.js +114 -22
- package/lib/esm/label.js +3 -3
- package/lib/esm/listview.js +3 -1
- package/lib/esm/messagebox.js +16 -0
- package/lib/esm/popup.js +2 -2
- package/lib/esm/tools.js +1 -1
- package/lib/esm/version.js +1 -1
- package/lib/src/calendar.ts +8 -2
- package/lib/src/combobox.ts +141 -38
- package/lib/src/label.ts +3 -3
- package/lib/src/listview.ts +5 -2
- package/lib/src/messagebox.ts +21 -0
- package/lib/src/popup.ts +2 -2
- package/lib/src/tools.ts +1 -1
- package/lib/src/version.ts +1 -1
- package/lib/types/calendar.d.ts +2 -1
- package/lib/types/combobox.d.ts +11 -5
- package/lib/types/listview.d.ts +1 -1
- package/lib/types/messagebox.d.ts +1 -0
- package/lib/types/popup.d.ts +1 -1
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,14 @@ see [home](https://x4js.org)
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
## Documentation
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
**12s**: it's the time needed to have a working project:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx x4build create name=demo model=html
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
see [full documentation](https://x4js.org/doc/)
|
|
15
22
|
|
|
16
23
|
## API
|
|
17
24
|
see [API](https://x4js.org/api/)
|
package/lib/README.md
CHANGED
|
@@ -11,7 +11,14 @@ see [home](https://x4js.org)
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
## Documentation
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
**12s**: it's the time needed to have a working project:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx x4build create name=demo model=html
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
see [full documentation](https://x4js.org/doc/)
|
|
15
22
|
|
|
16
23
|
## API
|
|
17
24
|
see [API](https://x4js.org/api/)
|
package/lib/changelog.txt
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
2022/12/xx : 1.5.7 --------------------------------------------------------
|
|
2
|
+
package.json - removed erroneous dependency to typescript
|
|
3
|
+
calendar.ts - show now has a parameter named 'at'
|
|
4
|
+
|
|
5
|
+
2022/12/08 : 1.5.6 --------------------------------------------------------
|
|
6
|
+
combobox.ts - allow editable
|
|
7
|
+
items can be a function
|
|
8
|
+
populate removed
|
|
9
|
+
|
|
10
|
+
listview.ts - focus bug on popuplistview
|
|
11
|
+
label.ts - bug: display dangerous html elements when multiline = true
|
|
12
|
+
|
|
1
13
|
2022/12/05 : 1.5.1 --------------------------------------------------------
|
|
2
14
|
icon.ts - now accepts direct <svg>..</svg> in argument (var or other)
|
|
3
15
|
|
package/lib/cjs/calendar.js
CHANGED
|
@@ -236,9 +236,14 @@ class PopupCalendar extends popup_1.Popup {
|
|
|
236
236
|
this.setContent(this.m_cal);
|
|
237
237
|
}
|
|
238
238
|
/** @ignore */
|
|
239
|
-
show(modal) {
|
|
239
|
+
show(modal, at) {
|
|
240
240
|
x4dom_1.x4document.addEventListener('mousedown', this._handleClick);
|
|
241
|
-
|
|
241
|
+
if (at) {
|
|
242
|
+
super.displayAt(at.x, at.y, 'top left', undefined, modal);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
super.show(modal);
|
|
246
|
+
}
|
|
242
247
|
}
|
|
243
248
|
/** @ignore */
|
|
244
249
|
close() {
|
package/lib/cjs/combobox.js
CHANGED
|
@@ -47,9 +47,36 @@ const tools_1 = require("./tools");
|
|
|
47
47
|
class ComboBox extends layout_1.HLayout {
|
|
48
48
|
constructor(props) {
|
|
49
49
|
super(props);
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
if (!props.editable) {
|
|
51
|
+
this.setDomEvent('keypress', () => this.showPopup());
|
|
52
|
+
}
|
|
53
|
+
this.setDomEvent('click', () => {
|
|
54
|
+
if (this.m_props.editable) {
|
|
55
|
+
this.m_ui_input.focus();
|
|
56
|
+
}
|
|
57
|
+
this.showPopup();
|
|
58
|
+
});
|
|
59
|
+
this.setDomEvent("keydown", e => this._onKey(e));
|
|
52
60
|
this.mapPropEvents(props, 'selectionChange');
|
|
61
|
+
this.m_popvis = false;
|
|
62
|
+
this.m_lockpop = false;
|
|
63
|
+
this.m_lockchg = false;
|
|
64
|
+
}
|
|
65
|
+
_onKey(e) {
|
|
66
|
+
if (this.m_popvis) {
|
|
67
|
+
if (e.key == "ArrowUp" || e.key == "ArrowDown") {
|
|
68
|
+
this.m_lockpop = true;
|
|
69
|
+
this.m_popup.handleKey(e);
|
|
70
|
+
this.m_lockpop = false;
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
e.stopPropagation();
|
|
73
|
+
}
|
|
74
|
+
else if (e.key == "Escape") {
|
|
75
|
+
this._hidePopup();
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
e.stopPropagation();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
53
80
|
}
|
|
54
81
|
set items(items) {
|
|
55
82
|
this.m_props.items = items;
|
|
@@ -61,16 +88,35 @@ class ComboBox extends layout_1.HLayout {
|
|
|
61
88
|
render(props) {
|
|
62
89
|
var _a;
|
|
63
90
|
if (!props.renderer) {
|
|
64
|
-
|
|
91
|
+
const input = new input_1.Input({
|
|
65
92
|
flex: 1,
|
|
66
|
-
readOnly: true,
|
|
93
|
+
readOnly: this.m_props.editable ? false : true,
|
|
67
94
|
tabIndex: 0,
|
|
68
95
|
name: props.name,
|
|
69
96
|
value_hook: {
|
|
70
97
|
get: () => { return this.value; },
|
|
71
98
|
set: (v) => { this.value = v; }
|
|
99
|
+
},
|
|
100
|
+
dom_events: {
|
|
101
|
+
focus: () => {
|
|
102
|
+
if (this.m_props.editable && input.value.length == 0) {
|
|
103
|
+
this.showPopup();
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
input: () => {
|
|
107
|
+
if (this.m_lockchg) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const text = input.value;
|
|
111
|
+
this.m_selection = { id: undefined, text };
|
|
112
|
+
let items = this.showPopup();
|
|
113
|
+
if (items && items.length && items[0].text == text) {
|
|
114
|
+
this.m_selection = { id: items[0].id, text };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
72
117
|
}
|
|
73
118
|
});
|
|
119
|
+
this.m_ui_input = input;
|
|
74
120
|
}
|
|
75
121
|
else {
|
|
76
122
|
this.m_ui_input = new component_1.Component({
|
|
@@ -104,7 +150,9 @@ class ComboBox extends layout_1.HLayout {
|
|
|
104
150
|
cls: 'gadget',
|
|
105
151
|
icon: 'var( --x4-icon-angle-down )',
|
|
106
152
|
tabIndex: false,
|
|
107
|
-
click: () =>
|
|
153
|
+
click: () => {
|
|
154
|
+
this.showPopup(false);
|
|
155
|
+
},
|
|
108
156
|
dom_events: {
|
|
109
157
|
focus: () => { this.dom.focus(); },
|
|
110
158
|
}
|
|
@@ -125,10 +173,18 @@ class ComboBox extends layout_1.HLayout {
|
|
|
125
173
|
/**
|
|
126
174
|
* display the popup
|
|
127
175
|
*/
|
|
128
|
-
showPopup() {
|
|
176
|
+
showPopup(filter_items = true) {
|
|
129
177
|
let props = this.m_props;
|
|
130
178
|
if (props.readOnly || this.hasClass("@disable")) {
|
|
131
|
-
return;
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
let items = props.items;
|
|
182
|
+
if ((0, tools_1.isFunction)(items)) {
|
|
183
|
+
const filter = filter_items ? this.m_ui_input.value : null;
|
|
184
|
+
items = items(filter);
|
|
185
|
+
}
|
|
186
|
+
if (items.length == 0) {
|
|
187
|
+
return null;
|
|
132
188
|
}
|
|
133
189
|
// need creation ?
|
|
134
190
|
if (!this.m_popup) {
|
|
@@ -138,10 +194,15 @@ class ComboBox extends layout_1.HLayout {
|
|
|
138
194
|
// prepare the combo listview
|
|
139
195
|
this.m_popup = new listview_1.PopupListView({
|
|
140
196
|
cls: '@combo-popup',
|
|
141
|
-
items: props.items,
|
|
142
197
|
populate: props.populate,
|
|
143
198
|
renderItem: this.m_props.renderer,
|
|
144
|
-
selectionChange: (e) =>
|
|
199
|
+
selectionChange: (e) => {
|
|
200
|
+
this._selectItem(e);
|
|
201
|
+
if (!this.m_lockpop) {
|
|
202
|
+
this._hidePopup();
|
|
203
|
+
this.focus();
|
|
204
|
+
}
|
|
205
|
+
},
|
|
145
206
|
cancel: (e) => this.signal('cancel', e),
|
|
146
207
|
style: {
|
|
147
208
|
fontFamily,
|
|
@@ -149,14 +210,18 @@ class ComboBox extends layout_1.HLayout {
|
|
|
149
210
|
}
|
|
150
211
|
});
|
|
151
212
|
}
|
|
213
|
+
this.m_popup.items = items;
|
|
152
214
|
let r1 = this.m_ui_button.getBoundingRect(), r2 = this.m_ui_input.getBoundingRect();
|
|
153
215
|
this.m_popup.setStyle({
|
|
154
216
|
minWidth: r1.right - r2.left,
|
|
155
217
|
});
|
|
156
218
|
this.m_popup.displayAt(r2.left, r2.bottom);
|
|
219
|
+
this.m_popvis = true;
|
|
220
|
+
this.startTimer("focus-check", 100, true, () => this._checkFocus());
|
|
157
221
|
if (this.value !== undefined) {
|
|
158
222
|
this.m_popup.selection = this.value;
|
|
159
223
|
}
|
|
224
|
+
return items;
|
|
160
225
|
}
|
|
161
226
|
/** @ignore
|
|
162
227
|
*/
|
|
@@ -165,15 +230,17 @@ class ComboBox extends layout_1.HLayout {
|
|
|
165
230
|
if (!item) {
|
|
166
231
|
return;
|
|
167
232
|
}
|
|
233
|
+
this.m_lockchg = true;
|
|
168
234
|
this._setInput(item, true);
|
|
235
|
+
this.m_lockchg = false;
|
|
169
236
|
this.m_selection = {
|
|
170
237
|
id: item.id,
|
|
171
238
|
text: item.text
|
|
172
239
|
};
|
|
173
240
|
this.emit('selectionChange', (0, x4events_1.EvSelectionChange)(item));
|
|
174
241
|
this.emit('change', (0, x4events_1.EvChange)(item.id));
|
|
175
|
-
this.m_ui_input.focus();
|
|
176
|
-
this.m_popup.hide();
|
|
242
|
+
//this.m_ui_input.focus( );
|
|
243
|
+
//this.m_popup.hide( );
|
|
177
244
|
}
|
|
178
245
|
/**
|
|
179
246
|
*
|
|
@@ -209,7 +276,13 @@ class ComboBox extends layout_1.HLayout {
|
|
|
209
276
|
return this.m_selection ? this.m_selection.id : undefined;
|
|
210
277
|
}
|
|
211
278
|
get valueText() {
|
|
212
|
-
|
|
279
|
+
if (this.m_selection) {
|
|
280
|
+
return this.m_selection.text;
|
|
281
|
+
}
|
|
282
|
+
if (this.m_props.editable) {
|
|
283
|
+
return this.m_ui_input.value;
|
|
284
|
+
}
|
|
285
|
+
return '';
|
|
213
286
|
}
|
|
214
287
|
/**
|
|
215
288
|
*
|
|
@@ -217,7 +290,7 @@ class ComboBox extends layout_1.HLayout {
|
|
|
217
290
|
set value(id) {
|
|
218
291
|
let items = this.m_props.items;
|
|
219
292
|
if ((0, tools_1.isFunction)(items)) {
|
|
220
|
-
items = items();
|
|
293
|
+
items = items(null);
|
|
221
294
|
}
|
|
222
295
|
const found = items.some((v) => {
|
|
223
296
|
if (v.id === id) {
|
|
@@ -234,6 +307,23 @@ class ComboBox extends layout_1.HLayout {
|
|
|
234
307
|
get input() {
|
|
235
308
|
return this.m_ui_input instanceof input_1.Input ? this.m_ui_input : null;
|
|
236
309
|
}
|
|
310
|
+
_checkFocus() {
|
|
311
|
+
const focus = document.activeElement;
|
|
312
|
+
if (this.dom && this.dom.contains(focus) || focus == document.body) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (this.m_popup && this.m_popup.dom && this.m_popup.dom.contains(focus)) {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
this._hidePopup();
|
|
319
|
+
}
|
|
320
|
+
_hidePopup() {
|
|
321
|
+
if (this.m_popvis) {
|
|
322
|
+
this.m_popup.close();
|
|
323
|
+
this.m_popvis = false;
|
|
324
|
+
this.stopTimer("focus-check");
|
|
325
|
+
}
|
|
326
|
+
}
|
|
237
327
|
static storeProxy(props) {
|
|
238
328
|
let view = props.store instanceof datastore_1.DataStore ? props.store.createView() : props.store;
|
|
239
329
|
return () => {
|
|
@@ -247,13 +337,13 @@ class ComboBox extends layout_1.HLayout {
|
|
|
247
337
|
return result;
|
|
248
338
|
};
|
|
249
339
|
}
|
|
340
|
+
focus() {
|
|
341
|
+
if (this.m_props.editable) {
|
|
342
|
+
this.m_ui_input.focus();
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
super.focus();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
250
348
|
}
|
|
251
349
|
exports.ComboBox = ComboBox;
|
|
252
|
-
/*
|
|
253
|
-
export type CBComboBoxRenderer = ( rec: Record ) => string;
|
|
254
|
-
export interface ComboBoxStore {
|
|
255
|
-
store: DataStore;
|
|
256
|
-
display: string | CBComboBoxRenderer; // if string, the field name to display
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
*/
|
package/lib/cjs/label.js
CHANGED
|
@@ -49,7 +49,7 @@ class Label extends component_1.Component {
|
|
|
49
49
|
var _a;
|
|
50
50
|
let text = this.m_props.text;
|
|
51
51
|
if (this.m_props.multiline && !(text instanceof tools_1.HtmlString)) {
|
|
52
|
-
text = new tools_1.HtmlString(
|
|
52
|
+
text = new tools_1.HtmlString((0, tools_1.escapeHtml)(text, true));
|
|
53
53
|
}
|
|
54
54
|
if (!props.icon) {
|
|
55
55
|
this.setContent(text);
|
|
@@ -74,7 +74,7 @@ class Label extends component_1.Component {
|
|
|
74
74
|
props.text = txt;
|
|
75
75
|
let text = this.m_props.text;
|
|
76
76
|
if (this.m_props.multiline && !(text instanceof tools_1.HtmlString)) {
|
|
77
|
-
text = new tools_1.HtmlString(
|
|
77
|
+
text = new tools_1.HtmlString((0, tools_1.escapeHtml)(text, true));
|
|
78
78
|
}
|
|
79
79
|
if (this.dom) {
|
|
80
80
|
let comp = this;
|
package/lib/cjs/listview.js
CHANGED
|
@@ -64,7 +64,7 @@ class ListView extends layout_1.VLayout {
|
|
|
64
64
|
this._buildItems();
|
|
65
65
|
}
|
|
66
66
|
else if (this.m_props.populate) {
|
|
67
|
-
this.items = this.m_props.populate();
|
|
67
|
+
this.items = this.m_props.populate(null);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
render(props) {
|
|
@@ -316,6 +316,8 @@ class ListView extends layout_1.VLayout {
|
|
|
316
316
|
}
|
|
317
317
|
/** @ignore */
|
|
318
318
|
_handleClick(e) {
|
|
319
|
+
e.stopImmediatePropagation();
|
|
320
|
+
e.preventDefault();
|
|
319
321
|
let dom = e.target, self = this.dom, list_items = this.m_props.items; // already created by build
|
|
320
322
|
// go up until we find something interesting
|
|
321
323
|
while (dom && dom != self) {
|
package/lib/cjs/messagebox.js
CHANGED
|
@@ -27,6 +27,15 @@
|
|
|
27
27
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
28
28
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
29
29
|
**/
|
|
30
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
31
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
32
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
33
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
34
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
35
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
36
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
37
|
+
});
|
|
38
|
+
};
|
|
30
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
40
|
exports.PromptDialogBox = exports.MessageBox = void 0;
|
|
32
41
|
const dialog_1 = require("./dialog");
|
|
@@ -79,6 +88,24 @@ class MessageBox extends dialog_1.Dialog {
|
|
|
79
88
|
msg.show();
|
|
80
89
|
return msg;
|
|
81
90
|
}
|
|
91
|
+
static showAsync(props) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
let _props;
|
|
95
|
+
const cb = (btn) => {
|
|
96
|
+
resolve(btn);
|
|
97
|
+
};
|
|
98
|
+
if ((0, tools_1.isString)(props) || (0, tools_1.isHtmlString)(props)) {
|
|
99
|
+
_props = { message: props, click: cb };
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
_props = Object.assign(Object.assign({}, props), { click: cb });
|
|
103
|
+
}
|
|
104
|
+
const msg = new MessageBox(_props);
|
|
105
|
+
msg.show();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
82
109
|
/**
|
|
83
110
|
* display an alert message
|
|
84
111
|
*/
|
package/lib/cjs/popup.js
CHANGED
|
@@ -136,8 +136,8 @@ class Popup extends component_1.Container {
|
|
|
136
136
|
* @param x
|
|
137
137
|
* @param y
|
|
138
138
|
*/
|
|
139
|
-
displayAt(x, y, align = 'top left', offset) {
|
|
140
|
-
this.show();
|
|
139
|
+
displayAt(x, y, align = 'top left', offset, modal = false) {
|
|
140
|
+
this.show(modal);
|
|
141
141
|
let halign = 'l', valign = 't';
|
|
142
142
|
if (align.indexOf('right') >= 0) {
|
|
143
143
|
halign = 'r';
|
package/lib/cjs/tools.js
CHANGED
|
@@ -273,7 +273,7 @@ exports.sprintf = sprintf;
|
|
|
273
273
|
*/
|
|
274
274
|
function escapeHtml(unsafe, nl_br = false) {
|
|
275
275
|
if (!unsafe || unsafe.length == 0) {
|
|
276
|
-
return
|
|
276
|
+
return "";
|
|
277
277
|
}
|
|
278
278
|
let result = unsafe.replace(/[<>\&\"\']/g, function (c) {
|
|
279
279
|
return '&#' + c.charCodeAt(0) + ';';
|
package/lib/cjs/version.js
CHANGED
package/lib/esm/calendar.js
CHANGED
|
@@ -232,9 +232,14 @@ export class PopupCalendar extends Popup {
|
|
|
232
232
|
this.close();
|
|
233
233
|
};
|
|
234
234
|
/** @ignore */
|
|
235
|
-
show(modal) {
|
|
235
|
+
show(modal, at) {
|
|
236
236
|
x4document.addEventListener('mousedown', this._handleClick);
|
|
237
|
-
|
|
237
|
+
if (at) {
|
|
238
|
+
super.displayAt(at.x, at.y, 'top left', undefined, modal);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
super.show(modal);
|
|
242
|
+
}
|
|
238
243
|
}
|
|
239
244
|
/** @ignore */
|
|
240
245
|
close() {
|
package/lib/esm/combobox.js
CHANGED
|
@@ -45,13 +45,42 @@ export class ComboBox extends HLayout {
|
|
|
45
45
|
m_ui_input;
|
|
46
46
|
m_ui_button;
|
|
47
47
|
m_popup;
|
|
48
|
+
m_lockpop;
|
|
49
|
+
m_lockchg;
|
|
50
|
+
m_popvis;
|
|
48
51
|
m_selection;
|
|
49
|
-
m_defer_sel;
|
|
50
52
|
constructor(props) {
|
|
51
53
|
super(props);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
if (!props.editable) {
|
|
55
|
+
this.setDomEvent('keypress', () => this.showPopup());
|
|
56
|
+
}
|
|
57
|
+
this.setDomEvent('click', () => {
|
|
58
|
+
if (this.m_props.editable) {
|
|
59
|
+
this.m_ui_input.focus();
|
|
60
|
+
}
|
|
61
|
+
this.showPopup();
|
|
62
|
+
});
|
|
63
|
+
this.setDomEvent("keydown", e => this._onKey(e));
|
|
54
64
|
this.mapPropEvents(props, 'selectionChange');
|
|
65
|
+
this.m_popvis = false;
|
|
66
|
+
this.m_lockpop = false;
|
|
67
|
+
this.m_lockchg = false;
|
|
68
|
+
}
|
|
69
|
+
_onKey(e) {
|
|
70
|
+
if (this.m_popvis) {
|
|
71
|
+
if (e.key == "ArrowUp" || e.key == "ArrowDown") {
|
|
72
|
+
this.m_lockpop = true;
|
|
73
|
+
this.m_popup.handleKey(e);
|
|
74
|
+
this.m_lockpop = false;
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
e.stopPropagation();
|
|
77
|
+
}
|
|
78
|
+
else if (e.key == "Escape") {
|
|
79
|
+
this._hidePopup();
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
e.stopPropagation();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
55
84
|
}
|
|
56
85
|
set items(items) {
|
|
57
86
|
this.m_props.items = items;
|
|
@@ -62,16 +91,35 @@ export class ComboBox extends HLayout {
|
|
|
62
91
|
/** @ignore */
|
|
63
92
|
render(props) {
|
|
64
93
|
if (!props.renderer) {
|
|
65
|
-
|
|
94
|
+
const input = new Input({
|
|
66
95
|
flex: 1,
|
|
67
|
-
readOnly: true,
|
|
96
|
+
readOnly: this.m_props.editable ? false : true,
|
|
68
97
|
tabIndex: 0,
|
|
69
98
|
name: props.name,
|
|
70
99
|
value_hook: {
|
|
71
100
|
get: () => { return this.value; },
|
|
72
101
|
set: (v) => { this.value = v; }
|
|
102
|
+
},
|
|
103
|
+
dom_events: {
|
|
104
|
+
focus: () => {
|
|
105
|
+
if (this.m_props.editable && input.value.length == 0) {
|
|
106
|
+
this.showPopup();
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
input: () => {
|
|
110
|
+
if (this.m_lockchg) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const text = input.value;
|
|
114
|
+
this.m_selection = { id: undefined, text };
|
|
115
|
+
let items = this.showPopup();
|
|
116
|
+
if (items && items.length && items[0].text == text) {
|
|
117
|
+
this.m_selection = { id: items[0].id, text };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
73
120
|
}
|
|
74
121
|
});
|
|
122
|
+
this.m_ui_input = input;
|
|
75
123
|
}
|
|
76
124
|
else {
|
|
77
125
|
this.m_ui_input = new Component({
|
|
@@ -105,7 +153,9 @@ export class ComboBox extends HLayout {
|
|
|
105
153
|
cls: 'gadget',
|
|
106
154
|
icon: 'var( --x4-icon-angle-down )',
|
|
107
155
|
tabIndex: false,
|
|
108
|
-
click: () =>
|
|
156
|
+
click: () => {
|
|
157
|
+
this.showPopup(false);
|
|
158
|
+
},
|
|
109
159
|
dom_events: {
|
|
110
160
|
focus: () => { this.dom.focus(); },
|
|
111
161
|
}
|
|
@@ -126,10 +176,18 @@ export class ComboBox extends HLayout {
|
|
|
126
176
|
/**
|
|
127
177
|
* display the popup
|
|
128
178
|
*/
|
|
129
|
-
showPopup() {
|
|
179
|
+
showPopup(filter_items = true) {
|
|
130
180
|
let props = this.m_props;
|
|
131
181
|
if (props.readOnly || this.hasClass("@disable")) {
|
|
132
|
-
return;
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
let items = props.items;
|
|
185
|
+
if (isFunction(items)) {
|
|
186
|
+
const filter = filter_items ? this.m_ui_input.value : null;
|
|
187
|
+
items = items(filter);
|
|
188
|
+
}
|
|
189
|
+
if (items.length == 0) {
|
|
190
|
+
return null;
|
|
133
191
|
}
|
|
134
192
|
// need creation ?
|
|
135
193
|
if (!this.m_popup) {
|
|
@@ -139,10 +197,15 @@ export class ComboBox extends HLayout {
|
|
|
139
197
|
// prepare the combo listview
|
|
140
198
|
this.m_popup = new PopupListView({
|
|
141
199
|
cls: '@combo-popup',
|
|
142
|
-
items: props.items,
|
|
143
200
|
populate: props.populate,
|
|
144
201
|
renderItem: this.m_props.renderer,
|
|
145
|
-
selectionChange: (e) =>
|
|
202
|
+
selectionChange: (e) => {
|
|
203
|
+
this._selectItem(e);
|
|
204
|
+
if (!this.m_lockpop) {
|
|
205
|
+
this._hidePopup();
|
|
206
|
+
this.focus();
|
|
207
|
+
}
|
|
208
|
+
},
|
|
146
209
|
cancel: (e) => this.signal('cancel', e),
|
|
147
210
|
style: {
|
|
148
211
|
fontFamily,
|
|
@@ -150,14 +213,18 @@ export class ComboBox extends HLayout {
|
|
|
150
213
|
}
|
|
151
214
|
});
|
|
152
215
|
}
|
|
216
|
+
this.m_popup.items = items;
|
|
153
217
|
let r1 = this.m_ui_button.getBoundingRect(), r2 = this.m_ui_input.getBoundingRect();
|
|
154
218
|
this.m_popup.setStyle({
|
|
155
219
|
minWidth: r1.right - r2.left,
|
|
156
220
|
});
|
|
157
221
|
this.m_popup.displayAt(r2.left, r2.bottom);
|
|
222
|
+
this.m_popvis = true;
|
|
223
|
+
this.startTimer("focus-check", 100, true, () => this._checkFocus());
|
|
158
224
|
if (this.value !== undefined) {
|
|
159
225
|
this.m_popup.selection = this.value;
|
|
160
226
|
}
|
|
227
|
+
return items;
|
|
161
228
|
}
|
|
162
229
|
/** @ignore
|
|
163
230
|
*/
|
|
@@ -166,15 +233,17 @@ export class ComboBox extends HLayout {
|
|
|
166
233
|
if (!item) {
|
|
167
234
|
return;
|
|
168
235
|
}
|
|
236
|
+
this.m_lockchg = true;
|
|
169
237
|
this._setInput(item, true);
|
|
238
|
+
this.m_lockchg = false;
|
|
170
239
|
this.m_selection = {
|
|
171
240
|
id: item.id,
|
|
172
241
|
text: item.text
|
|
173
242
|
};
|
|
174
243
|
this.emit('selectionChange', EvSelectionChange(item));
|
|
175
244
|
this.emit('change', EvChange(item.id));
|
|
176
|
-
this.m_ui_input.focus();
|
|
177
|
-
this.m_popup.hide();
|
|
245
|
+
//this.m_ui_input.focus( );
|
|
246
|
+
//this.m_popup.hide( );
|
|
178
247
|
}
|
|
179
248
|
/**
|
|
180
249
|
*
|
|
@@ -210,7 +279,13 @@ export class ComboBox extends HLayout {
|
|
|
210
279
|
return this.m_selection ? this.m_selection.id : undefined;
|
|
211
280
|
}
|
|
212
281
|
get valueText() {
|
|
213
|
-
|
|
282
|
+
if (this.m_selection) {
|
|
283
|
+
return this.m_selection.text;
|
|
284
|
+
}
|
|
285
|
+
if (this.m_props.editable) {
|
|
286
|
+
return this.m_ui_input.value;
|
|
287
|
+
}
|
|
288
|
+
return '';
|
|
214
289
|
}
|
|
215
290
|
/**
|
|
216
291
|
*
|
|
@@ -218,7 +293,7 @@ export class ComboBox extends HLayout {
|
|
|
218
293
|
set value(id) {
|
|
219
294
|
let items = this.m_props.items;
|
|
220
295
|
if (isFunction(items)) {
|
|
221
|
-
items = items();
|
|
296
|
+
items = items(null);
|
|
222
297
|
}
|
|
223
298
|
const found = items.some((v) => {
|
|
224
299
|
if (v.id === id) {
|
|
@@ -235,6 +310,23 @@ export class ComboBox extends HLayout {
|
|
|
235
310
|
get input() {
|
|
236
311
|
return this.m_ui_input instanceof Input ? this.m_ui_input : null;
|
|
237
312
|
}
|
|
313
|
+
_checkFocus() {
|
|
314
|
+
const focus = document.activeElement;
|
|
315
|
+
if (this.dom && this.dom.contains(focus) || focus == document.body) {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (this.m_popup && this.m_popup.dom && this.m_popup.dom.contains(focus)) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
this._hidePopup();
|
|
322
|
+
}
|
|
323
|
+
_hidePopup() {
|
|
324
|
+
if (this.m_popvis) {
|
|
325
|
+
this.m_popup.close();
|
|
326
|
+
this.m_popvis = false;
|
|
327
|
+
this.stopTimer("focus-check");
|
|
328
|
+
}
|
|
329
|
+
}
|
|
238
330
|
static storeProxy(props) {
|
|
239
331
|
let view = props.store instanceof DataStore ? props.store.createView() : props.store;
|
|
240
332
|
return () => {
|
|
@@ -248,12 +340,12 @@ export class ComboBox extends HLayout {
|
|
|
248
340
|
return result;
|
|
249
341
|
};
|
|
250
342
|
}
|
|
343
|
+
focus() {
|
|
344
|
+
if (this.m_props.editable) {
|
|
345
|
+
this.m_ui_input.focus();
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
super.focus();
|
|
349
|
+
}
|
|
350
|
+
}
|
|
251
351
|
}
|
|
252
|
-
/*
|
|
253
|
-
export type CBComboBoxRenderer = ( rec: Record ) => string;
|
|
254
|
-
export interface ComboBoxStore {
|
|
255
|
-
store: DataStore;
|
|
256
|
-
display: string | CBComboBoxRenderer; // if string, the field name to display
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
*/
|