@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,5 +1,6 @@
1
- import { FxAction } from './fx-action.js';
2
- import {AbstractAction} from "./abstract-action";
1
+ import { Fore } from '../fore.js';
2
+ import { AbstractAction } from './abstract-action.js';
3
+ import { resolveId } from '../xpath-evaluation.js';
3
4
 
4
5
  /**
5
6
  * `fx-hide`
@@ -11,14 +12,16 @@ import {AbstractAction} from "./abstract-action";
11
12
  export class FxHide extends AbstractAction {
12
13
  connectedCallback() {
13
14
  this.dialog = this.getAttribute('dialog');
14
- if(!this.dialog){
15
- this.dispatch('error',{message:'dialog does not exist'})
15
+ if (!this.dialog) {
16
+ Fore.dispatch(this, 'error', { message: 'dialog does not exist' });
16
17
  }
17
18
  }
18
19
 
19
20
  perform() {
20
- document.getElementById(this.dialog).hide();
21
+ resolveId(this.dialog, this).hide();
21
22
  }
22
23
  }
23
24
 
24
- window.customElements.define('fx-hide', FxHide);
25
+ if (!customElements.get('fx-hide')) {
26
+ window.customElements.define('fx-hide', FxHide);
27
+ }
@@ -1,7 +1,6 @@
1
1
  import { AbstractAction } from './abstract-action.js';
2
2
  import getInScopeContext from '../getInScopeContext.js';
3
3
  import {
4
- evaluateXPath,
5
4
  evaluateXPathToNodes,
6
5
  evaluateXPathToFirstNode,
7
6
  evaluateXPathToNumber,
@@ -47,6 +46,12 @@ export class FxInsert extends AbstractAction {
47
46
  // ### if there's an origin attribute use it
48
47
  let originTarget;
49
48
  try {
49
+ /*
50
+ todo: discuss where to pass vars from event.detail into function context
51
+ */
52
+ // this.setInScopeVariables(this.detail);
53
+
54
+ // originTarget = evaluateXPathToFirstNode(this.origin, inscope, this);
50
55
  originTarget = evaluateXPathToFirstNode(this.origin, inscope, this.getOwnerForm());
51
56
  if (Array.isArray(originTarget) && originTarget.length === 0) {
52
57
  console.warn('invalid origin for this insert action - ignoring...', this);
@@ -88,15 +93,19 @@ export class FxInsert extends AbstractAction {
88
93
  let inscope;
89
94
  // ### 'context' attribute takes precedence over 'ref'
90
95
  let targetSequence;
91
- if(this.hasAttribute('context')){
96
+ if (this.hasAttribute('context')) {
92
97
  inscope = getInScopeContext(this.getAttributeNode('context'), this.getAttribute('context'));
93
- targetSequence = evaluateXPathToNodes(this.getAttribute('context'), inscope, this.getOwnerForm());
98
+ targetSequence = evaluateXPathToNodes(
99
+ this.getAttribute('context'),
100
+ inscope,
101
+ this.getOwnerForm(),
102
+ );
94
103
  }
95
104
 
96
- if(this.hasAttribute('ref')){
97
- if(inscope){
105
+ if (this.hasAttribute('ref')) {
106
+ if (inscope) {
98
107
  targetSequence = evaluateXPathToNodes(this.ref, inscope, this.getOwnerForm());
99
- }else{
108
+ } else {
100
109
  inscope = getInScopeContext(this.getAttributeNode('ref'), this.ref);
101
110
  targetSequence = evaluateXPathToNodes(this.ref, inscope, this.getOwnerForm());
102
111
  }
@@ -117,7 +126,6 @@ export class FxInsert extends AbstractAction {
117
126
  index = 1;
118
127
  console.log('appended', inscope);
119
128
  } else {
120
-
121
129
  /* ### insert at position given by 'at' or use the last item in the targetSequence ### */
122
130
  if (this.hasAttribute('at')) {
123
131
  // todo: eval 'at'
@@ -137,7 +145,11 @@ export class FxInsert extends AbstractAction {
137
145
  index = 1;
138
146
 
139
147
  insertLocationNode = targetSequence;
140
- const context = evaluateXPath('count(preceding::*)', targetSequence, this.getOwnerForm());
148
+ const context = evaluateXPathToNumber(
149
+ 'count(preceding::*)',
150
+ targetSequence,
151
+ this.getOwnerForm(),
152
+ );
141
153
  // console.log('context', context);
142
154
  index = context + 1;
143
155
  // index = targetSequence.findIndex(insertLocationNode);
@@ -152,14 +164,13 @@ export class FxInsert extends AbstractAction {
152
164
  // insertLocationNode.parentNode.append(originSequence);
153
165
  // const nextSibl = insertLocationNode.nextSibling;
154
166
  index += 1;
155
- if(this.hasAttribute('context') && this.hasAttribute('ref')){
167
+ if (this.hasAttribute('context') && this.hasAttribute('ref')) {
156
168
  // index=1;
157
169
  inscope.append(originSequenceClone);
158
- }else if(this.hasAttribute('context')){
159
- const contextAttr = this.getAttribute('context');
160
- index=1;
170
+ } else if (this.hasAttribute('context')) {
171
+ index = 1;
161
172
  insertLocationNode.prepend(originSequenceClone);
162
- }else{
173
+ } else {
163
174
  insertLocationNode.insertAdjacentElement('afterend', originSequenceClone);
164
175
  }
165
176
  }
@@ -232,4 +243,6 @@ export class FxInsert extends AbstractAction {
232
243
  }
233
244
  }
234
245
 
235
- window.customElements.define('fx-insert', FxInsert);
246
+ if (!customElements.get('fx-insert')) {
247
+ window.customElements.define('fx-insert', FxInsert);
248
+ }
@@ -61,4 +61,6 @@ class FxMessage extends AbstractAction {
61
61
  }
62
62
  }
63
63
 
64
- window.customElements.define('fx-message', FxMessage);
64
+ if (!customElements.get('fx-message')) {
65
+ window.customElements.define('fx-message', FxMessage);
66
+ }
@@ -1,4 +1,6 @@
1
1
  import { AbstractAction } from './abstract-action.js';
2
+ import { Fore } from '../fore.js';
3
+ import {resolveId} from "../xpath-evaluation.js";
2
4
 
3
5
  /**
4
6
  * `fx-refresh`
@@ -8,8 +10,29 @@ import { AbstractAction } from './abstract-action.js';
8
10
  */
9
11
  class FxRefresh extends AbstractAction {
10
12
  perform() {
13
+ if (this.hasAttribute('self')) {
14
+ const control = Fore.getClosest('fx-control', this);
15
+ if (control) {
16
+ control.refresh();
17
+ return;
18
+ }
19
+ }
20
+ if(this.hasAttribute('force')){
21
+ this.getOwnerForm().forceRefresh();
22
+ return;
23
+ }
24
+ if(this.hasAttribute('control')){
25
+ const targetId = this.getAttribute('control');
26
+ const ctrl = resolveId(targetId, this);
27
+ if (Fore.isUiElement(ctrl.nodeName) && typeof ctrl.refresh === 'function') {
28
+ ctrl.refresh();
29
+ }
30
+ return;
31
+ }
11
32
  this.getOwnerForm().refresh();
12
33
  }
13
34
  }
14
35
 
15
- window.customElements.define('fx-refresh', FxRefresh);
36
+ if (!customElements.get('fx-refresh')) {
37
+ window.customElements.define('fx-refresh', FxRefresh);
38
+ }
@@ -0,0 +1,74 @@
1
+ // import { FxAction } from './fx-action.js';
2
+ import '../fx-model.js';
3
+ import { AbstractAction } from './abstract-action.js';
4
+ import { evaluateXPathToFirstNode } from '../xpath-evaluation.js';
5
+ import getInScopeContext from "../getInScopeContext";
6
+
7
+ /**
8
+ * `fx-replace` - replaces the node referred to with 'ref' with node referred to with 'with' attribute.
9
+ *
10
+ * @customElement
11
+ */
12
+ export default class FxReplace extends AbstractAction {
13
+ static get properties() {
14
+ return {
15
+ ...super.properties,
16
+ with: {
17
+ type: String,
18
+ },
19
+ replaceNode: Object,
20
+ };
21
+ }
22
+
23
+ constructor() {
24
+ super();
25
+ this.with = '';
26
+ }
27
+
28
+ connectedCallback() {
29
+ if (super.connectedCallback) {
30
+ super.connectedCallback();
31
+ }
32
+ this.with = this.getAttribute('with');
33
+ }
34
+
35
+ perform() {
36
+ super.perform();
37
+ console.log('replace action');
38
+ // console.log('replace action variables', this.inScopeVariables);
39
+ // if (!this.nodeset) {
40
+ // return;
41
+ // }
42
+ const target = evaluateXPathToFirstNode(this.with, this.nodeset, this);
43
+ if (!target) return;
44
+
45
+
46
+ this.replace(this.nodeset, target);
47
+ }
48
+
49
+ replace(toReplace, replaceWith) {
50
+ console.log('replace', toReplace, replaceWith);
51
+ if (!toReplace || !replaceWith) return; // bail out silently
52
+ if (!toReplace.nodeName || !replaceWith.nodeName) {
53
+ console.warn('fx-replace: one argument is not a node');
54
+ return;
55
+ }
56
+
57
+ if (toReplace.nodeType === Node.ATTRIBUTE_NODE) {
58
+ const { ownerElement } = toReplace;
59
+ ownerElement.setAttribute(replaceWith.nodeName, replaceWith.textContent);
60
+ ownerElement.removeAttribute(toReplace.nodeName);
61
+ console.log('owner', ownerElement);
62
+ } else if (toReplace.nodeType === Node.ELEMENT_NODE) {
63
+ const cloned = replaceWith.cloneNode(true);
64
+ toReplace.replaceWith(cloned);
65
+ }
66
+ // const modelitem = this.getModelItem();
67
+ // this.getModel().changed.push(modelitem);
68
+ this.needsUpdate = true;
69
+ }
70
+ }
71
+
72
+ if (!customElements.get('fx-replace')) {
73
+ window.customElements.define('fx-replace', FxReplace);
74
+ }
@@ -0,0 +1,42 @@
1
+ import { AbstractAction } from './abstract-action.js';
2
+
3
+ /**
4
+ * `fx-return`
5
+ * returns data from a nested Fore to it's host Fore.
6
+ *
7
+ * behaves like a `<fx-submission @replace='instance' with `targetref` and respects relevance processing.
8
+ *
9
+ * `targetref` will be the `ref` of the host control.
10
+ *
11
+ * todo: deos not relevant selection yet
12
+ *
13
+ * @customElement
14
+ */
15
+ export class FxReturn extends AbstractAction {
16
+ connectedCallback() {
17
+ if (super.connectedCallback) {
18
+ super.connectedCallback();
19
+ }
20
+ // const nonrelevant = this.hasAttribute('nonrelevant') ? this.getAttribute('nonrelevant') : null;
21
+ }
22
+
23
+ perform() {
24
+ super.perform();
25
+ console.log('performing return with nodes', this.nodeset);
26
+
27
+ /*
28
+ ### note that this event does not use Fore.dispatch as the event uses 'composed:true' to let the event travel
29
+ up through the shadowRoot and being catched in outer form.
30
+ */
31
+ const event = new CustomEvent('return', {
32
+ composed: true,
33
+ bubbles: true,
34
+ detail: { nodeset: this.nodeset },
35
+ });
36
+ this.getOwnerForm().dispatchEvent(event);
37
+ }
38
+ }
39
+
40
+ if (!customElements.get('fx-return')) {
41
+ window.customElements.define('fx-return', FxReturn);
42
+ }
@@ -45,4 +45,6 @@ class FxSend extends AbstractAction {
45
45
  }
46
46
  }
47
47
 
48
- window.customElements.define('fx-send', FxSend);
48
+ if (!customElements.get('fx-send')) {
49
+ window.customElements.define('fx-send', FxSend);
50
+ }
@@ -0,0 +1,37 @@
1
+ import {AbstractAction} from "./abstract-action";
2
+ import {resolveId} from "../xpath-evaluation";
3
+
4
+ /**
5
+ * `fx-setfocus`
6
+ * Set the focus to a target control.
7
+ *
8
+ * @customElement
9
+ */
10
+ export class FxSetfocus extends AbstractAction {
11
+ connectedCallback() {
12
+ super.connectedCallback();
13
+ this.control = this.hasAttribute('control') ? this.getAttribute('control') : null;
14
+ }
15
+
16
+ perform() {
17
+ console.log('setting focus', this.control);
18
+ // super.perform();
19
+
20
+ // const targetElement = resolveId(this.control, this);
21
+ const selector = '#'+this.control;
22
+ let targetElement = document.querySelector(selector);
23
+ const repeatitem = targetElement.closest('fx-repeatitem, .fx-repeatitem');
24
+ if(repeatitem){
25
+ // targetElement is repeated
26
+ // get the active repeatitem (only for fx-repeat for now - todo: support repeat attributes
27
+ const repeat = repeatitem.parentNode;
28
+ targetElement = repeat.querySelector('[repeat-index] ' + selector);
29
+
30
+ }
31
+ targetElement.getWidget().focus();
32
+ }
33
+ }
34
+
35
+ if (!customElements.get('fx-setfocus')) {
36
+ window.customElements.define('fx-setfocus', FxSetfocus);
37
+ }
@@ -1,7 +1,7 @@
1
1
  // import { FxAction } from './fx-action.js';
2
2
  import '../fx-model.js';
3
- import { AbstractAction } from './abstract-action.js';
4
- import { evaluateXPath } from '../xpath-evaluation.js';
3
+ import {AbstractAction} from './abstract-action.js';
4
+ import {evaluateXPath} from '../xpath-evaluation.js';
5
5
 
6
6
  /**
7
7
  * `fx-setvalue`
@@ -9,64 +9,71 @@ import { evaluateXPath } from '../xpath-evaluation.js';
9
9
  * @customElement
10
10
  */
11
11
  export default class FxSetvalue extends AbstractAction {
12
- static get properties() {
13
- return {
14
- ...super.properties,
15
- ref: {
16
- type: String,
17
- },
18
- valueAttr: {
19
- type: String,
20
- },
21
- };
22
- }
23
-
24
- constructor() {
25
- super();
26
- this.ref = '';
27
- this.valueAttr = '';
28
- }
12
+ static get properties() {
13
+ return {
14
+ ...super.properties,
15
+ ref: {
16
+ type: String,
17
+ },
18
+ valueAttr: {
19
+ type: String,
20
+ },
21
+ };
22
+ }
29
23
 
30
- connectedCallback() {
31
- if (super.connectedCallback) {
32
- super.connectedCallback();
24
+ constructor() {
25
+ super();
26
+ this.ref = '';
27
+ this.valueAttr = '';
33
28
  }
34
29
 
35
- if (this.hasAttribute('ref')) {
36
- this.ref = this.getAttribute('ref');
37
- } else {
38
- throw new Error('fx-setvalue must specify a "ref" attribute');
30
+ connectedCallback() {
31
+ if (super.connectedCallback) {
32
+ super.connectedCallback();
33
+ }
34
+
35
+ if (this.hasAttribute('ref')) {
36
+ this.ref = this.getAttribute('ref');
37
+ } else {
38
+ throw new Error('fx-setvalue must specify a "ref" attribute');
39
+ }
40
+ this.valueAttr = this.getAttribute('value');
39
41
  }
40
- this.valueAttr = this.getAttribute('value');
41
- }
42
42
 
43
- perform() {
44
- super.perform();
45
- let { value } = this;
46
- if (this.valueAttr !== null) {
47
- value = evaluateXPath(this.valueAttr, this.nodeset, this, this.detail);
48
- } else if (this.textContent !== '') {
49
- value = this.textContent;
50
- } else {
51
- value = '';
43
+ perform() {
44
+ super.perform();
45
+ let {value} = this;
46
+ if (this.valueAttr !== null) {
47
+ [value] = evaluateXPath(this.valueAttr, this.nodeset, this, this.detail);
48
+ } else if (this.textContent !== '') {
49
+ value = this.textContent;
50
+ } else {
51
+ value = '';
52
+ }
53
+ console.log('value', value);
54
+ if (value.nodeType === Node.ATTRIBUTE_NODE) {
55
+ console.log('value', value.nodeValue);
56
+ value = value.nodeValue;
57
+ }
58
+ const mi = this.getModelItem();
59
+ this.setValue(mi, value);
52
60
  }
53
- const mi = this.getModelItem();
54
- this.setValue(mi, value);
55
- }
56
61
 
57
- setValue(modelItem, newVal) {
58
- console.log('setvalue[1] ', modelItem, newVal);
62
+ setValue(modelItem, newVal) {
63
+ console.log('setvalue[1] ', modelItem, newVal);
59
64
 
60
- const item = modelItem;
61
- if (!item) return;
65
+ const item = modelItem;
66
+ if (!item) return;
62
67
 
63
- if (item.value !== newVal) {
64
- item.value = newVal;
65
- this.getModel().changed.push(modelItem);
66
- this.needsUpdate = true;
67
- console.log('setvalue[2] ', item, newVal);
68
+ if (item.value !== newVal) {
69
+ item.value = newVal;
70
+ this.getModel().changed.push(modelItem);
71
+ this.needsUpdate = true;
72
+ console.log('setvalue[2] ', item, newVal);
73
+ }
68
74
  }
69
- }
70
75
  }
71
76
 
72
- window.customElements.define('fx-setvalue', FxSetvalue);
77
+ if (!customElements.get('fx-setvalue')) {
78
+ window.customElements.define('fx-setvalue', FxSetvalue);
79
+ }
@@ -1,4 +1,6 @@
1
+ import { Fore } from '../fore.js';
1
2
  import { FxAction } from './fx-action.js';
3
+ import { resolveId } from '../xpath-evaluation.js';
2
4
 
3
5
  /**
4
6
  * `fx-confirm`
@@ -10,14 +12,20 @@ import { FxAction } from './fx-action.js';
10
12
  export class FxShow extends FxAction {
11
13
  connectedCallback() {
12
14
  this.dialog = this.getAttribute('dialog');
13
- if(!this.dialog){
14
- this.dispatch('error',{message:'dialog does not exist'})
15
+ if (!this.dialog) {
16
+ Fore.dispatch(this, 'error', { message: 'dialog does not exist' });
15
17
  }
16
18
  }
17
19
 
18
20
  perform() {
19
- document.getElementById(this.dialog).open();
21
+ const targetDlg = resolveId(this.dialog,this);
22
+ if(!targetDlg){
23
+ console.error('target dialog with given id does not exist',this.dialog);
24
+ }
25
+ targetDlg.open();
20
26
  }
21
27
  }
22
28
 
23
- window.customElements.define('fx-show', FxShow);
29
+ if (!customElements.get('fx-show')) {
30
+ window.customElements.define('fx-show', FxShow);
31
+ }
@@ -1,22 +1,23 @@
1
- import { FxAction } from './fx-action.js';
1
+ import { AbstractAction } from './abstract-action.js';
2
2
 
3
3
  /**
4
4
  * `fx-toggle`
5
5
  *
6
6
  */
7
- class FxToggle extends FxAction {
7
+ class FxToggle extends AbstractAction {
8
+ /*
9
+ constructor() {
10
+ super();
11
+ this.attachShadow({ mode: 'open' });
12
+ }
13
+ */
8
14
  connectedCallback() {
15
+ super.connectedCallback();
9
16
  if (this.hasAttribute('case')) {
10
17
  this.case = this.getAttribute('case');
11
18
  }
12
19
  }
13
20
 
14
- /*
15
- disconnectedCallback() {
16
- super.disconnectedCallback();
17
- }
18
-
19
- */
20
21
  perform() {
21
22
  super.perform();
22
23
  console.log('### fx-toggle.execute ');
@@ -26,7 +27,10 @@ class FxToggle extends FxAction {
26
27
  const fxSwitch = caseElement.parentNode;
27
28
  fxSwitch.toggle(caseElement);
28
29
  }
30
+ // this.needsUpdate = true;
29
31
  }
30
32
  }
31
33
 
32
- window.customElements.define('fx-toggle', FxToggle);
34
+ if (!customElements.get('fx-toggle')) {
35
+ window.customElements.define('fx-toggle', FxToggle);
36
+ }
@@ -12,4 +12,6 @@ class FxUpdate extends AbstractAction {
12
12
  }
13
13
  }
14
14
 
15
- window.customElements.define('fx-update', FxUpdate);
15
+ if (!customElements.get('fx-update')) {
16
+ window.customElements.define('fx-update', FxUpdate);
17
+ }
package/src/dep_graph.js CHANGED
@@ -80,7 +80,7 @@ function createDFS(edges, leavesOnly, result, circular) {
80
80
  currentPath.push(node);
81
81
  window.dispatchEvent(
82
82
  new CustomEvent('compute-exception', {
83
- composed: true,
83
+ composed: false,
84
84
  bubbles: true,
85
85
  detail: {
86
86
  path: currentPath,