x4js 1.4.22 → 1.4.24
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/lib/action.d.ts +57 -0
- package/lib/action.js +59 -0
- package/lib/application.d.ts +2 -1
- package/lib/application.js +15 -11
- package/lib/base_component.d.ts +6 -0
- package/lib/base_component.js +13 -0
- package/lib/button.d.ts +2 -0
- package/lib/button.js +18 -4
- package/lib/component.d.ts +0 -1
- package/lib/component.js +0 -8
- package/lib/menu.d.ts +4 -0
- package/lib/menu.js +17 -1
- package/lib/settings.js +2 -2
- package/package.json +1 -1
- package/src/action.ts +88 -0
- package/src/application.ts +19 -10
- package/src/base_component.ts +15 -0
- package/src/button.ts +25 -5
- package/src/component.ts +4 -10
- package/src/menu.ts +24 -2
- package/src/settings.ts +2 -2
- package/src/smartedit.ts +0 -537
package/lib/action.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ___ ___ __
|
|
3
|
+
* \ \/ / / _
|
|
4
|
+
* \ / /_| |_
|
|
5
|
+
* / \____ _|
|
|
6
|
+
* /__/\__\ |_|
|
|
7
|
+
*
|
|
8
|
+
* @file action.ts
|
|
9
|
+
* @author Etienne Cochard
|
|
10
|
+
*
|
|
11
|
+
* Copyright (c) 2019-2022 R-libre ingenierie
|
|
12
|
+
*
|
|
13
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
* in the Software without restriction, including without limitation the rights
|
|
16
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
17
|
+
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
18
|
+
* subject to the following conditions:
|
|
19
|
+
* The above copyright notice and this permission notice shall be included in all copies
|
|
20
|
+
* or substantial portions of the Software.
|
|
21
|
+
*
|
|
22
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
23
|
+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
24
|
+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
25
|
+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
26
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
27
|
+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
|
+
**/
|
|
29
|
+
import { BasicEvent } from './x4events';
|
|
30
|
+
import { BaseComponent, BaseComponentEventMap, BaseComponentProps } from './base_component';
|
|
31
|
+
import { IconID } from "./icon";
|
|
32
|
+
import { EvChange, EventHandler } from 'x4js';
|
|
33
|
+
export interface EvAction extends BasicEvent {
|
|
34
|
+
}
|
|
35
|
+
export declare function EvAction(source: Action): EvAction;
|
|
36
|
+
interface ActionEventMap extends BaseComponentEventMap {
|
|
37
|
+
run: EvAction;
|
|
38
|
+
change: EvChange;
|
|
39
|
+
}
|
|
40
|
+
interface ActionProps extends BaseComponentProps<ActionEventMap> {
|
|
41
|
+
id?: any;
|
|
42
|
+
text?: string;
|
|
43
|
+
icon?: IconID;
|
|
44
|
+
disabled?: boolean;
|
|
45
|
+
hidden?: boolean;
|
|
46
|
+
checked?: boolean;
|
|
47
|
+
run: EventHandler<EvAction>;
|
|
48
|
+
change?: EventHandler<EvChange>;
|
|
49
|
+
}
|
|
50
|
+
export declare class Action extends BaseComponent<ActionProps, ActionEventMap> {
|
|
51
|
+
constructor(props: ActionProps);
|
|
52
|
+
get props(): ActionProps;
|
|
53
|
+
set text(t: string);
|
|
54
|
+
set icon(i: IconID);
|
|
55
|
+
fire(): void;
|
|
56
|
+
}
|
|
57
|
+
export {};
|
package/lib/action.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ___ ___ __
|
|
4
|
+
* \ \/ / / _
|
|
5
|
+
* \ / /_| |_
|
|
6
|
+
* / \____ _|
|
|
7
|
+
* /__/\__\ |_|
|
|
8
|
+
*
|
|
9
|
+
* @file action.ts
|
|
10
|
+
* @author Etienne Cochard
|
|
11
|
+
*
|
|
12
|
+
* Copyright (c) 2019-2022 R-libre ingenierie
|
|
13
|
+
*
|
|
14
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
* in the Software without restriction, including without limitation the rights
|
|
17
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
18
|
+
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
19
|
+
* subject to the following conditions:
|
|
20
|
+
* The above copyright notice and this permission notice shall be included in all copies
|
|
21
|
+
* or substantial portions of the Software.
|
|
22
|
+
*
|
|
23
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
24
|
+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
25
|
+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
26
|
+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
27
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
28
|
+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
29
|
+
**/
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.Action = exports.EvAction = void 0;
|
|
32
|
+
const x4events_1 = require("./x4events");
|
|
33
|
+
const base_component_1 = require("./base_component");
|
|
34
|
+
const x4js_1 = require("x4js");
|
|
35
|
+
function EvAction(source) {
|
|
36
|
+
return (0, x4events_1.BasicEvent)({ source });
|
|
37
|
+
}
|
|
38
|
+
exports.EvAction = EvAction;
|
|
39
|
+
class Action extends base_component_1.BaseComponent {
|
|
40
|
+
constructor(props) {
|
|
41
|
+
super(props);
|
|
42
|
+
this.mapPropEvents(props, "run");
|
|
43
|
+
}
|
|
44
|
+
get props() {
|
|
45
|
+
return this.m_props;
|
|
46
|
+
}
|
|
47
|
+
set text(t) {
|
|
48
|
+
this.m_props.text = t;
|
|
49
|
+
this.emit("change", (0, x4js_1.EvChange)(this));
|
|
50
|
+
}
|
|
51
|
+
set icon(i) {
|
|
52
|
+
this.m_props.icon = i;
|
|
53
|
+
this.emit("change", (0, x4js_1.EvChange)(this));
|
|
54
|
+
}
|
|
55
|
+
fire() {
|
|
56
|
+
this.emit("run", EvAction(this));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.Action = Action;
|
package/lib/application.d.ts
CHANGED
|
@@ -91,8 +91,9 @@ export declare class Application<P extends ApplicationProps = ApplicationProps,
|
|
|
91
91
|
*
|
|
92
92
|
* let myApp = new Application( ... );
|
|
93
93
|
* let mainView = new VLayout( ... );
|
|
94
|
-
* myApp.
|
|
94
|
+
* myApp.mainView = mainView;
|
|
95
95
|
*/
|
|
96
|
+
setMainView(root: Component, clearBefore: boolean): void;
|
|
96
97
|
set mainView(root: Component);
|
|
97
98
|
get mainView(): Component;
|
|
98
99
|
setTitle(title: string): void;
|
package/lib/application.js
CHANGED
|
@@ -33,7 +33,7 @@ const x4dom_1 = require("./x4dom");
|
|
|
33
33
|
const base_component_1 = require("./base_component");
|
|
34
34
|
const component_1 = require("./component");
|
|
35
35
|
const settings_1 = require("./settings");
|
|
36
|
-
const
|
|
36
|
+
const x4js_1 = require("x4js");
|
|
37
37
|
const _x4_touch_time = Symbol();
|
|
38
38
|
/**
|
|
39
39
|
* Represents an x4 application, which is typically a single page app.
|
|
@@ -123,18 +123,22 @@ class Application extends base_component_1.BaseComponent {
|
|
|
123
123
|
*
|
|
124
124
|
* let myApp = new Application( ... );
|
|
125
125
|
* let mainView = new VLayout( ... );
|
|
126
|
-
* myApp.
|
|
126
|
+
* myApp.mainView = mainView;
|
|
127
127
|
*/
|
|
128
|
-
|
|
128
|
+
setMainView(root, clearBefore) {
|
|
129
|
+
const ddom = this.m_props.renderTo ?? x4dom_1.x4document.body;
|
|
130
|
+
const dest = (0, x4js_1.flyWrap)(ddom);
|
|
131
|
+
dest.addClass('x4-root-element');
|
|
132
|
+
if (clearBefore) {
|
|
133
|
+
dest._empty();
|
|
134
|
+
}
|
|
129
135
|
this.m_mainView = root;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
dest.appendChild(root._build());
|
|
137
|
-
});
|
|
136
|
+
root.setStyleValue('position', 'absolute');
|
|
137
|
+
root._build();
|
|
138
|
+
ddom.appendChild(root.dom);
|
|
139
|
+
}
|
|
140
|
+
set mainView(root) {
|
|
141
|
+
this.setMainView(root, false);
|
|
138
142
|
}
|
|
139
143
|
get mainView() {
|
|
140
144
|
return this.m_mainView;
|
package/lib/base_component.d.ts
CHANGED
|
@@ -77,5 +77,11 @@ export declare class BaseComponent<P extends BaseComponentProps<BaseComponentEve
|
|
|
77
77
|
* @param timeout
|
|
78
78
|
*/
|
|
79
79
|
singleShot(callback: TimerCallback, timeout?: number): void;
|
|
80
|
+
/**
|
|
81
|
+
*
|
|
82
|
+
* @param props
|
|
83
|
+
* @param elements
|
|
84
|
+
*/
|
|
85
|
+
mapPropEvents<N extends keyof E>(props: P, ...elements: N[]): void;
|
|
80
86
|
}
|
|
81
87
|
export {};
|
package/lib/base_component.js
CHANGED
|
@@ -94,5 +94,18 @@ class BaseComponent extends x4events_1.EventSource {
|
|
|
94
94
|
singleShot(callback, timeout = 0) {
|
|
95
95
|
setTimeout(callback, timeout);
|
|
96
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
*
|
|
99
|
+
* @param props
|
|
100
|
+
* @param elements
|
|
101
|
+
*/
|
|
102
|
+
mapPropEvents(props, ...elements) {
|
|
103
|
+
elements.forEach(name => {
|
|
104
|
+
const n = name;
|
|
105
|
+
if (props[n]) {
|
|
106
|
+
this._on(n, props[n]);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
97
110
|
}
|
|
98
111
|
exports.BaseComponent = BaseComponent;
|
package/lib/button.d.ts
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
**/
|
|
29
29
|
import { Component, CProps, CEventMap, HtmlString } from './component';
|
|
30
30
|
import { EventCallback, EvClick, EvChange } from './x4events';
|
|
31
|
+
import { Action } from './action';
|
|
31
32
|
import { IconID } from './icon';
|
|
32
33
|
import { MenuItem, MenuOrSep } from './menu';
|
|
33
34
|
/**
|
|
@@ -48,6 +49,7 @@ interface ButtonProps<E extends ButtonEventMap = ButtonEventMap> extends CProps<
|
|
|
48
49
|
autoRepeat?: number;
|
|
49
50
|
menu?: MenuOrSep[] | MenuCallBack;
|
|
50
51
|
click?: EventCallback<EvClick>;
|
|
52
|
+
action?: Action;
|
|
51
53
|
}
|
|
52
54
|
/**
|
|
53
55
|
* Base button
|
package/lib/button.js
CHANGED
|
@@ -49,10 +49,21 @@ class BaseButton extends component_1.Component {
|
|
|
49
49
|
this.mapPropEvents(props, 'click');
|
|
50
50
|
}
|
|
51
51
|
render(props) {
|
|
52
|
-
|
|
53
|
-
let
|
|
54
|
-
let
|
|
55
|
-
|
|
52
|
+
const action = props.action;
|
|
53
|
+
let icon = props.icon;
|
|
54
|
+
let text = props.text;
|
|
55
|
+
if (action) {
|
|
56
|
+
if (!icon && action.props.icon) {
|
|
57
|
+
icon = action.props.icon;
|
|
58
|
+
}
|
|
59
|
+
if (text === undefined && action.props.text) {
|
|
60
|
+
text = action.props.text;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const ui_icon = icon ? new icon_1.Icon({ icon, cls: 'left', ref: 'l_icon' }) : null;
|
|
64
|
+
const ui_label = new label_1.Label({ flex: 1, text: text ?? '', align: props.align, ref: 'label' });
|
|
65
|
+
const ui_ricon = props.rightIcon ? new icon_1.Icon({ icon: props.rightIcon, cls: 'right', ref: 'r_icon' }) : null;
|
|
66
|
+
this.setContent([ui_icon, ui_label, ui_ricon]);
|
|
56
67
|
this._setTabIndex(props.tabIndex);
|
|
57
68
|
}
|
|
58
69
|
/**
|
|
@@ -115,6 +126,9 @@ class BaseButton extends component_1.Component {
|
|
|
115
126
|
}
|
|
116
127
|
else {
|
|
117
128
|
this.emit('click', (0, x4events_1.EvClick)());
|
|
129
|
+
if (this.m_props.action) {
|
|
130
|
+
this.m_props.action.fire();
|
|
131
|
+
}
|
|
118
132
|
}
|
|
119
133
|
}
|
|
120
134
|
/**
|
package/lib/component.d.ts
CHANGED
|
@@ -314,7 +314,6 @@ export declare class Component<P extends CProps<BaseComponentEventMap> = CProps<
|
|
|
314
314
|
*
|
|
315
315
|
*/
|
|
316
316
|
clearDomEvent<K extends keyof X4ElementEventMap>(type: K): void;
|
|
317
|
-
mapPropEvents<N extends keyof E>(props: P, ...elements: N[]): void;
|
|
318
317
|
/**
|
|
319
318
|
*
|
|
320
319
|
* @param name
|
package/lib/component.js
CHANGED
|
@@ -849,14 +849,6 @@ class Component extends base_component_1.BaseComponent {
|
|
|
849
849
|
}
|
|
850
850
|
}
|
|
851
851
|
}
|
|
852
|
-
mapPropEvents(props, ...elements) {
|
|
853
|
-
elements.forEach(name => {
|
|
854
|
-
const n = name;
|
|
855
|
-
if (props[n]) {
|
|
856
|
-
this._on(n, props[n]);
|
|
857
|
-
}
|
|
858
|
-
});
|
|
859
|
-
}
|
|
860
852
|
/**
|
|
861
853
|
*
|
|
862
854
|
* @param name
|
package/lib/menu.d.ts
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
**/
|
|
29
29
|
import { CEventMap, Component, CProps } from './component';
|
|
30
30
|
import { EvClick, EventCallback } from './x4events';
|
|
31
|
+
import { Action } from './action';
|
|
31
32
|
import { Popup, PopupProps } from './popup';
|
|
32
33
|
import { IconID } from './icon';
|
|
33
34
|
import { Label } from './label';
|
|
@@ -99,10 +100,13 @@ export interface MenuItemProps extends CProps {
|
|
|
99
100
|
checked?: boolean;
|
|
100
101
|
cls?: string;
|
|
101
102
|
click?: EventCallback<EvClick>;
|
|
103
|
+
action?: Action;
|
|
102
104
|
}
|
|
103
105
|
export declare class MenuItem extends Component<MenuItemProps, MenuItemEventMap> {
|
|
104
106
|
private m_menu;
|
|
105
107
|
private m_isOpen;
|
|
108
|
+
private m_action;
|
|
109
|
+
constructor(action: Action);
|
|
106
110
|
constructor(text: string, click: EventCallback<EvClick>);
|
|
107
111
|
constructor(props: MenuItemProps);
|
|
108
112
|
/** @ignore */
|
package/lib/menu.js
CHANGED
|
@@ -32,6 +32,7 @@ exports.MenuBar = exports.MenuItem = exports.Menu = exports.MenuTitle = exports.
|
|
|
32
32
|
const x4dom_1 = require("./x4dom");
|
|
33
33
|
const component_1 = require("./component");
|
|
34
34
|
const x4events_1 = require("./x4events");
|
|
35
|
+
const action_1 = require("./action");
|
|
35
36
|
const popup_1 = require("./popup");
|
|
36
37
|
const icon_1 = require("./icon");
|
|
37
38
|
const label_1 = require("./label");
|
|
@@ -177,8 +178,15 @@ exports.Menu = Menu;
|
|
|
177
178
|
class MenuItem extends component_1.Component {
|
|
178
179
|
m_menu;
|
|
179
180
|
m_isOpen;
|
|
181
|
+
m_action;
|
|
180
182
|
constructor(a, b) {
|
|
181
|
-
if (
|
|
183
|
+
if (a instanceof action_1.Action) {
|
|
184
|
+
super({
|
|
185
|
+
click: () => { a.fire(); }
|
|
186
|
+
});
|
|
187
|
+
this.m_action = a;
|
|
188
|
+
}
|
|
189
|
+
else if ((0, tools_1.isString)(a)) {
|
|
182
190
|
super({
|
|
183
191
|
text: a,
|
|
184
192
|
click: b
|
|
@@ -200,6 +208,14 @@ class MenuItem extends component_1.Component {
|
|
|
200
208
|
if (props.checked !== undefined) {
|
|
201
209
|
icon = props.checked ? 'cls(far fa-check)' : 0; //todo: use stylesheet
|
|
202
210
|
}
|
|
211
|
+
if (this.m_action) {
|
|
212
|
+
if (!icon) {
|
|
213
|
+
icon = this.m_action.props.icon;
|
|
214
|
+
}
|
|
215
|
+
if (text === undefined) {
|
|
216
|
+
text = this.m_action.props.text;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
203
219
|
let popIco = null;
|
|
204
220
|
if (this.isPopup) {
|
|
205
221
|
this.addClass('@popup-menu-item');
|
package/lib/settings.js
CHANGED
|
@@ -47,14 +47,14 @@ class Settings {
|
|
|
47
47
|
}
|
|
48
48
|
_save() {
|
|
49
49
|
let data = JSON.stringify(this.m_data);
|
|
50
|
-
localStorage.
|
|
50
|
+
localStorage.setItem(this.m_name, data);
|
|
51
51
|
}
|
|
52
52
|
_load() {
|
|
53
53
|
if (this.m_data) {
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
this.m_data = {};
|
|
57
|
-
let data = localStorage.
|
|
57
|
+
let data = localStorage.getItem(this.m_name);
|
|
58
58
|
if (data !== null) {
|
|
59
59
|
data = JSON.parse(data);
|
|
60
60
|
if (data) {
|
package/package.json
CHANGED
package/src/action.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ___ ___ __
|
|
3
|
+
* \ \/ / / _
|
|
4
|
+
* \ / /_| |_
|
|
5
|
+
* / \____ _|
|
|
6
|
+
* /__/\__\ |_|
|
|
7
|
+
*
|
|
8
|
+
* @file action.ts
|
|
9
|
+
* @author Etienne Cochard
|
|
10
|
+
*
|
|
11
|
+
* Copyright (c) 2019-2022 R-libre ingenierie
|
|
12
|
+
*
|
|
13
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
* in the Software without restriction, including without limitation the rights
|
|
16
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
17
|
+
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
18
|
+
* subject to the following conditions:
|
|
19
|
+
* The above copyright notice and this permission notice shall be included in all copies
|
|
20
|
+
* or substantial portions of the Software.
|
|
21
|
+
*
|
|
22
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
23
|
+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
24
|
+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
25
|
+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
26
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
27
|
+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
|
+
**/
|
|
29
|
+
|
|
30
|
+
import { BasicEvent } from './x4events'
|
|
31
|
+
import { BaseComponent, BaseComponentEventMap, BaseComponentProps } from './base_component'
|
|
32
|
+
import { IconID } from "./icon"
|
|
33
|
+
import { EvChange, EventHandler } from 'x4js';
|
|
34
|
+
|
|
35
|
+
//TODO: implement all
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
export interface EvAction extends BasicEvent {
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function EvAction( source: Action ) {
|
|
42
|
+
return BasicEvent<EvAction>({source});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface ActionEventMap extends BaseComponentEventMap {
|
|
46
|
+
run: EvAction;
|
|
47
|
+
change: EvChange;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface ActionProps extends BaseComponentProps<ActionEventMap> {
|
|
51
|
+
id?: any;
|
|
52
|
+
text?: string;
|
|
53
|
+
icon?: IconID;
|
|
54
|
+
disabled?: boolean;
|
|
55
|
+
hidden?: boolean;
|
|
56
|
+
checked?: boolean;
|
|
57
|
+
|
|
58
|
+
run: EventHandler<EvAction>;
|
|
59
|
+
change?: EventHandler<EvChange>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export class Action extends BaseComponent<ActionProps,ActionEventMap> {
|
|
63
|
+
|
|
64
|
+
constructor( props: ActionProps ) {
|
|
65
|
+
super( props );
|
|
66
|
+
|
|
67
|
+
this.mapPropEvents( props, "run" );
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get props( ) {
|
|
71
|
+
return this.m_props;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
set text( t: string ) {
|
|
75
|
+
this.m_props.text = t;
|
|
76
|
+
this.emit( "change", EvChange(this) );
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
set icon( i: IconID ) {
|
|
80
|
+
this.m_props.icon = i;
|
|
81
|
+
this.emit( "change", EvChange(this) );
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
fire( ) {
|
|
85
|
+
this.emit( "run", EvAction(this) );
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
package/src/application.ts
CHANGED
|
@@ -34,6 +34,7 @@ import { Component } from './component'
|
|
|
34
34
|
import { Settings } from './settings'
|
|
35
35
|
import { deferCall } from './tools'
|
|
36
36
|
import { _tr } from './i18n'
|
|
37
|
+
import { flyWrap } from 'x4js'
|
|
37
38
|
|
|
38
39
|
const _x4_touch_time = Symbol( );
|
|
39
40
|
|
|
@@ -165,21 +166,29 @@ export class Application<P extends ApplicationProps = ApplicationProps, E extend
|
|
|
165
166
|
*
|
|
166
167
|
* let myApp = new Application( ... );
|
|
167
168
|
* let mainView = new VLayout( ... );
|
|
168
|
-
* myApp.
|
|
169
|
+
* myApp.mainView = mainView;
|
|
169
170
|
*/
|
|
170
171
|
|
|
171
|
-
public
|
|
172
|
+
public setMainView( root: Component, clearBefore: boolean ) {
|
|
173
|
+
|
|
174
|
+
const ddom = this.m_props.renderTo ?? x4document.body;
|
|
175
|
+
const dest = flyWrap( ddom );
|
|
176
|
+
|
|
177
|
+
dest.addClass( 'x4-root-element' );
|
|
178
|
+
if( clearBefore ) {
|
|
179
|
+
dest._empty( );
|
|
180
|
+
}
|
|
172
181
|
|
|
173
182
|
this.m_mainView = root;
|
|
174
|
-
this.mainView.addClass( 'x4-root-element' );
|
|
175
183
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
184
|
+
root.setStyleValue( 'position', 'absolute' );
|
|
185
|
+
root._build();
|
|
186
|
+
|
|
187
|
+
ddom.appendChild( root.dom );
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
set mainView( root: Component ) {
|
|
191
|
+
this.setMainView( root, false );
|
|
183
192
|
}
|
|
184
193
|
|
|
185
194
|
public get mainView( ) : Component {
|
package/src/base_component.ts
CHANGED
|
@@ -132,4 +132,19 @@ export class BaseComponent< P extends BaseComponentProps<BaseComponentEventMap>,
|
|
|
132
132
|
singleShot( callback: TimerCallback, timeout = 0 ) {
|
|
133
133
|
setTimeout( callback, timeout );
|
|
134
134
|
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
*
|
|
138
|
+
* @param props
|
|
139
|
+
* @param elements
|
|
140
|
+
*/
|
|
141
|
+
|
|
142
|
+
public mapPropEvents<N extends keyof E>(props: P, ...elements: N[] ) {
|
|
143
|
+
elements.forEach( name => {
|
|
144
|
+
const n = name as string;
|
|
145
|
+
if (props[n]) {
|
|
146
|
+
this._on(n, props[n]);
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
}
|
|
135
150
|
}
|
package/src/button.ts
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
import { Component, CProps, CEventMap, HtmlString } from './component'
|
|
32
32
|
import { EventCallback, EvClick, EvChange } from './x4events'
|
|
33
33
|
|
|
34
|
+
import { Action } from './action'
|
|
34
35
|
import { Icon, IconID } from './icon'
|
|
35
36
|
import { Label } from './label'
|
|
36
37
|
import { Menu, MenuItem, MenuOrSep } from './menu'
|
|
@@ -57,8 +58,9 @@ interface ButtonProps<E extends ButtonEventMap = ButtonEventMap> extends CProps<
|
|
|
57
58
|
align?: 'center' | 'left' | 'right'; // text alignment
|
|
58
59
|
autoRepeat?: number; // time in ms or 0/undefined for none
|
|
59
60
|
menu?: MenuOrSep[] | MenuCallBack;
|
|
60
|
-
|
|
61
61
|
click?: EventCallback<EvClick>; // shortcut to events: { click: ... }
|
|
62
|
+
|
|
63
|
+
action?: Action;
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
|
|
@@ -83,11 +85,26 @@ export class BaseButton<P extends ButtonProps = ButtonProps, E extends ButtonEve
|
|
|
83
85
|
|
|
84
86
|
render(props: ButtonProps) {
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
let
|
|
88
|
+
const action = props.action;
|
|
89
|
+
|
|
90
|
+
let icon = props.icon;
|
|
91
|
+
let text = props.text;
|
|
92
|
+
|
|
93
|
+
if( action ) {
|
|
94
|
+
if( !icon && action.props.icon ) {
|
|
95
|
+
icon = action.props.icon;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if( text===undefined && action.props.text ) {
|
|
99
|
+
text = action.props.text;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
89
102
|
|
|
90
|
-
|
|
103
|
+
const ui_icon = icon ? new Icon({ icon, cls: 'left', ref: 'l_icon' }) : null;
|
|
104
|
+
const ui_label = new Label({ flex: 1, text: text ?? '', align: props.align, ref: 'label' });
|
|
105
|
+
const ui_ricon = props.rightIcon ? new Icon({ icon: props.rightIcon, cls: 'right', ref: 'r_icon' }) : null;
|
|
106
|
+
|
|
107
|
+
this.setContent([ui_icon, ui_label, ui_ricon]);
|
|
91
108
|
this._setTabIndex(props.tabIndex);
|
|
92
109
|
}
|
|
93
110
|
|
|
@@ -164,6 +181,9 @@ export class BaseButton<P extends ButtonProps = ButtonProps, E extends ButtonEve
|
|
|
164
181
|
}
|
|
165
182
|
else {
|
|
166
183
|
this.emit('click', EvClick());
|
|
184
|
+
if( this.m_props.action ) {
|
|
185
|
+
this.m_props.action.fire( );
|
|
186
|
+
}
|
|
167
187
|
}
|
|
168
188
|
}
|
|
169
189
|
|
package/src/component.ts
CHANGED
|
@@ -41,6 +41,7 @@ import { _tr } from './i18n';
|
|
|
41
41
|
import { BasicEvent, EventCallback } from './x4events';
|
|
42
42
|
import { BaseComponent, BaseComponentProps, BaseComponentEventMap } from './base_component';
|
|
43
43
|
import { IDOMEvents, X4ElementEventMap } from './dom_events';
|
|
44
|
+
import { IconID } from 'x4js';
|
|
44
45
|
|
|
45
46
|
export { HtmlString, isHtmlString, html } from './tools'
|
|
46
47
|
|
|
@@ -1143,15 +1144,6 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
1143
1144
|
}
|
|
1144
1145
|
}
|
|
1145
1146
|
|
|
1146
|
-
public mapPropEvents<N extends keyof E>(props: P, ...elements: N[] ) {
|
|
1147
|
-
elements.forEach( name => {
|
|
1148
|
-
const n = name as string;
|
|
1149
|
-
if (props[n]) {
|
|
1150
|
-
this._on(n, props[n]);
|
|
1151
|
-
}
|
|
1152
|
-
})
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
1147
|
/**
|
|
1156
1148
|
*
|
|
1157
1149
|
* @param name
|
|
@@ -2333,4 +2325,6 @@ export class Container<P extends ContainerProps = ContainerProps, E extends Cont
|
|
|
2333
2325
|
}
|
|
2334
2326
|
}
|
|
2335
2327
|
|
|
2336
|
-
export type ComponentConstructor<T> = new (props: CProps) => T;
|
|
2328
|
+
export type ComponentConstructor<T> = new (props: CProps) => T;
|
|
2329
|
+
|
|
2330
|
+
|
package/src/menu.ts
CHANGED
|
@@ -32,6 +32,8 @@ import { x4document } from './x4dom'
|
|
|
32
32
|
import { CEventMap, Component, CProps } from './component'
|
|
33
33
|
import { EvClick, EventCallback } from './x4events'
|
|
34
34
|
|
|
35
|
+
import { Action } from './action'
|
|
36
|
+
|
|
35
37
|
import { Popup, PopupProps } from './popup'
|
|
36
38
|
import { Icon, IconID } from './icon'
|
|
37
39
|
import { Label } from './label'
|
|
@@ -244,8 +246,9 @@ export interface MenuItemProps extends CProps {
|
|
|
244
246
|
items?: MenuOrSep[];
|
|
245
247
|
checked?: boolean;
|
|
246
248
|
cls?: string;
|
|
247
|
-
|
|
248
249
|
click?: EventCallback<EvClick>; // shortcut to events: { click ... }
|
|
250
|
+
|
|
251
|
+
action?: Action;
|
|
249
252
|
}
|
|
250
253
|
|
|
251
254
|
|
|
@@ -254,12 +257,21 @@ export class MenuItem extends Component<MenuItemProps, MenuItemEventMap> {
|
|
|
254
257
|
|
|
255
258
|
private m_menu: Menu;
|
|
256
259
|
private m_isOpen: boolean;
|
|
260
|
+
private m_action: Action;
|
|
257
261
|
|
|
262
|
+
constructor( action: Action );
|
|
258
263
|
constructor( text: string, click: EventCallback<EvClick> );
|
|
259
264
|
constructor( props: MenuItemProps);
|
|
260
265
|
constructor( a, b? ) {
|
|
261
266
|
|
|
262
|
-
if(
|
|
267
|
+
if( a instanceof Action ) {
|
|
268
|
+
super( {
|
|
269
|
+
click: ( ) => { a.fire(); }
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
this.m_action = a;
|
|
273
|
+
}
|
|
274
|
+
else if( isString(a) ) {
|
|
263
275
|
super( {
|
|
264
276
|
text: a,
|
|
265
277
|
click: b
|
|
@@ -288,6 +300,16 @@ export class MenuItem extends Component<MenuItemProps, MenuItemEventMap> {
|
|
|
288
300
|
icon = props.checked ? 'cls(far fa-check)' : 0; //todo: use stylesheet
|
|
289
301
|
}
|
|
290
302
|
|
|
303
|
+
if( this.m_action ) {
|
|
304
|
+
if( !icon ) {
|
|
305
|
+
icon = this.m_action.props.icon;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if( text===undefined ) {
|
|
309
|
+
text = this.m_action.props.text;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
291
313
|
let popIco = null;
|
|
292
314
|
if (this.isPopup) {
|
|
293
315
|
this.addClass('@popup-menu-item');
|
package/src/settings.ts
CHANGED
|
@@ -50,7 +50,7 @@ export class Settings {
|
|
|
50
50
|
|
|
51
51
|
private _save( ) {
|
|
52
52
|
let data = JSON.stringify(this.m_data);
|
|
53
|
-
localStorage.
|
|
53
|
+
localStorage.setItem( this.m_name, data );
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
private _load( ) {
|
|
@@ -60,7 +60,7 @@ export class Settings {
|
|
|
60
60
|
|
|
61
61
|
this.m_data = {};
|
|
62
62
|
|
|
63
|
-
let data = localStorage.
|
|
63
|
+
let data = localStorage.getItem( this.m_name );
|
|
64
64
|
if( data!==null ) {
|
|
65
65
|
data = JSON.parse( data );
|
|
66
66
|
if( data ) {
|
package/src/smartedit.ts
DELETED
|
@@ -1,537 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ___ ___ __
|
|
3
|
-
* \ \_/ / / _
|
|
4
|
-
* \ / /_| |_
|
|
5
|
-
* / _ \____ _|
|
|
6
|
-
* /__/ \__\ |_|
|
|
7
|
-
*
|
|
8
|
-
* @file smartedit.ts
|
|
9
|
-
* @author Etienne Cochard
|
|
10
|
-
*
|
|
11
|
-
* Copyright (c) 2019-2022 R-libre ingenierie
|
|
12
|
-
*
|
|
13
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
15
|
-
* in the Software without restriction, including without limitation the rights
|
|
16
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
17
|
-
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
18
|
-
* subject to the following conditions:
|
|
19
|
-
* The above copyright notice and this permission notice shall be included in all copies
|
|
20
|
-
* or substantial portions of the Software.
|
|
21
|
-
*
|
|
22
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
23
|
-
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
24
|
-
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
25
|
-
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
26
|
-
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
27
|
-
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
|
-
**/
|
|
29
|
-
|
|
30
|
-
import { x4document } from './dom-gen'
|
|
31
|
-
|
|
32
|
-
import { TextEdit, TextEditProps } from './textedit'
|
|
33
|
-
import { DataStore, DataView, Record } from './datastore'
|
|
34
|
-
import { Popup, PopupProps, PopupEventMap } from './popup';
|
|
35
|
-
import { Component, CProps, EvFocus } from './component';
|
|
36
|
-
import { EvChange, EvClick } from './x4_events';
|
|
37
|
-
|
|
38
|
-
type Renderer = (rec: Record) => CellData[];
|
|
39
|
-
|
|
40
|
-
export interface ToolItem {
|
|
41
|
-
text: string;
|
|
42
|
-
callback: (target: TextEdit) => void;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface SmartEditProps extends TextEditProps {
|
|
46
|
-
store: DataStore;
|
|
47
|
-
field: string;
|
|
48
|
-
minDisplay?: number; // min char number before displaying items
|
|
49
|
-
maxCount?: number; // max count elements to display
|
|
50
|
-
autoFill?: boolean; // force selected element into edit (cannot select empty)
|
|
51
|
-
renderer: Renderer;
|
|
52
|
-
tools?: ToolItem[]; // elements to add at end
|
|
53
|
-
searchCallback?: (value: string, view: DataView) => boolean
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export class SmartEdit extends TextEdit<SmartEditProps> {
|
|
57
|
-
|
|
58
|
-
m_popup: PopupTable;
|
|
59
|
-
m_dataview: DataView;
|
|
60
|
-
m_field: string;
|
|
61
|
-
m_minDisplay: number;
|
|
62
|
-
m_maxCount: number;
|
|
63
|
-
m_autoFill: boolean;
|
|
64
|
-
m_renderer: Renderer;
|
|
65
|
-
m_tools: ToolItem[];
|
|
66
|
-
m_searchCallback: (value: string, view: DataView) => boolean;
|
|
67
|
-
|
|
68
|
-
constructor(props: SmartEditProps) {
|
|
69
|
-
super(props);
|
|
70
|
-
|
|
71
|
-
this.m_dataview = props.store.createView();
|
|
72
|
-
this.m_field = props.field;
|
|
73
|
-
this.m_renderer = props.renderer;
|
|
74
|
-
this.m_minDisplay = props.minDisplay ?? 0;
|
|
75
|
-
this.m_maxCount = props.maxCount ?? 10;
|
|
76
|
-
this.m_autoFill = props.autoFill === undefined ? true : props.autoFill;
|
|
77
|
-
this.m_popup = null;
|
|
78
|
-
this.m_tools = props.tools ?? [];
|
|
79
|
-
this.m_searchCallback = props.searchCallback;
|
|
80
|
-
|
|
81
|
-
this.on('change', (e) => this._onChange(e));
|
|
82
|
-
this.on('focus', (e) => this._onFocus(e));
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
render(props: SmartEditProps) {
|
|
86
|
-
super.render(props);
|
|
87
|
-
|
|
88
|
-
this.m_ui_input.setDomEvent('keydown', (e) => this._onKey(e));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
private _onChange(ev: EvChange) {
|
|
92
|
-
this._showPopup(ev.value as string);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
private _onFocus(ev: EvFocus) {
|
|
96
|
-
if (ev.focus) {
|
|
97
|
-
this._showPopup(this.value);
|
|
98
|
-
}
|
|
99
|
-
else if (this.m_popup) {
|
|
100
|
-
this.m_popup.close();
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
private _onKey(e) {
|
|
105
|
-
|
|
106
|
-
console.log(e.key);
|
|
107
|
-
|
|
108
|
-
switch (e.key) {
|
|
109
|
-
case 'Backspace': {
|
|
110
|
-
|
|
111
|
-
// remove selection
|
|
112
|
-
let start = e.target.selectionStart;
|
|
113
|
-
let end = e.target.selectionEnd;
|
|
114
|
-
|
|
115
|
-
if (start > end) {
|
|
116
|
-
let t = start;
|
|
117
|
-
start = end;
|
|
118
|
-
end = t;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
let v = this.value;
|
|
122
|
-
let a = v.substr(0, start);
|
|
123
|
-
let b = v.substr(end);
|
|
124
|
-
|
|
125
|
-
this.value = a + b;
|
|
126
|
-
break;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
case 'ArrowUp':
|
|
130
|
-
case 'Up': {
|
|
131
|
-
if (this.m_popup) {
|
|
132
|
-
this._moveNext(false);
|
|
133
|
-
e.preventDefault();
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
break;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
case 'ArrowDown':
|
|
140
|
-
case 'Down': {
|
|
141
|
-
if (this.m_popup) {
|
|
142
|
-
this._moveNext(true);
|
|
143
|
-
e.preventDefault();
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
break;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
case 'Enter': {
|
|
150
|
-
if (this.m_popup) {
|
|
151
|
-
this._checkTool(e);
|
|
152
|
-
}
|
|
153
|
-
break;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
private _showSugg(text) {
|
|
159
|
-
let sel = this.getSelection();
|
|
160
|
-
this.value = text;
|
|
161
|
-
this.select(sel.start, sel.length);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
isOpen() {
|
|
165
|
-
return this.m_popup !== null;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
componentDisposed() {
|
|
170
|
-
if (this.m_popup) {
|
|
171
|
-
this.m_popup.close();
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
super.componentDisposed();
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// enter pressed on an element
|
|
178
|
-
private _checkTool(e: KeyboardEvent) {
|
|
179
|
-
|
|
180
|
-
let sel = this.m_popup.selection;
|
|
181
|
-
if (this._callTool(sel)) {
|
|
182
|
-
e.preventDefault();
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
private _callTool(sel: number): boolean {
|
|
187
|
-
let data = this.m_popup.getRowData(sel) as ToolItem;
|
|
188
|
-
if (data) {
|
|
189
|
-
if (this.m_popup) {
|
|
190
|
-
this.m_popup.close();
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
data.callback(this);
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
return false;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
private _moveNext(next: boolean) {
|
|
202
|
-
let sel = this.m_popup.selNext(next);
|
|
203
|
-
console.log('movenext: ', sel);
|
|
204
|
-
|
|
205
|
-
let data = this.m_popup.getRowData(sel);
|
|
206
|
-
|
|
207
|
-
if (!data) {
|
|
208
|
-
let text = this.m_popup.getCell(sel, 0).text;
|
|
209
|
-
this._showSugg(text);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
//_onKey( e: KeyboardEvent ) {
|
|
214
|
-
// if( e.key==' ' ) {
|
|
215
|
-
// this._showPopup( this.value )
|
|
216
|
-
// }
|
|
217
|
-
//}
|
|
218
|
-
|
|
219
|
-
private _showPopup(v: string) {
|
|
220
|
-
|
|
221
|
-
if (this.m_popup) {
|
|
222
|
-
this.m_popup.close();
|
|
223
|
-
this.m_popup = null;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
let cnt: number;
|
|
227
|
-
|
|
228
|
-
let sel = this.getSelection();
|
|
229
|
-
let search = sel.length ? v.substr(0, sel.start) : v;
|
|
230
|
-
|
|
231
|
-
if (search.length < this.m_minDisplay) {
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
let autoFill = this.m_autoFill;
|
|
236
|
-
|
|
237
|
-
if (search.length == 0) {
|
|
238
|
-
cnt = this.m_dataview.filter(null);
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
if (this.m_searchCallback) {
|
|
242
|
-
autoFill = this.m_searchCallback(search, this.m_dataview);
|
|
243
|
-
cnt = this.m_dataview.count;
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
cnt = this.m_dataview.filter({
|
|
247
|
-
op: '=',
|
|
248
|
-
field: this.m_field,
|
|
249
|
-
value: new RegExp('^' + search.trim() + '.*', 'mi')
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (cnt > 0) {
|
|
255
|
-
let rec = this.m_dataview.getByIndex(0);
|
|
256
|
-
|
|
257
|
-
if (autoFill) {
|
|
258
|
-
this.value = rec.getField(this.m_field);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
this.select(v.length);
|
|
262
|
-
|
|
263
|
-
let count = Math.min(this.m_dataview.count, this.m_maxCount);
|
|
264
|
-
let r2 = this.m_ui_input.getBoundingRect();
|
|
265
|
-
|
|
266
|
-
this.m_popup = new PopupTable({
|
|
267
|
-
cls: '@editor-popup',
|
|
268
|
-
minWidth: r2.width
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
this.m_popup.on('click', (ev: EvClick) => {
|
|
272
|
-
|
|
273
|
-
let { row, text } = ev.context;
|
|
274
|
-
|
|
275
|
-
if (!this._callTool(row)) {
|
|
276
|
-
this.value = text;
|
|
277
|
-
this.emit('click', EvClick());
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
let i;
|
|
282
|
-
for (i = 0; i < count; i++) {
|
|
283
|
-
|
|
284
|
-
let rec = this.m_dataview.getByIndex(i);
|
|
285
|
-
let texts = this.m_renderer(rec);
|
|
286
|
-
|
|
287
|
-
this.m_popup.setCell(i, 0, texts[0].text, texts[0].cls);
|
|
288
|
-
this.m_popup.setCell(i, 1, texts[1].text, texts[1].cls);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
for (let j = 0; j < this.m_tools.length; j++, i++) {
|
|
292
|
-
this.m_popup.setCell(i, 0, this.m_tools[j].text);
|
|
293
|
-
this.m_popup.setCell(i, 1, '');
|
|
294
|
-
this.m_popup.setRowData(i, this.m_tools[j]);
|
|
295
|
-
console.log('fill: ', i);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
this.m_popup.displayAt(r2.left, r2.bottom);
|
|
299
|
-
}
|
|
300
|
-
else if (this.m_tools.length) {
|
|
301
|
-
let r2 = this.m_ui_input.getBoundingRect();
|
|
302
|
-
|
|
303
|
-
this.m_popup = new PopupTable({
|
|
304
|
-
cls: '@editor-popup',
|
|
305
|
-
minWidth: r2.width
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
this.m_popup.on('click', (ev: EvClick) => {
|
|
309
|
-
|
|
310
|
-
let { row, text } = ev.context;
|
|
311
|
-
if (!this._callTool(row)) {
|
|
312
|
-
this.value = text;
|
|
313
|
-
}
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
for (let j = 0, i = 0; j < this.m_tools.length; j++, i++) {
|
|
317
|
-
this.m_popup.setCell(i, 0, this.m_tools[j].text);
|
|
318
|
-
this.m_popup.setCell(i, 1, '');
|
|
319
|
-
this.m_popup.setRowData(i, this.m_tools[j]);
|
|
320
|
-
console.log('fill: ', i);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
this.m_popup.displayAt(r2.left, r2.bottom);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
interface CellData {
|
|
329
|
-
text: string;
|
|
330
|
-
cls?: string;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
type CellMap = Map<number, CellData>;
|
|
334
|
-
|
|
335
|
-
interface PopupTableEventMap extends PopupEventMap {
|
|
336
|
-
click: EvClick;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
interface PopupTableProps extends PopupProps<PopupTableEventMap> {
|
|
340
|
-
rows?: number;
|
|
341
|
-
cols?: number;
|
|
342
|
-
minWidth?: number;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
export class PopupTable extends Popup<PopupTableProps, PopupTableEventMap> {
|
|
348
|
-
|
|
349
|
-
private m_rows: number;
|
|
350
|
-
private m_cols: number;
|
|
351
|
-
private m_cells: CellMap;
|
|
352
|
-
private m_data: Map<number, any>;
|
|
353
|
-
private m_minw: number;
|
|
354
|
-
private m_defcell: CellData;
|
|
355
|
-
private m_sel: number;
|
|
356
|
-
|
|
357
|
-
constructor(props: PopupTableProps) {
|
|
358
|
-
super(props);
|
|
359
|
-
|
|
360
|
-
this.m_rows = props.rows ?? 0;
|
|
361
|
-
this.m_cols = props.cols ?? 0;
|
|
362
|
-
this.m_minw = props.minWidth;
|
|
363
|
-
this.m_cells = new Map<number, CellData>();
|
|
364
|
-
this.m_data = new Map<number, any>();
|
|
365
|
-
this.m_defcell = { text: '', cls: undefined };
|
|
366
|
-
this.m_sel = 0;
|
|
367
|
-
this.enableMask(false);
|
|
368
|
-
|
|
369
|
-
this.setDomEvent('create', () => {
|
|
370
|
-
(<HTMLTableElement>this.dom).cellPadding = '0px';
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
this.setDomEvent('mousedown', (e: MouseEvent) => {
|
|
374
|
-
e.preventDefault();
|
|
375
|
-
|
|
376
|
-
let el = Component.getElement(<HTMLElement>e.target);
|
|
377
|
-
let row = el.getData('row');
|
|
378
|
-
|
|
379
|
-
this.m_sel = row;
|
|
380
|
-
this.update();
|
|
381
|
-
|
|
382
|
-
this.emit('click', EvClick({ row, text: this.getCell(row, 0).text }));
|
|
383
|
-
})
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
setRowData(row: number, data: any) {
|
|
387
|
-
this.m_data.set(row, data);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
getRowData(row: number): any {
|
|
391
|
-
return this.m_data.get(row);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
setCell(row: number, col: number, text: string, cls?: string) {
|
|
395
|
-
this.m_cells.set(_cid(row, col), { text, cls });
|
|
396
|
-
|
|
397
|
-
if (this.m_rows < (row + 1)) {
|
|
398
|
-
this.m_rows = (row + 1);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
if (this.m_cols < (col + 1)) {
|
|
402
|
-
this.m_cols = (col + 1);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
getCell(row, col): CellData {
|
|
407
|
-
|
|
408
|
-
let cd = this.m_cells.get(_cid(row, col));
|
|
409
|
-
if (cd == null) {
|
|
410
|
-
return this.m_defcell;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
return cd;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/** @ignore */
|
|
417
|
-
render() {
|
|
418
|
-
this.setProp('tag', 'table');
|
|
419
|
-
|
|
420
|
-
if (this.m_minw) {
|
|
421
|
-
this.setStyleValue('minWidth', this.m_minw);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
let rows = [];
|
|
425
|
-
|
|
426
|
-
for (let r = 0; r < this.m_rows; r++) {
|
|
427
|
-
|
|
428
|
-
let cols = [];
|
|
429
|
-
let data = { row: r };
|
|
430
|
-
|
|
431
|
-
for (let c = 0; c < this.m_cols; c++) {
|
|
432
|
-
|
|
433
|
-
let cell = this.getCell(r, c);
|
|
434
|
-
|
|
435
|
-
let col = new Component({
|
|
436
|
-
tag: 'td',
|
|
437
|
-
content: cell.text,
|
|
438
|
-
cls: cell.cls,
|
|
439
|
-
data
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
cols.push(col);
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
let cls = undefined;
|
|
446
|
-
if (r === this.m_sel) {
|
|
447
|
-
cls = '@selected';
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
let row = new Component({
|
|
451
|
-
tag: 'tr',
|
|
452
|
-
cls,
|
|
453
|
-
content: cols,
|
|
454
|
-
data
|
|
455
|
-
});
|
|
456
|
-
|
|
457
|
-
rows.push(row);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
this.setContent(rows);
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
/**
|
|
464
|
-
* display the popup at a specific position
|
|
465
|
-
* @param x
|
|
466
|
-
* @param y
|
|
467
|
-
*/
|
|
468
|
-
|
|
469
|
-
public displayAt(x: number, y: number, align: string = 'top left') {
|
|
470
|
-
|
|
471
|
-
this.show();
|
|
472
|
-
|
|
473
|
-
let halign = 'l',
|
|
474
|
-
valign = 't';
|
|
475
|
-
|
|
476
|
-
if (align.indexOf('right') >= 0) {
|
|
477
|
-
halign = 'r';
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
if (align.indexOf('bottom') >= 0) {
|
|
481
|
-
valign = 'b';
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// @TODO: this is a minimal overflow problem solution
|
|
485
|
-
let rc = x4document.body.getBoundingClientRect(),
|
|
486
|
-
rm = this.getBoundingRect();
|
|
487
|
-
|
|
488
|
-
if (halign == 'r') {
|
|
489
|
-
x -= rm.width;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
if (valign == 'b') {
|
|
493
|
-
y -= rm.height;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
if (x < 4) {
|
|
497
|
-
x = 4;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
if ((x + rm.width) > rc.right - 4) {
|
|
501
|
-
x = rc.right - 4 - rm.width;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
if (y < 4) {
|
|
505
|
-
y = 4;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
if ((y + rm.height) > rc.bottom - 4) {
|
|
509
|
-
y = rc.bottom - 4 - rm.height;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
this.setStyle({ left: x, top: y });
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
selNext(next: boolean): number {
|
|
516
|
-
|
|
517
|
-
this.m_sel += next ? 1 : -1;
|
|
518
|
-
if (this.m_sel >= this.m_rows) {
|
|
519
|
-
this.m_sel = 0;
|
|
520
|
-
}
|
|
521
|
-
else if (this.m_sel < 0) {
|
|
522
|
-
this.m_sel = this.m_rows - 1;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
this.update();
|
|
526
|
-
return this.m_sel;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
get selection() {
|
|
530
|
-
return this.m_sel;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
function _cid(row: number, col: number) {
|
|
536
|
-
return row * 1000 + col;
|
|
537
|
-
}
|