@jinntec/fore 1.0.0-1 → 1.0.0-4

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 (43) hide show
  1. package/README.md +20 -1
  2. package/dist/fore-all.js +10 -10
  3. package/dist/fore-debug.js +140 -0
  4. package/index.js +8 -0
  5. package/package.json +7 -6
  6. package/resources/{vars.css → fore-styles.css} +292 -0
  7. package/src/DependencyNotifyingDomFacade.js +9 -1
  8. package/src/ForeElementMixin.js +25 -17
  9. package/src/actions/abstract-action.js +8 -7
  10. package/src/actions/fx-action.js +6 -1
  11. package/src/actions/fx-dispatch.js +10 -2
  12. package/src/actions/fx-hide.js +23 -0
  13. package/src/actions/fx-insert.js +9 -9
  14. package/src/actions/fx-send.js +1 -1
  15. package/src/actions/fx-setvalue.js +2 -4
  16. package/src/actions/fx-show.js +23 -0
  17. package/src/dep_graph.js +9 -0
  18. package/src/drawdown.js +172 -0
  19. package/src/fore.js +56 -3
  20. package/src/fx-bind.js +20 -17
  21. package/src/fx-fore.js +297 -33
  22. package/src/fx-instance.js +27 -6
  23. package/src/fx-model.js +182 -37
  24. package/src/fx-submission.js +29 -7
  25. package/src/fx-var.js +43 -0
  26. package/src/getInScopeContext.js +28 -7
  27. package/src/modelitem.js +1 -0
  28. package/src/ui/abstract-control.js +17 -4
  29. package/src/ui/fx-alert.js +16 -20
  30. package/src/ui/fx-container.js +9 -4
  31. package/src/ui/fx-control.js +76 -39
  32. package/src/ui/fx-dialog.js +68 -0
  33. package/src/ui/fx-inspector.js +44 -0
  34. package/src/ui/fx-items.js +120 -0
  35. package/src/ui/fx-output.js +50 -12
  36. package/src/ui/fx-repeat.js +83 -16
  37. package/src/ui/fx-repeatitem.js +11 -4
  38. package/src/ui/fx-trigger.js +3 -0
  39. package/src/xpath-evaluation.js +372 -135
  40. package/src/xpath-util.js +52 -12
  41. package/dist/fore.js +0 -2
  42. package/resources/fore.css +0 -86
  43. package/resources/toastify.css +0 -87
@@ -44,7 +44,7 @@ export default class FxSetvalue extends AbstractAction {
44
44
  super.perform();
45
45
  let { value } = this;
46
46
  if (this.valueAttr !== null) {
47
- value = evaluateXPath(this.valueAttr, this.nodeset, this.getOwnerForm(), this.detail);
47
+ value = evaluateXPath(this.valueAttr, this.nodeset, this, this.detail);
48
48
  } else if (this.textContent !== '') {
49
49
  value = this.textContent;
50
50
  } else {
@@ -62,10 +62,8 @@ export default class FxSetvalue extends AbstractAction {
62
62
 
63
63
  if (item.value !== newVal) {
64
64
  item.value = newVal;
65
- item.changed = true;
66
-
65
+ this.getModel().changed.push(modelItem);
67
66
  this.needsUpdate = true;
68
-
69
67
  console.log('setvalue[2] ', item, newVal);
70
68
  }
71
69
  }
@@ -0,0 +1,23 @@
1
+ import { FxAction } from './fx-action.js';
2
+
3
+ /**
4
+ * `fx-confirm`
5
+ * Displays a simple confirmation before actually executing the nested actions.
6
+ *
7
+ * @customElement
8
+ * @demo demo/project.html
9
+ */
10
+ export class FxShow extends FxAction {
11
+ connectedCallback() {
12
+ this.dialog = this.getAttribute('dialog');
13
+ if(!this.dialog){
14
+ this.dispatch('error',{message:'dialog does not exist'})
15
+ }
16
+ }
17
+
18
+ perform() {
19
+ document.getElementById(this.dialog).open();
20
+ }
21
+ }
22
+
23
+ window.customElements.define('fx-show', FxShow);
package/src/dep_graph.js CHANGED
@@ -320,6 +320,15 @@ DepGraph.prototype = {
320
320
  }
321
321
  throw new Error(`Node does not exist: ${node}`);
322
322
  },
323
+
324
+ /**
325
+ * Get an array of nodes that have no dependants (i.e. nothing depends on them).
326
+ */
327
+ entryNodes() {
328
+ const self = this;
329
+ return Object.keys(this.nodes).filter(node => self.incomingEdges[node].length === 0);
330
+ },
331
+
323
332
  /**
324
333
  * Construct the overall processing order for the dependency graph.
325
334
  *
@@ -0,0 +1,172 @@
1
+ /**
2
+ * drawdown.js
3
+ * (c) Adam Leggett
4
+ */
5
+
6
+ function markdown(src) {
7
+ var rx_lt = /</g;
8
+ var rx_gt = />/g;
9
+ var rx_space = /\t|\r|\uf8ff/g;
10
+ var rx_escape = /\\([\\\|`*_{}\[\]()#+\-~])/g;
11
+ var rx_hr = /^([*\-=_] *){3,}$/gm;
12
+ var rx_blockquote = /\n *&gt; *([^]*?)(?=(\n|$){2})/g;
13
+ var rx_list = /\n( *)(?:[*\-+]|((\d+)|([a-z])|[A-Z])[.)]) +([^]*?)(?=(\n|$){2})/g;
14
+ var rx_listjoin = /<\/(ol|ul)>\n\n<\1>/g;
15
+ var rx_highlight = /(^|[^A-Za-z\d\\])(([*_])|(~)|(\^)|(--)|(\+\+)|`)(\2?)([^<]*?)\2\8(?!\2)(?=\W|_|$)/g;
16
+ var rx_code = /\n((```|~~~).*\n?([^]*?)\n?\2|(( .*?\n)+))/g;
17
+ var rx_link = /((!?)\[(.*?)\]\((.*?)( ".*")?\)|\\([\\`*_{}\[\]()#+\-.!~]))/g;
18
+ var rx_table = /\n(( *\|.*?\| *\n)+)/g;
19
+ var rx_thead = /^.*\n( *\|( *\:?-+\:?-+\:? *\|)* *\n|)/;
20
+ var rx_row = /.*\n/g;
21
+ var rx_cell = /\||(.*?[^\\])\|/g;
22
+ var rx_heading = /(?=^|>|\n)([>\s]*?)(#{1,6}) (.*?)( #*)? *(?=\n|$)/g;
23
+ var rx_para = /(?=^|>|\n)\s*\n+([^<]+?)\n+\s*(?=\n|<|$)/g;
24
+ var rx_stash = /-\d+\uf8ff/g;
25
+
26
+ function replace(rex, fn) {
27
+ src = src.replace(rex, fn);
28
+ }
29
+
30
+ function element(tag, content) {
31
+ return '<' + tag + '>' + content + '</' + tag + '>';
32
+ }
33
+
34
+ function blockquote(src) {
35
+ return src.replace(rx_blockquote, function(all, content) {
36
+ return element('blockquote', blockquote(highlight(content.replace(/^ *&gt; */gm, ''))));
37
+ });
38
+ }
39
+
40
+ function list(src) {
41
+ return src.replace(rx_list, function(all, ind, ol, num, low, content) {
42
+ var entry = element(
43
+ 'li',
44
+ highlight(
45
+ content
46
+ .split(RegExp('\n ?' + ind + '(?:(?:\\d+|[a-zA-Z])[.)]|[*\\-+]) +', 'g'))
47
+ .map(list)
48
+ .join('</li><li>'),
49
+ ),
50
+ );
51
+
52
+ return (
53
+ '\n' +
54
+ (ol
55
+ ? '<ol start="' +
56
+ (num
57
+ ? ol + '">'
58
+ : parseInt(ol, 36) -
59
+ 9 +
60
+ '" style="list-style-type:' +
61
+ (low ? 'low' : 'upp') +
62
+ 'er-alpha">') +
63
+ entry +
64
+ '</ol>'
65
+ : element('ul', entry))
66
+ );
67
+ });
68
+ }
69
+
70
+ function highlight(src) {
71
+ return src.replace(rx_highlight, function(all, _, p1, emp, sub, sup, small, big, p2, content) {
72
+ return (
73
+ _ +
74
+ element(
75
+ emp
76
+ ? p2
77
+ ? 'strong'
78
+ : 'em'
79
+ : sub
80
+ ? p2
81
+ ? 's'
82
+ : 'sub'
83
+ : sup
84
+ ? 'sup'
85
+ : small
86
+ ? 'small'
87
+ : big
88
+ ? 'big'
89
+ : 'code',
90
+ highlight(content),
91
+ )
92
+ );
93
+ });
94
+ }
95
+
96
+ function unesc(str) {
97
+ return str.replace(rx_escape, '$1');
98
+ }
99
+
100
+ var stash = [];
101
+ var si = 0;
102
+
103
+ src = '\n' + src + '\n';
104
+
105
+ replace(rx_lt, '&lt;');
106
+ replace(rx_gt, '&gt;');
107
+ replace(rx_space, ' ');
108
+
109
+ // blockquote
110
+ src = blockquote(src);
111
+
112
+ // horizontal rule
113
+ replace(rx_hr, '<hr/>');
114
+
115
+ // list
116
+ src = list(src);
117
+ replace(rx_listjoin, '');
118
+
119
+ // code
120
+ replace(rx_code, function(all, p1, p2, p3, p4) {
121
+ stash[--si] = element('pre', element('code', p3 || p4.replace(/^ /gm, '')));
122
+ return si + '\uf8ff';
123
+ });
124
+
125
+ // link or image
126
+ replace(rx_link, function(all, p1, p2, p3, p4, p5, p6) {
127
+ stash[--si] = p4
128
+ ? p2
129
+ ? '<img src="' + p4 + '" alt="' + p3 + '"/>'
130
+ : '<a href="' + p4 + '">' + unesc(highlight(p3)) + '</a>'
131
+ : p6;
132
+ return si + '\uf8ff';
133
+ });
134
+
135
+ // table
136
+ replace(rx_table, function(all, table) {
137
+ var sep = table.match(rx_thead)[1];
138
+ return (
139
+ '\n' +
140
+ element(
141
+ 'table',
142
+ table.replace(rx_row, function(row, ri) {
143
+ return row == sep
144
+ ? ''
145
+ : element(
146
+ 'tr',
147
+ row.replace(rx_cell, function(all, cell, ci) {
148
+ return ci ? element(sep && !ri ? 'th' : 'td', unesc(highlight(cell || ''))) : '';
149
+ }),
150
+ );
151
+ }),
152
+ )
153
+ );
154
+ });
155
+
156
+ // heading
157
+ replace(rx_heading, function(all, _, p1, p2) {
158
+ return _ + element('h' + p1.length, unesc(highlight(p2)));
159
+ });
160
+
161
+ // paragraph
162
+ replace(rx_para, function(all, content) {
163
+ return element('p', unesc(highlight(content)));
164
+ });
165
+
166
+ // stash
167
+ replace(rx_stash, function(all) {
168
+ return stash[parseInt(all)];
169
+ });
170
+
171
+ return src.trim();
172
+ }
package/src/fore.js CHANGED
@@ -13,6 +13,7 @@ export class Fore {
13
13
  return [
14
14
  'FX-DELETE',
15
15
  'FX-DISPATCH',
16
+ 'FX-HIDE',
16
17
  'FX-INSERT',
17
18
  'FX-LOAD',
18
19
  'FX-MESSAGE',
@@ -29,11 +30,27 @@ export class Fore {
29
30
  'FX-SETFOCUS',
30
31
  'FX-SETINDEX',
31
32
  'FX-SETVALUE',
33
+ 'FX-SHOW',
32
34
  'FX-TOGGLE',
33
35
  'FX-UPDATE',
34
36
  ];
35
37
  }
36
38
 
39
+ static createUUID() {
40
+ // http://www.ietf.org/rfc/rfc4122.txt
41
+ const s = [];
42
+ const hexDigits = '0123456789abcdef';
43
+ for (let i = 0; i < 36; i += 1) {
44
+ s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
45
+ }
46
+ s[14] = '4'; // bits 12-15 of the time_hi_and_version field to 0010
47
+ s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
48
+ s[8] = s[13] = s[18] = s[23] = '-';
49
+
50
+ const uuid = s.join('');
51
+ return uuid;
52
+ }
53
+
37
54
  static get XFORMS_NAMESPACE_URI() {
38
55
  // todo: should be centralized somewhere as constant. Exists in several? places
39
56
  return 'http://www.w3.org/2002/xforms';
@@ -55,7 +72,7 @@ export class Fore {
55
72
  'FX-GROUP',
56
73
  'FX-HINT',
57
74
  'FX-INPUT',
58
- 'FX-ITEMSET',
75
+ 'FX-ITEMS',
59
76
  'FX-LABEL',
60
77
  'FX-OUTPUT',
61
78
  'FX-RANGE',
@@ -68,6 +85,7 @@ export class Fore {
68
85
  'FX-TEXTAREA',
69
86
  'FX-TRIGGER',
70
87
  'FX-UPLOAD',
88
+ 'FX-VAR',
71
89
  ];
72
90
  }
73
91
 
@@ -79,15 +97,40 @@ export class Fore {
79
97
  return Fore.UI_ELEMENTS.includes(elementName);
80
98
  }
81
99
 
82
- static async refreshChildren(startElement) {
100
+ /**
101
+ * recursively refreshes all UI Elements.
102
+ *
103
+ * todo: this could probably made more efficient with significant impact on rendering perf
104
+ *
105
+ * @param startElement
106
+ * @param force
107
+ * @returns {Promise<unknown>}
108
+ */
109
+ static async refreshChildren(startElement, force) {
83
110
  const refreshed = new Promise(resolve => {
111
+ /*
112
+ if there's an 'refresh-on-view' attribute the element wants to be handled by
113
+ handleIntersect function that calls the refresh of the respective element and
114
+ not the global one.
115
+ */
116
+ // if(!force && startElement.hasAttribute('refresh-on-view')) return;
117
+
118
+ /* ### attempt with querySelectorAll is even slower than iterating recursively
119
+
120
+ const children = startElement.querySelectorAll('[ref]');
121
+ Array.from(children).forEach(uiElement => {
122
+ if (Fore.isUiElement(uiElement.nodeName) && typeof uiElement.refresh === 'function') {
123
+ uiElement.refresh();
124
+ }
125
+ });
126
+ */
84
127
  const { children } = startElement;
85
128
  if (children) {
86
129
  Array.from(children).forEach(element => {
87
130
  if (Fore.isUiElement(element.nodeName) && typeof element.refresh === 'function') {
88
131
  element.refresh();
89
132
  } else if (element.nodeName.toUpperCase() !== 'FX-MODEL') {
90
- Fore.refreshChildren(element);
133
+ Fore.refreshChildren(element, force);
91
134
  }
92
135
  });
93
136
  }
@@ -167,6 +210,16 @@ export class Fore {
167
210
  return fadeOut();
168
211
  }
169
212
 
213
+ static dispatch(target, eventName, detail) {
214
+ const event = new CustomEvent(eventName, {
215
+ composed: true,
216
+ bubbles: true,
217
+ detail,
218
+ });
219
+ console.log('firing', event);
220
+ target.dispatchEvent(event);
221
+ }
222
+
170
223
  /**
171
224
  * clear all text nodes and attribute values to get a 'clean' template.
172
225
  * @param n
package/src/fx-bind.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  evaluateXPathToString,
8
8
  } from './xpath-evaluation.js';
9
9
  import { XPathUtil } from './xpath-util.js';
10
+ import getInScopeContext from './getInScopeContext.js';
10
11
 
11
12
  /**
12
13
  * FxBind declaratively attaches constraints to nodes in the data (instances).
@@ -182,12 +183,11 @@ export class FxBind extends foreElementMixin(HTMLElement) {
182
183
  if (this.bindType === 'xml') {
183
184
  this.nodeset.forEach(node => {
184
185
  const path = XPathUtil.getPath(node);
186
+ this.model.mainGraph.addNode(path, node);
185
187
 
186
188
  if (this.calculate) {
187
189
  this.model.mainGraph.addNode(`${path}:calculate`, node);
188
190
  // Calculated values are a dependency of the model item.
189
- // Make `model1` depend on `model1:calculate`
190
- this.model.mainGraph.addNode(path, node);
191
191
  this.model.mainGraph.addDependency(path, `${path}:calculate`);
192
192
  }
193
193
 
@@ -196,11 +196,13 @@ export class FxBind extends foreElementMixin(HTMLElement) {
196
196
  this._addDependencies(calculateRefs, node, path, 'calculate');
197
197
  }
198
198
 
199
- const readonlyRefs = this._getReferencesForProperty(this.readonly, node);
200
- if (readonlyRefs.length !== 0) {
201
- this._addDependencies(readonlyRefs, node, path, 'readonly');
202
- } else if (this.readonly) {
203
- this.model.mainGraph.addNode(`${path}:readonly`, node);
199
+ if (!this.calculate) {
200
+ const readonlyRefs = this._getReferencesForProperty(this.readonly, node);
201
+ if (readonlyRefs.length !== 0) {
202
+ this._addDependencies(readonlyRefs, node, path, 'readonly');
203
+ } else if (this.readonly) {
204
+ this.model.mainGraph.addNode(`${path}:readonly`, node);
205
+ }
204
206
  }
205
207
 
206
208
  // const requiredRefs = this.requiredReferences;
@@ -228,12 +230,6 @@ export class FxBind extends foreElementMixin(HTMLElement) {
228
230
  }
229
231
  }
230
232
 
231
- _addNode(path, node) {
232
- if (!this.model.mainGraph.hasNode(path)) {
233
- this.model.mainGraph.addNode(path, { node });
234
- }
235
- }
236
-
237
233
  /**
238
234
  * Add the dependencies of this bind
239
235
  *
@@ -244,6 +240,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
244
240
  * @param {string} property The property with this dependency
245
241
  */
246
242
  _addDependencies(refs, node, path, property) {
243
+ // console.log('_addDependencies',path);
247
244
  const nodeHash = `${path}:${property}`;
248
245
  if (refs.length !== 0) {
249
246
  if (!this.model.mainGraph.hasNode(nodeHash)) {
@@ -251,11 +248,15 @@ export class FxBind extends foreElementMixin(HTMLElement) {
251
248
  }
252
249
  refs.forEach(ref => {
253
250
  const otherPath = XPathUtil.getPath(ref);
251
+ // console.log('otherPath', otherPath)
254
252
 
255
- if (!this.model.mainGraph.hasNode(otherPath)) {
256
- this.model.mainGraph.addNode(otherPath, ref);
253
+ // todo: nasty hack to prevent duplicate pathes like 'a[1]' and 'a[1]/text()[1]' to end up as separate nodes in the graph
254
+ if(!otherPath.endsWith('text()[1]')){
255
+ if (!this.model.mainGraph.hasNode(otherPath)) {
256
+ this.model.mainGraph.addNode(otherPath, ref);
257
+ }
258
+ this.model.mainGraph.addDependency(nodeHash, otherPath);
257
259
  }
258
- this.model.mainGraph.addDependency(nodeHash, otherPath);
259
260
  });
260
261
  } else {
261
262
  this.model.mainGraph.addNode(nodeHash, node);
@@ -320,7 +321,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
320
321
  * overwrites
321
322
  */
322
323
  _evalInContext() {
323
- const inscopeContext = this.getInScopeContext();
324
+ const inscopeContext = getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
324
325
 
325
326
  // reset nodeset
326
327
  this.nodeset = [];
@@ -508,6 +509,8 @@ export class FxBind extends foreElementMixin(HTMLElement) {
508
509
  * @param {string} propertyExpr The XPath to get the referenced nodes from
509
510
  *
510
511
  * @return {Node[]} The nodes that are referenced by the XPath
512
+ *
513
+ * todo: DependencyNotifyingDomFacade reports back too much in some cases like 'a[1]' and 'a[1]/text[1]'
511
514
  */
512
515
  _getReferencesForProperty(propertyExpr) {
513
516
  if (propertyExpr) {