@jinntec/fore 1.1.0 → 1.3.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 (45) hide show
  1. package/dist/fore-dev.js +8 -8
  2. package/dist/fore-dev.js.map +1 -1
  3. package/dist/fore.js +7 -7
  4. package/dist/fore.js.map +1 -1
  5. package/index.js +1 -0
  6. package/package.json +2 -2
  7. package/resources/fore.css +95 -72
  8. package/src/ForeElementMixin.js +1 -1
  9. package/src/actions/abstract-action.js +55 -7
  10. package/src/actions/fx-action.js +2 -2
  11. package/src/actions/fx-confirm.js +2 -2
  12. package/src/actions/fx-delete.js +53 -62
  13. package/src/actions/fx-hide.js +3 -1
  14. package/src/actions/fx-message.js +25 -1
  15. package/src/actions/fx-refresh.js +9 -0
  16. package/src/actions/fx-reload.js +30 -0
  17. package/src/actions/fx-replace.js +1 -0
  18. package/src/actions/fx-send.js +11 -1
  19. package/src/actions/fx-setfocus.js +32 -5
  20. package/src/actions/fx-setvalue.js +4 -4
  21. package/src/actions/fx-show.js +1 -0
  22. package/src/actions/fx-toggle.js +5 -0
  23. package/src/events.js +24 -0
  24. package/src/fore.js +71 -8
  25. package/src/fx-bind.js +2 -2
  26. package/src/fx-fore.js +71 -20
  27. package/src/fx-instance.js +33 -8
  28. package/src/fx-model.js +435 -444
  29. package/src/fx-submission.js +78 -65
  30. package/src/getInScopeContext.js +91 -83
  31. package/src/modelitem.js +2 -2
  32. package/src/relevance.js +1 -1
  33. package/src/ui/abstract-control.js +114 -27
  34. package/src/ui/fx-alert.js +0 -1
  35. package/src/ui/fx-container.js +23 -27
  36. package/src/ui/fx-control.js +90 -34
  37. package/src/ui/fx-group.js +5 -0
  38. package/src/ui/fx-inspector.js +5 -2
  39. package/src/ui/fx-output.js +17 -15
  40. package/src/ui/fx-repeat.js +2 -2
  41. package/src/ui/fx-repeatitem.js +5 -3
  42. package/src/ui/fx-switch.js +11 -7
  43. package/src/ui/fx-trigger.js +15 -9
  44. package/src/xpath-evaluation.js +31 -18
  45. package/src/xpath-util.js +13 -0
package/index.js CHANGED
@@ -41,6 +41,7 @@ import './src/actions/fx-return.js';
41
41
  import './src/actions/fx-confirm.js';
42
42
  import './src/actions/fx-show.js';
43
43
  import './src/actions/fx-hide.js';
44
+ import './src/actions/fx-reload.js';
44
45
 
45
46
  import './src/functions/fx-function.js';
46
47
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jinntec/fore",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Fore - declarative user interfaces in plain HTML",
5
5
  "module": "./index.js",
6
6
  "publishConfig": {
@@ -31,7 +31,7 @@
31
31
  ],
32
32
  "dependencies": {
33
33
  "@jinntec/jinn-toast": "^1.0.4",
34
- "fontoxpath": "^3.26.0"
34
+ "fontoxpath": "^3.27.1"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@babel/plugin-proposal-class-properties": "^7.17.12",
@@ -17,32 +17,34 @@ html{
17
17
  pointer-events: none;
18
18
  cursor: default;
19
19
  }
20
- input[readonly]{
21
- background: lightgrey;
20
+ [refresh-on-view]{
21
+ /*opacity: 0;*/
22
22
  }
23
+ /*
24
+ defaults for relevance
23
25
 
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
- }
33
- fx-trigger a[disabled] {
34
- color:lightgrey;
26
+ You can overwrite these matchers to use transistions
27
+ */
28
+ [nonrelevant]{
29
+ display: none;
35
30
  }
36
- fx-trigger img[disabled]{
37
- filter:blur(2px);
31
+ [relevant]{
32
+ display: block;
38
33
  }
39
34
 
40
- .error{
41
- background: var(--paper-red-500);
35
+ [required]:after {
36
+ content: "*";
37
+ display: inline;
38
+ color: red;
42
39
  }
40
+
43
41
  fx-alert{
44
42
  color:darkred;
45
43
  font-size: 0.9rem;
44
+ display: none;
45
+ }
46
+ .visited[invalid] fx-alert{
47
+ display: block;
46
48
  }
47
49
 
48
50
  /* case not displayed by default - if you want e.g. apply transitions you have to overwrite this rule with display='inline' or similar */
@@ -50,44 +52,30 @@ fx-case{
50
52
  display: none;
51
53
  }
52
54
 
53
- fx-model, fx-model *, fx-model ::slotted(fx-instance), fx-instance{
54
- display:none;
55
+ fx-output[readonly] img{
56
+ background: inherit;
55
57
  }
56
58
 
57
- fx-control, fx-trigger{
58
- white-space: nowrap;
59
- /* position: relative; */
59
+ .error{
60
+ background: var(--paper-red-500);
60
61
  }
61
- .fx-checkbox{
62
+
63
+ fx-control, fx-trigger , .fx-checkbox{
62
64
  white-space: nowrap;
63
- }
64
- fx-hint{
65
- display: none;
66
- }
67
- fx-repeatitem{
68
- position:relative;
69
- /*
70
- opacity:1;
71
- -webkit-transition: opacity 3s;
72
- -moz-transition: opacity 3s;
73
- transition: opacity 3s;
74
- */
75
- }
76
- .hidden {
77
- visibility: hidden;
78
- opacity: 0;
79
- transition: visibility 0s 2s, opacity 2s linear;
65
+ /* position: relative; */
80
66
  }
81
67
 
82
- /* fx-inspector styles */
83
-
84
68
  /* ### FX-DIALOG STYLES ### */
85
69
  /* ### FX-DIALOG STYLES ### */
86
70
  /* ### FX-DIALOG STYLES ### */
87
71
  fx-dialog{
88
72
  display: none;
89
73
  opacity: 0;
74
+ width:100vw;
75
+ height: 100vh;
90
76
  transition: opacity 1s linear;
77
+ z-index: -1;
78
+ transition: none;
91
79
  }
92
80
  fx-dialog.show{
93
81
  display: block;
@@ -96,7 +84,7 @@ fx-dialog.show{
96
84
  opacity: 1;
97
85
  background:rgba(0,0,0,0.5);
98
86
  z-index: 10;
99
- transition: opacity 2s linear;
87
+ transition: opacity 0.4s linear;
100
88
  }
101
89
 
102
90
  fx-dialog.show .dialog-content{
@@ -126,48 +114,54 @@ fx-dialog .action{
126
114
  display: block;
127
115
  }
128
116
 
117
+ /* fx-fore{ */
118
+ /* opacity: 0; */
119
+ /* } */
120
+ /* fx-fore.fx-ready{ */
121
+ /* opacity: 1; */
122
+ /* } */
129
123
 
130
124
 
131
- /*
132
- .visible {
133
- visibility: visible;
134
- opacity: 1;
135
- transition: opacity 2s linear;
125
+ fx-group, fx-switch, fx-repeat, fx-dialog{
126
+ display: block;
136
127
  }
137
- */
138
128
 
139
- .required:after {
140
- content: '*';
141
- color: red;
142
- padding-left: 4px;
143
- right:3px;
144
- top:3px;
145
- z-index: 1;
129
+ fx-hint{
130
+ display: none;
146
131
  }
147
132
 
148
- [required]:after {
149
- content: "*";
150
- display: inline;
151
- color: red;
133
+ fx-model, fx-model *, fx-model ::slotted(fx-instance), fx-instance{
134
+ display:none;
152
135
  }
153
- .logtree details{
154
- padding:0.1rem 1rem;
155
- margin:0;
136
+
137
+ fx-trigger a[disabled] {
138
+ color:lightgrey;
156
139
  }
157
- .logtree details summary{
140
+ fx-trigger img[disabled]{
141
+ filter:blur(2px);
142
+ }
143
+
158
144
 
145
+ fx-repeatitem{
146
+ position:relative;
147
+ opacity:1;
148
+ /*
149
+ -webkit-transition: opacity 3s;
150
+ -moz-transition: opacity 3s;
151
+ transition: opacity 3s;
152
+ */
159
153
  }
160
- .non-relevant{
154
+
155
+ .hidden {
156
+ visibility: hidden;
161
157
  opacity: 0;
162
- height: 0;
163
- transition: opacity 1s;
164
- }
165
- .vertical label{
166
- display: block;
158
+ transition: visibility 0s 2s, opacity 2s linear;
167
159
  }
168
- [refresh-on-view]{
169
- /*opacity: 0;*/
160
+
161
+ .isEmpty.visited .widget{
162
+ background: lightpink;
170
163
  }
164
+
171
165
  .loaded{
172
166
  animation: fadein 0.3s forwards;
173
167
  }
@@ -176,6 +170,35 @@ fx-dialog .action{
176
170
  animation: none;
177
171
  opacity: 1;
178
172
  }
173
+
174
+ .logtree details{
175
+ padding:0.1rem 1rem;
176
+ margin:0;
177
+ }
178
+ .logtree details summary{
179
+
180
+ }
181
+
182
+ /*
183
+ .nonrelevant{
184
+ opacity: 0;
185
+ height: 0;
186
+ display: block;
187
+ padding: 0;
188
+ margin: 0;
189
+ border: none;
190
+ transition: opacity 0.4s;
191
+ }
192
+ */
193
+
194
+
195
+ .submit-validation-failed .isEmpty .widget{
196
+ background: lightpink;
197
+ }
198
+ .vertical label{
199
+ display: block;
200
+ }
201
+
179
202
  /* @keyframes fadein { */
180
203
  /* 0% { */
181
204
  /* opacity:0; */
@@ -59,7 +59,7 @@ export const foreElementMixin = superclass =>
59
59
  this.model = null;
60
60
  this.modelItem = {};
61
61
  this.ref = this.hasAttribute('ref') ? this.getAttribute('ref') : '';
62
- this.inScopeVariables = null;
62
+ this.inScopeVariables = new Map();
63
63
  }
64
64
 
65
65
  getModel() {
@@ -16,6 +16,9 @@ async function wait(howLong) {
16
16
  * @demo demo/index.html
17
17
  */
18
18
  export class AbstractAction extends foreElementMixin(HTMLElement) {
19
+ static outermostHandler = null;
20
+ static dataChanged = false;
21
+
19
22
  static get properties() {
20
23
  return {
21
24
  ...super.properties,
@@ -115,12 +118,33 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
115
118
  */
116
119
  async execute(e) {
117
120
  // console.log('executing', this);
121
+
118
122
  // console.log('executing e', e);
119
123
  // console.log('executing e phase', e.eventPhase);
124
+ if(AbstractAction.outermostHandler === null){
125
+ console.info(
126
+ `%coutermost Action `,
127
+ "background:#e65100; color:white; padding:0.3rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;",
128
+ this
129
+ );
130
+ // console.log('starting outermost handler',this);
131
+ AbstractAction.outermostHandler = this;
132
+ }
133
+
134
+ if(AbstractAction.outermostHandler !== this){
135
+ console.info(
136
+ `%cAction `,
137
+ "background:orange; color:white; padding:0.3rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;",
138
+ this
139
+ );
140
+ }
141
+ // console.log('>>> outermostHandler', AbstractAction.outermostHandler);
142
+
120
143
  if(e && e.code){
121
144
  const vars = new Map();
122
- vars.set('code',e.code);
123
- this.setInScopeVariables(vars);
145
+ vars.set('code', e.code);
146
+ // this.setInScopeVariables(vars);
147
+ this.setInScopeVariables(new Map([ ...this.inScopeVariables, ...vars]));
124
148
  }
125
149
 
126
150
  if (e && e.detail) {
@@ -131,12 +155,18 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
131
155
  // index: the ordinal position of the key within the object
132
156
  vars.set(key,e.detail[key]);
133
157
  });
134
- console.log("event detail vars", vars);
135
- this.setInScopeVariables(vars);
158
+ if(vars.size !== 0){
159
+ console.log("event detail vars", vars);
160
+ }
161
+ this.setInScopeVariables(new Map([ ...this.inScopeVariables, ...vars]));
136
162
  }
137
163
  this.needsUpdate = false;
138
164
 
139
- this.evalInContext();
165
+ try{
166
+ this.evalInContext();
167
+ }catch (error){
168
+ console.warn('evaluation faild',error);
169
+ }
140
170
  if (this.targetElement && this.targetElement.nodeset) {
141
171
  this.nodeset = this.targetElement.nodeset;
142
172
  }
@@ -172,6 +202,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
172
202
  // After loop is done call actionPerformed to update the model and UI
173
203
  await loop();
174
204
  this.actionPerformed();
205
+ Fore.dispatch(this, 'while-performed', {});
175
206
  return;
176
207
  }
177
208
 
@@ -187,15 +218,31 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
187
218
 
188
219
  this.perform();
189
220
  this.actionPerformed();
221
+ if(AbstractAction.outermostHandler === this){
222
+ AbstractAction.outermostHandler = null;
223
+ console.info(
224
+ `%coutermost Action done`,
225
+ "background:#e65100; color:white; padding:0.3rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;",
226
+ this
227
+ );
228
+
229
+ }
190
230
  }
191
231
 
192
232
  /**
193
233
  * Template method to be implemented by each action that is called by execute() as part of
194
234
  * the processing.
195
235
  *
196
- * todo: review - this could probably just be empty or throw error signalling that extender needs to implement it
236
+ * This function should not called on any action directly - call execute() instead to ensure proper execution of 'if' and 'while'
197
237
  */
198
238
  perform() {
239
+ console.info(
240
+ `%cperform `,
241
+ "background:orange; color:white; padding:0.3rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;",
242
+ this
243
+ );
244
+
245
+ //todo: review - this evaluation seems redundant as we already evaluated in execute
199
246
  if (this.isBound() || this.nodeName === 'FX-ACTION') {
200
247
  this.evalInContext();
201
248
  }
@@ -206,6 +253,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
206
253
  */
207
254
  actionPerformed() {
208
255
  // console.log('actionPerformed action parentNode ', this.parentNode);
256
+ // if (this.needsUpdate && AbstractAction.outermostHandler !== this) {
209
257
  if (this.needsUpdate) {
210
258
  const model = this.getModel();
211
259
  model.recalculate();
@@ -221,7 +269,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
221
269
  * @event action-performed - whenever an action has been run
222
270
  */
223
271
  dispatchActionPerformed() {
224
- console.log('action-performed ', this);
272
+ // console.log('action-performed ', this);
225
273
  Fore.dispatch(this, 'action-performed', {});
226
274
  }
227
275
  }
@@ -32,6 +32,7 @@ export class FxAction extends AbstractAction {
32
32
  }
33
33
 
34
34
  perform() {
35
+ super.perform();
35
36
  const { children } = this;
36
37
 
37
38
  if (this.src) {
@@ -47,8 +48,7 @@ export class FxAction extends AbstractAction {
47
48
  }
48
49
  const action = actionOrVar;
49
50
  action.detail = this.detail;
50
- action.perform();
51
- // action.execute();
51
+ action.execute();
52
52
  });
53
53
  this.dispatchActionPerformed();
54
54
  this.needsUpdate = true;
@@ -1,4 +1,4 @@
1
- import {AbstractAction} from "./abstract-action";
1
+ import {FxAction} from "./fx-action.js";
2
2
 
3
3
  /**
4
4
  * `fx-confirm`
@@ -7,7 +7,7 @@ import {AbstractAction} from "./abstract-action";
7
7
  * @customElement
8
8
  * @demo demo/project.html
9
9
  */
10
- export class FxConfirm extends AbstractAction {
10
+ export class FxConfirm extends FxAction {
11
11
  connectedCallback() {
12
12
  this.message = this.hasAttribute('message') ? this.getAttribute('message') : null;
13
13
  }
@@ -1,83 +1,74 @@
1
- import { AbstractAction } from './abstract-action.js';
2
- import { Fore } from '../fore.js';
1
+ import {AbstractAction} from './abstract-action.js';
2
+ import {Fore} from '../fore.js';
3
+ import {evaluateXPathToNodes} from "../xpath-evaluation.js";
4
+ import {XPathUtil} from "../xpath-util";
5
+ import getInScopeContext from '../getInScopeContext.js';
3
6
 
4
7
  /**
5
8
  * `fx-delete`
6
- * general class for bound elements
9
+ * deletes nodes from instance data.
7
10
  *
11
+ * @fires deleted event
8
12
  * @customElement
9
13
  * @demo demo/todo.html
10
14
  */
11
15
  class FxDelete extends AbstractAction {
12
- constructor() {
13
- super();
14
- this.repeatId = '';
15
- }
16
-
17
- /**
18
- * deletes a
19
- */
20
- perform() {
21
- super.perform();
22
- console.log('##### fx-delete executing...');
23
-
24
- // this.ref = this.getAttribute('ref');
25
- // const inscope = this.getInScopeContext();
26
- // this.nodeset = fx.evaluateXPathToNodes(this.ref, inscope, null, {});
27
-
28
- console.log('delete nodeset ', this.nodeset);
29
-
30
- // ### if there's no repeat the delete action is inside of a repeat template
31
- if (this.repeatId === '') {
32
- // find the index to delete
33
- const rItem = Fore.getClosest('fx-repeatitem', this.parentNode);
34
- const idx = Array.from(rItem.parentNode.children).indexOf(rItem) + 1;
35
- // console.log('>>> idx to delete ', idx);
16
+ constructor() {
17
+ super();
18
+ }
36
19
 
37
- // ### get the model now as it'll be hard once we've deleted ourselves ;)
38
- this.model = this.getModel();
39
- const repeat = Fore.getClosest('fx-repeat', this.parentNode);
20
+ /**
21
+ * deletes nodes from instance data.
22
+ *
23
+ * Will NOT perform delete if nodeset is pointing to document node, document fragment, root node or being readonly.
24
+ */
25
+ perform() {
26
+ console.log('##### fx-delete executing...');
27
+ const inscopeContext = getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
28
+ this.nodeset = evaluateXPathToNodes(this.ref, inscopeContext, this);
40
29
 
41
- // ### update the nodeset
42
- let nodeToDelete;
43
- if (Array.isArray(this.nodeset)) {
44
- nodeToDelete = this.nodeset[idx - 1];
45
- } else {
46
- nodeToDelete = this.nodeset;
47
- }
48
- const p = nodeToDelete.parentNode;
49
- p.removeChild(nodeToDelete);
30
+ console.log('delete nodeset ', this.nodeset);
50
31
 
51
- // ### remove the repeatitem
52
- rItem.parentNode.removeChild(rItem);
32
+ const nodesToDelete = this.nodeset;
33
+ let parent;
34
+ if (Array.isArray(nodesToDelete)) {
35
+ if(nodesToDelete.length === 0) return;
36
+ parent = nodesToDelete[0].parentNode;
37
+ nodesToDelete.forEach(item => {
38
+ this._deleteNode(parent, item);
39
+ });
40
+ } else {
41
+ parent = nodesToDelete.parentNode;
42
+ this._deleteNode(parent, nodesToDelete);
43
+ }
53
44
 
54
- // ### update the index (set 'repeat-index' attribute on repeatitem
55
- const { repeatSize } = repeat;
56
- if (idx === 1 || repeatSize === 1) {
57
- repeat.setIndex(1);
58
- } else if (idx > repeatSize) {
59
- repeat.setIndex(repeatSize);
60
- } else {
61
- repeat.setIndex(idx);
62
- }
45
+ const instanceId = XPathUtil.resolveInstance(this);
46
+ const instance = this.getModel().getInstance(instanceId);
47
+ Fore.dispatch(instance, 'deleted', {deletedNodes:nodesToDelete});
48
+ this.needsUpdate = true;
63
49
  }
64
50
 
65
- // this.needsRebuild = true;
66
- // this.needsRecalculate = true;
67
- // this.needsRevalidate = true;
68
- // this.needsRefresh = true;
51
+ _deleteNode(parent, node) {
52
+ if (parent.nodeType === Node.DOCUMENT_NODE) return;
53
+ if (node.nodeType === Node.DOCUMENT_NODE) return;
54
+ if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) return;
55
+ if (node.parentNode === null) return;
69
56
 
70
- this.needsUpdate = true;
57
+ const mi = this.getModelItem();
58
+ if (mi.readonly) return;
71
59
 
72
- // this.actionPerformed();
73
- }
60
+ parent.removeChild(node);
61
+ }
74
62
 
75
- actionPerformed() {
76
- this.getModel().rebuild();
77
- super.actionPerformed();
78
- }
63
+ /**
64
+ * overwriting as we need to perform additional rebuild()
65
+ */
66
+ actionPerformed() {
67
+ this.getModel().rebuild();
68
+ super.actionPerformed();
69
+ }
79
70
  }
80
71
 
81
72
  if (!customElements.get('fx-delete')) {
82
- window.customElements.define('fx-delete', FxDelete);
73
+ window.customElements.define('fx-delete', FxDelete);
83
74
  }
@@ -18,7 +18,9 @@ export class FxHide extends AbstractAction {
18
18
  }
19
19
 
20
20
  perform() {
21
- resolveId(this.dialog, this).hide();
21
+ const dialog = resolveId(this.dialog, this);
22
+ dialog.hide();
23
+ Fore.dispatch(dialog,'dialog-hidden',{})
22
24
  }
23
25
  }
24
26
 
@@ -1,4 +1,7 @@
1
1
  import { AbstractAction } from './abstract-action.js';
2
+ import {evaluateXPathToString} from "../xpath-evaluation";
3
+ import {Fore} from "../fore";
4
+ import getInScopeContext from '../getInScopeContext.js';
2
5
 
3
6
  /**
4
7
  * `fx-message`
@@ -17,6 +20,8 @@ class FxMessage extends AbstractAction {
17
20
  super.connectedCallback();
18
21
  this.event = this.hasAttribute('event') ? this.getAttribute('event') : '';
19
22
  this.level = this.hasAttribute('level') ? this.getAttribute('level') : 'ephemeral';
23
+
24
+ this.messageTextContent = this.textContent;
20
25
  const style = `
21
26
  :host{
22
27
  display:none;
@@ -46,8 +51,9 @@ class FxMessage extends AbstractAction {
46
51
  super.perform();
47
52
  let message;
48
53
  if (this.hasAttribute('value')) {
49
- message = this.getValue();
54
+ message = this._getValue();
50
55
  } else {
56
+ this.getOwnerForm().evaluateTemplateExpression(this.messageTextContent, this.firstChild);
51
57
  message = this.textContent;
52
58
  }
53
59
 
@@ -59,6 +65,24 @@ class FxMessage extends AbstractAction {
59
65
  }),
60
66
  );
61
67
  }
68
+
69
+ _getValue() {
70
+ if (this.hasAttribute('value')) {
71
+ const valAttr = this.getAttribute('value');
72
+ try {
73
+ const inscopeContext = getInScopeContext(this, valAttr);
74
+ return evaluateXPathToString(valAttr, inscopeContext, this);
75
+ } catch (error) {
76
+ console.error(error);
77
+ Fore.dispatch(this, 'error', { message: error });
78
+ }
79
+ }
80
+ if (this.textContent) {
81
+ return this.textContent;
82
+ }
83
+ return null;
84
+ }
85
+
62
86
  }
63
87
 
64
88
  if (!customElements.get('fx-message')) {
@@ -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-refresh`
@@ -20,6 +21,14 @@ class FxRefresh extends AbstractAction {
20
21
  this.getOwnerForm().forceRefresh();
21
22
  return;
22
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
+ }
23
32
  this.getOwnerForm().refresh();
24
33
  }
25
34
  }
@@ -0,0 +1,30 @@
1
+ import { Fore } from '../fore.js';
2
+ import { AbstractAction } from './abstract-action.js';
3
+ import { resolveId } from '../xpath-evaluation.js';
4
+
5
+ /**
6
+ * `fx-reload`
7
+ * reloads browser window when receiving 'reload' event
8
+ *
9
+ * @event reload dispatched when action executes. Usually calls its own handler but might get cancelled by other handler.
10
+ * @customElement
11
+ * @demo demo/project.html
12
+ */
13
+ export class FxReload extends AbstractAction {
14
+
15
+ connectedCallback() {
16
+ super.connectedCallback();
17
+ this.addEventListener('reload', event => {
18
+ window.location.reload();
19
+ },{once:true});
20
+ }
21
+
22
+ perform() {
23
+ Fore.dispatch(this, 'reload', {});
24
+ }
25
+ }
26
+
27
+ if (!customElements.get('fx-reload')) {
28
+ window.customElements.define('fx-reload', FxReload);
29
+ }
30
+