@jinntec/fore 1.0.0-5 → 1.2.0

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 (64) hide show
  1. package/README.md +7 -28
  2. package/dist/fore-dev.js +43 -0
  3. package/dist/fore-dev.js.map +1 -0
  4. package/dist/fore.js +37 -0
  5. package/dist/fore.js.map +1 -0
  6. package/index.js +3 -1
  7. package/package.json +39 -41
  8. package/resources/fore.css +27 -54
  9. package/src/DependencyNotifyingDomFacade.js +5 -13
  10. package/src/ForeElementMixin.js +15 -22
  11. package/src/actions/abstract-action.js +34 -10
  12. package/src/actions/fx-action.js +7 -5
  13. package/src/actions/fx-append.js +8 -17
  14. package/src/actions/fx-confirm.js +5 -3
  15. package/src/actions/fx-delete.js +6 -3
  16. package/src/actions/fx-dispatch.js +9 -8
  17. package/src/actions/fx-hide.js +9 -6
  18. package/src/actions/fx-insert.js +27 -14
  19. package/src/actions/fx-message.js +3 -1
  20. package/src/actions/fx-refresh.js +24 -1
  21. package/src/actions/fx-replace.js +74 -0
  22. package/src/actions/fx-return.js +42 -0
  23. package/src/actions/fx-send.js +3 -1
  24. package/src/actions/fx-setfocus.js +37 -0
  25. package/src/actions/fx-setvalue.js +58 -51
  26. package/src/actions/fx-show.js +12 -4
  27. package/src/actions/fx-toggle.js +13 -9
  28. package/src/actions/fx-update.js +3 -1
  29. package/src/dep_graph.js +1 -1
  30. package/src/drawdown.js +67 -82
  31. package/src/fore.js +143 -26
  32. package/src/functions/fx-function.js +17 -3
  33. package/src/fx-bind.js +40 -200
  34. package/src/fx-fore.js +598 -568
  35. package/src/fx-header.js +3 -1
  36. package/src/fx-instance.js +9 -1
  37. package/src/fx-model.js +60 -27
  38. package/src/fx-submission.js +108 -51
  39. package/src/fx-var.js +7 -4
  40. package/src/getInScopeContext.js +23 -16
  41. package/src/modelitem.js +4 -4
  42. package/src/relevance.js +64 -0
  43. package/src/ui/abstract-control.js +65 -37
  44. package/src/ui/fx-alert.js +7 -1
  45. package/src/ui/fx-case.js +4 -3
  46. package/src/ui/fx-container.js +4 -2
  47. package/src/ui/fx-control.js +315 -34
  48. package/src/ui/fx-dialog.js +50 -45
  49. package/src/ui/fx-group.js +3 -1
  50. package/src/ui/fx-hint.js +4 -1
  51. package/src/ui/fx-inspector.js +118 -17
  52. package/src/ui/fx-items.js +7 -5
  53. package/src/ui/fx-output.js +19 -6
  54. package/src/ui/fx-repeat.js +13 -26
  55. package/src/ui/fx-repeatitem.js +10 -4
  56. package/src/ui/fx-switch.js +5 -3
  57. package/src/ui/fx-trigger.js +3 -1
  58. package/src/xpath-evaluation.js +622 -553
  59. package/src/xpath-util.js +2 -6
  60. package/dist/fore-all.js +0 -140
  61. package/dist/fore-debug.js +0 -140
  62. package/src/.DS_Store +0 -0
  63. package/src/actions/.DS_Store +0 -0
  64. package/src/ui/.DS_Store +0 -0
@@ -1,44 +1,145 @@
1
+ import { Fore } from '../fore.js';
2
+
1
3
  /**
2
4
  * lists out all live instances in html 'details' and 'summary' elements.
3
5
  */
4
6
  export class FxInspector extends HTMLElement {
7
+ constructor() {
8
+ super();
9
+ this.attachShadow({ mode: 'open' });
10
+ }
11
+
5
12
  connectedCallback() {
6
13
  const style = `
7
14
  :host {
15
+ position:absolute;
8
16
  display: block;
9
- width:100%;
17
+ width:var(--inspector-handle-width);
10
18
  background:var(--inspector-bg);
19
+ top:0;
20
+ right:0;
21
+ bottom:0;
22
+ height: 100%;
23
+ background: var(--inspector-bg);
24
+ color: white;
25
+ /*max-height: 33%;*/
26
+ overflow: scroll;
27
+ transition:width 0.3s ease;
28
+ }
29
+ :host([open]){
30
+ width: 30%;
31
+ }
32
+ details{
33
+ margin:1rem;
34
+ }
35
+ .main{
36
+ padding-left:var(--inspector-handle-width);
37
+ color:var(--inspector-color);
38
+ overflow:scroll;
39
+ height:100%;
11
40
  }
12
41
  pre{
13
42
  background:var(--inspector-pre-bg);
14
43
  color:var(--inspector-color);
15
- max-height:var(--inspector-instance-height,300px);
16
44
  overflow:scroll;
45
+ padding:0.2rem;
46
+ }
47
+ .handle{
48
+ display:block;
49
+ height:100%;
50
+ width:var(--inspector-handle-width);
51
+ background:var(--inspector-handle-bg);
52
+ opacity:0.7;
53
+ position:absolute;
54
+ left:0;
55
+ color:white;
56
+ cursor:pointer;
57
+ }
58
+ .handle:hover{
59
+ opacity:1;
60
+ }
61
+ .handle::before{
62
+ content: 'Data Inspector';
63
+ white-space: nowrap;
64
+ transform: rotate(-90deg);
65
+ display: inline-block;
66
+ position: absolute;
67
+ left: -85px;
68
+ width: 200px;
69
+ top: 40px;
70
+ }
71
+ summary{
72
+ cursor:pointer;
17
73
  }
18
74
  `;
19
75
 
20
- const instances = Array.from(document.querySelectorAll('fx-instance'));
21
- this.innerHTML = `
76
+ const fore = this.closest('fx-fore');
77
+
78
+ // fore.addEventListener('ready', (e) => {
79
+ this.render(style);
80
+ // });
81
+ fore.addEventListener('refresh-done', () => {
82
+ this.update();
83
+ });
84
+ }
85
+
86
+ update() {
87
+ // console.log('update');
88
+ const pre = this.shadowRoot.querySelectorAll('pre');
89
+ // console.log('pre', pre);
90
+ const fore = this.closest('fx-fore');
91
+
92
+ Array.from(pre).forEach(element => {
93
+ const inst = fore.getModel().getInstance(element.getAttribute('id'));
94
+ if (inst.type === 'xml') {
95
+ element.innerText = this.serializeDOM(inst.instanceData);
96
+ }
97
+ if (inst.type === 'json') {
98
+ element.innerText = JSON.stringify(inst.instanceData, undefined, 2);
99
+ }
100
+ });
101
+ }
102
+
103
+ render(style) {
104
+ const fore = this.closest('fx-fore');
105
+ const instances = Array.from(fore.querySelectorAll('fx-instance'));
106
+ this.shadowRoot.innerHTML = `
22
107
  <style>
23
108
  ${style}
24
109
  </style>
110
+ <div class="main">
25
111
  <slot></slot>
26
- ${instances
27
- .map(
28
- (instance, index) => `
29
- <details ${index === 0 ? `open` : ''}>
30
- <summary>${instance.id}</summary>
31
- <pre>{log('${instance.id}')}</pre>
32
- </details>
33
- `,
34
- )
35
- .join('')}
112
+ <span class="handle"></span>
113
+ ${instances.map(
114
+ (instance, index) => `
115
+ <details>
116
+ <summary>${instance.id}</summary>
117
+ <pre id="${instance.id}"></pre>
118
+ </details>
119
+ `,
120
+ )}
121
+ </div>
36
122
  `;
37
123
 
38
- this.addEventListener('slotchange', e => {
39
- console.log('slotchange ', e);
124
+ const handle = this.shadowRoot.querySelector('.handle');
125
+ handle.addEventListener('click', e => {
126
+ // console.log('toggling');
127
+ const { target } = e;
128
+ if (this.hasAttribute('open')) {
129
+ this.removeAttribute('open');
130
+ } else {
131
+ this.setAttribute('open', 'open');
132
+ }
40
133
  });
41
134
  }
135
+
136
+ serializeDOM(data) {
137
+ // console.log('serializeDOM', data);
138
+ const ser = new XMLSerializer().serializeToString(data);
139
+ return Fore.prettifyXml(ser);
140
+ }
42
141
  }
43
142
 
44
- customElements.define('fx-inspector', FxInspector);
143
+ if (!customElements.get('fx-inspector')) {
144
+ customElements.define('fx-inspector', FxInspector);
145
+ }
@@ -1,4 +1,4 @@
1
- import { evaluateXPath, evaluateXPathToString, evaluateXPathToNodes } from '../xpath-evaluation.js';
1
+ import { evaluateXPathToString, resolveId } from '../xpath-evaluation.js';
2
2
  import FxControl from './fx-control.js';
3
3
  import { Fore } from '../fore.js';
4
4
 
@@ -33,7 +33,7 @@ export class FxItems extends FxControl {
33
33
 
34
34
  let target;
35
35
  if (e.target.nodeName === 'LABEL') {
36
- target = document.getElementById(e.target.getAttribute('for'));
36
+ target = resolveId(e.target.getAttribute('for'), this);
37
37
  target.checked = !target.checked;
38
38
  }
39
39
 
@@ -46,7 +46,7 @@ export class FxItems extends FxControl {
46
46
  this.setAttribute('value', val.trim());
47
47
 
48
48
  // ### check for parent control
49
- const parentBind = this.parentNode.closest('[ref]');
49
+ const parentBind = Fore.getClosest('[ref]', this.parentNode);
50
50
  if (!parentBind) return;
51
51
  const modelitem = parentBind.getModelItem();
52
52
  const setval = this.shadowRoot.getElementById('setvalue');
@@ -62,7 +62,7 @@ export class FxItems extends FxControl {
62
62
  async updateWidgetValue() {
63
63
  // console.log('setting items value');
64
64
 
65
- const parentBind = this.parentNode.closest('[ref]');
65
+ const parentBind = Fore.getClosest('[ref]', this.parentNode);
66
66
  if (parentBind) {
67
67
  this.value = parentBind.value;
68
68
  }
@@ -115,4 +115,6 @@ export class FxItems extends FxControl {
115
115
  }
116
116
  }
117
117
 
118
- customElements.define('fx-items', FxItems);
118
+ if (!customElements.get('fx-items')) {
119
+ customElements.define('fx-items', FxItems);
120
+ }
@@ -1,3 +1,4 @@
1
+ import { Fore } from '../fore.js';
1
2
  import XfAbstractControl from './abstract-control.js';
2
3
  import { evaluateXPath, evaluateXPathToStrings } from '../xpath-evaluation.js';
3
4
  import getInScopeContext from '../getInScopeContext.js';
@@ -7,6 +8,7 @@ import getInScopeContext from '../getInScopeContext.js';
7
8
  * todo: review placing of value. should probably work with value attribute and not allow slotted content.
8
9
  */
9
10
  export class FxOutput extends XfAbstractControl {
11
+ /*
10
12
  static get properties() {
11
13
  return {
12
14
  ...super.properties,
@@ -16,10 +18,13 @@ export class FxOutput extends XfAbstractControl {
16
18
  };
17
19
  }
18
20
 
21
+ */
19
22
  constructor() {
20
23
  super();
21
24
  this.attachShadow({ mode: 'open' });
22
25
  this.valueAttr = this.hasAttribute('value') ? this.getAttribute('value') : null;
26
+ // Outputs are always readonly!
27
+ this.readonly = true;
23
28
  }
24
29
 
25
30
  connectedCallback() {
@@ -62,9 +67,11 @@ export class FxOutput extends XfAbstractControl {
62
67
  // console.log('widget ', this.widget);
63
68
  this.mediatype = this.hasAttribute('mediatype') ? this.getAttribute('mediatype') : null;
64
69
 
70
+ /*
65
71
  this.addEventListener('slotchange', e => {
66
72
  console.log('slotchange ', e);
67
73
  });
74
+ */
68
75
  }
69
76
 
70
77
  async refresh() {
@@ -85,13 +92,13 @@ export class FxOutput extends XfAbstractControl {
85
92
  try {
86
93
  const inscopeContext = getInScopeContext(this, this.valueAttr);
87
94
  if (this.hasAttribute('html')) {
88
- return evaluateXPath(this.valueAttr, inscopeContext, this);
95
+ return evaluateXPath(this.valueAttr, inscopeContext, this)[0];
89
96
  }
90
97
 
91
98
  return evaluateXPathToStrings(this.valueAttr, inscopeContext, this)[0];
92
99
  } catch (error) {
93
100
  console.error(error);
94
- this.dispatch('error', { message: error });
101
+ Fore.dispatch(this, 'error', { message: error });
95
102
  }
96
103
  return null;
97
104
  }
@@ -101,8 +108,13 @@ export class FxOutput extends XfAbstractControl {
101
108
  return valueWrapper;
102
109
  }
103
110
 
111
+ handleReadonly() {
112
+ // An output is always read-only
113
+ this.setAttribute('readonly', 'readonly');
114
+ }
115
+
104
116
  async updateWidgetValue() {
105
- console.log('updateWidgetValue');
117
+ // console.log('updateWidgetValue');
106
118
  const valueWrapper = this.shadowRoot.getElementById('value');
107
119
 
108
120
  if (this.mediatype === 'markdown') {
@@ -150,9 +162,10 @@ export class FxOutput extends XfAbstractControl {
150
162
  }
151
163
 
152
164
  isReadonly() {
153
- this.readonly = true;
154
- return this.readonly;
165
+ return true;
155
166
  }
156
167
  }
157
168
 
158
- customElements.define('fx-output', FxOutput);
169
+ if (!customElements.get('fx-output')) {
170
+ customElements.define('fx-output', FxOutput);
171
+ }
@@ -4,7 +4,7 @@ import { Fore } from '../fore.js';
4
4
  import { foreElementMixin } from '../ForeElementMixin.js';
5
5
  import { evaluateXPath } from '../xpath-evaluation.js';
6
6
  import getInScopeContext from '../getInScopeContext.js';
7
- import { XPathUtil } from '../xpath-util';
7
+ import { XPathUtil } from '../xpath-util.js';
8
8
 
9
9
  /**
10
10
  * `fx-repeat`
@@ -18,6 +18,8 @@ import { XPathUtil } from '../xpath-util';
18
18
  *
19
19
  * @customElement
20
20
  * @demo demo/todo.html
21
+ *
22
+ * todo: it should be seriously be considered to extend FxContainer instead but needs refactoring first.
21
23
  */
22
24
  export class FxRepeat extends foreElementMixin(HTMLElement) {
23
25
  static get properties() {
@@ -133,7 +135,7 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
133
135
  // const index = prev.index();
134
136
  // this.applyIndex(this.index -1);
135
137
 
136
- this.dispatch('path-mutated', { path, index: this.index });
138
+ Fore.dispatch(this, 'path-mutated', { path, index: this.index });
137
139
  }
138
140
  }
139
141
  });
@@ -197,31 +199,13 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
197
199
  });
198
200
  }
199
201
 
200
- const seq = evaluateXPath(this.ref, inscope, this);
201
- // const seq = evaluateXPathToNodes(this.ref, inscope, this.getOwnerForm());
202
- if (seq === null) {
203
- // Empty sequence
204
- this.nodeset = [];
202
+ const rawNodeset = evaluateXPath(this.ref, inscope, this);
203
+ if (rawNodeset.length === 1 && Array.isArray(rawNodeset[0])) {
204
+ // This XPath likely returned an XPath array. Just collapse to that array
205
+ this.nodeset = rawNodeset[0];
205
206
  return;
206
207
  }
207
-
208
- if (typeof seq === 'object') {
209
- // Either a node or an array
210
- if ('nodeType' in seq) {
211
- // Node
212
- this.nodeset = [seq];
213
- return;
214
- }
215
-
216
- // if (Array.isArray(seq) && seq.every(item => typeof item === 'object')) {
217
- if (Array.isArray(seq)) {
218
- // multiple Nodes or maps
219
- this.nodeset = seq;
220
- return;
221
- }
222
- }
223
-
224
- throw new Error(`Unexpected result of repeat nodeset: ${seq}`);
208
+ this.nodeset = rawNodeset;
225
209
  }
226
210
 
227
211
  async refresh(force) {
@@ -269,6 +253,7 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
269
253
 
270
254
  newItem.nodeset = this.nodeset[position - 1];
271
255
  newItem.index = position;
256
+ this.getOwnerForm().someInstanceDataStructureChanged = true;
272
257
  }
273
258
  }
274
259
 
@@ -410,4 +395,6 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
410
395
  }
411
396
  }
412
397
 
413
- window.customElements.define('fx-repeat', FxRepeat);
398
+ if (!customElements.get('fx-repeat')) {
399
+ window.customElements.define('fx-repeat', FxRepeat);
400
+ }
@@ -73,16 +73,20 @@ export class FxRepeatitem extends foreElementMixin(HTMLElement) {
73
73
  this.inited = true;
74
74
  }
75
75
 
76
+ /*
76
77
  getModelItem() {
77
78
  super.getModelItem();
78
79
  // console.log('modelItem in repeatitem ', this.getModelItem()[this.index]);
79
80
  return this.getModelItem()[this.index];
80
81
  }
82
+ */
81
83
 
82
84
  refresh(force) {
83
- // console.log('refresh repeatitem: ',this.nodeset);
84
- // console.log('refresh repeatitem nodeset: ',this.nodeset);
85
- this.modelItem = this.getModel().getModelItem(this.nodeset);
85
+ this.modelItem = this.getModelItem();
86
+ // ### register ourselves as boundControl
87
+ if (!this.modelItem.boundControls.includes(this)) {
88
+ this.modelItem.boundControls.push(this);
89
+ }
86
90
 
87
91
  if (this.modelItem && !this.modelItem.relevant) {
88
92
  // await Fore.fadeOutElement(this)
@@ -105,4 +109,6 @@ export class FxRepeatitem extends foreElementMixin(HTMLElement) {
105
109
  }
106
110
  }
107
111
 
108
- window.customElements.define('fx-repeatitem', FxRepeatitem);
112
+ if (!customElements.get('fx-repeatitem')) {
113
+ window.customElements.define('fx-repeatitem', FxRepeatitem);
114
+ }
@@ -39,7 +39,7 @@ class FxSwitch extends FxContainer {
39
39
  refresh() {
40
40
  super.refresh();
41
41
  console.log('refresh on switch ');
42
- const cases = this.querySelectorAll('fx-case');
42
+ const cases = this.querySelectorAll(':scope > fx-case');
43
43
  if (this.isBound()) {
44
44
  Array.from(cases).forEach(caseElem => {
45
45
  const name = caseElem.getAttribute('name');
@@ -50,7 +50,7 @@ class FxSwitch extends FxContainer {
50
50
  }
51
51
  });
52
52
  } else {
53
- const selected = this.querySelector('.selected-case');
53
+ const selected = this.querySelector(':scope > .selected-case');
54
54
  if (!selected) {
55
55
  cases[0].classList.add('selected-case');
56
56
  }
@@ -74,4 +74,6 @@ class FxSwitch extends FxContainer {
74
74
  }
75
75
  }
76
76
 
77
- window.customElements.define('fx-switch', FxSwitch);
77
+ if (!customElements.get('fx-switch')) {
78
+ window.customElements.define('fx-switch', FxSwitch);
79
+ }
@@ -110,4 +110,6 @@ export class FxTrigger extends XfAbstractControl {
110
110
  */
111
111
  }
112
112
 
113
- customElements.define('fx-trigger', FxTrigger);
113
+ if (!customElements.get('fx-trigger')) {
114
+ customElements.define('fx-trigger', FxTrigger);
115
+ }