@schukai/monster 1.21.1 → 1.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (205) hide show
  1. package/CHANGELOG +48 -1
  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 +2 -0
  15. package/dist/modules/data/datasource/restapi/writeerror.js +2 -0
  16. package/dist/modules/data/datasource/restapi.js +2 -0
  17. package/dist/modules/data/datasource/storage/localstorage.js +2 -0
  18. package/dist/modules/data/datasource/storage/namespace.js +2 -0
  19. package/dist/modules/data/datasource/storage/sessionstorage.js +2 -0
  20. package/dist/modules/data/datasource/storage.js +2 -0
  21. package/dist/modules/data/datasource.js +2 -0
  22. package/dist/modules/data/diff.js +2 -2
  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 +2 -2
  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 +2 -2
  32. package/dist/modules/dom/customelement.js +2 -2
  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 +2 -2
  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 +2 -2
  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 +2 -2
  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 +2 -2
  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 +2 -2
  77. package/dist/modules/types/proxyobserver.js +2 -2
  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 +2 -2
  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 +2 -2
  88. package/dist/modules/util/comparator.js +2 -2
  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 +2 -2
  92. package/dist/modules/util/trimspaces.js +2 -0
  93. package/dist/monster.dev.js +1499 -732
  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 +16 -7
  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 +6 -6
  105. package/source/data/datasource/namespace.js +16 -0
  106. package/source/data/datasource/restapi/writeerror.js +49 -0
  107. package/source/data/datasource/restapi.js +266 -0
  108. package/source/data/datasource/storage/localstorage.js +64 -0
  109. package/source/data/datasource/storage/namespace.js +16 -0
  110. package/source/data/datasource/storage/sessionstorage.js +61 -0
  111. package/source/data/datasource/storage.js +131 -0
  112. package/source/data/datasource.js +246 -0
  113. package/source/data/diff.js +8 -8
  114. package/source/data/extend.js +5 -5
  115. package/source/data/pathfinder.js +12 -6
  116. package/source/data/pipe.js +6 -5
  117. package/source/data/transformer.js +131 -24
  118. package/source/dom/assembler.js +2 -2
  119. package/source/dom/attributes.js +24 -24
  120. package/source/dom/constants.js +305 -12
  121. package/source/dom/customcontrol.js +40 -19
  122. package/source/dom/customelement.js +182 -103
  123. package/source/dom/events.js +6 -6
  124. package/source/dom/focusmanager.js +251 -0
  125. package/source/dom/locale.js +4 -3
  126. package/source/dom/resource/data.js +170 -0
  127. package/source/dom/resource/link/stylesheet.js +54 -0
  128. package/source/dom/resource/link.js +125 -0
  129. package/source/dom/resource/script.js +112 -0
  130. package/source/dom/resource.js +268 -0
  131. package/source/dom/resourcemanager.js +214 -0
  132. package/source/dom/template.js +40 -10
  133. package/source/dom/theme.js +3 -3
  134. package/source/dom/updater.js +114 -58
  135. package/source/dom/util.js +6 -6
  136. package/source/dom/worker/factory.js +134 -0
  137. package/source/i18n/locale.js +8 -8
  138. package/source/i18n/provider.js +4 -4
  139. package/source/i18n/providers/fetch.js +8 -13
  140. package/source/i18n/translations.js +6 -5
  141. package/source/logging/handler/console.js +2 -2
  142. package/source/logging/handler.js +2 -2
  143. package/source/logging/logentry.js +2 -2
  144. package/source/logging/logger.js +4 -4
  145. package/source/math/random.js +11 -5
  146. package/source/namespace.js +1 -1
  147. package/source/text/formatter.js +82 -7
  148. package/source/types/base.js +4 -4
  149. package/source/types/basewithoptions.js +10 -15
  150. package/source/types/binary.js +8 -8
  151. package/source/types/dataurl.js +6 -6
  152. package/source/types/global.js +9 -7
  153. package/source/types/id.js +2 -2
  154. package/source/types/is.js +23 -23
  155. package/source/types/mediatype.js +4 -4
  156. package/source/types/observer.js +3 -3
  157. package/source/types/observerlist.js +3 -3
  158. package/source/types/proxyobserver.js +24 -7
  159. package/source/types/queue.js +5 -5
  160. package/source/types/randomid.js +2 -2
  161. package/source/types/stack.js +2 -2
  162. package/source/types/tokenlist.js +8 -9
  163. package/source/types/typeof.js +3 -3
  164. package/source/types/uniquequeue.js +4 -4
  165. package/source/types/uuid.js +102 -0
  166. package/source/types/validate.js +20 -20
  167. package/source/types/version.js +6 -6
  168. package/source/util/clone.js +5 -6
  169. package/source/util/comparator.js +5 -5
  170. package/source/util/freeze.js +5 -5
  171. package/source/util/processing.js +33 -36
  172. package/source/util/trimspaces.js +85 -0
  173. package/test/cases/data/datasource/restapi.js +89 -0
  174. package/test/cases/data/datasource/storage/localstorage.js +47 -0
  175. package/test/cases/data/datasource/storage/sessionstorage.js +47 -0
  176. package/test/cases/data/datasource.js +60 -0
  177. package/test/cases/data/diff.js +4 -4
  178. package/test/cases/data/pathfinder.js +18 -9
  179. package/test/cases/data/pipe.js +26 -2
  180. package/test/cases/data/transformer.js +41 -10
  181. package/test/cases/dom/customcontrol.js +6 -5
  182. package/test/cases/dom/customelement.js +25 -26
  183. package/test/cases/dom/focusmanager.js +111 -0
  184. package/test/cases/dom/locale.js +1 -4
  185. package/test/cases/dom/resource/data.js +129 -0
  186. package/test/cases/dom/resource/link/stylesheet.js +101 -0
  187. package/test/cases/dom/resource/link.js +101 -0
  188. package/test/cases/dom/resource/script.js +115 -0
  189. package/test/cases/dom/resourcemanager.js +118 -0
  190. package/test/cases/dom/updater.js +42 -19
  191. package/test/cases/dom/worker/factory.js +63 -0
  192. package/test/cases/monster.js +1 -1
  193. package/test/cases/text/formatter.js +38 -6
  194. package/test/cases/types/proxyobserver.js +55 -11
  195. package/test/cases/types/uuid.js +42 -0
  196. package/test/cases/util/freeze.js +30 -4
  197. package/test/cases/util/trimspaces.js +24 -0
  198. package/test/util/cleanupdom.js +48 -0
  199. package/test/util/jsdom.js +23 -9
  200. package/test/util/localstorage.js +81 -0
  201. package/test/web/import.js +13 -0
  202. package/test/web/monster-dev.html +3 -3
  203. package/test/web/monster.html +2 -2
  204. package/test/web/test.html +3 -3
  205. 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.21.1/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.21.1/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.21.1/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.21.1/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}