@schukai/monster 1.24.0 → 1.25.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 (190) hide show
  1. package/CHANGELOG +14 -0
  2. package/README.md +4 -4
  3. package/dist/modules/constants.js +2 -2
  4. package/dist/modules/constraints/abstract.js +1 -1
  5. package/dist/modules/constraints/abstractoperator.js +1 -1
  6. package/dist/modules/constraints/andoperator.js +1 -1
  7. package/dist/modules/constraints/invalid.js +1 -1
  8. package/dist/modules/constraints/isarray.js +1 -1
  9. package/dist/modules/constraints/isobject.js +1 -1
  10. package/dist/modules/constraints/namespace.js +1 -1
  11. package/dist/modules/constraints/oroperator.js +1 -1
  12. package/dist/modules/constraints/valid.js +1 -1
  13. package/dist/modules/data/buildmap.js +1 -1
  14. package/dist/modules/data/datasource/namespace.js +1 -1
  15. package/dist/modules/data/datasource/restapi/writeerror.js +1 -1
  16. package/dist/modules/data/datasource/restapi.js +1 -1
  17. package/dist/modules/data/datasource/storage/localstorage.js +1 -1
  18. package/dist/modules/data/datasource/storage/namespace.js +1 -1
  19. package/dist/modules/data/datasource/storage/sessionstorage.js +1 -1
  20. package/dist/modules/data/datasource/storage.js +1 -1
  21. package/dist/modules/data/datasource.js +1 -1
  22. package/dist/modules/data/diff.js +1 -1
  23. package/dist/modules/data/extend.js +1 -1
  24. package/dist/modules/data/namespace.js +1 -1
  25. package/dist/modules/data/pathfinder.js +1 -1
  26. package/dist/modules/data/pipe.js +1 -1
  27. package/dist/modules/data/transformer.js +2 -2
  28. package/dist/modules/dom/assembler.js +1 -1
  29. package/dist/modules/dom/attributes.js +1 -1
  30. package/dist/modules/dom/constants.js +2 -2
  31. package/dist/modules/dom/customcontrol.js +1 -1
  32. package/dist/modules/dom/customelement.js +1 -1
  33. package/dist/modules/dom/events.js +1 -1
  34. package/dist/modules/dom/focusmanager.js +2 -0
  35. package/dist/modules/dom/locale.js +1 -1
  36. package/dist/modules/dom/namespace.js +1 -1
  37. package/dist/modules/dom/resource/data.js +2 -0
  38. package/dist/modules/dom/resource/link/stylesheet.js +2 -0
  39. package/dist/modules/dom/resource/link.js +2 -0
  40. package/dist/modules/dom/resource/script.js +2 -0
  41. package/dist/modules/dom/resource.js +2 -0
  42. package/dist/modules/dom/resourcemanager.js +2 -0
  43. package/dist/modules/dom/template.js +1 -1
  44. package/dist/modules/dom/theme.js +1 -1
  45. package/dist/modules/dom/updater.js +1 -1
  46. package/dist/modules/dom/util.js +1 -1
  47. package/dist/modules/dom/worker/factory.js +2 -0
  48. package/dist/modules/i18n/locale.js +1 -1
  49. package/dist/modules/i18n/namespace.js +1 -1
  50. package/dist/modules/i18n/provider.js +1 -1
  51. package/dist/modules/i18n/providers/fetch.js +1 -1
  52. package/dist/modules/i18n/providers/namespace.js +1 -1
  53. package/dist/modules/i18n/translations.js +1 -1
  54. package/dist/modules/logging/handler/console.js +1 -1
  55. package/dist/modules/logging/handler/namespace.js +1 -1
  56. package/dist/modules/logging/handler.js +1 -1
  57. package/dist/modules/logging/logentry.js +1 -1
  58. package/dist/modules/logging/logger.js +1 -1
  59. package/dist/modules/logging/namespace.js +1 -1
  60. package/dist/modules/math/namespace.js +1 -1
  61. package/dist/modules/math/random.js +2 -2
  62. package/dist/modules/monster.js +1 -1
  63. package/dist/modules/namespace.js +1 -1
  64. package/dist/modules/text/formatter.js +1 -1
  65. package/dist/modules/text/namespace.js +1 -1
  66. package/dist/modules/types/base.js +1 -1
  67. package/dist/modules/types/basewithoptions.js +1 -1
  68. package/dist/modules/types/binary.js +1 -1
  69. package/dist/modules/types/dataurl.js +1 -1
  70. package/dist/modules/types/global.js +1 -1
  71. package/dist/modules/types/id.js +1 -1
  72. package/dist/modules/types/is.js +1 -1
  73. package/dist/modules/types/mediatype.js +1 -1
  74. package/dist/modules/types/namespace.js +1 -1
  75. package/dist/modules/types/observer.js +1 -1
  76. package/dist/modules/types/observerlist.js +1 -1
  77. package/dist/modules/types/proxyobserver.js +1 -1
  78. package/dist/modules/types/queue.js +1 -1
  79. package/dist/modules/types/randomid.js +1 -1
  80. package/dist/modules/types/stack.js +1 -1
  81. package/dist/modules/types/tokenlist.js +1 -1
  82. package/dist/modules/types/typeof.js +1 -1
  83. package/dist/modules/types/uniquequeue.js +1 -1
  84. package/dist/modules/types/uuid.js +2 -0
  85. package/dist/modules/types/validate.js +1 -1
  86. package/dist/modules/types/version.js +2 -2
  87. package/dist/modules/util/clone.js +1 -1
  88. package/dist/modules/util/comparator.js +1 -1
  89. package/dist/modules/util/freeze.js +1 -1
  90. package/dist/modules/util/namespace.js +1 -1
  91. package/dist/modules/util/processing.js +1 -1
  92. package/dist/modules/util/trimspaces.js +1 -1
  93. package/dist/monster.dev.js +549 -249
  94. package/dist/monster.dev.js.map +1 -1
  95. package/dist/monster.js +2 -2
  96. package/package.json +1 -1
  97. package/source/constants.js +11 -2
  98. package/source/constraints/andoperator.js +5 -5
  99. package/source/constraints/invalid.js +3 -3
  100. package/source/constraints/isarray.js +3 -3
  101. package/source/constraints/isobject.js +3 -3
  102. package/source/constraints/oroperator.js +5 -5
  103. package/source/constraints/valid.js +3 -3
  104. package/source/data/buildmap.js +4 -4
  105. package/source/data/datasource/restapi.js +3 -3
  106. package/source/data/datasource/storage/localstorage.js +2 -2
  107. package/source/data/datasource/storage/sessionstorage.js +2 -2
  108. package/source/data/datasource/storage.js +3 -3
  109. package/source/data/datasource.js +3 -3
  110. package/source/data/diff.js +3 -3
  111. package/source/data/extend.js +2 -2
  112. package/source/data/pathfinder.js +4 -4
  113. package/source/data/pipe.js +3 -3
  114. package/source/data/transformer.js +7 -5
  115. package/source/dom/assembler.js +2 -2
  116. package/source/dom/attributes.js +24 -24
  117. package/source/dom/constants.js +278 -9
  118. package/source/dom/customcontrol.js +1 -1
  119. package/source/dom/customelement.js +1 -1
  120. package/source/dom/events.js +4 -4
  121. package/source/dom/focusmanager.js +251 -0
  122. package/source/dom/locale.js +4 -3
  123. package/source/dom/resource/data.js +170 -0
  124. package/source/dom/resource/link/stylesheet.js +54 -0
  125. package/source/dom/resource/link.js +125 -0
  126. package/source/dom/resource/script.js +112 -0
  127. package/source/dom/resource.js +268 -0
  128. package/source/dom/resourcemanager.js +214 -0
  129. package/source/dom/template.js +40 -10
  130. package/source/dom/theme.js +3 -3
  131. package/source/dom/updater.js +7 -7
  132. package/source/dom/util.js +6 -6
  133. package/source/dom/worker/factory.js +134 -0
  134. package/source/i18n/locale.js +4 -4
  135. package/source/i18n/provider.js +2 -2
  136. package/source/i18n/providers/fetch.js +2 -2
  137. package/source/i18n/translations.js +3 -3
  138. package/source/logging/handler/console.js +2 -2
  139. package/source/logging/handler.js +2 -2
  140. package/source/logging/logentry.js +2 -2
  141. package/source/logging/logger.js +2 -2
  142. package/source/math/random.js +9 -5
  143. package/source/namespace.js +1 -1
  144. package/source/text/formatter.js +3 -3
  145. package/source/types/base.js +4 -4
  146. package/source/types/basewithoptions.js +2 -2
  147. package/source/types/binary.js +4 -4
  148. package/source/types/dataurl.js +4 -4
  149. package/source/types/global.js +4 -4
  150. package/source/types/id.js +2 -2
  151. package/source/types/is.js +23 -23
  152. package/source/types/mediatype.js +4 -4
  153. package/source/types/observer.js +3 -3
  154. package/source/types/observerlist.js +2 -2
  155. package/source/types/proxyobserver.js +5 -5
  156. package/source/types/queue.js +3 -3
  157. package/source/types/randomid.js +2 -2
  158. package/source/types/stack.js +2 -2
  159. package/source/types/tokenlist.js +2 -2
  160. package/source/types/typeof.js +3 -3
  161. package/source/types/uniquequeue.js +2 -2
  162. package/source/types/uuid.js +102 -0
  163. package/source/types/validate.js +20 -20
  164. package/source/types/version.js +6 -6
  165. package/source/util/clone.js +2 -2
  166. package/source/util/comparator.js +4 -4
  167. package/source/util/freeze.js +5 -5
  168. package/source/util/processing.js +3 -3
  169. package/source/util/trimspaces.js +3 -3
  170. package/test/cases/data/datasource/restapi.js +1 -1
  171. package/test/cases/data/transformer.js +2 -0
  172. package/test/cases/dom/customelement.js +0 -3
  173. package/test/cases/dom/focusmanager.js +111 -0
  174. package/test/cases/dom/locale.js +1 -4
  175. package/test/cases/dom/resource/data.js +129 -0
  176. package/test/cases/dom/resource/link/stylesheet.js +101 -0
  177. package/test/cases/dom/resource/link.js +101 -0
  178. package/test/cases/dom/resource/script.js +115 -0
  179. package/test/cases/dom/resourcemanager.js +118 -0
  180. package/test/cases/dom/worker/factory.js +63 -0
  181. package/test/cases/monster.js +1 -1
  182. package/test/cases/types/uuid.js +42 -0
  183. package/test/cases/util/freeze.js +30 -4
  184. package/test/util/cleanupdom.js +48 -0
  185. package/test/util/jsdom.js +23 -9
  186. package/test/web/import.js +8 -0
  187. package/test/web/monster-dev.html +3 -3
  188. package/test/web/monster.html +2 -2
  189. package/test/web/test.html +3 -3
  190. package/test/web/tests.js +7 -7
@@ -0,0 +1,112 @@
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 {
10
+ ATTRIBUTE_CLASS,
11
+ ATTRIBUTE_ID,
12
+ ATTRIBUTE_NONCE,
13
+ ATTRIBUTE_SRC,
14
+ ATTRIBUTE_TITLE,
15
+ ATTRIBUTE_TYPE,
16
+ TAG_SCRIPT
17
+ } from "../constants.js";
18
+ import {KEY_DOCUMENT, referenceSymbol, Resource} from "../resource.js";
19
+
20
+
21
+ /**
22
+ * This class is used by the resource manager to embed scripts.
23
+ *
24
+ * You can call the method via the monster namespace `new Monster.DOM.Resource.Script()`.
25
+ *
26
+ * ```
27
+ * <script type="module">
28
+ * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.25.0/dist/modules/dom/resource/script.js';
29
+ * new Monster.DOM.Resource.Script()
30
+ * </script>
31
+ * ```
32
+ *
33
+ * Alternatively, you can also integrate this function individually.
34
+ *
35
+ * ```
36
+ * <script type="module">
37
+ * import {Script} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.25.0/dist/modules/dom/resource/script.js';
38
+ * new Script()
39
+ * </script>
40
+ * ```
41
+ *
42
+ * @since 1.25.0
43
+ * @copyright schukai GmbH
44
+ * @memberOf Monster.DOM.Resource
45
+ * @summary A Resource class
46
+ */
47
+ class Script extends Resource {
48
+
49
+ /**
50
+ * @property {boolean} async=true {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-async}
51
+ * @property {string} crossOrigin=anonymous {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-crossorigin}
52
+ * @property {boolean} defer=false {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer}
53
+ * @property {string} integrity {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-integrity}
54
+ * @property {boolean} nomodule {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-nomodule}
55
+ * @property {string} nonce {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-nonce}
56
+ * @property {string} referrerpolicy {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-referrerpolicy}
57
+ * @property {string} type {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type}
58
+ */
59
+ get defaults() {
60
+ return extend({}, super.defaults, {
61
+ async: true,
62
+ crossOrigin: 'anonymous',
63
+ defer: false,
64
+ integrity: undefined,
65
+ nomodule: false,
66
+ nonce: undefined,
67
+ referrerpolicy: undefined,
68
+ type: 'text/javascript',
69
+ })
70
+ }
71
+
72
+ /**
73
+ *
74
+ * @return {Monster.DOM.Resource.Script}
75
+ */
76
+ create() {
77
+ createElement.call(this);
78
+ return this;
79
+ }
80
+
81
+ /**
82
+ * @return {string}
83
+ */
84
+ static getURLAttribute() {
85
+ return ATTRIBUTE_SRC
86
+ }
87
+
88
+ }
89
+
90
+ /**
91
+ * @private
92
+ * @return {Monster.DOM.Resource.Script}
93
+ */
94
+ function createElement() {
95
+ const self = this;
96
+
97
+ const document = self.getOption(KEY_DOCUMENT);
98
+ self[referenceSymbol] = document.createElement(TAG_SCRIPT);
99
+
100
+ for (let key of ['crossOrigin', 'defer', 'async', 'integrity', 'nomodule', ATTRIBUTE_NONCE, 'referrerpolicy', ATTRIBUTE_TYPE, ATTRIBUTE_SRC, ATTRIBUTE_ID, ATTRIBUTE_CLASS, ATTRIBUTE_TITLE]) {
101
+ if (self.getOption(key) !== undefined) {
102
+ self[referenceSymbol][key] = self.getOption(key);
103
+ }
104
+ }
105
+
106
+
107
+ return self;
108
+ }
109
+
110
+
111
+ assignToNamespace('Monster.DOM.Resource', Script);
112
+ export {Monster, Script}
@@ -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.25.0/dist/modules/dom/resource.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.25.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.25.0/dist/modules/dom/resourcemanager.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.25.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}
@@ -14,8 +14,8 @@ import {getDocumentTheme} from "./theme.js";
14
14
  *
15
15
  * ```
16
16
  * <script type="module">
17
- * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.24.0/dist/modules/dom/template.js';
18
- * console.log(new Monster.DOM.Template())
17
+ * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.25.0/dist/modules/dom/template.js';
18
+ * new Monster.DOM.Template()
19
19
  * </script>
20
20
  * ```
21
21
  *
@@ -23,8 +23,8 @@ import {getDocumentTheme} from "./theme.js";
23
23
  *
24
24
  * ```
25
25
  * <script type="module">
26
- * import {Template} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.24.0/dist/modules/dom/template.js';
27
- * console.log(new Template())
26
+ * import {Template} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.25.0/dist/modules/dom/template.js';
27
+ * new Template()
28
28
  * </script>
29
29
  * ```
30
30
  *
@@ -70,7 +70,7 @@ class Template extends Base {
70
70
  /**
71
71
  * This method loads a template with the given ID and returns it.
72
72
  *
73
- * To do this, it first fetches the theme of the document and looks for the `data-monster-theme-name` attribute in the HTML tag.
73
+ * 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
74
  *
75
75
  * ```
76
76
  * <html data-monster-theme-name="my-theme">
@@ -80,13 +80,13 @@ class Template extends Base {
80
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
82
  * 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
- *
83
+ *
84
84
  * You can call the method via the monster namespace `Monster.DOM.findDocumentTemplate()`.
85
85
  *
86
86
  * ```
87
87
  * <script type="module">
88
- * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.24.0/dist/modules/dom/template.js';
89
- * console.log(Monster.DOM.findDocumentTemplate())
88
+ * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.25.0/dist/modules/dom/template.js';
89
+ * Monster.DOM.findDocumentTemplate()
90
90
  * </script>
91
91
  * ```
92
92
  *
@@ -94,11 +94,41 @@ class Template extends Base {
94
94
  *
95
95
  * ```
96
96
  * <script type="module">
97
- * import {findTemplate} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.24.0/dist/modules/dom/template.js';
98
- * console.log(findDocumentTemplate())
97
+ * import {findTemplate} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.25.0/dist/modules/dom/template.js';
98
+ * findDocumentTemplate()
99
99
  * </script>
100
100
  * ```
101
101
  *
102
+ * @example
103
+ *
104
+ * import { findDocumentTemplate } from "https://cdn.jsdelivr.net/npm/@schukai/monster@1.25.0/dist/modules/dom/template.js";
105
+ *
106
+ * const template = document.createElement("template");
107
+ * template.id = "myTemplate";
108
+ * template.innerHTML = "<p>my default template</p>";
109
+ * document.body.appendChild(template);
110
+ *
111
+ * const themedTemplate = document.createElement("template");
112
+ * themedTemplate.id = "myTemplate-myTheme";
113
+ * themedTemplate.innerHTML = "<p>my themed template</p>";
114
+ * document.body.appendChild(themedTemplate);
115
+ *
116
+ * // loads the temple and since no theme is set the default template
117
+ * const template1 = findDocumentTemplate("myTemplate");
118
+ * console.log(template1.createDocumentFragment());
119
+ * // ↦ '<p>my default template</p>'
120
+ *
121
+ * // now we set our own theme
122
+ * document
123
+ * .querySelector("html")
124
+ * .setAttribute("data-monster-theme-name", "myTheme");
125
+ *
126
+ * // now we don't get the default template,
127
+ * // but the template with the theme in the id
128
+ * const template2 = findDocumentTemplate("myTemplate");
129
+ * console.log(template2.createDocumentFragment());
130
+ * // ↦ '<p>my themed template</p>'
131
+ *
102
132
  * @param {string} id
103
133
  * @param {Node} currentNode
104
134
  * @return {Monster.DOM.Template}