@jinntec/fore 1.0.0-3 → 1.0.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 (62) hide show
  1. package/README.md +25 -34
  2. package/dist/fore-dev.js +43 -0
  3. package/dist/fore-dev.js.map +1 -0
  4. package/dist/fore.js +36 -1
  5. package/dist/fore.js.map +1 -0
  6. package/index.js +3 -0
  7. package/package.json +34 -38
  8. package/resources/fore.css +35 -50
  9. package/src/DependencyNotifyingDomFacade.js +10 -16
  10. package/src/ForeElementMixin.js +25 -18
  11. package/src/actions/abstract-action.js +17 -9
  12. package/src/actions/fx-action.js +6 -4
  13. package/src/actions/fx-append.js +8 -17
  14. package/src/actions/fx-confirm.js +3 -1
  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 +10 -6
  18. package/src/actions/fx-insert.js +49 -39
  19. package/src/actions/fx-message.js +3 -1
  20. package/src/actions/fx-refresh.js +11 -1
  21. package/src/actions/fx-replace.js +68 -0
  22. package/src/actions/fx-return.js +42 -0
  23. package/src/actions/fx-send.js +3 -1
  24. package/src/actions/fx-setvalue.js +58 -51
  25. package/src/actions/fx-show.js +8 -4
  26. package/src/actions/fx-toggle.js +15 -10
  27. package/src/actions/fx-update.js +3 -1
  28. package/src/dep_graph.js +4 -2
  29. package/src/drawdown.js +67 -82
  30. package/src/fore.js +158 -11
  31. package/src/functions/fx-function.js +11 -3
  32. package/src/fx-bind.js +42 -202
  33. package/src/fx-fore.js +105 -70
  34. package/src/fx-header.js +3 -1
  35. package/src/fx-instance.js +9 -1
  36. package/src/fx-model.js +31 -23
  37. package/src/fx-submission.js +73 -47
  38. package/src/fx-var.js +7 -4
  39. package/src/getInScopeContext.js +37 -11
  40. package/src/modelitem.js +4 -4
  41. package/src/relevance.js +65 -0
  42. package/src/ui/abstract-control.js +55 -35
  43. package/src/ui/fx-alert.js +7 -1
  44. package/src/ui/fx-case.js +3 -1
  45. package/src/ui/fx-container.js +7 -1
  46. package/src/ui/fx-control.js +283 -33
  47. package/src/ui/fx-dialog.js +54 -40
  48. package/src/ui/fx-group.js +3 -1
  49. package/src/ui/fx-hint.js +4 -1
  50. package/src/ui/fx-inspector.js +117 -17
  51. package/src/ui/fx-items.js +8 -8
  52. package/src/ui/fx-output.js +14 -5
  53. package/src/ui/fx-repeat.js +33 -41
  54. package/src/ui/fx-repeatitem.js +10 -4
  55. package/src/ui/fx-switch.js +3 -1
  56. package/src/ui/fx-trigger.js +3 -1
  57. package/src/xpath-evaluation.js +121 -131
  58. package/src/xpath-util.js +14 -7
  59. package/dist/fore-all.js +0 -140
  60. package/src/.DS_Store +0 -0
  61. package/src/actions/.DS_Store +0 -0
  62. package/src/ui/.DS_Store +0 -0
package/index.js CHANGED
@@ -35,8 +35,11 @@ import './src/actions/fx-toggle.js';
35
35
  import './src/actions/fx-dispatch.js';
36
36
  import './src/actions/fx-update.js';
37
37
  import './src/actions/fx-refresh.js';
38
+ import './src/actions/fx-replace.js';
39
+ import './src/actions/fx-return.js';
38
40
  import './src/actions/fx-confirm.js';
39
41
  import './src/actions/fx-show.js';
40
42
  import './src/actions/fx-hide.js';
41
43
 
42
44
  import './src/functions/fx-function.js';
45
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jinntec/fore",
3
- "version": "1.0.0-3",
3
+ "version": "1.0.0",
4
4
  "description": "Fore - Forms for the Web",
5
5
  "module": "./index.js",
6
6
  "publishConfig": {
@@ -24,56 +24,52 @@
24
24
  "resources/toastify.css",
25
25
  "src/**/*",
26
26
  "dist/fore.js",
27
- "dist/fore-all.js"
27
+ "dist/fore.js.map",
28
+ "dist/fore-dev.js",
29
+ "dist/fore-dev.js.map",
30
+ "!.DS_Store"
28
31
  ],
29
32
  "dependencies": {
30
- "@jinntec/jinn-toast": "^1.0.2",
31
- "@polymer/iron-component-page": "^4.0.1",
32
- "@polymer/iron-demo-helpers": "^3.1.0",
33
- "@polymer/paper-button": "^3.0.1",
34
- "@polymer/paper-checkbox": "^3.1.0",
35
- "@polymer/paper-dialog": "^3.0.1",
36
- "@polymer/paper-dialog-scrollable": "^3.0.1",
37
- "@polymer/paper-input": "^3.2.1",
38
- "fontoxpath": "^3.20.4",
39
- "web-component-analyzer": "^1.1.6"
33
+ "@jinntec/jinn-toast": "^1.0.4",
34
+ "fontoxpath": "^3.26.0"
40
35
  },
41
36
  "devDependencies": {
42
- "@babel/plugin-proposal-class-properties": "^7.13.0",
43
- "@open-wc/building-rollup": "^0.21.1",
44
- "@open-wc/eslint-config": "^2.0.0",
37
+ "@babel/plugin-proposal-class-properties": "^7.17.12",
38
+ "@open-wc/building-rollup": "^2.0.1",
39
+ "@open-wc/eslint-config": "^7.0.0",
45
40
  "@open-wc/prettier-config": "^0.1.10",
46
- "@open-wc/semantic-dom-diff": "^0.19.4",
47
- "@open-wc/testing": "^2.0.0",
41
+ "@open-wc/semantic-dom-diff": "^0.19.6",
42
+ "@open-wc/testing": "^3.1.5",
48
43
  "@open-wc/testing-karma": "^4.0.9",
49
- "@open-wc/testing-karma-bs": "^1.0.0",
50
- "@rollup/plugin-commonjs": "^11.1.0",
51
- "@rollup/plugin-node-resolve": "^6.1.0",
44
+ "@open-wc/testing-karma-bs": "^1.3.94",
45
+ "@rollup/plugin-commonjs": "^22.0.0",
46
+ "@rollup/plugin-node-resolve": "^13.3.0",
52
47
  "@rollup/plugin-strip": "^2.1.0",
53
48
  "@skypack/package-check": "^0.2.2",
54
- "@webcomponents/webcomponentsjs": "^2.0.0",
55
- "deepmerge": "^3.3.0",
56
- "es-dev-server": "^1.57.8",
57
- "eslint": "^6.1.0",
58
- "husky": "^1.0.0",
59
- "jsdoc": "^3.6.7",
60
- "lint-staged": "^8.0.0",
61
- "lit-html": "^1.1.2",
62
- "mocha": "^7.0.1",
63
- "np": "^7.5.0",
64
- "rimraf": "^2.7.1",
65
- "rollup": "^1.32.1",
49
+ "@webcomponents/webcomponentsjs": "^2.6.0",
50
+ "deepmerge": "^4.2.2",
51
+ "es-dev-server": "^2.1.0",
52
+ "eslint": "^8.16.0",
53
+ "husky": "^8.0.1",
54
+ "jsdoc": "^3.6.10",
55
+ "lint-staged": "^12.4.3",
56
+ "lit-html": "^2.2.5",
57
+ "mocha": "^10.0.0",
58
+ "np": "^7.6.1",
59
+ "rimraf": "^3.0.2",
60
+ "rollup": "^2.75.4",
66
61
  "rollup-plugin-babel": "^4.4.0",
67
62
  "rollup-plugin-minify-html-literals": "^1.2.6",
68
- "typescript": "^3.7.5",
63
+ "typescript": "^4.7.2",
64
+ "web-component-analyzer": "^1.1.6",
69
65
  "xmlserializer": "^0.6.1"
70
66
  },
71
67
  "scripts": {
72
68
  "test": "karma start",
73
- "lint:eslint": "eslint --ext .js,.html . --ignore-path .gitignore",
74
- "format:eslint": "eslint --ext .js,.html . --fix --ignore-path .gitignore",
75
- "lint:prettier": "prettier \"**/*.js\" --check --ignore-path .gitignore",
76
- "format:prettier": "prettier \"**/*.js\" --write --ignore-path .gitignore",
69
+ "lint:eslint": "eslint --ext .js,.html . --ignore-path .eslintignore",
70
+ "format:eslint": "eslint --ext .js,.html . --fix --ignore-path .eslintignore",
71
+ "lint:prettier": "prettier \"**/*.js\" --check --ignore-path .eslintignore",
72
+ "format:prettier": "prettier \"**/*.js\" --write --ignore-path .eslintignore",
77
73
  "docs": "wca src -f json --outFile fore-elements.json",
78
74
  "lint": "npm run lint:eslint && npm run lint:prettier",
79
75
  "lint:types": "tsc",
@@ -84,7 +80,7 @@
84
80
  "test:bs": "karma start karma.bs.config.js --coverage",
85
81
  "start:build": "cd dist && es-dev-server --open",
86
82
  "build": "rimraf dist && rollup -c rollup.config.js",
87
- "start": "es-dev-server --app-index index.html --node-resolve --watch --open"
83
+ "start": "es-dev-server --app-index doc/index.html --node-resolve --watch --open"
88
84
  },
89
85
  "keywords": [
90
86
  "Fore",
@@ -2,10 +2,13 @@
2
2
  @import 'vars.css';
3
3
 
4
4
  html{
5
- --inspector-bg:var(--paper-grey-500);
5
+ --inspector-bg:var(--paper-grey-300);
6
6
  --inspector-pre-bg:var(--paper-grey-100);
7
7
  --inspector-color:var(--paper-grey-800);
8
8
  --inspector-instance-height:200px;
9
+ --inspector-handle-bg: var(--paper-blue-500);
10
+ --inspector-handle-width: 30px;
11
+
9
12
  }
10
13
  [unresolved]{
11
14
  display: none;
@@ -14,6 +17,19 @@ html{
14
17
  pointer-events: none;
15
18
  cursor: default;
16
19
  }
20
+ input[readonly]{
21
+ background: lightgrey;
22
+ }
23
+
24
+ /* fx-fore{ */
25
+ /* opacity: 0; */
26
+ /* } */
27
+ /* fx-fore.fx-ready{ */
28
+ /* opacity: 1; */
29
+ /* } */
30
+ fx-group, fx-switch, fx-repeat, fx-dialog{
31
+ display: block;
32
+ }
17
33
  fx-trigger a[disabled] {
18
34
  color:lightgrey;
19
35
  }
@@ -35,7 +51,7 @@ fx-model, fx-model *, fx-model ::slotted(fx-instance), fx-instance{
35
51
 
36
52
  fx-control, fx-trigger{
37
53
  white-space: nowrap;
38
- position: relative;
54
+ /* position: relative; */
39
55
  }
40
56
  .fx-checkbox{
41
57
  white-space: nowrap;
@@ -59,56 +75,25 @@ fx-repeatitem{
59
75
  }
60
76
 
61
77
  /* fx-inspector styles */
62
- fx-inspector{
63
- position:fixed;
64
- left:0;
65
- right:0;
66
- bottom:0;
67
- width: 100%;
68
- background: var(--inspector-bg);
69
- color: white;
70
- max-height: 33%;
71
- overflow: scroll;
72
- border-top:3px solid black;
73
- opacity: 0.9;
74
- }
75
- fx-inspector::before{
76
- content:'Instance Inspector';
77
- font-style:italic;
78
- position:absolute;
79
- top:0;
80
- right: 0.3rem;
81
- z-index: 10;
82
- font-size: 0.8rem;
83
- }
84
- fx-inspector details{
85
- padding: 1rem;
86
- }
87
- fx-inspector pre{
88
- background: var(--inspector-pre-bg);
89
- border-radius: 0.5rem;
90
- padding: 0.3rem;
91
- max-height: var(--inspector-instance-height);
92
- /*overflow: scroll;*/
93
- }
94
- fx-inspector details{
95
- overflow: auto;
96
- margin:0;
97
- }
98
- fx-inspector summary{
99
- padding: 0;
100
- }
78
+
79
+ /* ### FX-DIALOG STYLES ### */
80
+ /* ### FX-DIALOG STYLES ### */
81
+ /* ### FX-DIALOG STYLES ### */
101
82
  fx-dialog{
102
83
  display: none;
84
+ opacity: 0;
85
+ transition: opacity 1s linear;
103
86
  }
104
87
  fx-dialog.show{
105
88
  display: block;
106
89
  min-height: 200px;
107
90
  border-radius: 0.5rem;
108
- /*opacity: 0.3;*/
91
+ opacity: 1;
109
92
  background:rgba(0,0,0,0.5);
110
93
  z-index: 10;
94
+ transition: opacity 2s linear;
111
95
  }
96
+
112
97
  fx-dialog.show .dialog-content{
113
98
  padding: 1rem;
114
99
  width:fit-content;
@@ -186,11 +171,11 @@ fx-dialog .action{
186
171
  animation: none;
187
172
  opacity: 1;
188
173
  }
189
- @keyframes fadein {
190
- 0% {
191
- opacity:0;
192
- }
193
- 100% {
194
- opacity:1;
195
- }
196
- }
174
+ /* @keyframes fadein { */
175
+ /* 0% { */
176
+ /* opacity:0; */
177
+ /* } */
178
+ /* 100% { */
179
+ /* opacity:1; */
180
+ /* } */
181
+ /* } */
@@ -45,21 +45,14 @@ export class DependencyNotifyingDomFacade {
45
45
  * @param bucket - The bucket that matches the attribute that will be used.
46
46
  */
47
47
  // eslint-disable-next-line class-methods-use-this
48
- /*
49
48
  getChildNodes(node, bucket) {
50
49
  const matchingNodes = Array.from(node.childNodes).filter(
51
50
  childNode => !bucket || getBucketsForNode(childNode).includes(bucket),
52
51
  );
53
- return matchingNodes;
54
- }
55
- */
56
-
57
- getChildNodes(node, bucket) {
58
- const matchingNodes = Array.from(node.childNodes).filter(
59
- childNode => !bucket || getBucketsForNode(childNode).includes(bucket));
60
52
  matchingNodes.forEach(matchingNode => this._onNodeTouched(matchingNode));
61
53
  return matchingNodes;
62
54
  }
55
+
63
56
  /**
64
57
  * Get the data of this node.
65
58
  *
@@ -83,11 +76,11 @@ export class DependencyNotifyingDomFacade {
83
76
  * @param bucket - The bucket that matches the attribute that will be used.
84
77
  */
85
78
  getFirstChild(node, bucket) {
86
- const matchingNode = Array.from(this.getChildNodes()).filter(
87
- childNode => !bucket || getBucketsForNode(childNode).includes(bucket),
88
- )[0];
89
- if (matchingNode) {
90
- return matchingNode;
79
+ for (const child of node.childNodes) {
80
+ if (!bucket || getBucketsForNode(child).includes(bucket)) {
81
+ this._onNodeTouched(child);
82
+ return child;
83
+ }
91
84
  }
92
85
  return null;
93
86
  }
@@ -120,12 +113,13 @@ export class DependencyNotifyingDomFacade {
120
113
  */
121
114
  // eslint-disable-next-line class-methods-use-this
122
115
  getNextSibling(node, bucket) {
123
- for (let { nextSibling } = node; nextSibling; nextSibling = nextSibling.nextSibling) {
124
- if (!getBucketsForNode(nextSibling).includes(bucket)) {
116
+ for (let sibling = node.nextSibling; sibling; sibling = sibling.nextSibling) {
117
+ if (!getBucketsForNode(sibling).includes(bucket)) {
125
118
  // eslint-disable-next-line no-continue
126
119
  continue;
127
120
  }
128
- return nextSibling;
121
+ this._onNodeTouched(sibling);
122
+ return sibling;
129
123
  }
130
124
  return null;
131
125
  }
@@ -1,5 +1,6 @@
1
1
  import { XPathUtil } from './xpath-util.js';
2
2
  import { FxModel } from './fx-model.js';
3
+ import { Fore } from './fore.js';
3
4
  import {
4
5
  evaluateXPath,
5
6
  evaluateXPathToFirstNode,
@@ -7,6 +8,11 @@ import {
7
8
  } from './xpath-evaluation.js';
8
9
  import getInScopeContext from './getInScopeContext.js';
9
10
 
11
+ /**
12
+ * Mixin containing all general functions that are shared by all Fore element classes.
13
+ * @param superclass
14
+ * @returns {{readonly properties: {ref: {type: StringConstructor}, context: {type: ObjectConstructor}, nodeset: {type: ObjectConstructor}, model: {type: ObjectConstructor}, inScopeVariables: {type: MapConstructor}, modelItem: {type: ObjectConstructor}}, new(): ForeElementMixin, context: null, model: null, modelItem: {}, ref: *|string, inScopeVariables: null, nodeset: *, prototype: ForeElementMixin}}
15
+ */
10
16
  export const foreElementMixin = superclass =>
11
17
  class ForeElementMixin extends superclass {
12
18
  static get properties() {
@@ -94,10 +100,21 @@ export const foreElementMixin = superclass =>
94
100
  */
95
101
  evalInContext() {
96
102
  // const inscopeContext = this.getInScopeContext();
97
- const inscopeContext = getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
103
+ let inscopeContext;
104
+ if (this.hasAttribute('context')) {
105
+ inscopeContext = getInScopeContext(this.getAttributeNode('context') || this, this.context);
106
+ }
107
+ if (this.hasAttribute('ref')) {
108
+ inscopeContext = getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
109
+ }
98
110
  if (!inscopeContext) {
99
- console.warn('no in scopeContext for ', this);
100
- return;
111
+ // ### always fall back to default context with there's neither a 'context' or 'ref' present
112
+ inscopeContext = this.getModel()
113
+ .getDefaultInstance()
114
+ .getDefaultContext();
115
+ // console.warn('no in scopeContext for ', this);
116
+ // console.warn('using default context ', this);
117
+ // return;
101
118
  }
102
119
  if (this.ref === '') {
103
120
  this.nodeset = inscopeContext;
@@ -120,7 +137,7 @@ export const foreElementMixin = superclass =>
120
137
  if (nodeType) {
121
138
  this.nodeset = evaluateXPathToFirstNode(this.ref, inscopeContext, this);
122
139
  } else {
123
- this.nodeset = evaluateXPath(this.ref, inscopeContext, this);
140
+ [this.nodeset] = evaluateXPath(this.ref, inscopeContext, this);
124
141
  }
125
142
  }
126
143
  // console.log('UiElement evaluated to nodeset: ', this.nodeset);
@@ -139,7 +156,7 @@ export const foreElementMixin = superclass =>
139
156
  return this.getAttribute('ref');
140
157
  }
141
158
  // try to get closest parent bind
142
- const parent = this.parentNode.closest('[ref]');
159
+ const parent = Fore.getClosest('[ref]', this.parentNode);
143
160
  if (!parent) {
144
161
  return 'instance()'; // the default instance
145
162
  }
@@ -178,10 +195,10 @@ export const foreElementMixin = superclass =>
178
195
  this.modelItem = mi;
179
196
  }
180
197
 
181
- const repeated = this.closest('fx-repeatitem');
198
+ const repeated = Fore.getClosest('fx-repeatitem', this);
182
199
  let existed;
183
200
  if (repeated) {
184
- const { index } = this.closest('fx-repeatitem');
201
+ const { index } = repeated;
185
202
  if (Array.isArray(this.nodeset)) {
186
203
  existed = this.getModel().getModelItem(this.nodeset[index - 1]);
187
204
  } else {
@@ -211,7 +228,7 @@ export const foreElementMixin = superclass =>
211
228
  return evaluateXPathToString(valAttr, inscopeContext, this.getOwnerForm());
212
229
  } catch (error) {
213
230
  console.error(error);
214
- this.dispatch('error', { message: error });
231
+ Fore.dispatch(this, 'error', { message: error });
215
232
  }
216
233
  }
217
234
  if (this.textContent) {
@@ -227,14 +244,4 @@ export const foreElementMixin = superclass =>
227
244
  setInScopeVariables(inScopeVariables) {
228
245
  this.inScopeVariables = inScopeVariables;
229
246
  }
230
-
231
- dispatch(eventName, detail) {
232
- const event = new CustomEvent(eventName, {
233
- composed: true,
234
- bubbles: true,
235
- detail,
236
- });
237
- // console.log('firing', event);
238
- this.dispatchEvent(event);
239
- }
240
247
  };
@@ -1,5 +1,7 @@
1
1
  import { foreElementMixin } from '../ForeElementMixin.js';
2
- import { evaluateXPathToBoolean } from '../xpath-evaluation.js';
2
+ import { evaluateXPathToBoolean, resolveId } from '../xpath-evaluation.js';
3
+ import getInScopeContext from '../getInScopeContext.js';
4
+ import { Fore } from '../fore.js';
3
5
 
4
6
  async function wait(howLong) {
5
7
  return new Promise(resolve => setTimeout(() => resolve(), howLong));
@@ -86,7 +88,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
86
88
  } else if (this.target === '#document') {
87
89
  document.addEventListener(this.event, e => this.execute(e));
88
90
  } else {
89
- this.targetElement = document.getElementById(this.target);
91
+ this.targetElement = resolveId(this.target, this);
90
92
  this.targetElement.addEventListener(this.event, e => this.execute(e));
91
93
  }
92
94
  } else {
@@ -112,9 +114,12 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
112
114
  * @param e
113
115
  */
114
116
  async execute(e) {
115
- console.log('executing', this);
117
+ // console.log('executing', this);
118
+ // console.log('executing e', e);
119
+ // console.log('executing e phase', e.eventPhase);
116
120
  if (e && e.detail) {
117
121
  this.detail = e.detail;
122
+ // console.log('#### detail', e.detail);
118
123
  }
119
124
  this.needsUpdate = false;
120
125
 
@@ -124,7 +129,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
124
129
  }
125
130
 
126
131
  // First check if 'if' condition is true - otherwise exist right away
127
- if (this.ifExpr && !evaluateXPathToBoolean(this.ifExpr, this.nodeset, this)) {
132
+ if (this.ifExpr && !evaluateXPathToBoolean(this.ifExpr, getInScopeContext(this), this)) {
128
133
  return;
129
134
  }
130
135
 
@@ -139,7 +144,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
139
144
  return;
140
145
  }
141
146
 
142
- if (!evaluateXPathToBoolean(this.whileExpr, this.nodeset, this)) {
147
+ if (!evaluateXPathToBoolean(this.whileExpr, getInScopeContext(this), this)) {
143
148
  // Done with iterating
144
149
  return;
145
150
  }
@@ -198,13 +203,16 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
198
203
  }
199
204
 
200
205
  /**
206
+ * dispathes action-performed event
207
+ *
208
+ * @event action-performed - whenever an action has been run
201
209
  */
202
210
  dispatchActionPerformed() {
203
211
  console.log('action-performed ', this);
204
- this.dispatchEvent(
205
- new CustomEvent('action-performed', { composed: true, bubbles: true, detail: {} }),
206
- );
212
+ Fore.dispatch(this, 'action-performed', {});
207
213
  }
208
214
  }
209
215
 
210
- window.customElements.define('abstract-action', AbstractAction);
216
+ if (!customElements.get('abstract-action')) {
217
+ window.customElements.define('abstract-action', AbstractAction);
218
+ }
@@ -47,13 +47,15 @@ export class FxAction extends AbstractAction {
47
47
  }
48
48
  const action = actionOrVar;
49
49
  action.detail = this.detail;
50
- // action.perform();
51
- action.execute();
50
+ action.perform();
51
+ // action.execute();
52
52
  });
53
53
  this.dispatchActionPerformed();
54
- // this.needsUpdate = false;
54
+ this.needsUpdate = true;
55
55
  }
56
56
  }
57
57
  }
58
58
 
59
- window.customElements.define('fx-action', FxAction);
59
+ if (!customElements.get('fx-action')) {
60
+ window.customElements.define('fx-action', FxAction);
61
+ }
@@ -1,5 +1,6 @@
1
1
  import { AbstractAction } from './abstract-action.js';
2
2
  import { Fore } from '../fore.js';
3
+ import { resolveId } from '../xpath-evaluation.js';
3
4
 
4
5
  /**
5
6
  * `fx-append` appends an entry to a repeat.
@@ -77,7 +78,7 @@ class FxAppend extends AbstractAction {
77
78
  super.actionPerformed();
78
79
  // const repeat = document.getElementById(this.repeat);
79
80
  // repeat.setIndex(repeat.nodeset.length);
80
- this.dispatch();
81
+ this._dispatch();
81
82
  }
82
83
 
83
84
  /**
@@ -117,22 +118,10 @@ class FxAppend extends AbstractAction {
117
118
  *
118
119
  * The target repeat is a child of the same repeat-item as the append action.
119
120
  */
120
- dispatch() {
121
- let targetRepeat;
122
- if (Fore.isRepeated(this)) {
123
- console.log('append repeated ', this.repeatContext);
124
- targetRepeat = Fore.getRepeatTarget(this, this.repeat);
125
- } else {
126
- targetRepeat = document.getElementById(this.repeat);
127
- }
121
+ _dispatch() {
122
+ const targetRepeat = resolveId(this.repeat, this);
128
123
  console.log('dispatching index change ', targetRepeat.nodeset.length);
129
- targetRepeat.dispatchEvent(
130
- new CustomEvent('index-changed', {
131
- composed: true,
132
- bubbles: true,
133
- detail: { index: targetRepeat.nodeset.length },
134
- }),
135
- );
124
+ Fore.dispatch(targetRepeat, 'index-changed', { index: targetRepeat.nodeset.length });
136
125
  }
137
126
 
138
127
  /**
@@ -213,4 +202,6 @@ class FxAppend extends AbstractAction {
213
202
  */
214
203
  }
215
204
 
216
- window.customElements.define('fx-append', FxAppend);
205
+ if (!customElements.get('fx-append')) {
206
+ window.customElements.define('fx-append', FxAppend);
207
+ }
@@ -19,4 +19,6 @@ export class FxConfirm extends FxAction {
19
19
  }
20
20
  }
21
21
 
22
- window.customElements.define('fx-confirm', FxConfirm);
22
+ if (!customElements.get('fx-confirm')) {
23
+ window.customElements.define('fx-confirm', FxConfirm);
24
+ }
@@ -1,4 +1,5 @@
1
1
  import { AbstractAction } from './abstract-action.js';
2
+ import { Fore } from '../fore.js';
2
3
 
3
4
  /**
4
5
  * `fx-delete`
@@ -29,13 +30,13 @@ class FxDelete extends AbstractAction {
29
30
  // ### if there's no repeat the delete action is inside of a repeat template
30
31
  if (this.repeatId === '') {
31
32
  // find the index to delete
32
- const rItem = this.parentNode.closest('fx-repeatitem');
33
+ const rItem = Fore.getClosest('fx-repeatitem', this.parentNode);
33
34
  const idx = Array.from(rItem.parentNode.children).indexOf(rItem) + 1;
34
35
  // console.log('>>> idx to delete ', idx);
35
36
 
36
37
  // ### get the model now as it'll be hard once we've deleted ourselves ;)
37
38
  this.model = this.getModel();
38
- const repeat = this.parentNode.closest('fx-repeat');
39
+ const repeat = Fore.getClosest('fx-repeat', this.parentNode);
39
40
 
40
41
  // ### update the nodeset
41
42
  let nodeToDelete;
@@ -77,4 +78,6 @@ class FxDelete extends AbstractAction {
77
78
  }
78
79
  }
79
80
 
80
- window.customElements.define('fx-delete', FxDelete);
81
+ if (!customElements.get('fx-delete')) {
82
+ window.customElements.define('fx-delete', FxDelete);
83
+ }
@@ -1,6 +1,5 @@
1
1
  import { AbstractAction } from './abstract-action.js';
2
2
  import { evaluateXPath, resolveId } from '../xpath-evaluation.js';
3
- import { XPathUtil } from '../xpath-util.js';
4
3
 
5
4
  /**
6
5
  * `fx-dispatch`
@@ -68,7 +67,8 @@ export class FxDispatch extends AbstractAction {
68
67
  if (value) {
69
68
  throw new Error('if "expr" is given there must not be a "value" attribute');
70
69
  }
71
- const result = evaluateXPath(expr, this.getInScopeContext(), this.getOwnerForm());
70
+ const [result] = evaluateXPath(expr, this.getInScopeContext(), this.getOwnerForm());
71
+
72
72
  let serialized = null;
73
73
  if (result.nodeName) {
74
74
  const serializer = new XMLSerializer();
@@ -90,11 +90,10 @@ export class FxDispatch extends AbstractAction {
90
90
 
91
91
  // ### when targetid is given dispatch to that if present (throw an error if not) - otherwise dispatch to document
92
92
  if (this.targetid) {
93
- // const target = document.getElementById(this.targetid);
94
- let target;
95
- if (XPathUtil.isRepeated(this)) {
96
- target = resolveId(this.targetid, this.parentNode, null);
97
- } else {
93
+ let target = resolveId(this.targetid, this.parentNode, null);
94
+ if (!target) {
95
+ // TODO: essentially, we want to highly prefer the closest target. in the same subcontrol.
96
+ // However, it may be that our target is elsewhere. Do a global search for that case
98
97
  target = document.getElementById(this.targetid);
99
98
  }
100
99
  console.log('target', target);
@@ -120,4 +119,6 @@ export class FxDispatch extends AbstractAction {
120
119
  }
121
120
  }
122
121
 
123
- window.customElements.define('fx-dispatch', FxDispatch);
122
+ if (!customElements.get('fx-dispatch')) {
123
+ window.customElements.define('fx-dispatch', FxDispatch);
124
+ }
@@ -1,4 +1,6 @@
1
- import { FxAction } from './fx-action.js';
1
+ import { Fore } from '../fore.js';
2
+ import { AbstractAction } from './abstract-action.js';
3
+ import { resolveId } from '../xpath-evaluation.js';
2
4
 
3
5
  /**
4
6
  * `fx-hide`
@@ -7,17 +9,19 @@ import { FxAction } from './fx-action.js';
7
9
  * @customElement
8
10
  * @demo demo/project.html
9
11
  */
10
- export class FxHide extends FxAction {
12
+ export class FxHide extends AbstractAction {
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).hide();
21
+ resolveId(this.dialog, this).hide();
20
22
  }
21
23
  }
22
24
 
23
- window.customElements.define('fx-hide', FxHide);
25
+ if (!customElements.get('fx-hide')) {
26
+ window.customElements.define('fx-hide', FxHide);
27
+ }