x4js 1.5.29 → 1.5.32
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/cjs/index.js +9 -9
- package/lib/cjs/index.js.map +4 -4
- package/lib/esm/index.mjs +260 -214
- package/lib/esm/index.mjs.map +3 -3
- package/lib/src/autocomplete.ts +15 -4
- package/lib/src/calendar.ts +1 -1
- package/lib/src/combobox.ts +12 -22
- package/lib/src/component.ts +41 -15
- package/lib/src/datastore.ts +49 -61
- package/lib/src/input.ts +57 -9
- package/lib/src/menu.ts +1 -1
- package/lib/src/router.ts +7 -3
- package/lib/src/sidebarview.ts +6 -1
- package/lib/src/svgcomponent.ts +16 -6
- package/lib/src/textedit.ts +15 -26
- package/lib/src/version.ts +1 -1
- package/lib/src/x4.less +3 -5
- package/lib/styles/x4.css +2 -2
- package/lib/styles/x4.less +3 -5
- package/lib/types/autocomplete.d.ts +4 -1
- package/lib/types/combobox.d.ts +0 -1
- package/lib/types/component.d.ts +3 -2
- package/lib/types/datastore.d.ts +29 -29
- package/lib/types/input.d.ts +6 -0
- package/lib/types/router.d.ts +1 -1
- package/lib/types/sidebarview.d.ts +2 -0
- package/lib/types/svgcomponent.d.ts +5 -4
- package/lib/types/textedit.d.ts +5 -2
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -1
package/lib/src/autocomplete.ts
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
28
|
**/
|
|
29
29
|
|
|
30
|
-
import { ListViewItem, PopupListView } from "./listview";
|
|
30
|
+
import { RenderListItem, ListViewItem, PopupListView } from "./listview";
|
|
31
31
|
import { TextEdit, TextEditProps } from './textedit';
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -40,6 +40,7 @@ interface AutoCompleteProps extends TextEditProps {
|
|
|
40
40
|
|
|
41
41
|
// a way to change the real value vs displayed value in the popup list
|
|
42
42
|
selectValue?: ( text: string ) => string;
|
|
43
|
+
renderItem?: RenderListItem
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
/**
|
|
@@ -113,8 +114,13 @@ export class AutoComplete extends TextEdit<AutoCompleteProps> {
|
|
|
113
114
|
super.componentDisposed( );
|
|
114
115
|
}
|
|
115
116
|
|
|
116
|
-
showPopup( ) {
|
|
117
|
-
|
|
117
|
+
showPopup( show = true ) {
|
|
118
|
+
if( show ) {
|
|
119
|
+
this._onChange( );
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
this._hidePopup( );
|
|
123
|
+
}
|
|
118
124
|
}
|
|
119
125
|
|
|
120
126
|
/**
|
|
@@ -156,7 +162,8 @@ export class AutoComplete extends TextEdit<AutoCompleteProps> {
|
|
|
156
162
|
style: {
|
|
157
163
|
fontFamily,
|
|
158
164
|
fontSize
|
|
159
|
-
}
|
|
165
|
+
},
|
|
166
|
+
renderItem: props.renderItem,
|
|
160
167
|
});
|
|
161
168
|
}
|
|
162
169
|
|
|
@@ -218,4 +225,8 @@ export class AutoComplete extends TextEdit<AutoCompleteProps> {
|
|
|
218
225
|
|
|
219
226
|
this.m_needval = true;
|
|
220
227
|
}
|
|
228
|
+
|
|
229
|
+
isPopupVisible( ) {
|
|
230
|
+
return this.m_popvis;
|
|
231
|
+
}
|
|
221
232
|
}
|
package/lib/src/calendar.ts
CHANGED
|
@@ -241,7 +241,7 @@ export class Calendar extends VLayout<CalendarProps, CalendarEventMap>
|
|
|
241
241
|
let min = this.m_props.minDate?.getFullYear() ?? 1900;
|
|
242
242
|
let max = this.m_props.maxDate?.getFullYear() ?? 2037;
|
|
243
243
|
|
|
244
|
-
for (let m =
|
|
244
|
+
for (let m = max; m >= min; m--) {
|
|
245
245
|
items.push(new MenuItem({
|
|
246
246
|
text: '' + m,
|
|
247
247
|
click: () => { this.m_date.setFullYear(m); this.update(); }
|
package/lib/src/combobox.ts
CHANGED
|
@@ -86,20 +86,27 @@ export interface ComboBoxProps extends CProps<ComboBoxEventMap> {
|
|
|
86
86
|
editable?: boolean;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
abstract class InputLike extends Component {
|
|
90
|
+
abstract setValue( text: string );
|
|
91
|
+
abstract getValue( ): string;
|
|
92
|
+
abstract showError( text: string );
|
|
93
|
+
abstract clearError( );
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
89
97
|
/**
|
|
90
98
|
* @review use textedit
|
|
91
99
|
*/
|
|
92
100
|
|
|
93
101
|
export class ComboBox extends HLayout<ComboBoxProps,ComboBoxEventMap> {
|
|
94
102
|
|
|
95
|
-
private m_ui_input: Input |
|
|
103
|
+
private m_ui_input: Input | InputLike;
|
|
96
104
|
private m_ui_button: Button;
|
|
97
105
|
private m_popup: PopupListView;
|
|
98
106
|
private m_lockpop: boolean;
|
|
99
107
|
private m_lockchg: boolean;
|
|
100
108
|
private m_popvis: boolean;
|
|
101
109
|
private m_selection: ListViewItem;
|
|
102
|
-
private m_error_tip: Tooltip;
|
|
103
110
|
|
|
104
111
|
constructor(props: ComboBoxProps) {
|
|
105
112
|
super(props);
|
|
@@ -193,7 +200,7 @@ export class ComboBox extends HLayout<ComboBoxProps,ComboBoxEventMap> {
|
|
|
193
200
|
flex: 1,
|
|
194
201
|
cls: '@fake-input @hlayout',
|
|
195
202
|
tabIndex: 1
|
|
196
|
-
} );
|
|
203
|
+
} ) as any;
|
|
197
204
|
}
|
|
198
205
|
|
|
199
206
|
let width = undefined,
|
|
@@ -245,10 +252,6 @@ export class ComboBox extends HLayout<ComboBoxProps,ComboBoxEventMap> {
|
|
|
245
252
|
}
|
|
246
253
|
|
|
247
254
|
componentDisposed( ) {
|
|
248
|
-
if (this.m_error_tip) {
|
|
249
|
-
this.m_error_tip.dispose();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
255
|
if( this.m_popup ) {
|
|
253
256
|
this.m_popup.close( );
|
|
254
257
|
}
|
|
@@ -340,24 +343,11 @@ export class ComboBox extends HLayout<ComboBoxProps,ComboBoxEventMap> {
|
|
|
340
343
|
}
|
|
341
344
|
|
|
342
345
|
public showError(text: string) {
|
|
343
|
-
|
|
344
|
-
if (!this.m_error_tip) {
|
|
345
|
-
this.m_error_tip = new Tooltip({ cls: 'error' });
|
|
346
|
-
x4document.body.appendChild(this.m_error_tip._build());
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
let rc = this.m_ui_input.getBoundingRect();
|
|
350
|
-
this.m_error_tip.text = text;
|
|
351
|
-
this.m_error_tip.displayAt(rc.right, rc.top-8, 'top right');
|
|
352
|
-
|
|
353
|
-
this.addClass('@error');
|
|
346
|
+
this.m_ui_input.showError( text );
|
|
354
347
|
}
|
|
355
348
|
|
|
356
349
|
public clearError() {
|
|
357
|
-
|
|
358
|
-
this.m_error_tip.hide();
|
|
359
|
-
this.removeClass('@error');
|
|
360
|
-
}
|
|
350
|
+
this.m_ui_input.clearError( );
|
|
361
351
|
}
|
|
362
352
|
|
|
363
353
|
/** @ignore
|
package/lib/src/component.ts
CHANGED
|
@@ -170,8 +170,13 @@ export interface CProps<T extends CEventMap = CEventMap> extends BaseComponentPr
|
|
|
170
170
|
enabled?: boolean; // add @disabled to the element if false
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
interface DomListener {
|
|
174
|
+
listener: EventListener,
|
|
175
|
+
passive?: boolean
|
|
176
|
+
}
|
|
177
|
+
|
|
173
178
|
interface CInternalProps {
|
|
174
|
-
dom_events:
|
|
179
|
+
dom_events: Record<string,DomListener[]>;
|
|
175
180
|
classes: IMap<boolean>;
|
|
176
181
|
uid: number;
|
|
177
182
|
created: boolean;
|
|
@@ -205,6 +210,7 @@ export class Component<P extends CProps<CEventMap> = CProps<CEventMap>, E extend
|
|
|
205
210
|
dom_events: {},
|
|
206
211
|
uid: Component.__comp_guid++,
|
|
207
212
|
inrender: false,
|
|
213
|
+
created: false,
|
|
208
214
|
};
|
|
209
215
|
|
|
210
216
|
// prepare iprops
|
|
@@ -279,6 +285,20 @@ export class Component<P extends CProps<CEventMap> = CProps<CEventMap>, E extend
|
|
|
279
285
|
}
|
|
280
286
|
}
|
|
281
287
|
|
|
288
|
+
removeChild( item: Component ) {
|
|
289
|
+
if( this.m_props.content ) {
|
|
290
|
+
if (!isArray(this.m_props.content)) {
|
|
291
|
+
this.m_props.content = [this.m_props.content];
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
this.m_props.content = this.m_props.content.filter( x => x!==item );
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if( this.dom && item.dom ) {
|
|
298
|
+
this.dom.removeChild( item.dom );
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
282
302
|
/**
|
|
283
303
|
*
|
|
284
304
|
*/
|
|
@@ -524,11 +544,12 @@ export class Component<P extends CProps<CEventMap> = CProps<CEventMap>, E extend
|
|
|
524
544
|
return this.m_dom.getAttribute(name);
|
|
525
545
|
}
|
|
526
546
|
else {
|
|
527
|
-
|
|
528
|
-
|
|
547
|
+
//todo move to attrs
|
|
548
|
+
if( name=='id' ) {
|
|
549
|
+
return this.m_props.id;
|
|
529
550
|
}
|
|
530
551
|
|
|
531
|
-
return this.m_props.attrs[name];
|
|
552
|
+
return this.m_props.attrs ? this.m_props.attrs[name] : undefined;
|
|
532
553
|
}
|
|
533
554
|
}
|
|
534
555
|
|
|
@@ -830,7 +851,7 @@ export class Component<P extends CProps<CEventMap> = CProps<CEventMap>, E extend
|
|
|
830
851
|
for (let e in evt) {
|
|
831
852
|
let handlers = evt[e];
|
|
832
853
|
for (let h of handlers) {
|
|
833
|
-
this.
|
|
854
|
+
this._createEvent(e, h.listener, h.passive );
|
|
834
855
|
}
|
|
835
856
|
}
|
|
836
857
|
}
|
|
@@ -1095,12 +1116,12 @@ export class Component<P extends CProps<CEventMap> = CProps<CEventMap>, E extend
|
|
|
1095
1116
|
* this.setDomEvent( 'dblclick', this._handleDblClick, this );
|
|
1096
1117
|
*/
|
|
1097
1118
|
|
|
1098
|
-
public setDomEvent<K extends keyof X4ElementEventMap>(type: K, listener: (this: HTMLDivElement, ev: X4ElementEventMap[K]) => void) {
|
|
1119
|
+
public setDomEvent<K extends keyof X4ElementEventMap>(type: K, listener: (this: HTMLDivElement, ev: X4ElementEventMap[K]) => void, passive?: boolean ) {
|
|
1099
1120
|
let _listener = listener as EventListener;
|
|
1100
|
-
this._setDomEvent(type as string, _listener);
|
|
1121
|
+
this._setDomEvent(type as string, _listener, passive);
|
|
1101
1122
|
}
|
|
1102
1123
|
|
|
1103
|
-
private _setDomEvent(type: string, listener: EventListener) {
|
|
1124
|
+
private _setDomEvent(type: string, listener: EventListener, passive?: boolean) {
|
|
1104
1125
|
|
|
1105
1126
|
// add event to the vdom
|
|
1106
1127
|
if (!this.m_iprops.dom_events) {
|
|
@@ -1109,15 +1130,15 @@ export class Component<P extends CProps<CEventMap> = CProps<CEventMap>, E extend
|
|
|
1109
1130
|
|
|
1110
1131
|
let listeners = this.m_iprops.dom_events[type];
|
|
1111
1132
|
if (!listeners) {
|
|
1112
|
-
listeners = this.m_iprops.dom_events[type] = [listener];
|
|
1133
|
+
listeners = this.m_iprops.dom_events[type] = [{listener,passive}];
|
|
1113
1134
|
}
|
|
1114
1135
|
else {
|
|
1115
|
-
listeners.push(listener);
|
|
1136
|
+
listeners.push({listener,passive});
|
|
1116
1137
|
}
|
|
1117
1138
|
|
|
1118
1139
|
if (this.m_dom) {
|
|
1119
1140
|
//this.m_dom.addEventListener(type, listener);
|
|
1120
|
-
this.
|
|
1141
|
+
this._createEvent(type, listener,passive);
|
|
1121
1142
|
}
|
|
1122
1143
|
}
|
|
1123
1144
|
|
|
@@ -1147,7 +1168,7 @@ export class Component<P extends CProps<CEventMap> = CProps<CEventMap>, E extend
|
|
|
1147
1168
|
* @param handler
|
|
1148
1169
|
*/
|
|
1149
1170
|
|
|
1150
|
-
|
|
1171
|
+
private _createEvent(name: string, handler: Function, passive?: boolean) {
|
|
1151
1172
|
|
|
1152
1173
|
let _dom = this.m_dom;
|
|
1153
1174
|
let store = _dom[_x4_el_store];
|
|
@@ -1171,11 +1192,16 @@ export class Component<P extends CProps<CEventMap> = CProps<CEventMap>, E extend
|
|
|
1171
1192
|
else if (!Component.__privateEvents[name]) {
|
|
1172
1193
|
Component.__privateEvents[name] = true; // todo count it
|
|
1173
1194
|
|
|
1174
|
-
if
|
|
1175
|
-
|
|
1195
|
+
if( passive===undefined ) {
|
|
1196
|
+
if ( passiveEvents[name] ) {
|
|
1197
|
+
x4document.addEventListener(name as any, Component._dispatchEvent, { passive: false, capture: true });
|
|
1198
|
+
}
|
|
1199
|
+
else {
|
|
1200
|
+
x4document.addEventListener(name as any, Component._dispatchEvent, true);
|
|
1201
|
+
}
|
|
1176
1202
|
}
|
|
1177
1203
|
else {
|
|
1178
|
-
x4document.addEventListener(name as any, Component._dispatchEvent, true);
|
|
1204
|
+
x4document.addEventListener(name as any, Component._dispatchEvent, { passive, capture: passive ? true : false } );
|
|
1179
1205
|
}
|
|
1180
1206
|
}
|
|
1181
1207
|
|
package/lib/src/datastore.ts
CHANGED
|
@@ -239,7 +239,7 @@ interface RecordConstructor {
|
|
|
239
239
|
*/
|
|
240
240
|
|
|
241
241
|
export function array( ctor: RecordConstructor, props?: MetaData ) {
|
|
242
|
-
return data.field( { ...props, type: 'array', model: new ctor() } )
|
|
242
|
+
return data.field( { ...props, type: 'array', model: ctor ? new ctor() : null } )
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
}
|
|
@@ -572,41 +572,28 @@ export class DataProxy extends BaseComponent<DataProxyProps,DataEventMap> {
|
|
|
572
572
|
super( props );
|
|
573
573
|
}
|
|
574
574
|
|
|
575
|
-
load( url?: string ) {
|
|
575
|
+
async load( url?: string ) {
|
|
576
576
|
if( url ) {
|
|
577
577
|
this.m_props.url = url;
|
|
578
578
|
}
|
|
579
|
+
else {
|
|
580
|
+
url = this.m_props.url;
|
|
581
|
+
}
|
|
579
582
|
|
|
580
|
-
this.
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
private _refresh( delay: number = 0 ) {
|
|
584
|
-
|
|
585
|
-
const load = async ( ) => {
|
|
586
|
-
|
|
587
|
-
let url = this.m_props.url;
|
|
588
|
-
if( this.m_props.params ) {
|
|
589
|
-
url += '?' + this.m_props.params.join( '&' );
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
const r = await fetch( url );
|
|
593
|
-
if( r.ok ) {
|
|
594
|
-
const raw = await r.json( );
|
|
595
|
-
|
|
596
|
-
let json = raw;
|
|
597
|
-
if( this.m_props.solver ) {
|
|
598
|
-
json = this.m_props.solver( json );
|
|
599
|
-
}
|
|
583
|
+
if( this.m_props.params ) {
|
|
584
|
+
url += '?' + this.m_props.params.join( '&' );
|
|
585
|
+
}
|
|
600
586
|
|
|
601
|
-
|
|
587
|
+
const r = await fetch( url );
|
|
588
|
+
if( r.ok ) {
|
|
589
|
+
const raw = await r.json( );
|
|
590
|
+
|
|
591
|
+
let json = raw;
|
|
592
|
+
if( this.m_props.solver ) {
|
|
593
|
+
json = this.m_props.solver( json );
|
|
602
594
|
}
|
|
603
|
-
}
|
|
604
595
|
|
|
605
|
-
|
|
606
|
-
setTimeout( load, delay );
|
|
607
|
-
}
|
|
608
|
-
else {
|
|
609
|
-
load( );
|
|
596
|
+
this.emit( 'change', EvChange(json,raw) );
|
|
610
597
|
}
|
|
611
598
|
}
|
|
612
599
|
}
|
|
@@ -616,10 +603,11 @@ export class DataProxy extends BaseComponent<DataProxyProps,DataEventMap> {
|
|
|
616
603
|
*
|
|
617
604
|
*/
|
|
618
605
|
|
|
619
|
-
interface DataStoreProps extends BaseComponentProps<DataStoreEventMap> {
|
|
620
|
-
model:
|
|
621
|
-
data?:
|
|
606
|
+
interface DataStoreProps<T extends Record> extends BaseComponentProps<DataStoreEventMap> {
|
|
607
|
+
model: T;
|
|
608
|
+
data?: T[];
|
|
622
609
|
url?: string;
|
|
610
|
+
autoload?: false;
|
|
623
611
|
}
|
|
624
612
|
|
|
625
613
|
|
|
@@ -633,16 +621,16 @@ interface DataStoreEventMap extends EventMap {
|
|
|
633
621
|
*
|
|
634
622
|
*/
|
|
635
623
|
|
|
636
|
-
export class DataStore extends EventSource<DataStoreEventMap> {
|
|
624
|
+
export class DataStore<T extends Record = Record> extends EventSource<DataStoreEventMap> {
|
|
637
625
|
|
|
638
|
-
protected m_model:
|
|
626
|
+
protected m_model: T;
|
|
639
627
|
protected m_fields: FieldInfo[];
|
|
640
|
-
protected m_records:
|
|
628
|
+
protected m_records: T[];
|
|
641
629
|
|
|
642
630
|
protected m_proxy: DataProxy;
|
|
643
631
|
protected m_rec_index: DataIndex;
|
|
644
632
|
|
|
645
|
-
constructor(props: DataStoreProps) {
|
|
633
|
+
constructor(props: DataStoreProps<T> ) {
|
|
646
634
|
super( );
|
|
647
635
|
|
|
648
636
|
this.m_fields = undefined;
|
|
@@ -661,7 +649,9 @@ export class DataStore extends EventSource<DataStoreEventMap> {
|
|
|
661
649
|
events: { change: (ev) => { this.setData( ev.value ); } }
|
|
662
650
|
});
|
|
663
651
|
|
|
664
|
-
|
|
652
|
+
if( props.autoload!=false ) {
|
|
653
|
+
this.m_proxy.load( );
|
|
654
|
+
}
|
|
665
655
|
}
|
|
666
656
|
}
|
|
667
657
|
|
|
@@ -670,12 +660,12 @@ export class DataStore extends EventSource<DataStoreEventMap> {
|
|
|
670
660
|
* @param records
|
|
671
661
|
*/
|
|
672
662
|
|
|
673
|
-
load( url?: string ) {
|
|
674
|
-
this.m_proxy.load( url );
|
|
663
|
+
async load( url?: string ) {
|
|
664
|
+
return this.m_proxy.load( url );
|
|
675
665
|
}
|
|
676
666
|
|
|
677
|
-
reload( ) {
|
|
678
|
-
this.m_proxy.load( );
|
|
667
|
+
async reload( ) {
|
|
668
|
+
return this.m_proxy.load( );
|
|
679
669
|
}
|
|
680
670
|
|
|
681
671
|
/**
|
|
@@ -685,7 +675,7 @@ export class DataStore extends EventSource<DataStoreEventMap> {
|
|
|
685
675
|
|
|
686
676
|
public setData( records: any[] ) {
|
|
687
677
|
|
|
688
|
-
let realRecords:
|
|
678
|
+
let realRecords: T[] = [];
|
|
689
679
|
|
|
690
680
|
records.forEach( (rec) => {
|
|
691
681
|
realRecords.push( this.m_model.clone(rec) );
|
|
@@ -699,7 +689,7 @@ export class DataStore extends EventSource<DataStoreEventMap> {
|
|
|
699
689
|
* @param records - must be of the same type as model
|
|
700
690
|
*/
|
|
701
691
|
|
|
702
|
-
public setRawData(records:
|
|
692
|
+
public setRawData(records: T[]) {
|
|
703
693
|
|
|
704
694
|
this.m_records = records;
|
|
705
695
|
this._rebuildIndex( );
|
|
@@ -717,7 +707,7 @@ export class DataStore extends EventSource<DataStoreEventMap> {
|
|
|
717
707
|
*
|
|
718
708
|
*/
|
|
719
709
|
|
|
720
|
-
public update( rec:
|
|
710
|
+
public update( rec: T ) {
|
|
721
711
|
let id = rec.getID();
|
|
722
712
|
let index = this.indexOfId(id);
|
|
723
713
|
if (index < 0) {
|
|
@@ -734,7 +724,7 @@ export class DataStore extends EventSource<DataStoreEventMap> {
|
|
|
734
724
|
* @param data
|
|
735
725
|
*/
|
|
736
726
|
|
|
737
|
-
public append( rec:
|
|
727
|
+
public append( rec: T | any ) {
|
|
738
728
|
|
|
739
729
|
if( !(rec instanceof Record) ) {
|
|
740
730
|
let nrec = this.m_model.clone( );
|
|
@@ -835,7 +825,7 @@ export class DataStore extends EventSource<DataStoreEventMap> {
|
|
|
835
825
|
* @returns record or null
|
|
836
826
|
*/
|
|
837
827
|
|
|
838
|
-
public getById(id: any):
|
|
828
|
+
public getById(id: any): T {
|
|
839
829
|
let idx = this.indexOfId( id );
|
|
840
830
|
if( idx<0 ) {
|
|
841
831
|
return null;
|
|
@@ -850,16 +840,16 @@ export class DataStore extends EventSource<DataStoreEventMap> {
|
|
|
850
840
|
* @returns record or null
|
|
851
841
|
*/
|
|
852
842
|
|
|
853
|
-
public getByIndex( index: number ):
|
|
843
|
+
public getByIndex( index: number ): T {
|
|
854
844
|
let idx = this.m_rec_index[index];
|
|
855
845
|
return this._getRecord( idx );
|
|
856
846
|
}
|
|
857
847
|
|
|
858
|
-
private _getRecord( index: number ) :
|
|
848
|
+
private _getRecord( index: number ) : T {
|
|
859
849
|
return this.m_records[index] ?? null;
|
|
860
850
|
}
|
|
861
851
|
|
|
862
|
-
public moveTo( other: DataStore ) {
|
|
852
|
+
public moveTo( other: DataStore<T> ) {
|
|
863
853
|
other.setRawData( this.m_records );
|
|
864
854
|
}
|
|
865
855
|
|
|
@@ -868,7 +858,7 @@ export class DataStore extends EventSource<DataStoreEventMap> {
|
|
|
868
858
|
* @param opts
|
|
869
859
|
*/
|
|
870
860
|
|
|
871
|
-
createView( opts?: DataViewProps ) : DataView {
|
|
861
|
+
createView( opts?: DataViewProps<T> ) : DataView<T> {
|
|
872
862
|
let eopts = { ...opts, store: this };
|
|
873
863
|
return new DataView( eopts );
|
|
874
864
|
}
|
|
@@ -1074,7 +1064,7 @@ export class DataStore extends EventSource<DataStoreEventMap> {
|
|
|
1074
1064
|
*
|
|
1075
1065
|
*/
|
|
1076
1066
|
|
|
1077
|
-
forEach( cb: ( rec:
|
|
1067
|
+
forEach( cb: ( rec:T, index: number ) => any ) {
|
|
1078
1068
|
|
|
1079
1069
|
if( this.m_rec_index ) {
|
|
1080
1070
|
this.m_rec_index.some( (ri,index) => {
|
|
@@ -1118,8 +1108,8 @@ interface DataViewEventMap extends BaseComponentEventMap {
|
|
|
1118
1108
|
view_change: EvViewChange;
|
|
1119
1109
|
}
|
|
1120
1110
|
|
|
1121
|
-
interface DataViewProps extends BaseComponentProps<DataViewEventMap> {
|
|
1122
|
-
store?: DataStore
|
|
1111
|
+
interface DataViewProps<T extends Record> extends BaseComponentProps<DataViewEventMap> {
|
|
1112
|
+
store?: DataStore<T>;
|
|
1123
1113
|
filter?: FilterInfo;
|
|
1124
1114
|
order?: string | SortProp[] | SortProp;
|
|
1125
1115
|
}
|
|
@@ -1147,15 +1137,15 @@ export interface SortProp {
|
|
|
1147
1137
|
* You can have multiple views for a single DataStore
|
|
1148
1138
|
*/
|
|
1149
1139
|
|
|
1150
|
-
export class DataView extends BaseComponent<DataViewProps
|
|
1140
|
+
export class DataView<T extends Record = Record> extends BaseComponent<DataViewProps<T>,DataViewEventMap>
|
|
1151
1141
|
{
|
|
1152
1142
|
protected m_index: DataIndex;
|
|
1153
|
-
protected m_store: DataStore
|
|
1143
|
+
protected m_store: DataStore<T>;
|
|
1154
1144
|
|
|
1155
1145
|
protected m_sort: SortProp[];
|
|
1156
1146
|
protected m_filter: FilterInfo;
|
|
1157
1147
|
|
|
1158
|
-
constructor( props: DataViewProps ) {
|
|
1148
|
+
constructor( props: DataViewProps<T> ) {
|
|
1159
1149
|
super( props );
|
|
1160
1150
|
|
|
1161
1151
|
this.m_store = props.store;
|
|
@@ -1269,7 +1259,7 @@ export class DataView extends BaseComponent<DataViewProps,DataViewEventMap>
|
|
|
1269
1259
|
* @param index
|
|
1270
1260
|
*/
|
|
1271
1261
|
|
|
1272
|
-
public getByIndex(index: number):
|
|
1262
|
+
public getByIndex(index: number): T {
|
|
1273
1263
|
|
|
1274
1264
|
if (index >= 0 && index < this.m_index.length) {
|
|
1275
1265
|
let rid = this.m_index[index];
|
|
@@ -1284,7 +1274,7 @@ export class DataView extends BaseComponent<DataViewProps,DataViewEventMap>
|
|
|
1284
1274
|
* @param id
|
|
1285
1275
|
*/
|
|
1286
1276
|
|
|
1287
|
-
public getById( id: any):
|
|
1277
|
+
public getById( id: any): T {
|
|
1288
1278
|
return this.m_store.getById( id );
|
|
1289
1279
|
}
|
|
1290
1280
|
|
|
@@ -1296,9 +1286,7 @@ export class DataView extends BaseComponent<DataViewProps,DataViewEventMap>
|
|
|
1296
1286
|
*
|
|
1297
1287
|
*/
|
|
1298
1288
|
|
|
1299
|
-
forEach( cb: ( rec:
|
|
1300
|
-
|
|
1301
|
-
debugger;
|
|
1289
|
+
forEach( cb: ( rec:T, index: number ) => any ) {
|
|
1302
1290
|
this.m_index.some( ( index ) => {
|
|
1303
1291
|
let rec = this.m_store.getByIndex( index );
|
|
1304
1292
|
if( rec ) {
|
package/lib/src/input.ts
CHANGED
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
28
|
**/
|
|
29
29
|
|
|
30
|
+
import { x4document } from './x4dom'
|
|
31
|
+
import { Tooltip } from './tooltips';
|
|
30
32
|
import { Component, CProps, CEventMap, EvFocus } from './component'
|
|
31
33
|
//import { EvChange } from './x4_events';
|
|
32
34
|
|
|
@@ -67,10 +69,20 @@ export interface InputProps<P extends InputEventMap = InputEventMap> extends CPr
|
|
|
67
69
|
|
|
68
70
|
export class Input extends Component<InputProps,InputEventMap>
|
|
69
71
|
{
|
|
72
|
+
private m_error_tip: Tooltip;
|
|
73
|
+
|
|
70
74
|
constructor( props: InputProps ) {
|
|
71
75
|
super( props );
|
|
72
76
|
}
|
|
73
77
|
|
|
78
|
+
componentDisposed() {
|
|
79
|
+
if (this.m_error_tip) {
|
|
80
|
+
this.m_error_tip.dispose();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
super.componentDisposed();
|
|
84
|
+
}
|
|
85
|
+
|
|
74
86
|
/** @ignore */
|
|
75
87
|
render( props: InputProps ) {
|
|
76
88
|
|
|
@@ -105,6 +117,28 @@ export class Input extends Component<InputProps,InputEventMap>
|
|
|
105
117
|
}
|
|
106
118
|
}
|
|
107
119
|
|
|
120
|
+
public showError(text: string) {
|
|
121
|
+
|
|
122
|
+
if (!this.m_error_tip) {
|
|
123
|
+
this.m_error_tip = new Tooltip({ cls: 'error' });
|
|
124
|
+
x4document.body.appendChild(this.m_error_tip._build());
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let rc = this.getBoundingRect();
|
|
128
|
+
|
|
129
|
+
this.m_error_tip.text = text;
|
|
130
|
+
this.m_error_tip.displayAt(rc.right, rc.top-8, 'top right');
|
|
131
|
+
this.addClass('@error');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public clearError() {
|
|
135
|
+
|
|
136
|
+
if (this.m_error_tip) {
|
|
137
|
+
this.m_error_tip.hide();
|
|
138
|
+
this.removeClass('@error');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
108
142
|
public getType( ) {
|
|
109
143
|
return this.m_props.type;
|
|
110
144
|
}
|
|
@@ -114,22 +148,27 @@ export class Input extends Component<InputProps,InputEventMap>
|
|
|
114
148
|
*/
|
|
115
149
|
|
|
116
150
|
public get value( ) : string {
|
|
117
|
-
|
|
151
|
+
return this.getValue( );
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
public getValue( ): string {
|
|
155
|
+
const dom = this.dom as HTMLInputElement;
|
|
156
|
+
|
|
118
157
|
if( this.dom ) {
|
|
119
|
-
this.m_props.value =
|
|
158
|
+
this.m_props.value = dom.value;
|
|
120
159
|
}
|
|
121
160
|
|
|
122
161
|
if( this.m_props.uppercase ) {
|
|
123
162
|
let upper = this.m_props.value.toUpperCase( ); // todo: locale ?
|
|
124
|
-
if(
|
|
125
|
-
|
|
163
|
+
if( dom && upper!=this.m_props.value ) {
|
|
164
|
+
dom.value = upper; // update the input
|
|
126
165
|
}
|
|
127
166
|
|
|
128
167
|
this.m_props.value = upper;
|
|
129
168
|
}
|
|
130
169
|
|
|
131
170
|
return this.m_props.value;
|
|
132
|
-
|
|
171
|
+
}
|
|
133
172
|
|
|
134
173
|
/**
|
|
135
174
|
* Change the editor value
|
|
@@ -137,7 +176,10 @@ export class Input extends Component<InputProps,InputEventMap>
|
|
|
137
176
|
*/
|
|
138
177
|
|
|
139
178
|
public set value( value: string ) {
|
|
140
|
-
|
|
179
|
+
this.setValue( value );
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public setValue( value: string ) {
|
|
141
183
|
this.m_props.value = value;
|
|
142
184
|
|
|
143
185
|
if( this.dom ) {
|
|
@@ -154,8 +196,8 @@ export class Input extends Component<InputProps,InputEventMap>
|
|
|
154
196
|
let type = this.getAttribute('type');
|
|
155
197
|
if( type ) { type = type.toLowerCase( ); }
|
|
156
198
|
|
|
157
|
-
let value
|
|
158
|
-
|
|
199
|
+
let value;
|
|
200
|
+
const dom = this.dom as HTMLInputElement;
|
|
159
201
|
|
|
160
202
|
if( type === "file") {
|
|
161
203
|
value = [];
|
|
@@ -181,6 +223,12 @@ export class Input extends Component<InputProps,InputEventMap>
|
|
|
181
223
|
else if( type === 'date' ) {
|
|
182
224
|
debugger;
|
|
183
225
|
}
|
|
226
|
+
else if( type=='number' ) {
|
|
227
|
+
value = this.value;
|
|
228
|
+
if (value.indexOf(",") >= 0) {
|
|
229
|
+
value = value.replace(",", ".");
|
|
230
|
+
}
|
|
231
|
+
}
|
|
184
232
|
else {
|
|
185
233
|
value = this.value;
|
|
186
234
|
}
|
|
@@ -190,7 +238,7 @@ export class Input extends Component<InputProps,InputEventMap>
|
|
|
190
238
|
}
|
|
191
239
|
|
|
192
240
|
public setStoreValue( v: any ) {
|
|
193
|
-
|
|
241
|
+
this.clearError( );
|
|
194
242
|
if( this.m_props.value_hook ) {
|
|
195
243
|
return this.m_props.value_hook.set( v );
|
|
196
244
|
}
|
package/lib/src/menu.ts
CHANGED
|
@@ -329,7 +329,7 @@ export class MenuItem extends Component<MenuItemProps, MenuItemEventMap> {
|
|
|
329
329
|
// this.setAttribute( 'tabindex', '0' );
|
|
330
330
|
|
|
331
331
|
this.setContent([
|
|
332
|
-
icon
|
|
332
|
+
icon ? null : new Icon({ icon }),
|
|
333
333
|
new Label({ flex: 1, text }),
|
|
334
334
|
popIco
|
|
335
335
|
]);
|