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.
Files changed (124) hide show
  1. package/README.md +4 -3
  2. package/lib/application.d.ts +1 -1
  3. package/lib/application.js +4 -3
  4. package/lib/base_component.d.ts +1 -1
  5. package/lib/base_component.js +3 -3
  6. package/lib/button.d.ts +1 -1
  7. package/lib/button.js +3 -3
  8. package/lib/calendar.d.ts +1 -1
  9. package/lib/calendar.js +5 -4
  10. package/lib/canvas.d.ts +1 -1
  11. package/lib/canvas.js +2 -2
  12. package/lib/cardview.d.ts +1 -1
  13. package/lib/cardview.js +2 -2
  14. package/lib/checkbox.d.ts +1 -1
  15. package/lib/checkbox.js +2 -2
  16. package/lib/colorpicker.d.ts +1 -1
  17. package/lib/colorpicker.js +5 -5
  18. package/lib/combobox.d.ts +1 -1
  19. package/lib/combobox.js +3 -3
  20. package/lib/component.d.ts +1 -5
  21. package/lib/component.js +35 -39
  22. package/lib/datastore.d.ts +1 -1
  23. package/lib/datastore.js +5 -5
  24. package/lib/dialog.d.ts +1 -1
  25. package/lib/dialog.js +4 -3
  26. package/lib/drag_manager.js +30 -1
  27. package/lib/fileupload.js +2 -1
  28. package/lib/form.d.ts +1 -1
  29. package/lib/gridview.d.ts +1 -5
  30. package/lib/gridview.js +8 -7
  31. package/lib/i18n.d.ts +35 -33
  32. package/lib/i18n.js +180 -93
  33. package/lib/icon.d.ts +1 -1
  34. package/lib/icon.js +19 -16
  35. package/lib/image.js +4 -3
  36. package/lib/index.d.ts +1 -1
  37. package/lib/index.js +1 -1
  38. package/lib/input.js +1 -1
  39. package/lib/link.d.ts +1 -1
  40. package/lib/link.js +2 -2
  41. package/lib/listview.d.ts +1 -1
  42. package/lib/listview.js +10 -9
  43. package/lib/menu.d.ts +1 -1
  44. package/lib/menu.js +5 -4
  45. package/lib/popup.d.ts +1 -1
  46. package/lib/popup.js +13 -12
  47. package/lib/property_editor.d.ts +1 -1
  48. package/lib/property_editor.js +2 -2
  49. package/lib/radiobtn.d.ts +1 -1
  50. package/lib/radiobtn.js +4 -3
  51. package/lib/rating.d.ts +1 -1
  52. package/lib/rating.js +2 -2
  53. package/lib/router.d.ts +1 -1
  54. package/lib/router.js +5 -4
  55. package/lib/settings.js +2 -3
  56. package/lib/spreadsheet.d.ts +1 -1
  57. package/lib/spreadsheet.js +9 -8
  58. package/lib/styles.js +6 -5
  59. package/lib/svgcomponent.d.ts +1 -1
  60. package/lib/svgcomponent.js +4 -1
  61. package/lib/tabbar.d.ts +1 -1
  62. package/lib/tabbar.js +2 -2
  63. package/lib/textarea.d.ts +1 -1
  64. package/lib/textarea.js +2 -2
  65. package/lib/textedit.d.ts +1 -1
  66. package/lib/textedit.js +5 -4
  67. package/lib/tools.d.ts +1 -0
  68. package/lib/tools.js +15 -6
  69. package/lib/tooltips.js +6 -5
  70. package/lib/treeview.d.ts +1 -1
  71. package/lib/treeview.js +8 -8
  72. package/lib/x4dom.d.ts +49 -0
  73. package/lib/x4dom.js +32 -0
  74. package/lib/x4events.d.ts +266 -0
  75. package/lib/x4events.js +389 -0
  76. package/package.json +4 -3
  77. package/src/application.ts +5 -4
  78. package/src/base_component.ts +1 -1
  79. package/src/button.ts +1 -1
  80. package/src/calendar.ts +5 -3
  81. package/src/canvas.ts +1 -1
  82. package/src/cardview.ts +1 -1
  83. package/src/checkbox.ts +1 -1
  84. package/src/colorpicker.ts +1 -1
  85. package/src/combobox.ts +1 -1
  86. package/src/component.ts +34 -39
  87. package/src/datastore.ts +1 -1
  88. package/src/dialog.ts +4 -2
  89. package/src/drag_manager.ts +4 -1
  90. package/src/fileupload.ts +2 -1
  91. package/src/form.ts +1 -1
  92. package/src/gridview.ts +4 -3
  93. package/src/i18n.ts +234 -97
  94. package/src/icon.ts +18 -16
  95. package/src/image.ts +5 -3
  96. package/src/index.ts +1 -1
  97. package/src/input.ts +1 -1
  98. package/src/layout.ts +1 -1
  99. package/src/link.ts +1 -1
  100. package/src/listview.ts +6 -4
  101. package/src/menu.ts +5 -3
  102. package/src/popup.ts +14 -12
  103. package/src/property_editor.ts +1 -1
  104. package/src/radiobtn.ts +4 -2
  105. package/src/rating.ts +1 -1
  106. package/src/router.ts +4 -2
  107. package/src/settings.ts +2 -4
  108. package/src/smartedit.ts +3 -2
  109. package/src/spreadsheet.ts +8 -6
  110. package/src/styles.ts +7 -5
  111. package/src/svgcomponent.ts +4 -1
  112. package/src/tabbar.ts +1 -1
  113. package/src/textarea.ts +1 -1
  114. package/src/textedit.ts +4 -2
  115. package/src/tools.ts +15 -5
  116. package/src/tooltips.ts +7 -5
  117. package/src/treeview.ts +1 -1
  118. package/src/x4dom.ts +57 -0
  119. package/src/{x4_events.ts → x4events.ts} +1 -1
  120. package/tsconfig.json +5 -3
  121. package/src/hosts/electron.ts +0 -161
  122. package/src/hosts/host.ts +0 -100
  123. package/src/hosts/nwjs.ts +0 -141
  124. 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 './x4_events';
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>document.createElementNS(props.ns, props.tag ?? 'div');
796
+ this.m_dom = <HTMLElement>x4document.createElementNS(props.ns, props.tag ?? 'div');
804
797
  }
805
798
  else {
806
- this.m_dom = document.createElement(props.tag ?? 'div');
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(document.body, { childList: true, subtree: true });
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
- document.addEventListener(name, Component._dispatchEvent, { passive: false, capture: true });
1186
+ x4document.addEventListener(name as any, Component._dispatchEvent, { passive: false, capture: true });
1194
1187
  }
1195
1188
  else {
1196
- document.addEventListener(name, Component._dispatchEvent, true);
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: UIEvent) {
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 = document.querySelectorAll("iframe");
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 = document.querySelectorAll(":hover");
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 = document.createElement('div');
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
- document.body.appendChild(mask.dom);
1465
+ x4document.body.appendChild(mask.dom);
1473
1466
 
1474
- document.addEventListener('mousedown', Component.dispatchCaptures);
1475
- document.addEventListener('mousemove', Component.dispatchCaptures);
1476
- document.addEventListener('mouseup', Component.dispatchCaptures);
1467
+ x4document.addEventListener('mousedown', Component.dispatchCaptures);
1468
+ x4document.addEventListener('mousemove', Component.dispatchCaptures);
1469
+ x4document.addEventListener('mouseup', Component.dispatchCaptures);
1477
1470
 
1478
- document.addEventListener('touchstart', Component.dispatchCaptures);
1479
- document.addEventListener('touchmove', Component.dispatchCaptures);
1480
- document.addEventListener('touchend', Component.dispatchCaptures);
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
- document.removeEventListener('touchstart', Component.dispatchCaptures);
1494
- document.removeEventListener('touchmove', Component.dispatchCaptures);
1495
- document.removeEventListener('touchend', Component.dispatchCaptures);
1486
+ x4document.removeEventListener('touchstart', Component.dispatchCaptures);
1487
+ x4document.removeEventListener('touchmove', Component.dispatchCaptures);
1488
+ x4document.removeEventListener('touchend', Component.dispatchCaptures);
1496
1489
 
1497
- document.removeEventListener('mousedown', Component.dispatchCaptures);
1498
- document.removeEventListener('mousemove', Component.dispatchCaptures);
1499
- document.removeEventListener('mouseup', Component.dispatchCaptures);
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
- document.body.removeChild(Component.__capture_mask);
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
- while( pn && pn!=document.body ) {
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 = document.createElement('div');
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 = document.createElement('div');
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
- document.body.appendChild(outerDiv);
1702
+ x4document.body.appendChild(outerDiv);
1708
1703
 
1709
1704
  Component.__sb_width = outerDiv.offsetWidth - outerDiv.clientWidth;
1710
- document.body.removeChild(outerDiv);
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 './x4_events';
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 './x4_events'
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(document.body).getBoundingRect();
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
 
@@ -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
- document.body.appendChild(this.dragGhost);
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
- document.body.appendChild(g_file_input._build());
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 './x4_events'
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 "./x4_events";
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 = document.createElement('div');
622
+ let gr = x4document.createElement('div');
622
623
  gr.classList.add('x-row');
623
624
 
624
- let gv = document.createElement('div');
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} seconds',
257
+ diff_date_seconds: '{0} secondes',
59
258
  diff_date_minutes: '{0} minutes',
60
- diff_date_hours: '{0} hours',
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
- required_field: "required field",
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: 'Bad date format {0}',
312
+ invalid_date: 'Unrecognized date({0})',
313
+ empty_list: 'Empty list',
102
314
 
103
- copy: 'Copy',
104
- cut: 'Cut',
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
- /** @ignore */
110
- let all_langs = {
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
- * current language
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
- export let _tr: any = all_langs['fr'];
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
- * select the current language
138
- * @param name - language name
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
- _tr = all_langs[name];
150
- }
335
+ createLanguage( 'fr', null );
336
+ addTranslation( 'fr', fr );
151
337
 
152
- /**
153
- * define a translation
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
- export function extendTranslation( name, definition ) {
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
- }