x4js 1.4.18 → 1.4.22
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 +4 -3
- package/lib/application.d.ts +1 -1
- package/lib/application.js +4 -3
- package/lib/base_component.d.ts +1 -1
- package/lib/base_component.js +3 -3
- package/lib/button.d.ts +1 -1
- package/lib/button.js +3 -3
- package/lib/calendar.d.ts +1 -1
- package/lib/calendar.js +5 -4
- package/lib/canvas.d.ts +1 -1
- package/lib/canvas.js +2 -2
- package/lib/cardview.d.ts +1 -1
- package/lib/cardview.js +2 -2
- package/lib/checkbox.d.ts +1 -1
- package/lib/checkbox.js +2 -2
- package/lib/colorpicker.d.ts +1 -1
- package/lib/colorpicker.js +5 -5
- package/lib/combobox.d.ts +1 -1
- package/lib/combobox.js +3 -3
- package/lib/component.d.ts +1 -5
- package/lib/component.js +35 -39
- package/lib/datastore.d.ts +1 -1
- package/lib/datastore.js +5 -5
- package/lib/dialog.d.ts +1 -1
- package/lib/dialog.js +4 -3
- package/lib/drag_manager.js +30 -1
- package/lib/fileupload.js +2 -1
- package/lib/form.d.ts +1 -1
- package/lib/gridview.d.ts +1 -5
- package/lib/gridview.js +8 -7
- package/lib/i18n.d.ts +35 -33
- package/lib/i18n.js +180 -93
- package/lib/icon.d.ts +1 -1
- package/lib/icon.js +19 -16
- package/lib/image.js +4 -3
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/input.js +1 -1
- package/lib/link.d.ts +1 -1
- package/lib/link.js +2 -2
- package/lib/listview.d.ts +1 -1
- package/lib/listview.js +10 -9
- package/lib/menu.d.ts +1 -1
- package/lib/menu.js +5 -4
- package/lib/popup.d.ts +1 -1
- package/lib/popup.js +13 -12
- package/lib/property_editor.d.ts +1 -1
- package/lib/property_editor.js +2 -2
- package/lib/radiobtn.d.ts +1 -1
- package/lib/radiobtn.js +4 -3
- package/lib/rating.d.ts +1 -1
- package/lib/rating.js +2 -2
- package/lib/router.d.ts +1 -1
- package/lib/router.js +5 -4
- package/lib/settings.js +2 -3
- package/lib/spreadsheet.d.ts +1 -1
- package/lib/spreadsheet.js +9 -8
- package/lib/styles.js +6 -5
- package/lib/svgcomponent.d.ts +1 -1
- package/lib/svgcomponent.js +4 -1
- package/lib/tabbar.d.ts +1 -1
- package/lib/tabbar.js +2 -2
- package/lib/textarea.d.ts +1 -1
- package/lib/textarea.js +2 -2
- package/lib/textedit.d.ts +1 -1
- package/lib/textedit.js +5 -4
- package/lib/tools.d.ts +1 -0
- package/lib/tools.js +15 -6
- package/lib/tooltips.js +6 -5
- package/lib/treeview.d.ts +1 -1
- package/lib/treeview.js +8 -8
- package/lib/x4dom.d.ts +49 -0
- package/lib/x4dom.js +32 -0
- package/lib/x4events.d.ts +266 -0
- package/lib/x4events.js +389 -0
- package/package.json +4 -3
- package/src/application.ts +5 -4
- package/src/base_component.ts +1 -1
- package/src/button.ts +1 -1
- package/src/calendar.ts +5 -3
- package/src/canvas.ts +1 -1
- package/src/cardview.ts +1 -1
- package/src/checkbox.ts +1 -1
- package/src/colorpicker.ts +1 -1
- package/src/combobox.ts +1 -1
- package/src/component.ts +34 -39
- package/src/datastore.ts +1 -1
- package/src/dialog.ts +4 -2
- package/src/drag_manager.ts +4 -1
- package/src/fileupload.ts +2 -1
- package/src/form.ts +1 -1
- package/src/gridview.ts +4 -3
- package/src/i18n.ts +234 -97
- package/src/icon.ts +18 -16
- package/src/image.ts +5 -3
- package/src/index.ts +1 -1
- package/src/input.ts +1 -1
- package/src/layout.ts +1 -1
- package/src/link.ts +1 -1
- package/src/listview.ts +6 -4
- package/src/menu.ts +5 -3
- package/src/popup.ts +14 -12
- package/src/property_editor.ts +1 -1
- package/src/radiobtn.ts +4 -2
- package/src/rating.ts +1 -1
- package/src/router.ts +4 -2
- package/src/settings.ts +2 -4
- package/src/smartedit.ts +3 -2
- package/src/spreadsheet.ts +8 -6
- package/src/styles.ts +7 -5
- package/src/svgcomponent.ts +4 -1
- package/src/tabbar.ts +1 -1
- package/src/textarea.ts +1 -1
- package/src/textedit.ts +4 -2
- package/src/tools.ts +15 -5
- package/src/tooltips.ts +7 -5
- package/src/treeview.ts +1 -1
- package/src/x4dom.ts +57 -0
- package/src/{x4_events.ts → x4events.ts} +1 -1
- package/tsconfig.json +5 -3
- package/src/hosts/electron.ts +0 -161
- package/src/hosts/host.ts +0 -100
- package/src/hosts/nwjs.ts +0 -141
- package/src/hosts/nwjs_types.ts +0 -339
package/src/component.ts
CHANGED
|
@@ -34,9 +34,11 @@
|
|
|
34
34
|
*/
|
|
35
35
|
|
|
36
36
|
import { pascalCase, Rect, isString, isArray, Size, Point, isNumber, asap, HtmlString, isHtmlString, Constructor, getMousePos } from './tools';
|
|
37
|
+
import { x4document } from './x4dom';
|
|
38
|
+
|
|
37
39
|
import { Stylesheet, ComputedStyle } from './styles';
|
|
38
40
|
import { _tr } from './i18n';
|
|
39
|
-
import { BasicEvent, EventCallback } from './
|
|
41
|
+
import { BasicEvent, EventCallback } from './x4events';
|
|
40
42
|
import { BaseComponent, BaseComponentProps, BaseComponentEventMap } from './base_component';
|
|
41
43
|
import { IDOMEvents, X4ElementEventMap } from './dom_events';
|
|
42
44
|
|
|
@@ -725,21 +727,12 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
725
727
|
}
|
|
726
728
|
}
|
|
727
729
|
|
|
728
|
-
///@deprecated
|
|
729
|
-
//private build(): void {}
|
|
730
|
-
/**
|
|
731
|
-
* @deprecated
|
|
732
|
-
*/
|
|
733
|
-
|
|
734
|
-
private Build(): void { }
|
|
735
|
-
|
|
736
730
|
public _build(): HTMLElement {
|
|
737
731
|
if (this.m_dom) {
|
|
738
732
|
return this.m_dom;
|
|
739
733
|
}
|
|
740
734
|
|
|
741
735
|
this._createDOM();
|
|
742
|
-
|
|
743
736
|
return this.m_dom;
|
|
744
737
|
}
|
|
745
738
|
|
|
@@ -800,10 +793,10 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
800
793
|
let vdom = this.m_iprops;
|
|
801
794
|
|
|
802
795
|
if (props.ns) {
|
|
803
|
-
this.m_dom = <HTMLElement>
|
|
796
|
+
this.m_dom = <HTMLElement>x4document.createElementNS(props.ns, props.tag ?? 'div');
|
|
804
797
|
}
|
|
805
798
|
else {
|
|
806
|
-
this.m_dom =
|
|
799
|
+
this.m_dom = x4document.createElement( (props.tag ?? 'div') as any );
|
|
807
800
|
}
|
|
808
801
|
|
|
809
802
|
this.m_dom[_x4_el_sym] = this;
|
|
@@ -880,7 +873,7 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
880
873
|
// wait for dom insertion inside document.body
|
|
881
874
|
if (!Component.__createObserver) {
|
|
882
875
|
Component.__createObserver = new MutationObserver(Component._observeCreation);
|
|
883
|
-
Component.__createObserver.observe(
|
|
876
|
+
Component.__createObserver.observe(x4document.body, { childList: true, subtree: true });
|
|
884
877
|
}
|
|
885
878
|
|
|
886
879
|
return this.m_dom;
|
|
@@ -1190,10 +1183,10 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
1190
1183
|
Component.__privateEvents[name] = true; // todo count it
|
|
1191
1184
|
|
|
1192
1185
|
if (passiveEvents[name]) {
|
|
1193
|
-
|
|
1186
|
+
x4document.addEventListener(name as any, Component._dispatchEvent, { passive: false, capture: true });
|
|
1194
1187
|
}
|
|
1195
1188
|
else {
|
|
1196
|
-
|
|
1189
|
+
x4document.addEventListener(name as any, Component._dispatchEvent, true);
|
|
1197
1190
|
}
|
|
1198
1191
|
}
|
|
1199
1192
|
|
|
@@ -1415,8 +1408,8 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
1415
1408
|
*
|
|
1416
1409
|
*/
|
|
1417
1410
|
|
|
1418
|
-
private static dispatchCaptures(event:
|
|
1419
|
-
Component.__capture.handler(event);
|
|
1411
|
+
private static dispatchCaptures(event: Event) {
|
|
1412
|
+
Component.__capture.handler(event as UIEvent);
|
|
1420
1413
|
}
|
|
1421
1414
|
|
|
1422
1415
|
/**
|
|
@@ -1447,12 +1440,12 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
1447
1440
|
|
|
1448
1441
|
// todo: review that
|
|
1449
1442
|
|
|
1450
|
-
let iframes =
|
|
1443
|
+
let iframes = x4document.querySelectorAll<HTMLIFrameElement>("iframe");
|
|
1451
1444
|
iframes.forEach( f => {
|
|
1452
1445
|
flyWrap(f).setStyleValue( 'pointer-events', 'none' );
|
|
1453
1446
|
});
|
|
1454
1447
|
|
|
1455
|
-
let overs =
|
|
1448
|
+
let overs = x4document.querySelectorAll(":hover");
|
|
1456
1449
|
|
|
1457
1450
|
let cursor = null;
|
|
1458
1451
|
if (overs.length) {
|
|
@@ -1461,7 +1454,7 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
1461
1454
|
cursor = style.cursor;
|
|
1462
1455
|
}
|
|
1463
1456
|
|
|
1464
|
-
Component.__capture_mask =
|
|
1457
|
+
Component.__capture_mask = x4document.createElement('div');
|
|
1465
1458
|
let mask = flyWrap(Component.__capture_mask);
|
|
1466
1459
|
mask.addClass('@capture-mask');
|
|
1467
1460
|
|
|
@@ -1469,15 +1462,15 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
1469
1462
|
mask.setStyleValue('cursor', cursor);
|
|
1470
1463
|
}
|
|
1471
1464
|
|
|
1472
|
-
|
|
1465
|
+
x4document.body.appendChild(mask.dom);
|
|
1473
1466
|
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1467
|
+
x4document.addEventListener('mousedown', Component.dispatchCaptures);
|
|
1468
|
+
x4document.addEventListener('mousemove', Component.dispatchCaptures);
|
|
1469
|
+
x4document.addEventListener('mouseup', Component.dispatchCaptures);
|
|
1477
1470
|
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1471
|
+
x4document.addEventListener('touchstart', Component.dispatchCaptures);
|
|
1472
|
+
x4document.addEventListener('touchmove', Component.dispatchCaptures);
|
|
1473
|
+
x4document.addEventListener('touchend', Component.dispatchCaptures);
|
|
1481
1474
|
|
|
1482
1475
|
Component.__capture = {
|
|
1483
1476
|
initiator,
|
|
@@ -1490,13 +1483,13 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
1490
1483
|
|
|
1491
1484
|
console.assert(!!Component.__capture);
|
|
1492
1485
|
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1486
|
+
x4document.removeEventListener('touchstart', Component.dispatchCaptures);
|
|
1487
|
+
x4document.removeEventListener('touchmove', Component.dispatchCaptures);
|
|
1488
|
+
x4document.removeEventListener('touchend', Component.dispatchCaptures);
|
|
1496
1489
|
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1490
|
+
x4document.removeEventListener('mousedown', Component.dispatchCaptures);
|
|
1491
|
+
x4document.removeEventListener('mousemove', Component.dispatchCaptures);
|
|
1492
|
+
x4document.removeEventListener('mouseup', Component.dispatchCaptures);
|
|
1500
1493
|
|
|
1501
1494
|
Component.__capture.iframes.forEach( f => {
|
|
1502
1495
|
flyWrap(f).setStyleValue( 'pointer-events', null );
|
|
@@ -1504,7 +1497,7 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
1504
1497
|
|
|
1505
1498
|
Component.__capture = null;
|
|
1506
1499
|
if (Component.__capture_mask) {
|
|
1507
|
-
|
|
1500
|
+
x4document.body.removeChild(Component.__capture_mask);
|
|
1508
1501
|
Component.__capture_mask = null;
|
|
1509
1502
|
}
|
|
1510
1503
|
}
|
|
@@ -1525,7 +1518,9 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
1525
1518
|
let right = undefined;
|
|
1526
1519
|
|
|
1527
1520
|
let pn = this.dom.parentElement;
|
|
1528
|
-
|
|
1521
|
+
const bdy = x4document.body;
|
|
1522
|
+
|
|
1523
|
+
while( pn && pn!=bdy ) {
|
|
1529
1524
|
|
|
1530
1525
|
const pr = pn.getBoundingClientRect( );
|
|
1531
1526
|
|
|
@@ -1696,18 +1691,18 @@ export class Component<P extends CProps<BaseComponentEventMap> = CProps<BaseComp
|
|
|
1696
1691
|
static getScrollbarSize() {
|
|
1697
1692
|
|
|
1698
1693
|
if (Component.__sb_width === undefined) {
|
|
1699
|
-
let outerDiv =
|
|
1694
|
+
let outerDiv = x4document.createElement('div');
|
|
1700
1695
|
outerDiv.style.cssText = 'overflow:auto;position:absolute;top:0;width:100px;height:100px';
|
|
1701
1696
|
|
|
1702
|
-
let innerDiv =
|
|
1697
|
+
let innerDiv = x4document.createElement('div');
|
|
1703
1698
|
innerDiv.style.width = '200px';
|
|
1704
1699
|
innerDiv.style.height = '200px';
|
|
1705
1700
|
|
|
1706
1701
|
outerDiv.appendChild(innerDiv);
|
|
1707
|
-
|
|
1702
|
+
x4document.body.appendChild(outerDiv);
|
|
1708
1703
|
|
|
1709
1704
|
Component.__sb_width = outerDiv.offsetWidth - outerDiv.clientWidth;
|
|
1710
|
-
|
|
1705
|
+
x4document.body.removeChild(outerDiv);
|
|
1711
1706
|
}
|
|
1712
1707
|
|
|
1713
1708
|
return Component.__sb_width;
|
package/src/datastore.ts
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
import { ajaxRequest } from './request';
|
|
31
31
|
import { isArray, isString } from './tools';
|
|
32
|
-
import { BasicEvent, EvChange, EventSource, EventMap, MapEvents } from './
|
|
32
|
+
import { BasicEvent, EvChange, EventSource, EventMap, MapEvents } from './x4events';
|
|
33
33
|
import { BaseComponent, BaseComponentEventMap, BaseComponentProps } from './base_component';
|
|
34
34
|
|
|
35
35
|
export type ChangeCallback = (type: string, id?: any) => void;
|
package/src/dialog.ts
CHANGED
|
@@ -27,13 +27,15 @@
|
|
|
27
27
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
28
|
**/
|
|
29
29
|
|
|
30
|
+
import { x4document } from './x4dom'
|
|
31
|
+
|
|
30
32
|
import { Popup, PopupProps, PopupEventMap, EvMove } from './popup'
|
|
31
33
|
import { Icon, IconID } from './icon'
|
|
32
34
|
import { HLayout } from './layout'
|
|
33
35
|
import { Label } from './label'
|
|
34
36
|
import { Form, FormButtons } from './form'
|
|
35
37
|
import { Component, ComponentContent, EvSize, flyWrap } from './component'
|
|
36
|
-
import { BasicEvent, EventCallback } from './
|
|
38
|
+
import { BasicEvent, EventCallback } from './x4events'
|
|
37
39
|
import { Rect, getMousePos, isFunction, isTouchDevice, isString, Size } from './tools'
|
|
38
40
|
|
|
39
41
|
interface Geometry {
|
|
@@ -458,7 +460,7 @@ export class Dialog<P extends DialogProps = DialogProps, E extends DialogBoxEven
|
|
|
458
460
|
|
|
459
461
|
let { x, y } = getMousePos(event, true);
|
|
460
462
|
|
|
461
|
-
let wrc = flyWrap(
|
|
463
|
+
let wrc = flyWrap(x4document.body).getBoundingRect();
|
|
462
464
|
let rc = this.getBoundingRect(true);
|
|
463
465
|
let trc = this.m_el_title.getBoundingRect();
|
|
464
466
|
|
package/src/drag_manager.ts
CHANGED
|
@@ -26,6 +26,9 @@
|
|
|
26
26
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
27
27
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
28
|
**/
|
|
29
|
+
|
|
30
|
+
import { x4document } from './x4dom'
|
|
31
|
+
|
|
29
32
|
import { Component } from './component';
|
|
30
33
|
import { Point } from './tools';
|
|
31
34
|
|
|
@@ -61,7 +64,7 @@ class DragManager {
|
|
|
61
64
|
this.dragGhost = el.dom.cloneNode(true) as HTMLElement;
|
|
62
65
|
|
|
63
66
|
this.dragGhost.classList.add('dragged');
|
|
64
|
-
|
|
67
|
+
x4document.body.appendChild(this.dragGhost);
|
|
65
68
|
|
|
66
69
|
el.addClass( 'dragging' );
|
|
67
70
|
|
package/src/fileupload.ts
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
28
|
**/
|
|
29
29
|
|
|
30
|
+
import { x4document } from './x4dom'
|
|
30
31
|
import { Component, CProps } from './component'
|
|
31
32
|
|
|
32
33
|
import { HLayout } from './layout'
|
|
@@ -157,7 +158,7 @@ function _createFileInput() {
|
|
|
157
158
|
});
|
|
158
159
|
|
|
159
160
|
// ajoute un input type:file caché pour pouvoir choir un fichier a ouvrir
|
|
160
|
-
|
|
161
|
+
x4document.body.appendChild(g_file_input._build());
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
g_file_input.clearDomEvent('change');
|
package/src/form.ts
CHANGED
|
@@ -33,7 +33,7 @@ import { Button } from './button'
|
|
|
33
33
|
import { Input } from './input'
|
|
34
34
|
import { TextEdit } from './textedit'
|
|
35
35
|
import { ajaxRequest, RequestProps } from './request'
|
|
36
|
-
import { EventCallback } from './
|
|
36
|
+
import { EventCallback } from './x4events'
|
|
37
37
|
import { EvBtnClick } from './dialog'
|
|
38
38
|
|
|
39
39
|
import { _tr } from './i18n'
|
package/src/gridview.ts
CHANGED
|
@@ -34,6 +34,7 @@ const T_UPDATE = Symbol('update');
|
|
|
34
34
|
* todo: button in a column
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
+
import { x4document } from './x4dom'
|
|
37
38
|
|
|
38
39
|
import { HLayout, VLayout } from './layout'
|
|
39
40
|
import { Component, ContainerEventMap, EvSize, EvDblClick, CProps, flyWrap, html, HtmlString, SizerOverlay, Flex } from './component'
|
|
@@ -43,7 +44,7 @@ import * as Formatters from './formatters'
|
|
|
43
44
|
import { downloadData } from './tools'
|
|
44
45
|
import { DataView, DataStore, Record } from './datastore'
|
|
45
46
|
|
|
46
|
-
import { EvContextMenu, EvSelectionChange, BasicEvent, EventDisposer } from "./
|
|
47
|
+
import { EvContextMenu, EvSelectionChange, BasicEvent, EventDisposer } from "./x4events";
|
|
47
48
|
import { Icon } from './icon.js';
|
|
48
49
|
|
|
49
50
|
export interface EvGridCheck extends BasicEvent {
|
|
@@ -618,10 +619,10 @@ export class GridView extends VLayout<GridViewProps, GridViewEventMap> {
|
|
|
618
619
|
*/
|
|
619
620
|
|
|
620
621
|
private _computeItemHeight() {
|
|
621
|
-
let gr =
|
|
622
|
+
let gr = x4document.createElement('div');
|
|
622
623
|
gr.classList.add('x-row');
|
|
623
624
|
|
|
624
|
-
let gv =
|
|
625
|
+
let gv = x4document.createElement('div');
|
|
625
626
|
gv.classList.add('x-grid-view');
|
|
626
627
|
gv.style.position = 'absolute';
|
|
627
628
|
gv.style.top = '-1000px';
|
package/src/i18n.ts
CHANGED
|
@@ -28,6 +28,205 @@
|
|
|
28
28
|
**/
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* language definition
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
interface Language {
|
|
38
|
+
name: string;
|
|
39
|
+
base: string;
|
|
40
|
+
src_translations: any;
|
|
41
|
+
translations: any;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const sym_lang = Symbol( "i18n" );
|
|
45
|
+
|
|
46
|
+
let languages: Record<string,Language> = {
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* create a new language
|
|
51
|
+
* @param name language name (code)
|
|
52
|
+
* @param base base language (code)
|
|
53
|
+
* @example:
|
|
54
|
+
* ```js
|
|
55
|
+
* createLanguage( 'en', 'fr' );
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
export function createLanguage( name: string, base: string ) {
|
|
60
|
+
languages[name] = {
|
|
61
|
+
name,
|
|
62
|
+
base,
|
|
63
|
+
src_translations: {},
|
|
64
|
+
translations: {}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* check if the given language is known
|
|
70
|
+
* @param name language name (code)
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
export function isLanguage( name: string ): boolean {
|
|
74
|
+
return languages[name]!==undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* build the language with given fragments
|
|
79
|
+
* @param name language name (code)
|
|
80
|
+
* @param parts misc elements that make the language
|
|
81
|
+
* @example:
|
|
82
|
+
* ```js
|
|
83
|
+
* createLanguage( 'en', 'fr' );
|
|
84
|
+
* const app = {
|
|
85
|
+
* clients: {
|
|
86
|
+
* translation1: "hello",
|
|
87
|
+
* }
|
|
88
|
+
* }
|
|
89
|
+
* addTranslation( 'en', app );
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
|
|
93
|
+
export function addTranslation( name, ...parts ) {
|
|
94
|
+
|
|
95
|
+
if( !isLanguage(name) ) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const lang = languages[name];
|
|
100
|
+
|
|
101
|
+
parts.forEach( p => {
|
|
102
|
+
_patch( lang.src_translations, p, lang.base );
|
|
103
|
+
} );
|
|
104
|
+
|
|
105
|
+
lang.translations = _mk_proxy( lang.src_translations, lang.base, true );
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
*
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
function _patch( obj: any, by: any, def: string ) {
|
|
113
|
+
for( let n in by ) {
|
|
114
|
+
if( obj[n] instanceof Object ) {
|
|
115
|
+
_patch( obj[n], by[n], def );
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
obj[n] = by[n];
|
|
119
|
+
obj[n] = _mk_proxy( obj[n], def, false );
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return obj;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* when we ask for _tr.xxx
|
|
128
|
+
* reqpath is set to [xxx]
|
|
129
|
+
*
|
|
130
|
+
* then when we try to get _tr.xxx.yyy
|
|
131
|
+
* reqpath is [xxx,yyy]
|
|
132
|
+
* if yyy is not found, we try with base langage for the full reqpath
|
|
133
|
+
* until no base found
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
let req_path: (string | symbol)[];
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
*
|
|
140
|
+
*/
|
|
141
|
+
|
|
142
|
+
function _findBaseTrans( base ) {
|
|
143
|
+
|
|
144
|
+
while( base ) {
|
|
145
|
+
const lang = languages[base];
|
|
146
|
+
let trans = lang.translations;
|
|
147
|
+
let value;
|
|
148
|
+
|
|
149
|
+
for( const p of req_path ) {
|
|
150
|
+
value = trans[p];
|
|
151
|
+
if( value===undefined ) {
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
trans = value;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if( value!==undefined ) {
|
|
159
|
+
return trans;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
base = lang.base;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
console.error( "I18N error: unable to find", '_tr.'+req_path.join('.') );
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
*
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
function _mk_proxy( obj: any, base: string, root: boolean ) : any {
|
|
174
|
+
return new Proxy( obj, {
|
|
175
|
+
get: (target, prop) => {
|
|
176
|
+
if( root ) {
|
|
177
|
+
req_path = [prop];
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
req_path.push( prop );
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
let value = target[prop];
|
|
184
|
+
if( value===undefined && base ) {
|
|
185
|
+
value = _findBaseTrans( base );
|
|
186
|
+
// keep it for later
|
|
187
|
+
target[prop] = value;
|
|
188
|
+
}
|
|
189
|
+
return value;
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export let _tr: any = {};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* select the given language as current
|
|
198
|
+
* @param name laguage name (code)
|
|
199
|
+
*/
|
|
200
|
+
|
|
201
|
+
export function selectLanguage( name: string ) {
|
|
202
|
+
|
|
203
|
+
if( !isLanguage(name) ) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
_tr = languages[name].translations;
|
|
208
|
+
_tr[sym_lang] = name;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
*
|
|
213
|
+
*/
|
|
214
|
+
|
|
215
|
+
export function getCurrentLanguage( ): string {
|
|
216
|
+
return _tr[sym_lang];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
*
|
|
221
|
+
*/
|
|
222
|
+
|
|
223
|
+
export function getAvailableLanguages( ): string[] {
|
|
224
|
+
return Object.keys( languages );
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
31
230
|
/**
|
|
32
231
|
* language definition
|
|
33
232
|
* x4 specific strings
|
|
@@ -55,9 +254,9 @@ let fr = {
|
|
|
55
254
|
invalid_email: 'adresse mail invalide',
|
|
56
255
|
invalid_number: 'valeur numérique invalide',
|
|
57
256
|
|
|
58
|
-
diff_date_seconds: '{0}
|
|
257
|
+
diff_date_seconds: '{0} secondes',
|
|
59
258
|
diff_date_minutes: '{0} minutes',
|
|
60
|
-
diff_date_hours: '{0}
|
|
259
|
+
diff_date_hours: '{0} heures',
|
|
61
260
|
|
|
62
261
|
invalid_date: 'Date non reconnue ({0})',
|
|
63
262
|
empty_list: 'Liste vide',
|
|
@@ -83,6 +282,7 @@ let fr = {
|
|
|
83
282
|
};
|
|
84
283
|
|
|
85
284
|
/** @ignore */
|
|
285
|
+
|
|
86
286
|
let en = {
|
|
87
287
|
global: {
|
|
88
288
|
ok: 'OK',
|
|
@@ -91,119 +291,56 @@ let en = {
|
|
|
91
291
|
yes: 'Yes',
|
|
92
292
|
no: 'No',
|
|
93
293
|
|
|
94
|
-
|
|
294
|
+
open: 'Open',
|
|
295
|
+
new: 'New',
|
|
296
|
+
delete: 'Delete',
|
|
297
|
+
close: 'Close',
|
|
298
|
+
save: 'Save',
|
|
299
|
+
|
|
300
|
+
search: 'Search',
|
|
301
|
+
search_tip: 'Type in the text to search. <b>Enter</b> to start the search. <b>Esc</b> to cancel.',
|
|
302
|
+
|
|
303
|
+
required_field: "missing information",
|
|
95
304
|
invalid_format: "invalid format",
|
|
305
|
+
invalid_email: 'invalid email address',
|
|
306
|
+
invalid_number: 'bad numeric value',
|
|
96
307
|
|
|
97
308
|
diff_date_seconds: '{0} seconds',
|
|
98
309
|
diff_date_minutes: '{0} minutes',
|
|
99
310
|
diff_date_hours: '{0} hours',
|
|
100
311
|
|
|
101
|
-
invalid_date: '
|
|
312
|
+
invalid_date: 'Unrecognized date({0})',
|
|
313
|
+
empty_list: 'Empty list',
|
|
102
314
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
paste: 'Paste'
|
|
106
|
-
}
|
|
107
|
-
}
|
|
315
|
+
date_input_formats: 'm/d/y|m.d.y|m d y|m-d-y|mdy',
|
|
316
|
+
date_format: 'M/D/Y',
|
|
108
317
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
'fr': fr,
|
|
112
|
-
'en': _mk_proxy( _patch( {}, en ) )
|
|
113
|
-
};
|
|
318
|
+
day_short: [ 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' ],
|
|
319
|
+
day_long: [ 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday' ],
|
|
114
320
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
* FR by default
|
|
118
|
-
* @example ```typescript
|
|
119
|
-
* console.log( _tr.global.ok );
|
|
120
|
-
*/
|
|
321
|
+
month_short: [ 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jui', 'aug', 'sep', 'oct', 'nov', 'dec' ],
|
|
322
|
+
month_long: [ 'january', 'february', 'march', 'april', 'mau', 'june', 'jully', 'august', 'september', 'october', 'november', 'december' ],
|
|
121
323
|
|
|
122
|
-
|
|
324
|
+
property: 'Property',
|
|
325
|
+
value: 'Value',
|
|
123
326
|
|
|
124
|
-
|
|
125
|
-
* check if the language is known
|
|
126
|
-
* @param name - language name to test
|
|
127
|
-
* @example ```typescript
|
|
128
|
-
* if( isLanguage('fr') ) {
|
|
129
|
-
* }
|
|
130
|
-
*/
|
|
131
|
-
|
|
132
|
-
export function isLanguage( name ) {
|
|
133
|
-
return all_langs[name]!==undefined;
|
|
134
|
-
}
|
|
327
|
+
err_403: `You do not have sufficient rights to do that action`,
|
|
135
328
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
* @example ```typescript
|
|
140
|
-
* selectLanguage( 'en' );
|
|
141
|
-
*/
|
|
142
|
-
|
|
143
|
-
export function selectLanguage( name ) {
|
|
144
|
-
|
|
145
|
-
if( !isLanguage(name) ) {
|
|
146
|
-
return;
|
|
329
|
+
copy: 'Copy',
|
|
330
|
+
cut: 'Cut',
|
|
331
|
+
paste: 'Paste'
|
|
147
332
|
}
|
|
333
|
+
};
|
|
148
334
|
|
|
149
|
-
|
|
150
|
-
|
|
335
|
+
createLanguage( 'fr', null );
|
|
336
|
+
addTranslation( 'fr', fr );
|
|
151
337
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
* you can also patch 'global' elements witch are defined by x4
|
|
155
|
-
* @param name - language name
|
|
156
|
-
* @param definition - definition of the language
|
|
157
|
-
* @example ```typescript
|
|
158
|
-
* setTranslation( 'fr', {
|
|
159
|
-
* this_is_an_example: 'ceci est un exemple',
|
|
160
|
-
* this_is: {
|
|
161
|
-
* another_example: 'ceci est un autre exemple'
|
|
162
|
-
* },
|
|
163
|
-
* global: {
|
|
164
|
-
* ok: 'O.K.'
|
|
165
|
-
* }
|
|
166
|
-
* });
|
|
167
|
-
* console.log( _tr.this_is_an_example ); // defined by the previous line
|
|
168
|
-
* selectLanguage( 'en' );
|
|
169
|
-
* console.log( _tr.this_is_an_example ); // 'en' do not define this, so we get 'fr' one
|
|
170
|
-
*
|
|
171
|
-
*/
|
|
338
|
+
createLanguage( 'en', 'fr' );
|
|
339
|
+
addTranslation( 'en', en );
|
|
172
340
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
if( !isLanguage(name) ) {
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
341
|
+
selectLanguage( 'fr' ); // by default
|
|
178
342
|
|
|
179
|
-
_patch( all_langs[name], definition );
|
|
180
|
-
}
|
|
181
343
|
|
|
182
344
|
|
|
183
|
-
function _patch( obj, by ) {
|
|
184
|
-
for( let n in by ) {
|
|
185
|
-
if( obj[n] instanceof Object ) {
|
|
186
|
-
_patch( obj[n], by[n] );
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
obj[n] = by[n];
|
|
190
|
-
if( obj[n] instanceof Object ) {
|
|
191
|
-
obj[n] = _mk_proxy( obj[n] );
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
345
|
|
|
196
|
-
return obj;
|
|
197
|
-
}
|
|
198
346
|
|
|
199
|
-
function _mk_proxy( obj: any ) : any {
|
|
200
|
-
return new Proxy( obj, {
|
|
201
|
-
get: function(target, prop, receiver) {
|
|
202
|
-
let value = target[prop];
|
|
203
|
-
if( value===undefined ) {
|
|
204
|
-
return fr[prop];
|
|
205
|
-
}
|
|
206
|
-
return value;
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
}
|