@schukai/monster 1.13.0 → 1.15.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. package/CHANGELOG +46 -1
  2. package/README.md +5 -5
  3. package/dist/modules/constants.js +2 -2
  4. package/dist/modules/constraints/abstract.js +2 -2
  5. package/dist/modules/constraints/abstractoperator.js +2 -2
  6. package/dist/modules/constraints/andoperator.js +2 -2
  7. package/dist/modules/constraints/invalid.js +2 -2
  8. package/dist/modules/constraints/isarray.js +2 -2
  9. package/dist/modules/constraints/isobject.js +2 -2
  10. package/dist/modules/constraints/namespace.js +1 -1
  11. package/dist/modules/constraints/oroperator.js +2 -2
  12. package/dist/modules/constraints/valid.js +2 -2
  13. package/dist/modules/data/buildmap.js +2 -2
  14. package/dist/modules/data/diff.js +2 -2
  15. package/dist/modules/data/extend.js +2 -2
  16. package/dist/modules/data/namespace.js +1 -1
  17. package/dist/modules/data/pathfinder.js +2 -2
  18. package/dist/modules/data/pipe.js +2 -2
  19. package/dist/modules/data/transformer.js +2 -2
  20. package/dist/modules/dom/assembler.js +2 -2
  21. package/dist/modules/dom/attributes.js +2 -2
  22. package/dist/modules/dom/constants.js +2 -2
  23. package/dist/modules/dom/customcontrol.js +2 -0
  24. package/dist/modules/dom/customelement.js +2 -2
  25. package/dist/modules/dom/events.js +2 -2
  26. package/dist/modules/dom/locale.js +2 -2
  27. package/dist/modules/dom/namespace.js +1 -1
  28. package/dist/modules/dom/template.js +2 -2
  29. package/dist/modules/dom/theme.js +2 -2
  30. package/dist/modules/dom/updater.js +2 -2
  31. package/dist/modules/dom/util.js +2 -2
  32. package/dist/modules/i18n/locale.js +2 -2
  33. package/dist/modules/i18n/namespace.js +1 -1
  34. package/dist/modules/i18n/provider.js +2 -2
  35. package/dist/modules/i18n/providers/fetch.js +2 -2
  36. package/dist/modules/i18n/providers/namespace.js +1 -1
  37. package/dist/modules/i18n/translations.js +2 -2
  38. package/dist/modules/logging/handler/console.js +2 -2
  39. package/dist/modules/logging/handler/namespace.js +1 -1
  40. package/dist/modules/logging/handler.js +2 -2
  41. package/dist/modules/logging/logentry.js +2 -2
  42. package/dist/modules/logging/logger.js +2 -2
  43. package/dist/modules/logging/namespace.js +1 -1
  44. package/dist/modules/math/namespace.js +1 -1
  45. package/dist/modules/math/random.js +2 -2
  46. package/dist/modules/monster.js +2 -2
  47. package/dist/modules/namespace.js +2 -2
  48. package/dist/modules/text/formatter.js +2 -2
  49. package/dist/modules/text/namespace.js +1 -1
  50. package/dist/modules/types/base.js +2 -2
  51. package/dist/modules/types/basewithoptions.js +2 -2
  52. package/dist/modules/types/global.js +2 -2
  53. package/dist/modules/types/id.js +2 -2
  54. package/dist/modules/types/is.js +2 -2
  55. package/dist/modules/types/namespace.js +1 -1
  56. package/dist/modules/types/observer.js +2 -2
  57. package/dist/modules/types/observerlist.js +2 -2
  58. package/dist/modules/types/proxyobserver.js +2 -2
  59. package/dist/modules/types/queue.js +2 -2
  60. package/dist/modules/types/randomid.js +2 -2
  61. package/dist/modules/types/stack.js +2 -2
  62. package/dist/modules/types/tokenlist.js +2 -2
  63. package/dist/modules/types/typeof.js +2 -2
  64. package/dist/modules/types/uniquequeue.js +2 -2
  65. package/dist/modules/types/validate.js +2 -2
  66. package/dist/modules/types/version.js +2 -2
  67. package/dist/modules/util/clone.js +2 -2
  68. package/dist/modules/util/comparator.js +2 -2
  69. package/dist/modules/util/freeze.js +2 -2
  70. package/dist/modules/util/namespace.js +1 -1
  71. package/dist/monster.dev.js +8622 -7709
  72. package/dist/monster.dev.js.map +1 -1
  73. package/dist/monster.js +2 -9
  74. package/package.json +1 -1
  75. package/source/constants.js +7 -6
  76. package/source/constraints/abstract.js +2 -2
  77. package/source/constraints/abstractoperator.js +4 -4
  78. package/source/constraints/andoperator.js +8 -8
  79. package/source/constraints/invalid.js +6 -6
  80. package/source/constraints/isarray.js +7 -7
  81. package/source/constraints/isobject.js +7 -7
  82. package/source/constraints/namespace.js +2 -2
  83. package/source/constraints/oroperator.js +8 -8
  84. package/source/constraints/valid.js +7 -7
  85. package/source/data/buildmap.js +15 -15
  86. package/source/data/diff.js +9 -9
  87. package/source/data/extend.js +55 -13
  88. package/source/data/namespace.js +2 -2
  89. package/source/data/pathfinder.js +13 -14
  90. package/source/data/pipe.js +8 -8
  91. package/source/data/transformer.js +11 -11
  92. package/source/dom/assembler.js +7 -7
  93. package/source/dom/attributes.js +89 -46
  94. package/source/dom/constants.js +9 -2
  95. package/source/dom/customcontrol.js +299 -0
  96. package/source/dom/customelement.js +181 -66
  97. package/source/dom/events.js +58 -8
  98. package/source/dom/locale.js +5 -5
  99. package/source/dom/namespace.js +2 -2
  100. package/source/dom/template.js +24 -19
  101. package/source/dom/theme.js +8 -9
  102. package/source/dom/updater.js +46 -24
  103. package/source/dom/util.js +10 -10
  104. package/source/i18n/locale.js +7 -7
  105. package/source/i18n/namespace.js +1 -1
  106. package/source/i18n/provider.js +6 -6
  107. package/source/i18n/providers/fetch.js +10 -10
  108. package/source/i18n/translations.js +5 -5
  109. package/source/logging/handler/console.js +5 -5
  110. package/source/logging/handler/namespace.js +1 -1
  111. package/source/logging/handler.js +8 -8
  112. package/source/logging/logentry.js +5 -5
  113. package/source/logging/logger.js +5 -5
  114. package/source/logging/namespace.js +2 -2
  115. package/source/math/namespace.js +2 -2
  116. package/source/math/random.js +5 -5
  117. package/source/monster.js +48 -44
  118. package/source/namespace.js +2 -2
  119. package/source/text/formatter.js +6 -7
  120. package/source/text/namespace.js +1 -1
  121. package/source/types/base.js +4 -5
  122. package/source/types/basewithoptions.js +10 -9
  123. package/source/types/global.js +7 -7
  124. package/source/types/id.js +7 -7
  125. package/source/types/is.js +22 -22
  126. package/source/types/namespace.js +2 -2
  127. package/source/types/observer.js +7 -7
  128. package/source/types/observerlist.js +4 -4
  129. package/source/types/proxyobserver.js +32 -26
  130. package/source/types/queue.js +13 -7
  131. package/source/types/randomid.js +6 -6
  132. package/source/types/stack.js +11 -4
  133. package/source/types/tokenlist.js +9 -9
  134. package/source/types/typeof.js +5 -5
  135. package/source/types/uniquequeue.js +14 -7
  136. package/source/types/validate.js +27 -27
  137. package/source/types/version.js +9 -9
  138. package/source/util/clone.js +6 -6
  139. package/source/util/comparator.js +7 -7
  140. package/source/util/freeze.js +7 -7
  141. package/source/util/namespace.js +2 -2
  142. package/test/cases/data/extend.js +66 -13
  143. package/test/cases/dom/attributes.js +56 -1
  144. package/test/cases/dom/customcontrol.js +264 -0
  145. package/test/cases/dom/customelement.js +112 -51
  146. package/test/cases/dom/events.js +32 -14
  147. package/test/cases/dom/template.js +40 -1
  148. package/test/cases/monster.js +1 -1
  149. package/test/cases/types/proxyobserver.js +9 -0
  150. package/test/util/jsdom.js +3 -0
  151. package/test/web/import.js +1 -0
  152. package/test/web/monster-dev.html +3 -3
  153. package/test/web/monster.html +2 -2
  154. package/test/web/test.html +3 -3
  155. package/test/web/tests.js +3 -3
@@ -0,0 +1,299 @@
1
+ 'use strict';
2
+
3
+ import {extend} from "../data/extend.js";
4
+ /**
5
+ * @author schukai GmbH
6
+ */
7
+ import {assignToNamespace, Monster} from '../namespace.js';
8
+ import {CustomElement} from "./customelement.js";
9
+
10
+
11
+ /**
12
+ * @private
13
+ * @type {symbol}
14
+ */
15
+ const internalSymbol = Symbol('internalSymbol');
16
+
17
+ /**
18
+ * To define a new HTML control we need the power of CustomElement
19
+ *
20
+ * IMPORTANT: after defining a `CustomElement`, the `registerCustomElement` method must be called
21
+ * with the new class name. only then will the tag defined via the `getTag` method be made known to the DOM.
22
+ *
23
+ * This control uses `attachInternals()` to integrate the control into a form.
24
+ * If the target environment does not support this method, the [polyfill](https://www.npmjs.com/package/element-internals-polyfill ) can be used.
25
+ *
26
+ * You can create the object via the monster namespace `new Monster.DOM.CustomControl()`.
27
+ *
28
+ * ```
29
+ * <script type="module">
30
+ * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.15.2/dist/modules/dom/customcontrol.js';
31
+ * console.log(new Monster.DOM.CustomControl())
32
+ * </script>
33
+ * ```
34
+ *
35
+ * Alternatively, you can also integrate this function individually.
36
+ *
37
+ * ```
38
+ * <script type="module">
39
+ * import {CustomControl} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.15.2/dist/modules/dom/customcontrol.js';
40
+ * console.log(new CustomControl())
41
+ * </script>
42
+ * ```
43
+ *
44
+ * @see https://www.npmjs.com/package/element-internals-polyfill
45
+ * @see https://github.com/WICG/webcomponents
46
+ * @see https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements
47
+ * @since 1.14.0
48
+ * @copyright schukai GmbH
49
+ * @memberOf Monster/DOM
50
+ */
51
+ class CustomControl extends CustomElement {
52
+
53
+ /**
54
+ *
55
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
56
+ */
57
+ constructor() {
58
+ super();
59
+
60
+ if (typeof this['attachInternals'] === 'function') {
61
+ // currently only supported by chrome
62
+ this[internalSymbol] = this.attachInternals();
63
+ }
64
+
65
+ }
66
+
67
+ /**
68
+ *
69
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals
70
+ * @since 1.14.0
71
+ * @return {boolean}
72
+ */
73
+ static get formAssociated() {
74
+ return true;
75
+ }
76
+
77
+ /**
78
+ * | option | description |
79
+ * |----------------|---------------------------------|
80
+ * | | |
81
+ *
82
+ * Derived classes can override and extend this method as follows.
83
+ *
84
+ * ```
85
+ * get defaults() {
86
+ * return extends{}, super.defaults, {
87
+ * myValue:true
88
+ * });
89
+ * }
90
+ * ```
91
+ *
92
+ * @see https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-face-example
93
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals
94
+ * @return {object}
95
+ * @since 1.14.0
96
+ */
97
+ get defaults() {
98
+ return extend({}, super.defaults);
99
+ }
100
+
101
+ /**
102
+ * Must be overridden by a derived class and return the value of the control.
103
+ *
104
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
105
+ *
106
+ * @since 1.14.0
107
+ * @throws {Error} the value getter must be overwritten by the derived class
108
+ */
109
+ get value() {
110
+ throw Error('the value getter must be overwritten by the derived class');
111
+ }
112
+
113
+ /**
114
+ * Must be overridden by a derived class and return the value of the control.
115
+ *
116
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
117
+ *
118
+ * @param {*} value
119
+ * @since 1.14.0
120
+ * @throws {Error} the value setter must be overwritten by the derived class
121
+ */
122
+ set value(value) {
123
+ throw Error('the value setter must be overwritten by the derived class');
124
+ }
125
+
126
+ /**
127
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
128
+ *
129
+ * @return {NodeList}
130
+ * @since 1.14.0
131
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/labels
132
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
133
+ */
134
+ get labels() {
135
+ return getInternal.call(this)?.labels;
136
+ }
137
+
138
+ /**
139
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
140
+ *
141
+ * @return {string|null}
142
+ */
143
+ get name() {
144
+ return this.getAttribute('name');
145
+ }
146
+
147
+ /**
148
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
149
+ *
150
+ * @return {string}
151
+ */
152
+ get type() {
153
+ return this.constructor.getTag();
154
+ }
155
+
156
+ /**
157
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
158
+ *
159
+ * @return {ValidityState}
160
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
161
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ValidityState
162
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/validity
163
+ */
164
+ get validity() {
165
+ return getInternal.call(this)?.validity;
166
+ }
167
+
168
+ /**
169
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
170
+ *
171
+ * @return {string}
172
+ * @since 1.14.0
173
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/validationMessage
174
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
175
+ */
176
+ get validationMessage() {
177
+ return getInternal.call(this)?.validationMessage;
178
+ }
179
+
180
+ /**
181
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
182
+ *
183
+ * @return {boolean}
184
+ * @since 1.14.0
185
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/willValidate
186
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
187
+ */
188
+ get willValidate() {
189
+ return getInternal.call(this)?.willValidate;
190
+ }
191
+
192
+ /**
193
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
194
+ *
195
+ * @return {CustomStateSet}
196
+ * @since 1.14.0
197
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/states
198
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
199
+ */
200
+ get states() {
201
+ return getInternal.call(this)?.states;
202
+ }
203
+
204
+ /**
205
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
206
+ *
207
+ * @return {HTMLFontElement|null}
208
+ * @since 1.14.0
209
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/form
210
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
211
+ */
212
+ get form() {
213
+ return getInternal.call(this)?.form;
214
+ }
215
+
216
+ /**
217
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
218
+ *
219
+ * ```
220
+ * // Use the control's name as the base name for submitted data
221
+ * const n = this.getAttribute('name');
222
+ * const entries = new FormData();
223
+ * entries.append(n + '-first-name', this.firstName_);
224
+ * entries.append(n + '-last-name', this.lastName_);
225
+ * this.setFormValue(entries);
226
+ * ```
227
+ *
228
+ * @param {File|string|FormData} value
229
+ * @param {File|string|FormData} state
230
+ * @since 1.14.0
231
+ * @return {undefined}
232
+ * @throws {DOMException} NotSupportedError
233
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
234
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setFormValue
235
+ */
236
+ setFormValue(value, state) {
237
+ getInternal.call(this).setFormValue(value, state);
238
+ }
239
+
240
+ /**
241
+ *
242
+ * @param {object} flags
243
+ * @param {string|undefined} message
244
+ * @param {HTMLElement} anchor
245
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setValidity
246
+ * @since 1.14.0
247
+ * @return {undefined}
248
+ * @throws {DOMException} NotSupportedError
249
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
250
+ */
251
+ setValidity(flags, message, anchor) {
252
+ getInternal.call(this).setValidity(flags, message, anchor);
253
+ }
254
+
255
+ /**
256
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
257
+ *
258
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/checkValidity
259
+ * @since 1.14.0
260
+ * @return {boolean}
261
+ * @throws {DOMException} NotSupportedError
262
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
263
+ */
264
+ checkValidity() {
265
+ return getInternal.call(this)?.checkValidity();
266
+ }
267
+
268
+ /**
269
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
270
+ *
271
+ * @return {boolean}
272
+ * @since 1.14.0
273
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/reportValidity
274
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
275
+ * @throws {DOMException} NotSupportedError
276
+ */
277
+ reportValidity() {
278
+ return getInternal.call(this)?.reportValidity();
279
+ }
280
+
281
+ }
282
+
283
+ /**
284
+ * @private
285
+ * @return {object}
286
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
287
+ */
288
+ function getInternal() {
289
+ const self = this;
290
+
291
+ if (!(internalSymbol in this)) {
292
+ throw new Error('ElementInternals is not supported and a polyfill is necessary');
293
+ }
294
+
295
+ return this[internalSymbol];
296
+ }
297
+
298
+ assignToNamespace('Monster.DOM', CustomControl);
299
+ export {Monster, CustomControl}
@@ -1,26 +1,28 @@
1
1
  'use strict';
2
2
 
3
+ import {PROPERTY_KEY_INTERNALDATA} from "../constants.js";
4
+ import {extend} from "../data/extend.js";
5
+ import {Pathfinder} from "../data/pathfinder.js";
3
6
  /**
4
7
  * @author schukai GmbH
5
8
  */
6
-
7
- import {Monster, Updater} from "./updater.js";
8
- import {extend} from "../data/extend.js";
9
- import {Pathfinder} from "../data/pathfinder.js";
10
- import {ATTRIBUTE_OPTIONS, OBJECTLINK_KEY_UPDATER} from "./constants.js";
11
- import {findDocumentTemplate, Template} from "./template.js";
12
- import {addToObjectLink, hasObjectLink} from "./attributes.js";
9
+ import {assignToNamespace, Monster} from '../namespace.js';
13
10
  import {getGlobalObject} from "../types/global.js";
14
- import {validateFunction, validateObject} from "../types/validate.js";
15
11
  import {isString} from "../types/is.js";
16
- import {getDocument} from "./util.js";
17
- import {PROPERTY_KEY_OPTIONS} from "../constants.js";
12
+ import {Observer} from "../types/observer.js";
13
+ import {ProxyObserver} from "../types/proxyobserver.js";
14
+ import {validateFunction, validateObject} from "../types/validate.js";
15
+ import {clone} from "../util/clone.js";
16
+ import {addToObjectLink, getLinkedObjects, hasObjectLink} from "./attributes.js";
17
+ import {ATTRIBUTE_OPTIONS, OBJECTLINK_KEY_UPDATER} from "./constants.js";
18
+ import {findDocumentTemplate, Template} from "./template.js";
19
+ import {Updater} from "./updater.js";
18
20
 
19
21
  /**
20
22
  * @private
21
23
  * @type {symbol}
22
24
  */
23
- const optionsSymbol = Symbol.for(PROPERTY_KEY_OPTIONS);
25
+ const internalDataSymbol = Symbol.for(PROPERTY_KEY_INTERNALDATA);
24
26
 
25
27
  /**
26
28
  * @private
@@ -38,12 +40,6 @@ const initMethodSymbol = Symbol('initMethodSymbol');
38
40
  */
39
41
  const assembleMethodSymbol = Symbol('assembleMethodSymbol');
40
42
 
41
- /**
42
- * @private
43
- * @type {Document}
44
- */
45
- const document = getDocument();
46
-
47
43
  /**
48
44
  * To define a new HTML element we need the power of CustomElement
49
45
  *
@@ -54,7 +50,7 @@ const document = getDocument();
54
50
  *
55
51
  * ```
56
52
  * <script type="module">
57
- * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.13.0/dist/modules/dom/customelement.js';
53
+ * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.15.2/dist/modules/dom/customelement.js';
58
54
  * console.log(new Monster.DOM.CustomElement())
59
55
  * </script>
60
56
  * ```
@@ -63,7 +59,7 @@ const document = getDocument();
63
59
  *
64
60
  * ```
65
61
  * <script type="module">
66
- * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.13.0/dist/modules/dom/customelement.js';
62
+ * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.15.2/dist/modules/dom/customelement.js';
67
63
  * console.log(new CustomElement())
68
64
  * </script>
69
65
  * ```
@@ -161,10 +157,21 @@ class CustomElement extends HTMLElement {
161
157
  */
162
158
  constructor() {
163
159
  super();
164
- this[optionsSymbol] = extend({}, this.defaults, getOptionsFromAttributes.call(this));
160
+ this[internalDataSymbol] = new ProxyObserver({'options': extend({}, this.defaults, getOptionsFromAttributes.call(this))});
161
+ initOptionObserver.call(this);
165
162
  this[initMethodSymbol]();
166
163
  }
167
164
 
165
+ /**
166
+ * This method determines which attributes are to be monitored by `attributeChangedCallback()`.
167
+ *
168
+ * @return {string[]}
169
+ * @since 1.15.0
170
+ */
171
+ static get observedAttributes() {
172
+ return [ATTRIBUTE_OPTIONS];
173
+ }
174
+
168
175
  /**
169
176
  * | option | description |
170
177
  * |----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -196,6 +203,75 @@ class CustomElement extends HTMLElement {
196
203
  };
197
204
  }
198
205
 
206
+ /**
207
+ * There is no check on the name by this class. the developer is responsible for assigning an appropriate tag.
208
+ * if the name is not valid, registerCustomElement() will issue an error
209
+ *
210
+ * @link https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
211
+ * @return {string}
212
+ * @throws {Error} the method getTag must be overwritten by the derived class.
213
+ * @since 1.7.0
214
+ */
215
+ static getTag() {
216
+ throw new Error("the method getTag must be overwritten by the derived class.");
217
+ }
218
+
219
+ /**
220
+ * At this point a `CSSStyleSheet` object can be returned. If the environment does not
221
+ * support a constructor, then an object can also be built using the following detour.
222
+ *
223
+ * If `undefined` is returned then the shadowRoot does not get a stylesheet.
224
+ *
225
+ * ```
226
+ * const doc = document.implementation.createHTMLDocument('title');
227
+ *
228
+ * let style = doc.createElement("style");
229
+ * style.innerHTML="p{color:red;}";
230
+ *
231
+ * // WebKit Hack
232
+ * style.appendChild(document.createTextNode(""));
233
+ * // Add the <style> element to the page
234
+ * doc.head.appendChild(style);
235
+ * return doc.styleSheets[0];
236
+ * ;
237
+ * ```
238
+ *
239
+ * @return {CSSStyleSheet|undefined}
240
+ */
241
+ static getCSSStyleSheet() {
242
+ return undefined;
243
+ }
244
+
245
+ /**
246
+ * attach a new observer
247
+ *
248
+ * @param {Observer} observer
249
+ * @returns {CustomElement}
250
+ */
251
+ attachObserver(observer) {
252
+ this[internalDataSymbol].attachObserver(observer)
253
+ return this;
254
+ }
255
+
256
+ /**
257
+ * detach a observer
258
+ *
259
+ * @param {Observer} observer
260
+ * @returns {CustomElement}
261
+ */
262
+ detachObserver(observer) {
263
+ this[internalDataSymbol].detachObserver(observer)
264
+ return this;
265
+ }
266
+
267
+ /**
268
+ * @param {Observer} observer
269
+ * @returns {ProxyObserver}
270
+ */
271
+ containsObserver(observer) {
272
+ return this[internalDataSymbol].containsObserver(observer)
273
+ }
274
+
199
275
  /**
200
276
  * nested options can be specified by path `a.b.c`
201
277
  *
@@ -208,7 +284,7 @@ class CustomElement extends HTMLElement {
208
284
  let value;
209
285
 
210
286
  try {
211
- value = new Pathfinder(this[optionsSymbol]).getVia(path);
287
+ value = new Pathfinder(this[internalDataSymbol].getRealSubject()['options']).getVia(path);
212
288
  } catch (e) {
213
289
 
214
290
  }
@@ -217,6 +293,38 @@ class CustomElement extends HTMLElement {
217
293
  return value;
218
294
  }
219
295
 
296
+ /**
297
+ * Set option and inform elements
298
+ *
299
+ * @param {string} path
300
+ * @param {*} value
301
+ * @return {CustomElement}
302
+ * @since 1.14.0
303
+ */
304
+ setOption(path, value) {
305
+ new Pathfinder(this[internalDataSymbol].getSubject()['options']).setVia(path, value);
306
+ //this[internalDataSymbol].notifyObservers();
307
+ return this;
308
+ }
309
+
310
+ /**
311
+ * @since 1.15.0
312
+ * @param {string|object} options
313
+ * @return {CustomElement}
314
+ */
315
+ setOptions(options) {
316
+
317
+ if (isString(options)) {
318
+ options = parseOptionsJSON(options)
319
+ }
320
+
321
+ const self = this;
322
+ extend(self[internalDataSymbol].getSubject()['options'], self.defaults, options);
323
+ //this[internalDataSymbol].notifyObservers();
324
+
325
+ return self;
326
+ }
327
+
220
328
  /**
221
329
  *
222
330
  * @return {CustomElement}
@@ -256,8 +364,8 @@ class CustomElement extends HTMLElement {
256
364
  for (const [, element] of Object.entries(elements)) {
257
365
 
258
366
  if (!(element instanceof HTMLElement)) continue;
259
-
260
- const u = new Updater(element, this[optionsSymbol])
367
+ if ((element instanceof HTMLTemplateElement)) continue;
368
+ const u = new Updater(element, clone(self[internalDataSymbol].getRealSubject()['options']))
261
369
  updater.add(u);
262
370
 
263
371
  u.run().then(() => {
@@ -266,7 +374,6 @@ class CustomElement extends HTMLElement {
266
374
 
267
375
  }
268
376
 
269
-
270
377
  return this;
271
378
  }
272
379
 
@@ -308,58 +415,53 @@ class CustomElement extends HTMLElement {
308
415
 
309
416
  /**
310
417
  * Called when an observed attribute has been added, removed, updated, or replaced. Also called for initial
311
- * values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes property will receive this callback.
418
+ * values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes
419
+ * property will receive this callback.
312
420
  *
313
421
  * @param {string} attrName
314
422
  * @param {string} oldVal
315
423
  * @param {string} newVal
316
424
  * @return {void}
317
- * @since 1.7.0
425
+ * @since 1.15.0
318
426
  */
319
427
  attributeChangedCallback(attrName, oldVal, newVal) {
320
- }
428
+ const self = this;
321
429
 
322
- /**
323
- * There is no check on the name by this class. the developer is responsible for assigning an appropriate tag.
324
- * if the name is not valid, registerCustomElement() will issue an erro
325
- *
326
- * @link https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
327
- * @return {string}
328
- * @throws {Error} the method getTag must be overwritten by the derived class.
329
- * @since 1.7.0
330
- */
331
- static getTag() {
332
- throw new Error("the method getTag must be overwritten by the derived class.");
333
- }
430
+ if (attrName === ATTRIBUTE_OPTIONS) {
431
+ self.setOptions(newVal);
432
+ }
334
433
 
335
- /**
336
- * At this point a `CSSStyleSheet` object can be returned. If the environment does not
337
- * support a constructor, then an object can also be built using the following detour.
338
- *
339
- * If `undefined` is returned then the shadowRoot does not get a stylesheet.
340
- *
341
- * ```
342
- * const doc = document.implementation.createHTMLDocument('title');
343
- *
344
- * let style = doc.createElement("style");
345
- * style.innerHTML="p{color:red;}";
346
- *
347
- * // WebKit Hack
348
- * style.appendChild(document.createTextNode(""));
349
- * // Add the <style> element to the page
350
- * doc.head.appendChild(style);
351
- * return doc.styleSheets[0];
352
- * ;
353
- * ```
354
- *
355
- * @return {CSSStyleSheet|undefined}
356
- */
357
- static getCSSStyleSheet() {
358
- return undefined;
359
434
  }
360
435
 
361
436
  }
362
437
 
438
+ /**
439
+ * @since 1.15.0
440
+ * @private
441
+ */
442
+ function initOptionObserver() {
443
+ const self = this;
444
+
445
+ self.attachObserver(new Observer(function () {
446
+
447
+ // not initialised
448
+ if (!hasObjectLink(self, Symbol.for(OBJECTLINK_KEY_UPDATER))) {
449
+ return;
450
+ }
451
+ // inform every element
452
+ const updaters = getLinkedObjects(self, Symbol.for(OBJECTLINK_KEY_UPDATER));
453
+
454
+ for (const list of updaters) {
455
+ for (const updater of list) {
456
+ let d = clone(self[internalDataSymbol].getRealSubject()['options']);
457
+ Object.assign(updater.getSubject(), d);
458
+ }
459
+ }
460
+
461
+ }));
462
+
463
+ }
464
+
363
465
  /**
364
466
  * @private
365
467
  * @return {object}
@@ -368,11 +470,24 @@ class CustomElement extends HTMLElement {
368
470
  function getOptionsFromAttributes() {
369
471
  if (this.hasAttribute(ATTRIBUTE_OPTIONS)) {
370
472
  try {
371
- let obj = JSON.parse(this.getAttribute(ATTRIBUTE_OPTIONS))
473
+ return parseOptionsJSON(this.getAttribute(ATTRIBUTE_OPTIONS))
474
+ } catch (e) {
475
+ throw new Error('the options attribute ' + ATTRIBUTE_OPTIONS + ' does not contain a valid json definition (actual: ' + this.getAttribute(ATTRIBUTE_OPTIONS) + ').');
476
+ }
477
+ }
478
+
479
+ return {};
480
+ }
481
+
482
+
483
+ function parseOptionsJSON(data) {
484
+ if (isString(data)) {
485
+ try {
486
+ let obj = JSON.parse(data);
372
487
  validateObject(obj);
373
488
  return obj;
374
489
  } catch (e) {
375
- throw new Error('the options attribute ' + ATTRIBUTE_OPTIONS + ' does not contain a valid json definition (actual: ' + this.getAttribute(ATTRIBUTE_OPTIONS) + ').');
490
+ throw new Error('the options does not contain a valid json definition (actual: ' + data + ').');
376
491
  }
377
492
  }
378
493
 
@@ -458,5 +573,5 @@ function registerCustomElement(element) {
458
573
  getGlobalObject('customElements').define(element.getTag(), element);
459
574
  }
460
575
 
461
- Monster.assignToNamespace('Monster.DOM', CustomElement, registerCustomElement);
576
+ assignToNamespace('Monster.DOM', CustomElement, registerCustomElement);
462
577
  export {Monster, registerCustomElement, CustomElement, initMethodSymbol, assembleMethodSymbol}