@jinntec/fore 1.4.0 → 1.6.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 (71) hide show
  1. package/dist/fore-dev.js +2 -36
  2. package/dist/fore-dev.js.map +1 -1
  3. package/dist/fore.js +2 -30
  4. package/dist/fore.js.map +1 -1
  5. package/index.js +13 -0
  6. package/package.json +9 -5
  7. package/resources/fore.css +178 -92
  8. package/src/DependencyNotifyingDomFacade.js +1 -2
  9. package/src/ForeElementMixin.js +31 -5
  10. package/src/actions/abstract-action.js +379 -270
  11. package/src/actions/fx-action.js +0 -1
  12. package/src/actions/fx-append.js +1 -2
  13. package/src/actions/fx-confirm.js +12 -0
  14. package/src/actions/fx-copy.js +0 -1
  15. package/src/actions/fx-delete.js +31 -9
  16. package/src/actions/fx-dispatch.js +19 -5
  17. package/src/actions/fx-hide.js +19 -0
  18. package/src/actions/fx-insert.js +72 -8
  19. package/src/actions/fx-load.js +253 -0
  20. package/src/actions/fx-message.js +22 -7
  21. package/src/actions/fx-refresh.js +11 -1
  22. package/src/actions/fx-reload.js +12 -2
  23. package/src/actions/fx-replace.js +5 -4
  24. package/src/actions/fx-reset.js +48 -0
  25. package/src/actions/fx-return.js +0 -1
  26. package/src/actions/fx-send.js +40 -2
  27. package/src/actions/fx-setfocus.js +25 -7
  28. package/src/actions/fx-setvalue.js +32 -4
  29. package/src/actions/fx-show.js +14 -2
  30. package/src/actions/fx-toggle.js +0 -1
  31. package/src/actions/fx-update.js +9 -0
  32. package/src/events.js +0 -1
  33. package/src/fore.js +119 -63
  34. package/src/functions/common-function.js +28 -0
  35. package/src/fx-bind.js +7 -7
  36. package/src/fx-fore.js +207 -54
  37. package/src/fx-instance.js +55 -17
  38. package/src/fx-model.js +31 -33
  39. package/src/fx-submission.js +50 -47
  40. package/src/getInScopeContext.js +22 -8
  41. package/src/lab/fore-component.js +90 -0
  42. package/src/lab/instance-inspector.js +56 -0
  43. package/src/lab/template.html +16 -0
  44. package/src/relevance.js +27 -1
  45. package/src/tools/adi.js +1056 -0
  46. package/src/tools/fx-action-log.js +662 -0
  47. package/src/tools/fx-devtools.js +444 -0
  48. package/src/tools/fx-dom-inspector.js +609 -0
  49. package/src/tools/fx-json-instance.js +435 -0
  50. package/src/tools/fx-log-item.js +133 -0
  51. package/src/tools/fx-log-settings.js +474 -0
  52. package/src/tools/fx-minimap.js +194 -0
  53. package/src/tools/helpers.js +132 -0
  54. package/src/ui/abstract-control.js +41 -3
  55. package/src/ui/fx-action-log.js +358 -0
  56. package/src/ui/fx-alert.js +0 -1
  57. package/src/ui/fx-container.js +14 -3
  58. package/src/ui/fx-control.js +553 -474
  59. package/src/ui/fx-dialog.js +2 -0
  60. package/src/ui/fx-dom-inspector.js +1255 -0
  61. package/src/ui/fx-group.js +3 -4
  62. package/src/ui/fx-hint.js +2 -4
  63. package/src/ui/fx-inspector.js +5 -6
  64. package/src/ui/fx-items.js +55 -14
  65. package/src/ui/fx-output.js +36 -17
  66. package/src/ui/fx-repeat-attributes.js +409 -0
  67. package/src/ui/fx-repeat.js +12 -6
  68. package/src/ui/fx-switch.js +14 -3
  69. package/src/ui/fx-trigger.js +13 -1
  70. package/src/xpath-evaluation.js +109 -26
  71. package/src/xpath-util.js +55 -1
@@ -0,0 +1,132 @@
1
+ export function addClass(element, strClass) {
2
+ element.classList.add(strClass);
3
+ }
4
+
5
+ export function removeClass(element, strClass) {
6
+ element.classList.remove(strClass);
7
+ }
8
+
9
+ // Checks whether the text node is not empty or contains only the EOL
10
+ export function isEmptyTextNode(node) {
11
+ if (typeof node !== 'object') {
12
+ throw new Error(
13
+ `isEmptyTextNode: Expected argument node of type object, ${typeof node} given.`,
14
+ );
15
+ }
16
+
17
+ return /^\s*$/.test(node.textContent);
18
+ }
19
+
20
+ // Checks whether the node or its children contains only text information
21
+ export function containsOnlyText(node, checkChildren) {
22
+ if (typeof node !== 'object') {
23
+ throw new Error(
24
+ `containsOnlyText: Expected argument node of type object, ${typeof node} given.`,
25
+ );
26
+ }
27
+
28
+ checkChildren = checkChildren || false;
29
+
30
+ let result = false;
31
+ let nodeTmp = null;
32
+
33
+ // does the node contain only text nodes?
34
+ if (checkChildren) {
35
+ for (let i = 0, len = node.childNodes.length; i < len; i += 1) {
36
+ nodeTmp = node.childNodes[i];
37
+ result =
38
+ nodeTmp.nodeType === Node.TEXT_NODE ||
39
+ nodeTmp.nodeType === Node.COMMENT_NODE ||
40
+ nodeTmp.nodeType === Node.CDATA_SECTION_NODE;
41
+
42
+ if (!result) {
43
+ break;
44
+ }
45
+ }
46
+ } else {
47
+ // check the node type if it doesn't have any children
48
+ result =
49
+ node.nodeType === Node.TEXT_NODE ||
50
+ node.nodeType === Node.COMMENT_NODE ||
51
+ node.nodeType === Node.CDATA_SECTION_NODE;
52
+ }
53
+
54
+ return result;
55
+ }
56
+
57
+ // Create element wrapper -- allows to set attributes using the config object.
58
+ export function newElement(elem, attrs) {
59
+ const el = document.createElement(elem);
60
+
61
+ attrs = attrs || {};
62
+ for (const attr of Object.keys(attrs)) {
63
+ el.setAttribute(attr, attrs[attr]);
64
+ }
65
+
66
+ return el;
67
+ }
68
+
69
+ // Helper function for options view
70
+ export function drawOptionRow(optionCode, optionText) {
71
+ const row = newElement('span', { class: 'adi-opt' });
72
+ row.innerHTML = `<label><input type="checkbox" data-opt="${optionCode}">${optionText}</label>`;
73
+
74
+ return row;
75
+ }
76
+
77
+ // Renders the options panel
78
+ export function drawOptions() {
79
+ const ui = newElement('div', { id: 'adi-opts-view', class: 'adi-hidden' });
80
+ const head1 = newElement('span', { class: 'adi-opt-heading' });
81
+ const head2 = newElement('span', { class: 'adi-opt-heading' });
82
+ const close = newElement('span', { class: 'adi-opt-close' });
83
+
84
+ head1.textContent = 'General options';
85
+ head2.textContent = 'Observed nodes';
86
+
87
+ ui.appendChild(head1);
88
+ ui.appendChild(drawOptionRow('saving', 'Enable saving of settings'));
89
+ ui.appendChild(drawOptionRow('makeVisible', 'Scroll to the active element in DOM View'));
90
+ ui.appendChild(drawOptionRow('omitEmptyText', 'Hide empty text nodes'));
91
+ ui.appendChild(drawOptionRow('foldText', 'Fold the text nodes'));
92
+ ui.appendChild(drawOptionRow('transparent', 'Enable transparent background'));
93
+ ui.appendChild(head2);
94
+ ui.appendChild(drawOptionRow('nodeTypes-3', 'Text node'));
95
+ ui.appendChild(drawOptionRow('nodeTypes-8', 'Comment node'));
96
+ // ui.appendChild(drawOptionRow('nodeTypes-1', 'Element node'));
97
+ // ui.appendChild(drawOptionRow('nodeTypes-9', 'Document node'));
98
+ ui.appendChild(close);
99
+
100
+ return ui;
101
+ }
102
+
103
+ // Stops event propagation and also prevents the default behavior.
104
+ export function pauseEvent(e) {
105
+ if (e.stopPropagation) {
106
+ e.stopPropagation();
107
+ }
108
+
109
+ if (e.preventDefault) {
110
+ e.preventDefault();
111
+ }
112
+
113
+ e.cancelBubble = true;
114
+ e.returnValue = false;
115
+
116
+ return false;
117
+ }
118
+ // Helper function for attributes view
119
+ export function drawAttrRow(attrName, attrValue) {
120
+ const row = newElement('span', { class: 'adi-attr' });
121
+ switch (attrName.toLowerCase()) {
122
+ case 'defaultaction':
123
+ row.innerHTML = `<label>${attrName}: <select data-attr="${attrName}" value="${attrValue}"><option>perform</option><option>cancel</option></label>`;
124
+ break;
125
+ case 'delay':
126
+ row.innerHTML = `<label>${attrName}: <input type="number" data-attr="${attrName}" value="${attrValue}" readonly="readonly"></label>`;
127
+ break;
128
+ default:
129
+ row.innerHTML = `<label>${attrName}: <input type="text" data-attr="${attrName}" value="${attrValue}" readonly="readonly"></label>`;
130
+ }
131
+ return row;
132
+ }
@@ -2,6 +2,9 @@ import '../fx-model.js';
2
2
  import { foreElementMixin } from '../ForeElementMixin.js';
3
3
  import { ModelItem } from '../modelitem.js';
4
4
  import { Fore } from '../fore.js';
5
+ import {XPathUtil} from "../xpath-util";
6
+ import getInScopeContext from "../getInScopeContext";
7
+ import { evaluateXPathToFirstNode} from '../xpath-evaluation.js';
5
8
 
6
9
  /**
7
10
  * `AbstractControl` -
@@ -69,7 +72,41 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
69
72
  // this.control = this.querySelector('#control');
70
73
 
71
74
  if(!this.nodeset){
72
- this.style.display = 'none';
75
+
76
+ const create = this.closest('[create]');
77
+ if(create){
78
+ // ### check if parent element exists
79
+ let attrName,parentPath, parentNode;
80
+
81
+ if(this.ref.includes('/')){
82
+ parentPath = this.ref.substring(0, this.ref.indexOf('/'));
83
+ const inscope = getInScopeContext(this.parentNode, this.ref);
84
+ parentNode = evaluateXPathToFirstNode(parentPath,inscope,this);
85
+
86
+ if(parentNode && parentNode.nodeType === Node.ELEMENT_NODE){
87
+ if(this.ref.includes('@')){
88
+ attrName = this.ref.substring(this.ref.indexOf('/')+2);
89
+ parentNode.setAttribute(attrName,'');
90
+ }else{
91
+ Fore.dispatch(this,'warn',{message:'"create" is not implemented for elements'})
92
+ }
93
+ }
94
+ }else{
95
+ let inscope = getInScopeContext(this, this.ref);
96
+
97
+ if(this.ref.includes('@')) {
98
+ attrName = this.ref.substring(this.ref.indexOf('@') + 1);
99
+ inscope.setAttribute(attrName, '');
100
+ }else{
101
+ Fore.dispatch(this,'warn',{message:'"create" is not implemented for elements'})
102
+ // inscope = getInScopeContext(this.parentNode, this.ref);
103
+ }
104
+ }
105
+ }else{
106
+ // ### this actually makes the control nonrelevant
107
+ // todo: we should call a template function here to allow detachment of event-listeners and resetting eventual state
108
+ this.style.display = 'none';
109
+ }
73
110
  return;
74
111
  }
75
112
 
@@ -119,6 +156,9 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
119
156
  this.handleModelItemProperties();
120
157
 
121
158
  // if(!this.closest('fx-fore').ready) return; // state change event do not fire during init phase (initial refresh)
159
+ if(this.getOwnerForm().initialRun){
160
+ Fore.dispatch(this,'init',{});
161
+ }
122
162
  if (!this.getOwnerForm().ready) return; // state change event do not fire during init phase (initial refresh)
123
163
  if (currentVal !== this.value ) {
124
164
  // todo: discuss how to prevent unnecessary/unwanted value-changes e.g. when repeatitems are inserted
@@ -254,9 +294,7 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
254
294
  // todo - review alert handling altogether. There could be potentially multiple ones in model
255
295
  handleValid() {
256
296
  // console.log('mip valid', this.modelItem.required);
257
- const alert = this.querySelector('fx-alert');
258
297
 
259
- const mi = this.getModelItem();
260
298
  // console.log('late modelItem', mi);
261
299
  if (this.isValid() !== this.modelItem.constraint) {
262
300
  if (this.modelItem.constraint) {
@@ -0,0 +1,358 @@
1
+ import {XPathUtil} from "../xpath-util";
2
+
3
+ export class FxActionLog extends HTMLElement {
4
+ constructor() {
5
+ super();
6
+ this.attachShadow({ mode: 'open' });
7
+ this.listenTo = [];
8
+ this.listeners = [];
9
+ }
10
+
11
+ connectedCallback() {
12
+ const style = `
13
+ :host {
14
+ display:block;
15
+ margin-top:1rem;
16
+ position:relative;
17
+ max-width:40em;
18
+ }
19
+ .buttons button{
20
+ margin-right:0.5rem;
21
+ }
22
+ .info{
23
+ padding:0.25em;
24
+ }
25
+ ol{
26
+ background: #efefef;
27
+ padding: 0.5em 1.5em;
28
+ }
29
+ li .info{
30
+ margin:0.25em 0;
31
+ }
32
+ .info{
33
+ display:grid;
34
+ grid-template-columns:repeat(2, 1fr);
35
+ background:orange;
36
+ }
37
+ .action.info{
38
+ background:lightblue;
39
+ }
40
+
41
+ .event-name{
42
+ width:14rem;
43
+ display:inline-block;
44
+ }
45
+ /*
46
+ .event-name::before{
47
+ content:'triggered by';
48
+ font-size:0.8em;
49
+ text-decoration:italic;
50
+ }
51
+ */
52
+ #filter{
53
+ padding:1rem;
54
+ display:flex;
55
+ }
56
+ label{
57
+ margin-right:0.5rem;
58
+ white-space:nowrap;
59
+ display:inline-block;
60
+ }
61
+ .log-row{
62
+ margin:0.25em 0;
63
+ padding:0.5em;
64
+ position:relative;
65
+ }
66
+ .log-row.empty-row summary{
67
+ position:relative;
68
+ }
69
+ .log-row.empty-row summary{
70
+ list-style:none;
71
+ padding-left:1rem;
72
+ }
73
+ .log-row.empty-row summary::-webkit-details-marker {
74
+ display: none;
75
+ }
76
+ .outermost{
77
+ background:lightsteelblue;
78
+ }
79
+ `;
80
+
81
+ if(localStorage.getItem('fx-action-log-filters')){
82
+ this.listenTo = JSON.parse(localStorage.getItem('fx-action-log-filters'));
83
+ }else {
84
+ this._defaultSettings();
85
+ }
86
+
87
+
88
+ const html = `
89
+ <details open>
90
+ <summary>Event Log <span class="buttons"><button id="del"">del</a></button></span></summary>
91
+ <details id="filter">
92
+ <summary>filter <button id="reset">reset filters</button></summary>
93
+ <div class="boxes"></div>
94
+ </details>
95
+ <div id="log"></div>
96
+ </details>
97
+ `;
98
+
99
+ this.shadowRoot.innerHTML = `
100
+ <style>
101
+ ${style}
102
+ </style>
103
+ ${html}
104
+ `;
105
+
106
+ const fore = window.document.querySelector('fx-fore');
107
+ if(!fore){
108
+ console.error('fx-fore element not found in this page.');
109
+ }
110
+ const log = this.shadowRoot.querySelector('#log');
111
+ fore.classList.add('action-log');
112
+
113
+ this.listenTo.forEach(eventName => {
114
+ if(eventName.show){
115
+ fore.addEventListener(eventName.name, e => {
116
+ this._log(e,log);
117
+ });
118
+ }
119
+ });
120
+
121
+ const boxes = this.shadowRoot.querySelector('.boxes');
122
+
123
+ this.listenTo.forEach(item =>{
124
+ const lbl = document.createElement('label');
125
+ lbl.setAttribute('title',item.description);
126
+ lbl.innerText = item.name;
127
+ const cbx = document.createElement('input');
128
+ cbx.setAttribute('type', 'checkbox');
129
+ cbx.setAttribute('name', item.name);
130
+ if(item.show){
131
+ cbx.setAttribute('checked','');
132
+ }
133
+ lbl.append(cbx);
134
+ cbx.addEventListener('click', e =>{
135
+ console.log('filter box ticked', e);
136
+ if(!e.target.checked){
137
+ //remove event listener
138
+ const fore = document.querySelector('fx-fore');
139
+ fore.removeEventListener(item.name,this._log);
140
+ // e.preventDefault();
141
+ // e.stopPropagation();
142
+ }
143
+ const t = this.listenTo.find(evt => evt.name === item.name);
144
+ e.target.checked ? t.show=true:t.show=false;
145
+ // console.log('filter', this.listenTo);
146
+ localStorage.setItem('fx-action-log-filters', JSON.stringify(this.listenTo));
147
+ })
148
+ boxes.appendChild(lbl);
149
+ });
150
+
151
+ document.addEventListener('outermost-action-start', e => {
152
+ this.outermost = true;
153
+ },{capture:true});
154
+ document.addEventListener('outermost-action-end', e => {
155
+ this.outermost = false;
156
+ this.outermostAppender = null;
157
+ },{capture:true});
158
+
159
+ //buttons
160
+ const del = this.shadowRoot.querySelector('#del');
161
+ del.addEventListener('click', e => {
162
+ this.shadowRoot.querySelector('#log').innerHTML = '';
163
+ });
164
+ const reset = this.shadowRoot.querySelector('#reset');
165
+ reset.addEventListener('click', e => {
166
+ this._defaultSettings();
167
+ localStorage.removeItem('fx-action-log-filters');
168
+ window.location.reload();
169
+ });
170
+
171
+
172
+
173
+ }
174
+
175
+ _defaultSettings(){
176
+ this.listenTo=[
177
+ {name:"action-performed",show:true,description:'fired after an action has been performed'},
178
+ {name:"click",show:true,description:''},
179
+ {name:"deleted",show:true,description:'fired after a delete action has been executed'},
180
+ {name:"dialog-shown",show:true,description:'fired when a dialog has been shown'},
181
+ {name:"dialog-hidden",show:true,description:''},
182
+ {name:"error",show:true,description:''},
183
+ {name: "execute-action", show: true, description: ''},
184
+ {name:"init",show:false,description:''},
185
+ {name:"invalid",show:true,description:''},
186
+ {name:"index-changed",show:true,description:''},
187
+ {name:"instance-loaded",show:true,description:''},
188
+ {name:"item-created",show:false,description:''},
189
+ {name:"loaded",show:true,description:''},
190
+ {name:"model-construct",show:true,description:''},
191
+ {name:"model-construct-done",show:true,description:''},
192
+ {name:"nonrelevant",show:true,description:''},
193
+ {name:"optional",show:false,description:''},
194
+ {name:"path-mutated", show:true,description:''},
195
+ {name:"refresh-done", show:true,description:''},
196
+ {name:"readonly",show:true,description:''},
197
+ {name:"readwrite",show:true,description:''},
198
+ {name:"rebuild-done",show:true,description:''},
199
+ {name:"required",show:true,description:''},
200
+ {name:"ready",show:true,description:''},
201
+ {name:"recalculate-done",show:true,description:''},
202
+ {name:"relevant",show:false,description:''},
203
+ {name:"reload",show:true,description:''},
204
+ {name:"select",show:true,description:''},
205
+ {name:"deselect",show:true,description:''},
206
+ {name:"submit",show:true,description:''},
207
+ {name:"submit-error",show:true,description:''},
208
+ {name:"submit-done",show:true,description:''},
209
+ {name:"valid",show:false,description:''},
210
+ {name: "value-changed", show: true, description: ''},
211
+ {name: "outermost-action-start", show: true, description: ''},
212
+ {name: "outermost-action-end", show: true, description: ''}
213
+ ];
214
+ }
215
+
216
+ _log(e, log) {
217
+ if(e.target.nodeName === 'FX-ACTION-LOG') return;
218
+ e.preventDefault();
219
+ e.stopPropagation();
220
+
221
+
222
+
223
+
224
+ const row = document.createElement('div');
225
+ row.classList.add('log-row');
226
+ const logRow = this._logDetails(e);
227
+ if(e.detail &&
228
+ Object.keys(e.detail).length === 0 &&
229
+ Object.getPrototypeOf(e.detail) === Object.prototype){
230
+ row.classList.add('empty-row');
231
+ }
232
+
233
+ row.innerHTML = logRow;
234
+
235
+ if(this.outermost){
236
+ /*
237
+ outermost-action-start and outermost-action-end are use as marker events only to start/end a list.
238
+ They don't have aditional information to log.
239
+ */
240
+ if(e.type === 'outermost-action-start') return; // we don't want this event to actualy log something
241
+ if(!this.outermostAppender){
242
+ this.outermostAppender = document.createElement('ol');
243
+ log.append(this.outermostAppender);
244
+ }
245
+ const li = document.createElement('li');
246
+ li.innerHTML = logRow;
247
+ this.outermostAppender.append(li);
248
+ }else{
249
+ log.append(row);
250
+ }
251
+ const logRowTarget = row.querySelector('.event-target');
252
+ if(!logRowTarget) return;
253
+
254
+ const targetElement = e.target;
255
+ logRowTarget.addEventListener('click', e => {
256
+ const alreadyLogged = document.querySelectorAll('.fx-action-log-debug');
257
+ alreadyLogged.forEach(logged => {
258
+ logged.classList.remove('fx-action-log-debug')
259
+ });
260
+
261
+ targetElement.dispatchEvent(
262
+ new CustomEvent('log-action', {
263
+ composed: false,
264
+ bubbles: true,
265
+ cancelable:true,
266
+ detail: { target:targetElement },
267
+ }),
268
+ );
269
+
270
+
271
+ targetElement.classList.add('fx-action-log-debug');
272
+ targetElement.setAttribute('data-name', targetElement.nodeName)
273
+ this._highlight(targetElement);
274
+
275
+ });
276
+ // log.append(logElements);
277
+ }
278
+
279
+ _logDetails(e){
280
+ const {type} = e;
281
+ // console.log('>>>> event type', type)
282
+ const path = XPathUtil.getPath(e.target);
283
+ switch (type){
284
+ case 'outermost-action-start':
285
+ return `start`;
286
+ break;
287
+ case 'outermost-action-end':
288
+ return ``;
289
+ break;
290
+ case 'execute-action':
291
+ const stripped = e.detail.action.nodeName.split('-')[1];
292
+
293
+ switch (e.detail.action.nodeName){
294
+ case 'FX-SEND':
295
+ return `
296
+ <div class="info action"
297
+ <label class="action-name">${stripped} ${e.detail.action.getAttribute('submission')}</label>
298
+ <a href="#" class="event-name">${e.detail.event}</a>
299
+ </div>
300
+ `;
301
+ break;
302
+ default:
303
+ return `
304
+ <div class="info action">
305
+ <label class="action-name">${stripped}</label>
306
+ <a href="#" class="event-name">${e.detail.event}</a>
307
+ </div>
308
+ `;
309
+ }
310
+ break;
311
+ default:
312
+ return `
313
+ <div class="info event"
314
+ <label class="event-name">${e.type}</label>
315
+ <a href="#" class="event-target" title="${path}">${e.target.nodeName.toLowerCase()}</a>
316
+ ${this._listAttributes(e)}
317
+ </div>
318
+ `;
319
+
320
+ }
321
+
322
+ // }
323
+ }
324
+
325
+ _listAttributes(e){
326
+ console.log('_listAttributes',e)
327
+ return ``;
328
+ // return `${e.detail.model.id}`;
329
+ /*
330
+ if(e.detail &&
331
+ Object.keys(e.detail).length === 0 &&
332
+ Object.getPrototypeOf(e.detail) === Object.prototype){
333
+ return ``;
334
+ }else{
335
+ return `${e.detail.map((item) => `<span>${item}</span>`)}`;
336
+ }
337
+ */
338
+ }
339
+
340
+ _highlight(element) {
341
+ const defaultBG = element.style.backgroundColor;
342
+ const defaultTransition = element.style.transition;
343
+
344
+ element.style.transition = "background 1s";
345
+ element.style.backgroundColor = "#FDFF47";
346
+
347
+ setTimeout(() => {
348
+ element.style.backgroundColor = defaultBG;
349
+ setTimeout(() => {
350
+ element.style.transition = defaultTransition;
351
+ }, 400);
352
+ }, 400);
353
+ }
354
+
355
+ }
356
+ if (!customElements.get('fx-action-log')) {
357
+ customElements.define('fx-action-log', FxActionLog);
358
+ }
@@ -33,7 +33,6 @@ export class FxAlert extends AbstractControl {
33
33
  }
34
34
 
35
35
  async updateWidgetValue() {
36
- console.log('alert update', this);
37
36
  this.innerHTML = this.value;
38
37
  }
39
38
  }
@@ -1,5 +1,4 @@
1
1
  import '../fx-model.js';
2
- import { Fore } from '../fore.js';
3
2
  import { foreElementMixin } from '../ForeElementMixin.js';
4
3
 
5
4
  /**
@@ -32,6 +31,18 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
32
31
  `;
33
32
 
34
33
  this.getOwnerForm().registerLazyElement(this);
34
+
35
+ /*
36
+ this.addEventListener('mousedown', e => {
37
+
38
+ if(e.target === this){
39
+ e.preventDefault();
40
+ // e.stopImmediatePropagation();
41
+ }
42
+ } );
43
+ */
44
+
45
+ this.setAttribute('tabindex','0');
35
46
  }
36
47
 
37
48
  /**
@@ -58,7 +69,7 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
58
69
  }
59
70
 
60
71
  /**
61
- * anly relevance is processed for container controls
72
+ * relevance is processed for container controls only
62
73
  */
63
74
  handleModelItemProperties() {
64
75
  this.handleRelevant();
@@ -71,7 +82,7 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
71
82
  handleRelevant() {
72
83
  // console.log('mip valid', this.modelItem.enabled);
73
84
  if (!this.modelItem) {
74
- console.log('container is not relevant');
85
+ // console.log('container is not relevant');
75
86
  this.removeAttribute('relevant','');
76
87
  this.setAttribute('nonrelevant','');
77
88
  this.dispatchEvent(new CustomEvent('disabled', {}));