@jinntec/fore 1.0.0-0 → 1.0.0-3
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.
- package/README.md +17 -1
- package/dist/fore-all.js +10 -10
- package/dist/fore.js +1 -1
- package/index.js +8 -0
- package/package.json +4 -1
- package/resources/fore.css +111 -1
- package/src/DependencyNotifyingDomFacade.js +9 -1
- package/src/ForeElementMixin.js +25 -17
- package/src/actions/abstract-action.js +8 -7
- package/src/actions/fx-action.js +6 -1
- package/src/actions/fx-dispatch.js +10 -2
- package/src/actions/fx-hide.js +23 -0
- package/src/actions/fx-insert.js +14 -10
- package/src/actions/fx-send.js +1 -1
- package/src/actions/fx-setvalue.js +2 -4
- package/src/actions/fx-show.js +23 -0
- package/src/dep_graph.js +9 -0
- package/src/drawdown.js +172 -0
- package/src/fore.js +94 -3
- package/src/functions/fx-function.js +2 -2
- package/src/fx-bind.js +20 -17
- package/src/fx-fore.js +306 -33
- package/src/fx-instance.js +27 -6
- package/src/fx-model.js +182 -41
- package/src/fx-submission.js +29 -7
- package/src/fx-var.js +43 -0
- package/src/getInScopeContext.js +28 -7
- package/src/modelitem.js +1 -0
- package/src/ui/abstract-control.js +21 -6
- package/src/ui/fx-alert.js +16 -20
- package/src/ui/fx-container.js +9 -4
- package/src/ui/fx-control.js +76 -39
- package/src/ui/fx-dialog.js +68 -0
- package/src/ui/fx-inspector.js +44 -0
- package/src/ui/fx-items.js +120 -0
- package/src/ui/fx-output.js +77 -9
- package/src/ui/fx-repeat.js +86 -16
- package/src/ui/fx-repeatitem.js +16 -3
- package/src/ui/fx-trigger.js +3 -0
- package/src/xpath-evaluation.js +609 -267
- package/src/xpath-util.js +52 -12
package/src/ui/fx-container.js
CHANGED
|
@@ -30,18 +30,21 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
|
|
|
30
30
|
</style>
|
|
31
31
|
${html}
|
|
32
32
|
`;
|
|
33
|
+
|
|
34
|
+
this.getOwnerForm().registerLazyElement(this);
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
/**
|
|
36
38
|
* (re)apply all state properties to this control.
|
|
37
39
|
*/
|
|
38
|
-
refresh() {
|
|
39
|
-
|
|
40
|
+
refresh(force) {
|
|
41
|
+
if (!force && this.hasAttribute('refresh-on-view')) return;
|
|
42
|
+
// console.log('### FxContainer.refresh on : ', this);
|
|
40
43
|
|
|
41
44
|
if (this.isBound()) {
|
|
42
45
|
this.evalInContext();
|
|
43
46
|
this.modelItem = this.getModelItem();
|
|
44
|
-
this.value = this.modelItem.value;
|
|
47
|
+
// this.value = this.modelItem.value;
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
// await this.updateComplete;
|
|
@@ -50,7 +53,7 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
|
|
|
50
53
|
if (this._getForm().ready) {
|
|
51
54
|
this.handleModelItemProperties();
|
|
52
55
|
}
|
|
53
|
-
Fore.refreshChildren(this);
|
|
56
|
+
Fore.refreshChildren(this, force);
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
handleModelItemProperties() {
|
|
@@ -78,6 +81,8 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
|
|
|
78
81
|
|
|
79
82
|
handleRelevant() {
|
|
80
83
|
// console.log('mip valid', this.modelItem.enabled);
|
|
84
|
+
if (!this.modelItem) return;
|
|
85
|
+
|
|
81
86
|
if (this.isEnabled() !== this.modelItem.enabled) {
|
|
82
87
|
if (this.modelItem.enabled) {
|
|
83
88
|
this.dispatchEvent(new CustomEvent('enabled', {}));
|
package/src/ui/fx-control.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import XfAbstractControl from './abstract-control.js';
|
|
2
|
-
import { evaluateXPath, evaluateXPathToString } from '../xpath-evaluation.js';
|
|
2
|
+
import { evaluateXPath, evaluateXPathToString, evaluateXPathToNodes } from '../xpath-evaluation.js';
|
|
3
|
+
import getInScopeContext from '../getInScopeContext.js';
|
|
4
|
+
import { Fore } from '../fore.js';
|
|
3
5
|
|
|
4
6
|
const WIDGETCLASS = 'widget';
|
|
5
7
|
|
|
@@ -12,7 +14,7 @@ const WIDGETCLASS = 'widget';
|
|
|
12
14
|
* @customElement
|
|
13
15
|
* @demo demo/index.html
|
|
14
16
|
*/
|
|
15
|
-
class FxControl extends XfAbstractControl {
|
|
17
|
+
export default class FxControl extends XfAbstractControl {
|
|
16
18
|
constructor() {
|
|
17
19
|
super();
|
|
18
20
|
this.inited = false;
|
|
@@ -54,7 +56,7 @@ class FxControl extends XfAbstractControl {
|
|
|
54
56
|
`;
|
|
55
57
|
|
|
56
58
|
this.widget = this.getWidget();
|
|
57
|
-
console.log('widget ', this.widget);
|
|
59
|
+
// console.log('widget ', this.widget);
|
|
58
60
|
|
|
59
61
|
// ### convenience marker event
|
|
60
62
|
if (this.updateEvent === 'enter') {
|
|
@@ -64,15 +66,17 @@ class FxControl extends XfAbstractControl {
|
|
|
64
66
|
event.preventDefault();
|
|
65
67
|
this.setValue(this.widget[this.valueProp]);
|
|
66
68
|
}
|
|
67
|
-
// console.log('enter handler ', this.updateEvent);
|
|
68
|
-
// this.setValue(this.widget[this.valueProp]);
|
|
69
69
|
});
|
|
70
70
|
this.updateEvent = 'blur'; // needs to be registered too
|
|
71
71
|
}
|
|
72
72
|
this.widget.addEventListener(this.updateEvent, () => {
|
|
73
|
-
console.log('eventlistener ', this.updateEvent);
|
|
73
|
+
// console.log('eventlistener ', this.updateEvent);
|
|
74
74
|
this.setValue(this.widget[this.valueProp]);
|
|
75
75
|
});
|
|
76
|
+
|
|
77
|
+
const slot = this.shadowRoot.querySelector('slot');
|
|
78
|
+
this.template = this.querySelector('template');
|
|
79
|
+
// console.log('template',this.template);
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
setValue(val) {
|
|
@@ -95,6 +99,7 @@ class FxControl extends XfAbstractControl {
|
|
|
95
99
|
* @returns {HTMLElement|*}
|
|
96
100
|
*/
|
|
97
101
|
getWidget() {
|
|
102
|
+
if (this.widget) return this.widget;
|
|
98
103
|
let widget = this.querySelector(`.${WIDGETCLASS}`);
|
|
99
104
|
if (!widget) {
|
|
100
105
|
widget = this.querySelector('input');
|
|
@@ -127,23 +132,34 @@ class FxControl extends XfAbstractControl {
|
|
|
127
132
|
}
|
|
128
133
|
}
|
|
129
134
|
|
|
130
|
-
|
|
135
|
+
getTemplate() {
|
|
136
|
+
return this.querySelector('template');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async refresh(force) {
|
|
140
|
+
// console.log('fx-control refresh', this);
|
|
131
141
|
super.refresh();
|
|
142
|
+
// console.log('refresh template', this.template);
|
|
132
143
|
// const {widget} = this;
|
|
133
144
|
|
|
134
145
|
// ### if we find a ref on control we have a 'select' control of some kind
|
|
135
|
-
|
|
136
|
-
if (
|
|
137
|
-
const tmpl = this.widget.querySelector('template');
|
|
138
|
-
|
|
146
|
+
const widget = this.getWidget();
|
|
147
|
+
if (widget.hasAttribute('ref')) {
|
|
139
148
|
// ### eval nodeset for list control
|
|
140
|
-
const ref =
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
149
|
+
const ref = widget.getAttribute('ref');
|
|
150
|
+
/*
|
|
151
|
+
actually a ref on a select or similar component should point to a different instance
|
|
152
|
+
with an absolute expr e.g. 'instance('theId')/...'
|
|
153
|
+
|
|
154
|
+
todo: even bail out if ref is not absolute?
|
|
155
|
+
*/
|
|
156
|
+
|
|
157
|
+
const inscope = getInScopeContext(this, ref);
|
|
158
|
+
// const nodeset = evaluateXPathToNodes(ref, inscope, this);
|
|
159
|
+
const nodeset = evaluateXPath(ref, inscope, this);
|
|
144
160
|
|
|
145
161
|
// ### clear items
|
|
146
|
-
const { children } =
|
|
162
|
+
const { children } = widget;
|
|
147
163
|
Array.from(children).forEach(child => {
|
|
148
164
|
if (child.nodeName.toLowerCase() !== 'template') {
|
|
149
165
|
child.parentNode.removeChild(child);
|
|
@@ -151,33 +167,54 @@ class FxControl extends XfAbstractControl {
|
|
|
151
167
|
});
|
|
152
168
|
|
|
153
169
|
// ### build the items
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (this.value === evaluated) {
|
|
170
|
-
newEntry.setAttribute('selected', 'selected');
|
|
170
|
+
if (this.template) {
|
|
171
|
+
if (nodeset.length) {
|
|
172
|
+
// console.log('nodeset', nodeset);
|
|
173
|
+
Array.from(nodeset).forEach(node => {
|
|
174
|
+
// console.log('#### node', node);
|
|
175
|
+
const newEntry = this.createEntry();
|
|
176
|
+
|
|
177
|
+
// ### initialize new entry
|
|
178
|
+
// ### set value
|
|
179
|
+
this.updateEntry(newEntry, node);
|
|
180
|
+
});
|
|
181
|
+
} else {
|
|
182
|
+
const newEntry = this.createEntry();
|
|
183
|
+
this.updateEntry(newEntry, nodeset);
|
|
171
184
|
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
Fore.refreshChildren(this, force);
|
|
188
|
+
}
|
|
172
189
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const labelExpr = optionLabel.substring(1, optionLabel.length - 1);
|
|
190
|
+
updateEntry(newEntry, node) {
|
|
191
|
+
// ### >>> todo: needs rework this code is heavily assuming a select control with 'value' attribute - not generic at all yet.
|
|
176
192
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
193
|
+
if (this.widget.nodeName !== 'SELECT') return;
|
|
194
|
+
const valueAttribute = this._getValueAttribute(newEntry);
|
|
195
|
+
const valueExpr = valueAttribute.value;
|
|
196
|
+
const cutted = valueExpr.substring(1, valueExpr.length - 1);
|
|
197
|
+
const evaluated = evaluateXPath(cutted, node, newEntry);
|
|
198
|
+
valueAttribute.value = evaluated;
|
|
199
|
+
|
|
200
|
+
if (this.value === evaluated) {
|
|
201
|
+
newEntry.setAttribute('selected', 'selected');
|
|
180
202
|
}
|
|
203
|
+
|
|
204
|
+
// ### set label
|
|
205
|
+
const optionLabel = newEntry.textContent;
|
|
206
|
+
const labelExpr = optionLabel.substring(1, optionLabel.length - 1);
|
|
207
|
+
|
|
208
|
+
const label = evaluateXPathToString(labelExpr, node, newEntry);
|
|
209
|
+
newEntry.textContent = label;
|
|
210
|
+
// ### <<< needs rework
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
createEntry() {
|
|
214
|
+
const content = this.template.content.firstElementChild.cloneNode(true);
|
|
215
|
+
const newEntry = document.importNode(content, true);
|
|
216
|
+
this.template.parentNode.appendChild(newEntry);
|
|
217
|
+
return newEntry;
|
|
181
218
|
}
|
|
182
219
|
|
|
183
220
|
// eslint-disable-next-line class-methods-use-this
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export class FxDialog extends HTMLElement {
|
|
2
|
+
|
|
3
|
+
static get properties() {
|
|
4
|
+
return {
|
|
5
|
+
id: String
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
this.attachShadow({mode: 'open'});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
connectedCallback() {
|
|
15
|
+
const style = `
|
|
16
|
+
:host {
|
|
17
|
+
display: none;
|
|
18
|
+
height: 100vh;
|
|
19
|
+
width:100vw;
|
|
20
|
+
position:fixed;
|
|
21
|
+
left:0;
|
|
22
|
+
top:0;
|
|
23
|
+
right:0;
|
|
24
|
+
bottom:0;
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
this.shadowRoot.innerHTML = this.render(style);
|
|
29
|
+
this.id = this.getAttribute('id');
|
|
30
|
+
|
|
31
|
+
// const dialog = document.getElementById(this.id);
|
|
32
|
+
|
|
33
|
+
const closeBtn = this.querySelector('.close-dialog');
|
|
34
|
+
if (closeBtn) {
|
|
35
|
+
closeBtn.addEventListener('click', (e) => {
|
|
36
|
+
document.getElementById(this.id).classList.remove('show');
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.focus();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
render(styles) {
|
|
44
|
+
return `
|
|
45
|
+
<style>
|
|
46
|
+
${styles}
|
|
47
|
+
</style>
|
|
48
|
+
<slot></slot>
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
open(){
|
|
53
|
+
window.addEventListener('keyup', (e) => {
|
|
54
|
+
if (e.key === "Escape") {
|
|
55
|
+
this.hide();
|
|
56
|
+
}
|
|
57
|
+
},{once:true});
|
|
58
|
+
|
|
59
|
+
this.classList.add('show');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
hide(){
|
|
63
|
+
this.classList.remove('show');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
customElements.define('fx-dialog', FxDialog);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lists out all live instances in html 'details' and 'summary' elements.
|
|
3
|
+
*/
|
|
4
|
+
export class FxInspector extends HTMLElement {
|
|
5
|
+
connectedCallback() {
|
|
6
|
+
const style = `
|
|
7
|
+
:host {
|
|
8
|
+
display: block;
|
|
9
|
+
width:100%;
|
|
10
|
+
background:var(--inspector-bg);
|
|
11
|
+
}
|
|
12
|
+
pre{
|
|
13
|
+
background:var(--inspector-pre-bg);
|
|
14
|
+
color:var(--inspector-color);
|
|
15
|
+
max-height:var(--inspector-instance-height,300px);
|
|
16
|
+
overflow:scroll;
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
const instances = Array.from(document.querySelectorAll('fx-instance'));
|
|
21
|
+
this.innerHTML = `
|
|
22
|
+
<style>
|
|
23
|
+
${style}
|
|
24
|
+
</style>
|
|
25
|
+
<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('')}
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
this.addEventListener('slotchange', e => {
|
|
39
|
+
console.log('slotchange ', e);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
customElements.define('fx-inspector', FxInspector);
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import XfAbstractControl from './abstract-control.js';
|
|
2
|
+
import { evaluateXPath, evaluateXPathToString, evaluateXPathToNodes } from '../xpath-evaluation.js';
|
|
3
|
+
import getInScopeContext from '../getInScopeContext.js';
|
|
4
|
+
import FxControl from './fx-control.js';
|
|
5
|
+
import { Fore } from '../fore.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* FxItems provices a templated list over its bound nodes. It is not standalone but expects to be used
|
|
9
|
+
* within an fx-control element.
|
|
10
|
+
*
|
|
11
|
+
*
|
|
12
|
+
*
|
|
13
|
+
* @demo demo/selects3.html
|
|
14
|
+
*/
|
|
15
|
+
export class FxItems extends FxControl {
|
|
16
|
+
static get properties() {
|
|
17
|
+
return {
|
|
18
|
+
...super.properties,
|
|
19
|
+
valueAttr: {
|
|
20
|
+
type: String,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
constructor() {
|
|
26
|
+
super();
|
|
27
|
+
this.valueAttr = this.hasAttribute('value') ? this.getAttribute('value') : null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
connectedCallback() {
|
|
31
|
+
super.connectedCallback();
|
|
32
|
+
|
|
33
|
+
this.addEventListener('click', e => {
|
|
34
|
+
const items = this.querySelectorAll('[value]');
|
|
35
|
+
|
|
36
|
+
let target;
|
|
37
|
+
if (e.target.nodeName === 'LABEL') {
|
|
38
|
+
target = document.getElementById(e.target.getAttribute('for'));
|
|
39
|
+
target.checked = !target.checked;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let val = '';
|
|
43
|
+
Array.from(items).forEach(item => {
|
|
44
|
+
if (item.checked) {
|
|
45
|
+
val += ` ${item.getAttribute('value')}`;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
this.setAttribute('value', val.trim());
|
|
49
|
+
|
|
50
|
+
// ### check for parent control
|
|
51
|
+
const parentBind = this.parentNode.closest('[ref]');
|
|
52
|
+
if (!parentBind) return;
|
|
53
|
+
const modelitem = parentBind.getModelItem();
|
|
54
|
+
const setval = this.shadowRoot.getElementById('setvalue');
|
|
55
|
+
setval.setValue(modelitem, val.trim());
|
|
56
|
+
setval.actionPerformed();
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getWidget() {
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async updateWidgetValue() {
|
|
65
|
+
// console.log('setting items value');
|
|
66
|
+
|
|
67
|
+
const parentBind = this.parentNode.closest('[ref]');
|
|
68
|
+
if (parentBind) {
|
|
69
|
+
this.value = parentBind.value;
|
|
70
|
+
}
|
|
71
|
+
this.setAttribute('value', this.value);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Updates an entry by setting the label and the value.
|
|
76
|
+
*
|
|
77
|
+
* Will connect label and control with `for` attribute with generated id.
|
|
78
|
+
*
|
|
79
|
+
* attention: limitations here: assumes that there's an `label` element plus an element with an `value`
|
|
80
|
+
* attribute which it will update.
|
|
81
|
+
*
|
|
82
|
+
*
|
|
83
|
+
*
|
|
84
|
+
* @param newEntry
|
|
85
|
+
* @param node
|
|
86
|
+
*/
|
|
87
|
+
updateEntry(newEntry, node) {
|
|
88
|
+
// console.log('fx-items updateEntry', this.value);
|
|
89
|
+
// super.updateEntry(newEntry,node);
|
|
90
|
+
|
|
91
|
+
// ### danger zone - highly specific - assumes knowledge of the template structure ###
|
|
92
|
+
// ### danger zone - highly specific - assumes knowledge of the template structure ###
|
|
93
|
+
// ### danger zone - highly specific - assumes knowledge of the template structure ###
|
|
94
|
+
|
|
95
|
+
const label = newEntry.querySelector('label');
|
|
96
|
+
label.textContent = node.textContent;
|
|
97
|
+
|
|
98
|
+
const id = Fore.createUUID();
|
|
99
|
+
label.setAttribute('for', id);
|
|
100
|
+
|
|
101
|
+
// getting element which has 'value' attr
|
|
102
|
+
const input = newEntry.querySelector('[value]');
|
|
103
|
+
// getting expr
|
|
104
|
+
const expr = input.value;
|
|
105
|
+
const cutted = expr.substring(1, expr.length - 1);
|
|
106
|
+
const evaluated = evaluateXPath(cutted, node, newEntry);
|
|
107
|
+
|
|
108
|
+
// adding space around value to allow matching of 'words'
|
|
109
|
+
const spaced = ` ${evaluated} `;
|
|
110
|
+
|
|
111
|
+
const valAttr = ` ${this.getAttribute('value')} `;
|
|
112
|
+
input.value = evaluated;
|
|
113
|
+
input.setAttribute('id', id);
|
|
114
|
+
if (valAttr.indexOf(spaced) !== -1) {
|
|
115
|
+
input.checked = true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
customElements.define('fx-items', FxItems);
|
package/src/ui/fx-output.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import XfAbstractControl from './abstract-control.js';
|
|
2
|
+
import { evaluateXPath, evaluateXPathToStrings } from '../xpath-evaluation.js';
|
|
3
|
+
import getInScopeContext from '../getInScopeContext.js';
|
|
4
|
+
// import {markdown} from '../drawdown.js';
|
|
2
5
|
|
|
3
6
|
/**
|
|
4
7
|
* todo: review placing of value. should probably work with value attribute and not allow slotted content.
|
|
@@ -20,8 +23,6 @@ export class FxOutput extends XfAbstractControl {
|
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
connectedCallback() {
|
|
23
|
-
console.log('connectedCallback output', this.shadowRoot);
|
|
24
|
-
|
|
25
26
|
const style = `
|
|
26
27
|
:host {
|
|
27
28
|
display: inline-block;
|
|
@@ -32,12 +33,21 @@ export class FxOutput extends XfAbstractControl {
|
|
|
32
33
|
.label{
|
|
33
34
|
display: inline-block;
|
|
34
35
|
}
|
|
36
|
+
table,tbody{
|
|
37
|
+
width:100%;
|
|
38
|
+
}
|
|
39
|
+
th{
|
|
40
|
+
text-align:left;
|
|
41
|
+
}
|
|
42
|
+
td{
|
|
43
|
+
padding-right:1rem;
|
|
44
|
+
}
|
|
35
45
|
`;
|
|
36
46
|
|
|
37
47
|
const outputHtml = `
|
|
38
48
|
<slot name="label"></slot>
|
|
39
49
|
<span id="value">
|
|
40
|
-
<slot></slot>
|
|
50
|
+
<slot id="main"></slot>
|
|
41
51
|
</span>
|
|
42
52
|
`;
|
|
43
53
|
|
|
@@ -50,6 +60,7 @@ export class FxOutput extends XfAbstractControl {
|
|
|
50
60
|
// this.widget = this.shadowRoot.querySelector('#widget');
|
|
51
61
|
// this.widget = this.getWidget();
|
|
52
62
|
// console.log('widget ', this.widget);
|
|
63
|
+
this.mediatype = this.hasAttribute('mediatype') ? this.getAttribute('mediatype') : null;
|
|
53
64
|
|
|
54
65
|
this.addEventListener('slotchange', e => {
|
|
55
66
|
console.log('slotchange ', e);
|
|
@@ -57,18 +68,32 @@ export class FxOutput extends XfAbstractControl {
|
|
|
57
68
|
}
|
|
58
69
|
|
|
59
70
|
async refresh() {
|
|
60
|
-
//
|
|
71
|
+
// Resolve the ref first. The ref will set the `nodeset` which is important for the 'context'
|
|
72
|
+
if (this.ref) {
|
|
73
|
+
await super.refresh();
|
|
74
|
+
}
|
|
61
75
|
|
|
76
|
+
// ### 2. Eval the value
|
|
62
77
|
if (this.valueAttr) {
|
|
63
78
|
this.value = this.getValue();
|
|
64
79
|
await this.updateWidgetValue();
|
|
65
|
-
return;
|
|
66
80
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
getValue() {
|
|
84
|
+
// return 'foobar';
|
|
85
|
+
try {
|
|
86
|
+
const inscopeContext = getInScopeContext(this, this.valueAttr);
|
|
87
|
+
if (this.hasAttribute('html')) {
|
|
88
|
+
return evaluateXPath(this.valueAttr, inscopeContext, this);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return evaluateXPathToStrings(this.valueAttr, inscopeContext, this)[0];
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error(error);
|
|
94
|
+
this.dispatch('error', { message: error });
|
|
70
95
|
}
|
|
71
|
-
|
|
96
|
+
return null;
|
|
72
97
|
}
|
|
73
98
|
|
|
74
99
|
getWidget() {
|
|
@@ -77,7 +102,50 @@ export class FxOutput extends XfAbstractControl {
|
|
|
77
102
|
}
|
|
78
103
|
|
|
79
104
|
async updateWidgetValue() {
|
|
105
|
+
console.log('updateWidgetValue');
|
|
80
106
|
const valueWrapper = this.shadowRoot.getElementById('value');
|
|
107
|
+
|
|
108
|
+
if (this.mediatype === 'markdown') {
|
|
109
|
+
const md = markdown(this.nodeset);
|
|
110
|
+
this.innerHtml = md;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (this.mediatype === 'html') {
|
|
114
|
+
if (this.modelItem.node) {
|
|
115
|
+
/*
|
|
116
|
+
valueWrapper.innerHTML = this.modelItem.node.outerHTML;
|
|
117
|
+
return;
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
const { node } = this.modelItem;
|
|
121
|
+
|
|
122
|
+
if (node.nodeType) {
|
|
123
|
+
// const mainSlot = this.shadowRoot.querySelector('#main');
|
|
124
|
+
// valueWrapper.appendChild(node);
|
|
125
|
+
|
|
126
|
+
// todo: checking if ownerDocument of node and ownerDocument of this are the same - otherwise import first
|
|
127
|
+
// const imported = this.ownerDocument.importNode(node,true);
|
|
128
|
+
// const clone = node.cloneNode(true);
|
|
129
|
+
|
|
130
|
+
this.appendChild(node);
|
|
131
|
+
// this.innerHtml = node;
|
|
132
|
+
// this.innerHTML = node;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
Object.entries(node).map(obj => {
|
|
136
|
+
// valueWrapper.appendChild(obj[1]);
|
|
137
|
+
this.appendChild(obj[1]);
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// this.innerHTML = this.value.outerHTML;
|
|
143
|
+
valueWrapper.innerHTML = this.value.outerHTML;
|
|
144
|
+
|
|
145
|
+
// this.shadowRoot.appendChild(this.value);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
81
149
|
valueWrapper.innerHTML = this.value;
|
|
82
150
|
}
|
|
83
151
|
|