@schukai/monster 3.65.20 → 3.65.21
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/CHANGELOG.md +5 -39
- package/package.json +1 -1
- package/source/components/datatable/change-button.mjs +6 -6
- package/source/components/datatable/dataset.mjs +202 -202
- package/source/components/datatable/datatable.mjs +3 -6
- package/source/components/datatable/filter.mjs +4 -8
- package/source/components/datatable/pagination.mjs +4 -4
- package/source/components/datatable/save-button.mjs +5 -4
- package/source/components/datatable/status.mjs +5 -4
- package/source/data/datasource/dom.mjs +85 -84
- package/source/dom/resource/data.mjs +123 -120
- package/source/dom/resource.mjs +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,55 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
## [3.65.
|
|
6
|
-
|
|
7
|
-
### Bug Fixes
|
|
8
|
-
|
|
9
|
-
- wip new pipeline
|
|
10
|
-
- wip new pipeline
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
## [3.65.19] - 2024-06-20
|
|
15
|
-
|
|
16
|
-
### Bug Fixes
|
|
17
|
-
|
|
18
|
-
- wip new pipeline
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
## [3.65.18] - 2024-06-20
|
|
23
|
-
|
|
24
|
-
### Bug Fixes
|
|
25
|
-
|
|
26
|
-
- wip new pipeline
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
## [3.65.17] - 2024-06-20
|
|
31
|
-
|
|
32
|
-
### Bug Fixes
|
|
33
|
-
|
|
34
|
-
- wip new pipeline
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
## [3.65.16] - 2024-06-20
|
|
5
|
+
## [3.65.21] - 2024-06-20
|
|
39
6
|
|
|
40
7
|
### Bug Fixes
|
|
41
8
|
|
|
42
|
-
-
|
|
9
|
+
- exchange of document.selector with function findElementWithSelectorUpwards [#199](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/199)
|
|
43
10
|
|
|
11
|
+
## [3.65.20] - 2024-06-20
|
|
44
12
|
|
|
45
|
-
|
|
46
|
-
## [3.65.15] - 2024-06-20
|
|
47
|
-
|
|
13
|
+
- Changeover to new release process
|
|
48
14
|
|
|
49
15
|
## [3.65.3] - 2024-06-19
|
|
50
16
|
|
|
51
17
|
### Bug Fixes
|
|
52
18
|
|
|
53
|
-
- switch nodejs_22 to nodejs_20
|
|
19
|
+
- switch nodejs_22 to nodejs_20 (segmentation fault)
|
|
54
20
|
|
|
55
21
|
## [3.65.1] - 2024-06-17
|
|
56
22
|
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.5","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"3.65.
|
|
1
|
+
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.5","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"3.65.21"}
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
CustomElement,
|
|
21
21
|
registerCustomElement,
|
|
22
22
|
} from "../../dom/customelement.mjs";
|
|
23
|
+
import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
|
|
23
24
|
import { isString } from "../../types/is.mjs";
|
|
24
25
|
import { State } from "../form/types/state.mjs";
|
|
25
26
|
import "../form/state-button.mjs";
|
|
@@ -189,12 +190,12 @@ function initControlReferences() {
|
|
|
189
190
|
const selector = this.getOption("dataset.selector");
|
|
190
191
|
|
|
191
192
|
if (isString(selector)) {
|
|
192
|
-
|
|
193
|
-
|
|
193
|
+
|
|
194
|
+
const element = findElementWithSelectorUpwards( this,selector);
|
|
195
|
+
if (element===null) {
|
|
194
196
|
throw new Error("the selector must match exactly one element");
|
|
195
197
|
}
|
|
196
198
|
|
|
197
|
-
const element = elements[0];
|
|
198
199
|
if (!(element instanceof HTMLElement)) {
|
|
199
200
|
throw new TypeError("the element must be a dataset");
|
|
200
201
|
}
|
|
@@ -205,12 +206,11 @@ function initControlReferences() {
|
|
|
205
206
|
const selector2 = this.getOption("overlay.selector");
|
|
206
207
|
|
|
207
208
|
if (isString(selector2)) {
|
|
208
|
-
const
|
|
209
|
-
if (
|
|
209
|
+
const element = findElementWithSelectorUpwards( this,selector);
|
|
210
|
+
if (element===null) {
|
|
210
211
|
throw new Error("the selector must match exactly one element");
|
|
211
212
|
}
|
|
212
213
|
|
|
213
|
-
const element = elements[0];
|
|
214
214
|
if (!(element instanceof HTMLElement)) {
|
|
215
215
|
throw new TypeError("the element must be a overlay");
|
|
216
216
|
}
|
|
@@ -12,32 +12,33 @@
|
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
15
|
+
import {instanceSymbol, internalSymbol} from "../../constants.mjs";
|
|
16
|
+
import {Pathfinder} from "../../data/pathfinder.mjs";
|
|
17
|
+
import {getLinkedObjects, hasObjectLink} from "../../dom/attributes.mjs";
|
|
18
|
+
import {customElementUpdaterLinkSymbol} from "../../dom/constants.mjs";
|
|
19
19
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
assembleMethodSymbol,
|
|
21
|
+
CustomElement,
|
|
22
|
+
attributeObserverSymbol,
|
|
23
|
+
registerCustomElement,
|
|
24
24
|
} from "../../dom/customelement.mjs";
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
25
|
+
import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
|
|
26
|
+
import {isString} from "../../types/is.mjs";
|
|
27
|
+
import {Observer} from "../../types/observer.mjs";
|
|
28
|
+
import {clone} from "../../util/clone.mjs";
|
|
28
29
|
import {
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
ATTRIBUTE_DATASOURCE_SELECTOR,
|
|
31
|
+
ATTRIBUTE_DATATABLE_INDEX,
|
|
31
32
|
} from "./constants.mjs";
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
33
|
+
import {Datasource} from "./datasource.mjs";
|
|
34
|
+
import {DatasetStyleSheet} from "./stylesheet/dataset.mjs";
|
|
34
35
|
import {
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
handleDataSourceChanges,
|
|
37
|
+
datasourceLinkedElementSymbol,
|
|
37
38
|
} from "./util.mjs";
|
|
38
|
-
import {
|
|
39
|
+
import {FormStyleSheet} from "../stylesheet/form.mjs";
|
|
39
40
|
|
|
40
|
-
export {
|
|
41
|
+
export {DataSet};
|
|
41
42
|
|
|
42
43
|
/**
|
|
43
44
|
* The data set component is used to show the data of a data source.
|
|
@@ -78,185 +79,184 @@ export { DataSet };
|
|
|
78
79
|
* @summary A data set
|
|
79
80
|
*/
|
|
80
81
|
class DataSet extends CustomElement {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
82
|
+
/**
|
|
83
|
+
* This method is called by the `instanceof` operator.
|
|
84
|
+
* @returns {symbol}
|
|
85
|
+
*/
|
|
86
|
+
static get [instanceSymbol]() {
|
|
87
|
+
return Symbol.for("@schukai/monster/components/dataset@@instance");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* This method determines which attributes are to be monitored by `attributeChangedCallback()`.
|
|
92
|
+
*
|
|
93
|
+
* @return {string[]}
|
|
94
|
+
* @since 1.15.0
|
|
95
|
+
*/
|
|
96
|
+
static get observedAttributes() {
|
|
97
|
+
const attributes = super.observedAttributes;
|
|
98
|
+
attributes.push(ATTRIBUTE_DATATABLE_INDEX);
|
|
99
|
+
return attributes;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* To set the options via the html tag the attribute `data-monster-options` must be used.
|
|
104
|
+
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
|
105
|
+
*
|
|
106
|
+
* The individual configuration values can be found in the table.
|
|
107
|
+
*
|
|
108
|
+
* @property {Object} templates Template definitions
|
|
109
|
+
* @property {string} templates.main Main template
|
|
110
|
+
* @property {object} datasource The datasource
|
|
111
|
+
* @property {string} datasource.selector The selector of the datasource
|
|
112
|
+
* @property {object} mapping The mapping
|
|
113
|
+
* @property {string} mapping.data The data
|
|
114
|
+
* @property {number} mapping.index The index
|
|
115
|
+
* @property {Array} data The data
|
|
116
|
+
*/
|
|
117
|
+
get defaults() {
|
|
118
|
+
const obj = Object.assign({}, super.defaults, {
|
|
119
|
+
templates: {
|
|
120
|
+
main: getTemplate(),
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
datasource: {
|
|
124
|
+
selector: null,
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
mapping: {
|
|
128
|
+
data: "dataset",
|
|
129
|
+
index: 0,
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
data: {},
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
updateOptionsFromArguments.call(this, obj);
|
|
136
|
+
return obj;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
*
|
|
141
|
+
* @return {string}
|
|
142
|
+
*/
|
|
143
|
+
static getTag() {
|
|
144
|
+
return "monster-dataset";
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
write() {
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
if (!this[datasourceLinkedElementSymbol]) {
|
|
150
|
+
reject(new Error("No datasource"));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const internalUpdateCloneData = this.getInternalUpdateCloneData();
|
|
155
|
+
if (!internalUpdateCloneData) {
|
|
156
|
+
reject(new Error("No update data"));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const internalData = internalUpdateCloneData?.["data"];
|
|
161
|
+
if (
|
|
162
|
+
internalData === undefined ||
|
|
163
|
+
internalData === null ||
|
|
164
|
+
internalData === ""
|
|
165
|
+
) {
|
|
166
|
+
reject(new Error("No data"));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
setTimeout(() => {
|
|
171
|
+
const path = this.getOption("mapping.data");
|
|
172
|
+
const index = this.getOption("mapping.index");
|
|
173
|
+
|
|
174
|
+
let pathWithIndex;
|
|
175
|
+
|
|
176
|
+
if (isString(path) && path !== "") {
|
|
177
|
+
pathWithIndex = path + "." + index;
|
|
178
|
+
} else {
|
|
179
|
+
pathWithIndex = index;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const data = this[datasourceLinkedElementSymbol].data;
|
|
183
|
+
const unref = JSON.stringify(data);
|
|
184
|
+
const ref = JSON.parse(unref);
|
|
185
|
+
|
|
186
|
+
new Pathfinder(ref).setVia(pathWithIndex, internalData);
|
|
187
|
+
|
|
188
|
+
this[datasourceLinkedElementSymbol].data = ref;
|
|
189
|
+
|
|
190
|
+
resolve();
|
|
191
|
+
}, 0);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* This method is responsible for assembling the component.
|
|
197
|
+
*
|
|
198
|
+
* It calls the parent's assemble method first, then initializes control references and event handlers.
|
|
199
|
+
* If the `datasource.selector` option is provided and is a string, it searches for the corresponding
|
|
200
|
+
* element in the DOM using that selector.
|
|
201
|
+
*
|
|
202
|
+
* If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class.
|
|
203
|
+
*
|
|
204
|
+
* If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component
|
|
205
|
+
* attaches an observer to the datasource's changes.
|
|
206
|
+
*
|
|
207
|
+
* The observer is a function that calls the `handleDataSourceChanges` method in the context of the component.
|
|
208
|
+
* Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges`
|
|
209
|
+
* method in the component's context.
|
|
210
|
+
*/
|
|
211
|
+
[assembleMethodSymbol]() {
|
|
212
|
+
super[assembleMethodSymbol]();
|
|
213
|
+
|
|
214
|
+
// initControlReferences.call(self);
|
|
215
|
+
initEventHandler.call(this);
|
|
216
|
+
|
|
217
|
+
const selector = this.getOption("datasource.selector");
|
|
218
|
+
|
|
219
|
+
if (isString(selector)) {
|
|
220
|
+
const element = findElementWithSelectorUpwards(this, selector);
|
|
221
|
+
if (element === null) {
|
|
222
|
+
throw new Error("the selector must match exactly one element");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (!(element instanceof Datasource)) {
|
|
226
|
+
throw new TypeError("the element must be a datasource");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
this[datasourceLinkedElementSymbol] = element;
|
|
230
|
+
element.datasource.attachObserver(
|
|
231
|
+
new Observer(handleDataSourceChanges.bind(this)),
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
this.attachObserver(
|
|
236
|
+
new Observer(() => {
|
|
237
|
+
handleDataSourceChanges.call(this);
|
|
238
|
+
}),
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* @return [CSSStyleSheet]
|
|
244
|
+
*/
|
|
245
|
+
static getCSSStyleSheet() {
|
|
246
|
+
return [FormStyleSheet, DatasetStyleSheet];
|
|
247
|
+
}
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
/**
|
|
251
251
|
* @private
|
|
252
252
|
*/
|
|
253
253
|
function initEventHandler() {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
254
|
+
this[attributeObserverSymbol][ATTRIBUTE_DATATABLE_INDEX] = () => {
|
|
255
|
+
const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
|
|
256
|
+
if (index) {
|
|
257
|
+
this.setOption("mapping.index", parseInt(index, 10));
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
/**
|
|
@@ -264,17 +264,17 @@ function initEventHandler() {
|
|
|
264
264
|
* @param {Object} options
|
|
265
265
|
*/
|
|
266
266
|
function updateOptionsFromArguments(options) {
|
|
267
|
-
|
|
267
|
+
const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
|
|
268
268
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
269
|
+
if (index !== null && index !== undefined) {
|
|
270
|
+
options.mapping.index = parseInt(index, 10);
|
|
271
|
+
}
|
|
272
272
|
|
|
273
|
-
|
|
273
|
+
const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
|
|
274
274
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
275
|
+
if (selector) {
|
|
276
|
+
options.datasource.selector = selector;
|
|
277
|
+
}
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
/**
|
|
@@ -282,8 +282,8 @@ function updateOptionsFromArguments(options) {
|
|
|
282
282
|
* @return {string}
|
|
283
283
|
*/
|
|
284
284
|
function getTemplate() {
|
|
285
|
-
|
|
286
|
-
|
|
285
|
+
// language=HTML
|
|
286
|
+
return `
|
|
287
287
|
<div data-monster-role="control" part="control">
|
|
288
288
|
<slot></slot>
|
|
289
289
|
</div>
|
|
@@ -511,8 +511,7 @@ function getFilterConfigKey() {
|
|
|
511
511
|
* @returns {Promise}
|
|
512
512
|
*/
|
|
513
513
|
function getHostConfig(callback) {
|
|
514
|
-
const
|
|
515
|
-
const host = document.querySelector("monster-host");
|
|
514
|
+
const host = findElementWithSelectorUpwards( this,"monster-host");
|
|
516
515
|
|
|
517
516
|
if (!(host && this.id)) {
|
|
518
517
|
return Promise.resolve({});
|
|
@@ -608,8 +607,7 @@ function updateConfigColumnBar() {
|
|
|
608
607
|
map[option.name] = option.visible;
|
|
609
608
|
}
|
|
610
609
|
|
|
611
|
-
const
|
|
612
|
-
const host = document.querySelector("monster-host");
|
|
610
|
+
const host = findElementWithSelectorUpwards( this,"monster-host");
|
|
613
611
|
if (!(host && this.id)) {
|
|
614
612
|
return;
|
|
615
613
|
}
|
|
@@ -816,8 +814,7 @@ function storeOrderStatement(doFetch) {
|
|
|
816
814
|
const statement = createOrderStatement(headers);
|
|
817
815
|
setDataSource.call(this, { orderBy: statement }, doFetch);
|
|
818
816
|
|
|
819
|
-
const
|
|
820
|
-
const host = document.querySelector("monster-host");
|
|
817
|
+
const host = findElementWithSelectorUpwards( this,"monster-host");
|
|
821
818
|
if (!(host && this.id)) {
|
|
822
819
|
return;
|
|
823
820
|
}
|
|
@@ -726,8 +726,7 @@ function initTabEvents() {
|
|
|
726
726
|
}
|
|
727
727
|
}
|
|
728
728
|
|
|
729
|
-
const
|
|
730
|
-
const host = document.querySelector("monster-host");
|
|
729
|
+
const host = findElementWithSelectorUpwards( this,"monster-host");
|
|
731
730
|
if (!(host && this.id)) {
|
|
732
731
|
return;
|
|
733
732
|
}
|
|
@@ -768,8 +767,7 @@ function updateFilterTabs() {
|
|
|
768
767
|
return;
|
|
769
768
|
}
|
|
770
769
|
|
|
771
|
-
const
|
|
772
|
-
const host = document.querySelector("monster-host");
|
|
770
|
+
const host = findElementWithSelectorUpwards( this,"monster-host");
|
|
773
771
|
if (!(host && this.id)) {
|
|
774
772
|
return;
|
|
775
773
|
}
|
|
@@ -1067,8 +1065,7 @@ function getControlValuesFromLabel(label) {
|
|
|
1067
1065
|
* @returns {Promise<unknown>}
|
|
1068
1066
|
*/
|
|
1069
1067
|
function initFromConfig() {
|
|
1070
|
-
const
|
|
1071
|
-
const host = document.querySelector("monster-host");
|
|
1068
|
+
const host = findElementWithSelectorUpwards( this,"monster-host");
|
|
1072
1069
|
|
|
1073
1070
|
if (!(isInstance(host, Host) && this.id)) {
|
|
1074
1071
|
return Promise.resolve();
|
|
@@ -1111,8 +1108,7 @@ function initFromConfig() {
|
|
|
1111
1108
|
* @private
|
|
1112
1109
|
*/
|
|
1113
1110
|
function updateConfig() {
|
|
1114
|
-
const
|
|
1115
|
-
const host = document.querySelector("monster-host");
|
|
1111
|
+
const host = findElementWithSelectorUpwards( this,"monster-host");
|
|
1116
1112
|
if (!(host && this.id)) {
|
|
1117
1113
|
return;
|
|
1118
1114
|
}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
CustomElement,
|
|
18
18
|
registerCustomElement,
|
|
19
19
|
} from "../../dom/customelement.mjs";
|
|
20
|
+
import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
|
|
20
21
|
import { ThemeStyleSheet } from "../stylesheet/theme.mjs";
|
|
21
22
|
import { ATTRIBUTE_DATASOURCE_SELECTOR } from "./constants.mjs";
|
|
22
23
|
import { Datasource } from "./datasource.mjs";
|
|
@@ -188,12 +189,11 @@ class Pagination extends CustomElement {
|
|
|
188
189
|
const selector = this.getOption("datasource.selector", "");
|
|
189
190
|
|
|
190
191
|
if (isString(selector)) {
|
|
191
|
-
const
|
|
192
|
-
if (
|
|
192
|
+
const element = findElementWithSelectorUpwards( this,selector);
|
|
193
|
+
if (element===null) {
|
|
193
194
|
throw new Error("the selector must match exactly one element");
|
|
194
195
|
}
|
|
195
|
-
|
|
196
|
-
const element = elements[0];
|
|
196
|
+
|
|
197
197
|
if (!(element instanceof Datasource)) {
|
|
198
198
|
throw new TypeError("the element must be a datasource");
|
|
199
199
|
}
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
attributeObserverSymbol,
|
|
23
23
|
registerCustomElement,
|
|
24
24
|
} from "../../dom/customelement.mjs";
|
|
25
|
+
import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
|
|
25
26
|
import { isString, isArray } from "../../types/is.mjs";
|
|
26
27
|
import { Observer } from "../../types/observer.mjs";
|
|
27
28
|
import { TokenList } from "../../types/tokenlist.mjs";
|
|
@@ -154,12 +155,12 @@ class SaveButton extends CustomElement {
|
|
|
154
155
|
const selector = this.getOption("datasource.selector");
|
|
155
156
|
|
|
156
157
|
if (isString(selector)) {
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
|
|
159
|
+
const element = findElementWithSelectorUpwards( this,selector);
|
|
160
|
+
if (element===null) {
|
|
159
161
|
throw new Error("the selector must match exactly one element");
|
|
160
162
|
}
|
|
161
|
-
|
|
162
|
-
const element = elements[0];
|
|
163
|
+
|
|
163
164
|
if (!(element instanceof Datasource)) {
|
|
164
165
|
throw new TypeError("the element must be a datasource");
|
|
165
166
|
}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
CustomElement,
|
|
18
18
|
registerCustomElement,
|
|
19
19
|
} from "../../dom/customelement.mjs";
|
|
20
|
+
import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
|
|
20
21
|
import { ThemeStyleSheet } from "../stylesheet/theme.mjs";
|
|
21
22
|
import { Datasource } from "./datasource.mjs";
|
|
22
23
|
import { SpinnerStyleSheet } from "../stylesheet/spinner.mjs";
|
|
@@ -174,12 +175,12 @@ function initEventHandler() {
|
|
|
174
175
|
const self = this;
|
|
175
176
|
|
|
176
177
|
if (isString(selector)) {
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
|
|
179
|
+
const element = findElementWithSelectorUpwards( this,selector);
|
|
180
|
+
if (element===null) {
|
|
179
181
|
throw new Error("the selector must match exactly one element");
|
|
180
182
|
}
|
|
181
|
-
|
|
182
|
-
const element = elements[0];
|
|
183
|
+
|
|
183
184
|
if (!(element instanceof Datasource)) {
|
|
184
185
|
throw new TypeError("the element must be a datasource");
|
|
185
186
|
}
|
|
@@ -12,11 +12,12 @@
|
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
15
|
+
import {instanceSymbol} from "../../constants.mjs";
|
|
16
|
+
import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
|
|
17
|
+
import {isObject} from "../../types/is.mjs";
|
|
18
|
+
import {Datasource} from "../datasource.mjs";
|
|
18
19
|
|
|
19
|
-
export {
|
|
20
|
+
export {DomStorage};
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* The DomStorage is a class that stores data in memory.
|
|
@@ -26,93 +27,93 @@ export { DomStorage };
|
|
|
26
27
|
* @memberOf Monster.Data.Datasource
|
|
27
28
|
*/
|
|
28
29
|
class DomStorage extends Datasource {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
/**
|
|
31
|
+
* @param {Object} [options] options contains definitions for the datasource.
|
|
32
|
+
*/
|
|
33
|
+
constructor(options) {
|
|
34
|
+
super();
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
if (isObject(options)) {
|
|
37
|
+
this.setOptions(options);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
/**
|
|
42
|
+
* This method is called by the `instanceof` operator.
|
|
43
|
+
* @returns {symbol}
|
|
44
|
+
*/
|
|
45
|
+
static get [instanceSymbol]() {
|
|
46
|
+
return Symbol.for("@schukai/monster/data/datasource/storage/dom-storage");
|
|
47
|
+
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
49
|
+
/**
|
|
50
|
+
* @property {Object} defaults
|
|
51
|
+
* @property {Object} defaults.read
|
|
52
|
+
* @property {string} defaults.read.selector
|
|
53
|
+
* @property {Object} defaults.write
|
|
54
|
+
* @property {string} defaults.write.selector
|
|
55
|
+
*/
|
|
56
|
+
get defaults() {
|
|
57
|
+
return Object.assign({}, super.defaults, {
|
|
58
|
+
read: {
|
|
59
|
+
selector: undefined,
|
|
60
|
+
},
|
|
61
|
+
write: {
|
|
62
|
+
selector: undefined,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
/**
|
|
68
|
+
* @return {Promise}
|
|
69
|
+
* @throws {Error} The read selector is not defined
|
|
70
|
+
* @throws {Error} There are no storage element
|
|
71
|
+
*/
|
|
72
|
+
read() {
|
|
73
|
+
const selector = this.getOption("read.selector", undefined);
|
|
74
|
+
if (!selector) {
|
|
75
|
+
throw new Error("The read selector is not defined");
|
|
76
|
+
}
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
const storage = findElementWithSelectorUpwards(this, selector);
|
|
79
|
+
if (!storage) {
|
|
80
|
+
throw new Error("There is no storage element");
|
|
81
|
+
}
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
try {
|
|
85
|
+
const data = JSON.parse(storage.innerHTML);
|
|
86
|
+
this.set(data);
|
|
87
|
+
resolve(data);
|
|
88
|
+
} catch (e) {
|
|
89
|
+
reject(e);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
94
|
+
/**
|
|
95
|
+
* @return {Promise}
|
|
96
|
+
* @throws {Error} The write selector is not defined
|
|
97
|
+
* @throws {Error} There are no storage element
|
|
98
|
+
*/
|
|
99
|
+
write() {
|
|
100
|
+
const selector = this.getOption("write.selector");
|
|
101
|
+
if (!selector) {
|
|
102
|
+
throw new Error("The option write.selector is not defined");
|
|
103
|
+
}
|
|
103
104
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
const storage = findElementWithSelectorUpwards(this, selector);
|
|
106
|
+
if (!storage) {
|
|
107
|
+
throw new Error("There is no storage element");
|
|
108
|
+
}
|
|
108
109
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
return new Promise((resolve, reject) => {
|
|
111
|
+
try {
|
|
112
|
+
storage.innerHTML = JSON.stringify(this.get());
|
|
113
|
+
resolve(storage);
|
|
114
|
+
} catch (e) {
|
|
115
|
+
reject(e);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
118
119
|
}
|
|
@@ -12,26 +12,28 @@
|
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
15
|
+
import {internalStateSymbol} from "../../constants.mjs";
|
|
16
|
+
import {extend} from "../../data/extend.mjs";
|
|
17
|
+
import {getGlobalFunction} from "../../types/global.mjs";
|
|
18
|
+
import {addAttributeToken} from "../attributes.mjs";
|
|
18
19
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
ATTRIBUTE_CLASS,
|
|
21
|
+
ATTRIBUTE_ERRORMESSAGE,
|
|
22
|
+
ATTRIBUTE_ID,
|
|
23
|
+
ATTRIBUTE_SRC,
|
|
24
|
+
ATTRIBUTE_TITLE,
|
|
25
|
+
ATTRIBUTE_TYPE,
|
|
26
|
+
TAG_SCRIPT,
|
|
26
27
|
} from "../constants.mjs";
|
|
27
28
|
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
KEY_DOCUMENT,
|
|
30
|
+
KEY_QUERY,
|
|
31
|
+
referenceSymbol,
|
|
32
|
+
Resource,
|
|
32
33
|
} from "../resource.mjs";
|
|
33
|
-
import {
|
|
34
|
-
|
|
34
|
+
import {instanceSymbol} from "../../constants.mjs";
|
|
35
|
+
|
|
36
|
+
export {Data};
|
|
35
37
|
|
|
36
38
|
/**
|
|
37
39
|
* This class is used by the resource manager to embed data.
|
|
@@ -43,58 +45,59 @@ export { Data };
|
|
|
43
45
|
* @summary A Data Resource class
|
|
44
46
|
*/
|
|
45
47
|
class Data extends Resource {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
48
|
+
/**
|
|
49
|
+
* @property {string} mode=cors https://developer.mozilla.org/en-US/docs/Web/API/fetch
|
|
50
|
+
* @property {string} credentials=same-origin https://developer.mozilla.org/en-US/docs/Web/API/fetch
|
|
51
|
+
* @property {string} type=application/json {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type}
|
|
52
|
+
*/
|
|
53
|
+
get defaults() {
|
|
54
|
+
return extend({}, super.defaults, {
|
|
55
|
+
mode: "cors",
|
|
56
|
+
credentials: "same-origin",
|
|
57
|
+
type: "application/json",
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
*
|
|
63
|
+
* @return {Monster.DOM.Resource.Data}
|
|
64
|
+
*/
|
|
65
|
+
create() {
|
|
66
|
+
createElement.call(this);
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* This method appends the HTMLElement to the specified document
|
|
72
|
+
*
|
|
73
|
+
* throws {Error} target not found
|
|
74
|
+
* @return {Monster.DOM.Resource}
|
|
75
|
+
*/
|
|
76
|
+
connect() {
|
|
77
|
+
const self = this;
|
|
78
|
+
if (!(this[referenceSymbol] instanceof HTMLElement)) {
|
|
79
|
+
this.create();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
appendToDocument.call(this);
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* This method is called by the `instanceof` operator.
|
|
88
|
+
* @returns {symbol}
|
|
89
|
+
* @since 2.1.0
|
|
90
|
+
*/
|
|
91
|
+
static get [instanceSymbol]() {
|
|
92
|
+
return Symbol.for("@schukai/monster/dom/resource/data");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @return {string}
|
|
97
|
+
*/
|
|
98
|
+
static getURLAttribute() {
|
|
99
|
+
return ATTRIBUTE_SRC;
|
|
100
|
+
}
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
/**
|
|
@@ -102,21 +105,21 @@ class Data extends Resource {
|
|
|
102
105
|
* @return {Monster.DOM.Resource.Data}
|
|
103
106
|
*/
|
|
104
107
|
function createElement() {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
108
|
+
const document = this.getOption(KEY_DOCUMENT);
|
|
109
|
+
this[referenceSymbol] = document.createElement(TAG_SCRIPT);
|
|
110
|
+
|
|
111
|
+
for (const key of [
|
|
112
|
+
ATTRIBUTE_TYPE,
|
|
113
|
+
ATTRIBUTE_ID,
|
|
114
|
+
ATTRIBUTE_CLASS,
|
|
115
|
+
ATTRIBUTE_TITLE,
|
|
116
|
+
]) {
|
|
117
|
+
if (this.getOption(key) !== undefined) {
|
|
118
|
+
this[referenceSymbol][key] = this.getOption(key);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return this;
|
|
120
123
|
}
|
|
121
124
|
|
|
122
125
|
/**
|
|
@@ -125,41 +128,41 @@ function createElement() {
|
|
|
125
128
|
* throws {Error} target not found
|
|
126
129
|
*/
|
|
127
130
|
function appendToDocument() {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
131
|
+
const targetNode = document.querySelector(this.getOption(KEY_QUERY, "head"));
|
|
132
|
+
if (!(targetNode instanceof HTMLElement)) {
|
|
133
|
+
throw new Error("target not found");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
targetNode.appendChild(this[referenceSymbol]);
|
|
137
|
+
|
|
138
|
+
getGlobalFunction("fetch")(this.getOption(ATTRIBUTE_SRC), {
|
|
139
|
+
method: "GET", // *GET, POST, PUT, DELETE, etc.
|
|
140
|
+
mode: this.getOption("mode", "cors"), // no-cors, *cors, same-origin
|
|
141
|
+
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
|
|
142
|
+
credentials: this.getOption("credentials", "same-origin"), // include, *same-origin, omit
|
|
143
|
+
headers: {
|
|
144
|
+
Accept: this.getOption("type", "application/json"),
|
|
145
|
+
},
|
|
146
|
+
redirect: "follow", // manual, *follow, error
|
|
147
|
+
referrerPolicy: "no-referrer", // no-referrer,
|
|
148
|
+
})
|
|
149
|
+
.then((response) => {
|
|
150
|
+
return response.text();
|
|
151
|
+
})
|
|
152
|
+
.then((text) => {
|
|
153
|
+
const textNode = document.createTextNode(text);
|
|
154
|
+
this[referenceSymbol].appendChild(textNode);
|
|
155
|
+
|
|
156
|
+
this[internalStateSymbol].getSubject()["loaded"] = true;
|
|
157
|
+
})
|
|
158
|
+
.catch((e) => {
|
|
159
|
+
this[internalStateSymbol].setSubject({
|
|
160
|
+
loaded: true,
|
|
161
|
+
error: e.toString(),
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
targetNode.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.toString());
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return this;
|
|
165
168
|
}
|
package/source/dom/resource.mjs
CHANGED
|
@@ -242,7 +242,6 @@ function addEvents() {
|
|
|
242
242
|
this[referenceSymbol].removeEventListener("error", onError);
|
|
243
243
|
this[referenceSymbol].removeEventListener("load", onLoad);
|
|
244
244
|
this[internalStateSymbol].getSubject()["loaded"] = true;
|
|
245
|
-
return;
|
|
246
245
|
};
|
|
247
246
|
|
|
248
247
|
this[referenceSymbol].addEventListener("load", onLoad, false);
|