@schukai/monster 1.24.0 → 1.27.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.
- package/CHANGELOG +47 -0
- package/README.md +4 -4
- package/dist/modules/constants.js +2 -2
- package/dist/modules/constraints/abstract.js +1 -1
- package/dist/modules/constraints/abstractoperator.js +1 -1
- package/dist/modules/constraints/andoperator.js +1 -1
- package/dist/modules/constraints/invalid.js +1 -1
- package/dist/modules/constraints/isarray.js +1 -1
- package/dist/modules/constraints/isobject.js +1 -1
- package/dist/modules/constraints/namespace.js +1 -1
- package/dist/modules/constraints/oroperator.js +1 -1
- package/dist/modules/constraints/valid.js +1 -1
- package/dist/modules/data/buildmap.js +2 -2
- package/dist/modules/data/buildtree.js +2 -0
- package/dist/modules/data/datasource/namespace.js +1 -1
- package/dist/modules/data/datasource/restapi/writeerror.js +1 -1
- package/dist/modules/data/datasource/restapi.js +1 -1
- package/dist/modules/data/datasource/storage/localstorage.js +1 -1
- package/dist/modules/data/datasource/storage/namespace.js +1 -1
- package/dist/modules/data/datasource/storage/sessionstorage.js +1 -1
- package/dist/modules/data/datasource/storage.js +1 -1
- package/dist/modules/data/datasource.js +1 -1
- package/dist/modules/data/diff.js +1 -1
- package/dist/modules/data/extend.js +1 -1
- package/dist/modules/data/namespace.js +1 -1
- package/dist/modules/data/pathfinder.js +1 -1
- package/dist/modules/data/pipe.js +1 -1
- package/dist/modules/data/transformer.js +2 -2
- package/dist/modules/dom/assembler.js +1 -1
- package/dist/modules/dom/attributes.js +2 -2
- package/dist/modules/dom/constants.js +2 -2
- package/dist/modules/dom/customcontrol.js +1 -1
- package/dist/modules/dom/customelement.js +1 -1
- package/dist/modules/dom/events.js +1 -1
- package/dist/modules/dom/focusmanager.js +2 -0
- package/dist/modules/dom/locale.js +1 -1
- package/dist/modules/dom/namespace.js +1 -1
- package/dist/modules/dom/resource/data.js +2 -0
- package/dist/modules/dom/resource/link/stylesheet.js +2 -0
- package/dist/modules/dom/resource/link.js +2 -0
- package/dist/modules/dom/resource/script.js +2 -0
- package/dist/modules/dom/resource.js +2 -0
- package/dist/modules/dom/resourcemanager.js +2 -0
- package/dist/modules/dom/template.js +2 -2
- package/dist/modules/dom/theme.js +1 -1
- package/dist/modules/dom/updater.js +2 -2
- package/dist/modules/dom/util.js +1 -1
- package/dist/modules/dom/worker/factory.js +2 -0
- package/dist/modules/i18n/formatter.js +2 -0
- package/dist/modules/i18n/locale.js +1 -1
- package/dist/modules/i18n/namespace.js +1 -1
- package/dist/modules/i18n/provider.js +1 -1
- package/dist/modules/i18n/providers/fetch.js +1 -1
- package/dist/modules/i18n/providers/namespace.js +1 -1
- package/dist/modules/i18n/translations.js +1 -1
- package/dist/modules/logging/handler/console.js +1 -1
- package/dist/modules/logging/handler/namespace.js +1 -1
- package/dist/modules/logging/handler.js +1 -1
- package/dist/modules/logging/logentry.js +1 -1
- package/dist/modules/logging/logger.js +1 -1
- package/dist/modules/logging/namespace.js +1 -1
- package/dist/modules/math/namespace.js +1 -1
- package/dist/modules/math/random.js +2 -2
- package/dist/modules/monster.js +1 -1
- package/dist/modules/namespace.js +1 -1
- package/dist/modules/text/formatter.js +2 -2
- package/dist/modules/text/namespace.js +1 -1
- package/dist/modules/types/base.js +1 -1
- package/dist/modules/types/basewithoptions.js +1 -1
- package/dist/modules/types/binary.js +1 -1
- package/dist/modules/types/dataurl.js +1 -1
- package/dist/modules/types/global.js +1 -1
- package/dist/modules/types/id.js +1 -1
- package/dist/modules/types/is.js +2 -2
- package/dist/modules/types/mediatype.js +1 -1
- package/dist/modules/types/namespace.js +1 -1
- package/dist/modules/types/node.js +2 -0
- package/dist/modules/types/nodelist.js +2 -0
- package/dist/modules/types/noderecursiveiterator.js +2 -0
- package/dist/modules/types/observer.js +1 -1
- package/dist/modules/types/observerlist.js +1 -1
- package/dist/modules/types/proxyobserver.js +1 -1
- package/dist/modules/types/queue.js +1 -1
- package/dist/modules/types/randomid.js +1 -1
- package/dist/modules/types/regex.js +2 -0
- package/dist/modules/types/stack.js +1 -1
- package/dist/modules/types/tokenlist.js +1 -1
- package/dist/modules/types/typeof.js +1 -1
- package/dist/modules/types/uniquequeue.js +1 -1
- package/dist/modules/types/uuid.js +2 -0
- package/dist/modules/types/validate.js +1 -1
- package/dist/modules/types/version.js +2 -2
- package/dist/modules/util/clone.js +1 -1
- package/dist/modules/util/comparator.js +1 -1
- package/dist/modules/util/freeze.js +1 -1
- package/dist/modules/util/namespace.js +1 -1
- package/dist/modules/util/processing.js +1 -1
- package/dist/modules/util/trimspaces.js +1 -1
- package/dist/monster.dev.js +1528 -770
- package/dist/monster.dev.js.map +1 -1
- package/dist/monster.js +2 -2
- package/package.json +13 -2
- package/source/constants.js +11 -2
- package/source/constraints/abstract.js +5 -0
- package/source/constraints/abstractoperator.js +5 -0
- package/source/constraints/andoperator.js +10 -5
- package/source/constraints/invalid.js +8 -3
- package/source/constraints/isarray.js +9 -4
- package/source/constraints/isobject.js +8 -3
- package/source/constraints/oroperator.js +10 -5
- package/source/constraints/valid.js +8 -3
- package/source/data/buildmap.js +25 -9
- package/source/data/buildtree.js +95 -0
- package/source/data/datasource/restapi.js +3 -3
- package/source/data/datasource/storage/localstorage.js +2 -2
- package/source/data/datasource/storage/sessionstorage.js +2 -2
- package/source/data/datasource/storage.js +3 -3
- package/source/data/datasource.js +3 -3
- package/source/data/diff.js +3 -3
- package/source/data/extend.js +2 -2
- package/source/data/pathfinder.js +4 -4
- package/source/data/pipe.js +3 -3
- package/source/data/transformer.js +7 -5
- package/source/dom/assembler.js +2 -2
- package/source/dom/attributes.js +111 -28
- package/source/dom/constants.js +287 -10
- package/source/dom/customcontrol.js +1 -1
- package/source/dom/customelement.js +1 -1
- package/source/dom/events.js +6 -7
- package/source/dom/focusmanager.js +250 -0
- package/source/dom/locale.js +10 -5
- package/source/dom/resource/data.js +170 -0
- package/source/dom/resource/link/stylesheet.js +54 -0
- package/source/dom/resource/link.js +125 -0
- package/source/dom/resource/script.js +112 -0
- package/source/dom/resource.js +268 -0
- package/source/dom/resourcemanager.js +214 -0
- package/source/dom/template.js +86 -16
- package/source/dom/theme.js +3 -3
- package/source/dom/updater.js +138 -90
- package/source/dom/util.js +6 -6
- package/source/dom/worker/factory.js +134 -0
- package/source/i18n/formatter.js +140 -0
- package/source/i18n/locale.js +6 -4
- package/source/i18n/provider.js +2 -2
- package/source/i18n/providers/fetch.js +18 -3
- package/source/i18n/translations.js +18 -9
- package/source/logging/handler/console.js +2 -2
- package/source/logging/handler.js +2 -2
- package/source/logging/logentry.js +2 -2
- package/source/logging/logger.js +2 -2
- package/source/math/random.js +9 -5
- package/source/namespace.js +1 -1
- package/source/text/formatter.js +190 -48
- package/source/types/base.js +4 -4
- package/source/types/basewithoptions.js +2 -2
- package/source/types/binary.js +4 -4
- package/source/types/dataurl.js +4 -4
- package/source/types/global.js +4 -4
- package/source/types/id.js +6 -3
- package/source/types/is.js +103 -85
- package/source/types/mediatype.js +4 -4
- package/source/types/node.js +179 -0
- package/source/types/nodelist.js +125 -0
- package/source/types/noderecursiveiterator.js +126 -0
- package/source/types/observer.js +3 -3
- package/source/types/observerlist.js +2 -2
- package/source/types/proxyobserver.js +5 -5
- package/source/types/queue.js +4 -4
- package/source/types/randomid.js +2 -2
- package/source/types/regex.js +49 -0
- package/source/types/stack.js +2 -2
- package/source/types/tokenlist.js +2 -2
- package/source/types/typeof.js +3 -3
- package/source/types/uniquequeue.js +2 -2
- package/source/types/uuid.js +102 -0
- package/source/types/validate.js +20 -20
- package/source/types/version.js +6 -6
- package/source/util/clone.js +2 -2
- package/source/util/comparator.js +4 -4
- package/source/util/freeze.js +5 -5
- package/source/util/processing.js +3 -3
- package/source/util/trimspaces.js +3 -3
- package/test/cases/data/buildtree.js +149 -0
- package/test/cases/data/datasource/restapi.js +1 -1
- package/test/cases/data/transformer.js +2 -0
- package/test/cases/dom/attributes.js +46 -19
- package/test/cases/dom/customelement.js +0 -3
- package/test/cases/dom/focusmanager.js +111 -0
- package/test/cases/dom/locale.js +1 -4
- package/test/cases/dom/resource/data.js +129 -0
- package/test/cases/dom/resource/link/stylesheet.js +101 -0
- package/test/cases/dom/resource/link.js +101 -0
- package/test/cases/dom/resource/script.js +115 -0
- package/test/cases/dom/resourcemanager.js +118 -0
- package/test/cases/dom/template.js +72 -14
- package/test/cases/dom/updater.js +102 -75
- package/test/cases/dom/worker/factory.js +63 -0
- package/test/cases/i18n/formatter.js +66 -0
- package/test/cases/monster.js +1 -1
- package/test/cases/text/formatter.js +36 -5
- package/test/cases/types/node.js +196 -0
- package/test/cases/types/nodelist.js +64 -0
- package/test/cases/types/noderecursiveiterator.js +54 -0
- package/test/cases/types/regex.js +32 -0
- package/test/cases/types/uuid.js +42 -0
- package/test/cases/util/freeze.js +30 -4
- package/test/util/cleanupdom.js +48 -0
- package/test/util/jsdom.js +22 -9
- package/test/web/import.js +14 -0
- package/test/web/monster-dev.html +3 -3
- package/test/web/monster.html +2 -2
- package/test/web/test.html +3 -3
- package/test/web/tests.js +7 -7
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @author schukai GmbH
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {internalStateSymbol, internalSymbol,} from "../constants.js";
|
|
8
|
+
import {extend} from "../data/extend.js";
|
|
9
|
+
import {assignToNamespace, Monster} from "../namespace.js";
|
|
10
|
+
import {BaseWithOptions} from "../types/basewithoptions.js";
|
|
11
|
+
import {getGlobalObject} from "../types/global.js";
|
|
12
|
+
import {ID} from "../types/id.js";
|
|
13
|
+
import {isString} from "../types/is.js";
|
|
14
|
+
import {Observer} from "../types/observer.js";
|
|
15
|
+
import {ProxyObserver} from "../types/proxyobserver.js";
|
|
16
|
+
import {ATTRIBUTE_CLASS, ATTRIBUTE_ID, ATTRIBUTE_TITLE} from "./constants.js";
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @private
|
|
21
|
+
* @type {string}
|
|
22
|
+
*/
|
|
23
|
+
export const KEY_DOCUMENT = 'document';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @private
|
|
27
|
+
* @type {string}
|
|
28
|
+
*/
|
|
29
|
+
export const KEY_QUERY = 'query';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @private
|
|
33
|
+
* @type {string}
|
|
34
|
+
*/
|
|
35
|
+
export const KEY_TIMEOUT = 'timeout';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @private
|
|
39
|
+
* @type {symbol}
|
|
40
|
+
*/
|
|
41
|
+
export const referenceSymbol = Symbol('reference');
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* This class is the base class for all resources to be loaded.
|
|
45
|
+
*
|
|
46
|
+
* You can call the method via the monster namespace `new Monster.DOM.Resource()`.
|
|
47
|
+
*
|
|
48
|
+
* ```
|
|
49
|
+
* <script type="module">
|
|
50
|
+
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/monster.js';
|
|
51
|
+
* new Monster.DOM.Resource()
|
|
52
|
+
* </script>
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* Alternatively, you can also integrate this function individually.
|
|
56
|
+
*
|
|
57
|
+
* ```
|
|
58
|
+
* <script type="module">
|
|
59
|
+
* import {Resource} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/modules/dom/resource.js';
|
|
60
|
+
* new Resource()
|
|
61
|
+
* </script>
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @since 1.25.0
|
|
65
|
+
* @copyright schukai GmbH
|
|
66
|
+
* @memberOf Monster.DOM
|
|
67
|
+
* @summary A Resource class
|
|
68
|
+
*/
|
|
69
|
+
class Resource extends BaseWithOptions {
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
*
|
|
73
|
+
* @param {Object|undefined} options
|
|
74
|
+
*/
|
|
75
|
+
constructor(options) {
|
|
76
|
+
super(options);
|
|
77
|
+
|
|
78
|
+
let uri = this.getOption(this.constructor.getURLAttribute());
|
|
79
|
+
|
|
80
|
+
if (uri === undefined) {
|
|
81
|
+
throw new Error('missing source')
|
|
82
|
+
} else if (uri instanceof URL) {
|
|
83
|
+
uri = uri.toString();
|
|
84
|
+
} else if (!isString(uri)) {
|
|
85
|
+
throw new Error('unsupported url type')
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
this[internalSymbol][this.constructor.getURLAttribute()] = uri;
|
|
89
|
+
this[internalStateSymbol] = new ProxyObserver({
|
|
90
|
+
loaded: false,
|
|
91
|
+
error: undefined,
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
this[referenceSymbol] = undefined;
|
|
95
|
+
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @return {boolean}
|
|
100
|
+
*/
|
|
101
|
+
isConnected() {
|
|
102
|
+
|
|
103
|
+
if (this[referenceSymbol] instanceof HTMLElement) {
|
|
104
|
+
return this[referenceSymbol].isConnected;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* This method is overridden by the special classes and creates the DOM object.
|
|
112
|
+
* This method is also called implicitly, if not yet done explicitly, by calling `connect()`.
|
|
113
|
+
*
|
|
114
|
+
* @throws {Error} this method must be implemented by derived classes
|
|
115
|
+
* @return {Monster.DOM.Resource}
|
|
116
|
+
*/
|
|
117
|
+
create() {
|
|
118
|
+
throw new Error("this method must be implemented by derived classes");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* This method appends the HTMLElement to the specified document.
|
|
123
|
+
* If the element has not yet been created, `create()` is called implicitly.
|
|
124
|
+
*
|
|
125
|
+
* throws {Error} target not found
|
|
126
|
+
* @return {Monster.DOM.Resource}
|
|
127
|
+
*/
|
|
128
|
+
connect() {
|
|
129
|
+
|
|
130
|
+
if (!(this[referenceSymbol] instanceof HTMLElement)) {
|
|
131
|
+
this.create();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
appendToDocument.call(this);
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @property {Document} document the document object into which the node is to be appended
|
|
140
|
+
* @property {string} src/href url to the corresponding resource
|
|
141
|
+
* @property {string} query defines the location where the resource is to be hooked into the dom.
|
|
142
|
+
* @property {string} id element attribute id
|
|
143
|
+
* @property {string} title element attribute title
|
|
144
|
+
* @property {string} class element attribute class
|
|
145
|
+
* @property {int} timeout timeout
|
|
146
|
+
*/
|
|
147
|
+
get defaults() {
|
|
148
|
+
return extend({}, super.defaults, {
|
|
149
|
+
[this.constructor.getURLAttribute()]: undefined,
|
|
150
|
+
[KEY_DOCUMENT]: getGlobalObject('document'),
|
|
151
|
+
[KEY_QUERY]: 'head',
|
|
152
|
+
[KEY_TIMEOUT]: 10000,
|
|
153
|
+
[ATTRIBUTE_ID]: (new ID('resource')).toString(),
|
|
154
|
+
[ATTRIBUTE_CLASS]: undefined,
|
|
155
|
+
[ATTRIBUTE_TITLE]: undefined
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* With `available()` you can check if a resource is available.
|
|
161
|
+
* This is the case when the tag is included and the resource is loaded.
|
|
162
|
+
*
|
|
163
|
+
* @return {Promise}
|
|
164
|
+
*/
|
|
165
|
+
available() {
|
|
166
|
+
const self = this;
|
|
167
|
+
if (!(self[referenceSymbol] instanceof HTMLElement)) {
|
|
168
|
+
return Promise.reject('no element')
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (!self.isConnected()) {
|
|
172
|
+
return Promise.reject('element not connected')
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (self[internalStateSymbol].getSubject()['loaded'] === true) {
|
|
176
|
+
|
|
177
|
+
if (self[internalStateSymbol].getSubject()['error'] !== undefined) {
|
|
178
|
+
return Promise.reject(self[internalStateSymbol].getSubject()['error']);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return Promise.resolve();
|
|
182
|
+
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return new Promise(function (resolve, reject) {
|
|
186
|
+
|
|
187
|
+
const timeout = setTimeout(() => {
|
|
188
|
+
reject('timeout');
|
|
189
|
+
}, self.getOption('timeout'))
|
|
190
|
+
|
|
191
|
+
const observer = new Observer(() => {
|
|
192
|
+
clearTimeout(timeout);
|
|
193
|
+
self[internalStateSymbol].detachObserver(observer);
|
|
194
|
+
resolve();
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
self[internalStateSymbol].attachObserver(observer);
|
|
198
|
+
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @return {string}
|
|
205
|
+
*/
|
|
206
|
+
static getURLAttribute() {
|
|
207
|
+
throw new Error("this method must be implemented by derived classes");
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @private
|
|
215
|
+
* @return {Promise}
|
|
216
|
+
* throws {Error} target not found
|
|
217
|
+
*/
|
|
218
|
+
function appendToDocument() {
|
|
219
|
+
const self = this;
|
|
220
|
+
|
|
221
|
+
const targetNode = document.querySelector(self.getOption(KEY_QUERY, 'head'))
|
|
222
|
+
if (!(targetNode instanceof HTMLElement)) {
|
|
223
|
+
throw new Error('target not found')
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
addEvents.call(self);
|
|
227
|
+
targetNode.appendChild(self[referenceSymbol]);
|
|
228
|
+
|
|
229
|
+
return self;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* @private
|
|
234
|
+
* @return {addEvents}
|
|
235
|
+
*/
|
|
236
|
+
function addEvents() {
|
|
237
|
+
const self = this;
|
|
238
|
+
|
|
239
|
+
const onError = () => {
|
|
240
|
+
|
|
241
|
+
self[referenceSymbol].removeEventListener('error', onError);
|
|
242
|
+
self[referenceSymbol].removeEventListener('load', onLoad);
|
|
243
|
+
|
|
244
|
+
self[internalStateSymbol].setSubject({
|
|
245
|
+
loaded: true,
|
|
246
|
+
error: self[referenceSymbol][self.constructor.getURLAttribute()] + ' is not available',
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const onLoad = () => {
|
|
253
|
+
self[referenceSymbol].removeEventListener('error', onError);
|
|
254
|
+
self[referenceSymbol].removeEventListener('load', onLoad);
|
|
255
|
+
self[internalStateSymbol].getSubject()['loaded'] = true;
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
self[referenceSymbol].addEventListener('load', onLoad, false);
|
|
260
|
+
self[referenceSymbol].addEventListener('error', onError, false);
|
|
261
|
+
|
|
262
|
+
return self;
|
|
263
|
+
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
assignToNamespace('Monster.DOM', Resource);
|
|
268
|
+
export {Monster, Resource}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @author schukai GmbH
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {extend} from "../data/extend.js";
|
|
8
|
+
import {assignToNamespace, Monster} from "../namespace.js";
|
|
9
|
+
import {BaseWithOptions} from "../types/basewithoptions.js";
|
|
10
|
+
import {getGlobalObject} from "../types/global.js";
|
|
11
|
+
import {isArray} from "../types/is.js";
|
|
12
|
+
import {ATTRIBUTE_HREF, ATTRIBUTE_SRC} from "./constants.js";
|
|
13
|
+
import {Resource} from "./resource.js";
|
|
14
|
+
import {Data} from "./resource/data.js";
|
|
15
|
+
import {Stylesheet} from "./resource/link/stylesheet.js";
|
|
16
|
+
import {Script} from "./resource/script.js";
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* You can call the method via the monster namespace `new Monster.DOM.ResourceManager()`.
|
|
21
|
+
*
|
|
22
|
+
* ```
|
|
23
|
+
* <script type="module">
|
|
24
|
+
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/monster.js';
|
|
25
|
+
* new Monster.DOM.ResourceManager()
|
|
26
|
+
* </script>
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* Alternatively, you can also integrate this function individually.
|
|
30
|
+
*
|
|
31
|
+
* ```
|
|
32
|
+
* <script type="module">
|
|
33
|
+
* import {Resource} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/modules/dom/resourcemanager.js';
|
|
34
|
+
* new ResourceManager()
|
|
35
|
+
* </script>
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @since 1.25.0
|
|
39
|
+
* @copyright schukai GmbH
|
|
40
|
+
* @memberOf Monster.DOM
|
|
41
|
+
* @summary A Resource class
|
|
42
|
+
*/
|
|
43
|
+
class ResourceManager extends BaseWithOptions {
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @param {Object} options
|
|
48
|
+
* throw {Error} unsupported document type
|
|
49
|
+
*/
|
|
50
|
+
constructor(options) {
|
|
51
|
+
super(options);
|
|
52
|
+
|
|
53
|
+
if (!(this.getOption('document') instanceof Document)) {
|
|
54
|
+
throw new Error('unsupported document type')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @property {string} baseurl
|
|
62
|
+
*/
|
|
63
|
+
getBaseURL() {
|
|
64
|
+
this.getOption('document')?.baseURL;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* @property {HTMLDocument} document=document Document
|
|
70
|
+
* @property {Object} resources
|
|
71
|
+
* @property {Array} resources.scripts=[] array with {@link Monster.DOM.Resource.Script} objects
|
|
72
|
+
* @property {Array} resources.stylesheets=[] array with {@link Monster.DOM.Resource.Link.Stylesheet} objects
|
|
73
|
+
* @property {Array} resources.data=[] array with {@link Monster.DOM.Resource.Data} objects
|
|
74
|
+
*/
|
|
75
|
+
get defaults() {
|
|
76
|
+
return Object.assign({}, super.defaults, {
|
|
77
|
+
document: getGlobalObject('document'),
|
|
78
|
+
resources: {
|
|
79
|
+
scripts: [],
|
|
80
|
+
stylesheets: [],
|
|
81
|
+
data: []
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Append Tags to DOM
|
|
88
|
+
*
|
|
89
|
+
* @return {Monster.DOM.ResourceManager}
|
|
90
|
+
* @throws {Error} unsupported resource definition
|
|
91
|
+
*/
|
|
92
|
+
connect() {
|
|
93
|
+
runResourceMethod.call(this, 'connect');
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Check if available
|
|
99
|
+
*
|
|
100
|
+
* @return {Promise}
|
|
101
|
+
* @throws {Error} unsupported resource definition
|
|
102
|
+
*/
|
|
103
|
+
available() {
|
|
104
|
+
return Promise.all(runResourceMethod.call(this, 'available'));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Add a script
|
|
109
|
+
*
|
|
110
|
+
* @param {string|URL} url
|
|
111
|
+
* @param [Object|undefined} options
|
|
112
|
+
* @return {Monster.DOM.ResourceManager}
|
|
113
|
+
* @see Monster.DOM.Resource.Script
|
|
114
|
+
*/
|
|
115
|
+
addScript(url, options) {
|
|
116
|
+
return addResource.call(this, 'scripts', url, options);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Add Stylesheet
|
|
122
|
+
*
|
|
123
|
+
* @param {string|URL} url
|
|
124
|
+
* @param [Object|undefined} options
|
|
125
|
+
* @return {Monster.DOM.ResourceManager}
|
|
126
|
+
* @see Monster.DOM.Resource.Link.Stylesheet
|
|
127
|
+
*/
|
|
128
|
+
addStylesheet(url, options) {
|
|
129
|
+
return addResource.call(this, 'stylesheets', url, options);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Add Data Tag
|
|
134
|
+
*
|
|
135
|
+
* @param {string|URL} url
|
|
136
|
+
* @param [Object|undefined} options
|
|
137
|
+
* @return {Monster.DOM.ResourceManager}
|
|
138
|
+
* @see Monster.DOM.Resource.Data
|
|
139
|
+
*/
|
|
140
|
+
addData(url, options) {
|
|
141
|
+
return addResource.call(this, 'data', url, options);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @private
|
|
149
|
+
* @param {string} method
|
|
150
|
+
* @return {Array}
|
|
151
|
+
*/
|
|
152
|
+
function runResourceMethod(method) {
|
|
153
|
+
const self = this;
|
|
154
|
+
|
|
155
|
+
const result = [];
|
|
156
|
+
|
|
157
|
+
for (const type of ['scripts', 'stylesheets', 'data']) {
|
|
158
|
+
const resources = self.getOption('resources.' + type);
|
|
159
|
+
if (!isArray(resources)) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
for (const resource of resources) {
|
|
164
|
+
if (!(resource instanceof Resource)) {
|
|
165
|
+
throw new Error('unsupported resource definition')
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
result.push(resource[method]());
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
*
|
|
178
|
+
* @param {string} type
|
|
179
|
+
* @param {string|URL} url
|
|
180
|
+
* @param [Object|undefined} options
|
|
181
|
+
* @return {Monster.DOM.ResourceManager}
|
|
182
|
+
* @private
|
|
183
|
+
*/
|
|
184
|
+
function addResource(type, url, options) {
|
|
185
|
+
const self = this;
|
|
186
|
+
|
|
187
|
+
if (url instanceof URL) {
|
|
188
|
+
url = url.toString();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
options = options || {}
|
|
192
|
+
|
|
193
|
+
let resource;
|
|
194
|
+
switch (type) {
|
|
195
|
+
case 'scripts':
|
|
196
|
+
resource = new Script(extend({}, options, {[ATTRIBUTE_SRC]: url}))
|
|
197
|
+
break;
|
|
198
|
+
case 'stylesheets':
|
|
199
|
+
resource = new Stylesheet(extend({}, options, {[ATTRIBUTE_HREF]: url}))
|
|
200
|
+
break;
|
|
201
|
+
case 'data':
|
|
202
|
+
resource = new Data(extend({}, options, {[ATTRIBUTE_SRC]: url}))
|
|
203
|
+
break;
|
|
204
|
+
default:
|
|
205
|
+
throw new Error('unsupported type ' + type)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
(self.getOption('resources')?.[type]).push(resource);
|
|
209
|
+
return self;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
assignToNamespace('Monster.DOM', ResourceManager);
|
|
214
|
+
export {Monster, ResourceManager}
|
package/source/dom/template.js
CHANGED
|
@@ -7,6 +7,7 @@ import {assignToNamespace, Monster} from '../namespace.js';
|
|
|
7
7
|
import {Base} from '../types/base.js';
|
|
8
8
|
import {getGlobalFunction, getGlobalObject} from '../types/global.js';
|
|
9
9
|
import {validateInstance, validateString} from "../types/validate.js";
|
|
10
|
+
import {ATTRIBUTE_TEMPLATE_PREFIX} from "./constants.js";
|
|
10
11
|
import {getDocumentTheme} from "./theme.js";
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -14,8 +15,8 @@ import {getDocumentTheme} from "./theme.js";
|
|
|
14
15
|
*
|
|
15
16
|
* ```
|
|
16
17
|
* <script type="module">
|
|
17
|
-
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.
|
|
18
|
-
*
|
|
18
|
+
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/monster.js';
|
|
19
|
+
* new Monster.DOM.Template()
|
|
19
20
|
* </script>
|
|
20
21
|
* ```
|
|
21
22
|
*
|
|
@@ -23,8 +24,8 @@ import {getDocumentTheme} from "./theme.js";
|
|
|
23
24
|
*
|
|
24
25
|
* ```
|
|
25
26
|
* <script type="module">
|
|
26
|
-
* import {Template} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.
|
|
27
|
-
*
|
|
27
|
+
* import {Template} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/modules/dom/template.js';
|
|
28
|
+
* new Template()
|
|
28
29
|
* </script>
|
|
29
30
|
* ```
|
|
30
31
|
*
|
|
@@ -70,7 +71,7 @@ class Template extends Base {
|
|
|
70
71
|
/**
|
|
71
72
|
* This method loads a template with the given ID and returns it.
|
|
72
73
|
*
|
|
73
|
-
* To do this, it first
|
|
74
|
+
* To do this, it first reads the theme of the document and looks for the `data-monster-theme-name` attribute in the HTML tag.
|
|
74
75
|
*
|
|
75
76
|
* ```
|
|
76
77
|
* <html data-monster-theme-name="my-theme">
|
|
@@ -78,15 +79,15 @@ class Template extends Base {
|
|
|
78
79
|
*
|
|
79
80
|
* If no theme was specified, the default theme is `monster`.
|
|
80
81
|
*
|
|
81
|
-
* Now it is looked if there is a template with the given ID and theme `id-theme` and if yes it is returned.
|
|
82
|
+
* Now it is looked if there is a template with the given ID and theme `id-theme` and if yes it is returned.
|
|
82
83
|
* If there is no template a search for a template with the given ID `id` is done. If this is also not found, an error is thrown.
|
|
83
84
|
*
|
|
84
85
|
* You can call the method via the monster namespace `Monster.DOM.findDocumentTemplate()`.
|
|
85
86
|
*
|
|
86
87
|
* ```
|
|
87
88
|
* <script type="module">
|
|
88
|
-
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.
|
|
89
|
-
*
|
|
89
|
+
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/monster.js';
|
|
90
|
+
* Monster.DOM.findDocumentTemplate()
|
|
90
91
|
* </script>
|
|
91
92
|
* ```
|
|
92
93
|
*
|
|
@@ -94,11 +95,41 @@ class Template extends Base {
|
|
|
94
95
|
*
|
|
95
96
|
* ```
|
|
96
97
|
* <script type="module">
|
|
97
|
-
* import {findTemplate} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.
|
|
98
|
-
*
|
|
98
|
+
* import {findTemplate} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/modules/dom/template.js';
|
|
99
|
+
* findDocumentTemplate()
|
|
99
100
|
* </script>
|
|
100
101
|
* ```
|
|
101
102
|
*
|
|
103
|
+
* @example
|
|
104
|
+
*
|
|
105
|
+
* import { findDocumentTemplate } from "https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/modules/dom/template.js";
|
|
106
|
+
*
|
|
107
|
+
* const template = document.createElement("template");
|
|
108
|
+
* template.id = "myTemplate";
|
|
109
|
+
* template.innerHTML = "<p>my default template</p>";
|
|
110
|
+
* document.body.appendChild(template);
|
|
111
|
+
*
|
|
112
|
+
* const themedTemplate = document.createElement("template");
|
|
113
|
+
* themedTemplate.id = "myTemplate-myTheme";
|
|
114
|
+
* themedTemplate.innerHTML = "<p>my themed template</p>";
|
|
115
|
+
* document.body.appendChild(themedTemplate);
|
|
116
|
+
*
|
|
117
|
+
* // loads the temple and since no theme is set the default template
|
|
118
|
+
* const template1 = findDocumentTemplate("myTemplate");
|
|
119
|
+
* console.log(template1.createDocumentFragment());
|
|
120
|
+
* // ↦ '<p>my default template</p>'
|
|
121
|
+
*
|
|
122
|
+
* // now we set our own theme
|
|
123
|
+
* document
|
|
124
|
+
* .querySelector("html")
|
|
125
|
+
* .setAttribute("data-monster-theme-name", "myTheme");
|
|
126
|
+
*
|
|
127
|
+
* // now we don't get the default template,
|
|
128
|
+
* // but the template with the theme in the id
|
|
129
|
+
* const template2 = findDocumentTemplate("myTemplate");
|
|
130
|
+
* console.log(template2.createDocumentFragment());
|
|
131
|
+
* // ↦ '<p>my themed template</p>'
|
|
132
|
+
*
|
|
102
133
|
* @param {string} id
|
|
103
134
|
* @param {Node} currentNode
|
|
104
135
|
* @return {Monster.DOM.Template}
|
|
@@ -111,9 +142,22 @@ class Template extends Base {
|
|
|
111
142
|
function findDocumentTemplate(id, currentNode) {
|
|
112
143
|
validateString(id);
|
|
113
144
|
|
|
145
|
+
const document = getGlobalObject('document');
|
|
146
|
+
const HTMLTemplateElement = getGlobalFunction('HTMLTemplateElement');
|
|
147
|
+
const DocumentFragment = getGlobalFunction('DocumentFragment');
|
|
148
|
+
const Document = getGlobalFunction('Document');
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
let prefixID;
|
|
152
|
+
|
|
114
153
|
if (!(currentNode instanceof Document || currentNode instanceof DocumentFragment)) {
|
|
115
154
|
|
|
116
155
|
if (currentNode instanceof Node) {
|
|
156
|
+
|
|
157
|
+
if (currentNode.hasAttribute(ATTRIBUTE_TEMPLATE_PREFIX)) {
|
|
158
|
+
prefixID = currentNode.getAttribute(ATTRIBUTE_TEMPLATE_PREFIX)
|
|
159
|
+
}
|
|
160
|
+
|
|
117
161
|
currentNode = currentNode.getRootNode();
|
|
118
162
|
|
|
119
163
|
if (!(currentNode instanceof Document || currentNode instanceof DocumentFragment)) {
|
|
@@ -123,27 +167,53 @@ function findDocumentTemplate(id, currentNode) {
|
|
|
123
167
|
}
|
|
124
168
|
|
|
125
169
|
if (!(currentNode instanceof Document || currentNode instanceof DocumentFragment)) {
|
|
126
|
-
currentNode =
|
|
170
|
+
currentNode = document;
|
|
127
171
|
}
|
|
128
172
|
}
|
|
129
173
|
|
|
130
|
-
|
|
131
|
-
|
|
174
|
+
let template;
|
|
132
175
|
let theme = getDocumentTheme()
|
|
176
|
+
|
|
177
|
+
if (prefixID) {
|
|
178
|
+
let themedPrefixID = prefixID + '-' + id + '-' + theme.getName();
|
|
179
|
+
|
|
180
|
+
// current + themedPrefixID
|
|
181
|
+
template = currentNode.getElementById(themedPrefixID);
|
|
182
|
+
if (template instanceof HTMLTemplateElement) {
|
|
183
|
+
return new Template(template);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// document + themedPrefixID
|
|
187
|
+
template = document.getElementById(themedPrefixID);
|
|
188
|
+
if (template instanceof HTMLTemplateElement) {
|
|
189
|
+
return new Template(template);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
133
193
|
let themedID = id + '-' + theme.getName();
|
|
134
194
|
|
|
135
|
-
|
|
195
|
+
// current + themedID
|
|
196
|
+
template = currentNode.getElementById(themedID);
|
|
136
197
|
if (template instanceof HTMLTemplateElement) {
|
|
137
198
|
return new Template(template);
|
|
138
199
|
}
|
|
139
200
|
|
|
201
|
+
// document + themedID
|
|
202
|
+
template = document.getElementById(themedID);
|
|
203
|
+
if (template instanceof HTMLTemplateElement) {
|
|
204
|
+
return new Template(template);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// current + ID
|
|
140
208
|
template = currentNode.getElementById(id);
|
|
141
209
|
if (template instanceof HTMLTemplateElement) {
|
|
142
210
|
return new Template(template);
|
|
143
211
|
}
|
|
144
212
|
|
|
145
|
-
|
|
146
|
-
|
|
213
|
+
// document + ID
|
|
214
|
+
template = document.getElementById(id);
|
|
215
|
+
if (template instanceof HTMLTemplateElement) {
|
|
216
|
+
return new Template(template);
|
|
147
217
|
}
|
|
148
218
|
|
|
149
219
|
throw new Error("template " + id + " not found.")
|
package/source/dom/theme.js
CHANGED
|
@@ -15,7 +15,7 @@ import {ATTRIBUTE_THEME_NAME, DEFAULT_THEME} from "./constants.js";
|
|
|
15
15
|
*
|
|
16
16
|
* ```
|
|
17
17
|
* <script type="module">
|
|
18
|
-
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.
|
|
18
|
+
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/monster.js';
|
|
19
19
|
* console.log(new Monster.DOM.Theme())
|
|
20
20
|
* </script>
|
|
21
21
|
* ```
|
|
@@ -24,14 +24,14 @@ import {ATTRIBUTE_THEME_NAME, DEFAULT_THEME} from "./constants.js";
|
|
|
24
24
|
*
|
|
25
25
|
* ```
|
|
26
26
|
* <script type="module">
|
|
27
|
-
* import {Theme} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.
|
|
27
|
+
* import {Theme} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/modules/dom/theme.js';
|
|
28
28
|
* console.log(new Theme())
|
|
29
29
|
* </script>
|
|
30
30
|
* ```
|
|
31
31
|
*
|
|
32
32
|
* @example
|
|
33
33
|
*
|
|
34
|
-
* import {getDocumentTheme} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.
|
|
34
|
+
* import {getDocumentTheme} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.27.0/dist/modules/dom/theme.js';
|
|
35
35
|
*
|
|
36
36
|
* const theme = getDocumentTheme();
|
|
37
37
|
* console.log(theme.getName());
|