@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.
- package/CHANGELOG +14 -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 +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dist/modules/dom/theme.js +1 -1
- package/dist/modules/dom/updater.js +1 -1
- package/dist/modules/dom/util.js +1 -1
- package/dist/modules/dom/worker/factory.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 +1 -1
- 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 +1 -1
- package/dist/modules/types/mediatype.js +1 -1
- package/dist/modules/types/namespace.js +1 -1
- 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/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 +549 -249
- package/dist/monster.dev.js.map +1 -1
- package/dist/monster.js +2 -2
- package/package.json +1 -1
- package/source/constants.js +11 -2
- package/source/constraints/andoperator.js +5 -5
- package/source/constraints/invalid.js +3 -3
- package/source/constraints/isarray.js +3 -3
- package/source/constraints/isobject.js +3 -3
- package/source/constraints/oroperator.js +5 -5
- package/source/constraints/valid.js +3 -3
- package/source/data/buildmap.js +4 -4
- 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 +24 -24
- package/source/dom/constants.js +278 -9
- package/source/dom/customcontrol.js +1 -1
- package/source/dom/customelement.js +1 -1
- package/source/dom/events.js +4 -4
- package/source/dom/focusmanager.js +251 -0
- package/source/dom/locale.js +4 -3
- 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 +40 -10
- package/source/dom/theme.js +3 -3
- package/source/dom/updater.js +7 -7
- package/source/dom/util.js +6 -6
- package/source/dom/worker/factory.js +134 -0
- package/source/i18n/locale.js +4 -4
- package/source/i18n/provider.js +2 -2
- package/source/i18n/providers/fetch.js +2 -2
- package/source/i18n/translations.js +3 -3
- 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 +3 -3
- 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 +2 -2
- package/source/types/is.js +23 -23
- package/source/types/mediatype.js +4 -4
- 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 +3 -3
- package/source/types/randomid.js +2 -2
- 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/datasource/restapi.js +1 -1
- package/test/cases/data/transformer.js +2 -0
- 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/worker/factory.js +63 -0
- package/test/cases/monster.js +1 -1
- 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 +23 -9
- package/test/web/import.js +8 -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,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}
|
package/source/dom/template.js
CHANGED
|
@@ -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.
|
|
18
|
-
*
|
|
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.
|
|
27
|
-
*
|
|
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
|
|
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.
|
|
89
|
-
*
|
|
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.
|
|
98
|
-
*
|
|
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}
|