@schukai/monster 1.14.0 → 1.15.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. package/CHANGELOG +38 -0
  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 +1 -1
  23. package/dist/modules/dom/customcontrol.js +2 -2
  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 +8263 -7501
  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 +6 -5
  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 +10 -11
  92. package/source/dom/assembler.js +7 -7
  93. package/source/dom/attributes.js +27 -28
  94. package/source/dom/constants.js +1 -2
  95. package/source/dom/customcontrol.js +90 -128
  96. package/source/dom/customelement.js +166 -71
  97. package/source/dom/events.js +9 -9
  98. package/source/dom/locale.js +5 -5
  99. package/source/dom/namespace.js +2 -2
  100. package/source/dom/template.js +30 -19
  101. package/source/dom/theme.js +8 -9
  102. package/source/dom/updater.js +43 -26
  103. package/source/dom/util.js +11 -11
  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/customcontrol.js +17 -3
  144. package/test/cases/dom/customelement.js +65 -7
  145. package/test/cases/dom/template.js +40 -1
  146. package/test/cases/monster.js +1 -1
  147. package/test/cases/types/proxyobserver.js +9 -0
  148. package/test/web/monster-dev.html +3 -3
  149. package/test/web/monster.html +2 -2
  150. package/test/web/test.html +3 -3
  151. package/test/web/tests.js +3 -3
@@ -1,13 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ import {extend} from "../data/extend.js";
3
4
  /**
4
5
  * @author schukai GmbH
5
6
  */
6
-
7
- import {extend} from "../data/extend.js";
8
- import {isArray} from "../types/is.js";
9
- import {OBJECTLINK_KEY_UPDATER} from "./constants.js";
10
- import {Monster, CustomElement} from "./customelement.js";
7
+ import {assignToNamespace, Monster} from '../namespace.js';
8
+ import {CustomElement} from "./customelement.js";
11
9
 
12
10
 
13
11
  /**
@@ -29,7 +27,7 @@ const internalSymbol = Symbol('internalSymbol');
29
27
  *
30
28
  * ```
31
29
  * <script type="module">
32
- * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.14.0/dist/modules/dom/customcontrol.js';
30
+ * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.15.3/dist/modules/dom/customcontrol.js';
33
31
  * console.log(new Monster.DOM.CustomControl())
34
32
  * </script>
35
33
  * ```
@@ -38,7 +36,7 @@ const internalSymbol = Symbol('internalSymbol');
38
36
  *
39
37
  * ```
40
38
  * <script type="module">
41
- * import {CustomControl} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.14.0/dist/modules/dom/customcontrol.js';
39
+ * import {CustomControl} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.15.3/dist/modules/dom/customcontrol.js';
42
40
  * console.log(new CustomControl())
43
41
  * </script>
44
42
  * ```
@@ -59,7 +57,7 @@ class CustomControl extends CustomElement {
59
57
  constructor() {
60
58
  super();
61
59
 
62
- if (typeof this['attachInternals'] === 'function' && this.getOption('formAssociated') === true) {
60
+ if (typeof this['attachInternals'] === 'function') {
63
61
  // currently only supported by chrome
64
62
  this[internalSymbol] = this.attachInternals();
65
63
  }
@@ -67,15 +65,25 @@ class CustomControl extends CustomElement {
67
65
  }
68
66
 
69
67
  /**
70
- * | option | description |
71
- * |----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
72
- * | formAssociated | Adding a static formAssociated property, with a true value, makes an autonomous custom element a form-associated custom element. |
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
+ * | | |
73
81
  *
74
82
  * Derived classes can override and extend this method as follows.
75
83
  *
76
84
  * ```
77
85
  * get defaults() {
78
- * return Object.assign({}, super.defaults, {
86
+ * return extends{}, super.defaults, {
79
87
  * myValue:true
80
88
  * });
81
89
  * }
@@ -83,55 +91,11 @@ class CustomControl extends CustomElement {
83
91
  *
84
92
  * @see https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-face-example
85
93
  * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals
86
- * @return {{shadowMode: string, delegatesFocus: boolean}}
94
+ * @return {object}
87
95
  * @since 1.14.0
88
96
  */
89
97
  get defaults() {
90
-
91
- return Object.assign({}, super.defaults, {
92
- formAssociated: true
93
- });
94
-
95
- }
96
-
97
- /**
98
- * This method determines which attributes are to be monitored by `attributeChangedCallback()`.
99
- *
100
- * @return {string[]}
101
- * @since 1.14.0
102
- */
103
- static get observedAttributes() {
104
- return [];
105
- }
106
-
107
- /**
108
- * This method can be implemented in a derived class. The attributes must be defined in `observedAttributes()`.
109
- *
110
- * @param {string} name
111
- * @param {string} oldValue
112
- * @param {string} newValue
113
- * @since 1.14.0
114
- * @throws {Error} attributes but no handles have been defined
115
- */
116
- attributeChangedCallback(name, oldValue, newValue) {
117
-
118
- const a = this.constructor.observedAttributes();
119
-
120
- if (!a || (isArray(a) && a.length > 0)) {
121
- throw new Error('attributes but no handles have been defined');
122
- }
123
-
124
-
125
- }
126
-
127
- /**
128
- *
129
- * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals
130
- * @since 1.14.0
131
- * @return {boolean}
132
- */
133
- static get formAssociated() {
134
- return true;
98
+ return extend({}, super.defaults);
135
99
  }
136
100
 
137
101
  /**
@@ -159,73 +123,6 @@ class CustomControl extends CustomElement {
159
123
  throw Error('the value setter must be overwritten by the derived class');
160
124
  }
161
125
 
162
- /**
163
- * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
164
- *
165
- * ```
166
- * // Use the control's name as the base name for submitted data
167
- * const n = this.getAttribute('name');
168
- * const entries = new FormData();
169
- * entries.append(n + '-first-name', this.firstName_);
170
- * entries.append(n + '-last-name', this.lastName_);
171
- * this.setFormValue(entries);
172
- * ```
173
- *
174
- * @param {File|string|FormData} value
175
- * @param {File|string|FormData} state
176
- * @since 1.14.0
177
- * @return {undefined}
178
- * @throws {DOMException} NotSupportedError
179
- * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
180
- * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setFormValue
181
- */
182
- setFormValue(value, state) {
183
- getInternal.call(this).setFormValue(value, state);
184
- }
185
-
186
- /**
187
- *
188
- * @param {object} flags
189
- * @param {string|undefined} message
190
- * @param {HTMLElement} anchor
191
- * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setValidity
192
- * @since 1.14.0
193
- * @return {undefined}
194
- * @throws {DOMException} NotSupportedError
195
- * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
196
- */
197
- setValidity(flags, message, anchor) {
198
- getInternal.call(this).setValidity(flags, message, anchor);
199
- }
200
-
201
-
202
- /**
203
- * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
204
- *
205
- * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/checkValidity
206
- * @since 1.14.0
207
- * @return {boolean}
208
- * @throws {DOMException} NotSupportedError
209
- * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
210
- */
211
- checkValidity() {
212
- return getInternal.call(this)?.checkValidity();
213
- }
214
-
215
-
216
- /**
217
- * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
218
- *
219
- * @return {boolean}
220
- * @since 1.14.0
221
- * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/reportValidity
222
- * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
223
- * @throws {DOMException} NotSupportedError
224
- */
225
- reportValidity() {
226
- return getInternal.call(this)?.reportValidity();
227
- }
228
-
229
126
  /**
230
127
  * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
231
128
  *
@@ -316,6 +213,71 @@ class CustomControl extends CustomElement {
316
213
  return getInternal.call(this)?.form;
317
214
  }
318
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
+
319
281
  }
320
282
 
321
283
  /**
@@ -325,13 +287,13 @@ class CustomControl extends CustomElement {
325
287
  */
326
288
  function getInternal() {
327
289
  const self = this;
328
-
290
+
329
291
  if (!(internalSymbol in this)) {
330
- throw new Error('the ElementInternals is not supported and a polyfill is necessary');
292
+ throw new Error('ElementInternals is not supported and a polyfill is necessary');
331
293
  }
332
294
 
333
295
  return this[internalSymbol];
334
296
  }
335
297
 
336
- Monster.assignToNamespace('Monster.DOM', CustomControl);
298
+ assignToNamespace('Monster.DOM', CustomControl);
337
299
  export {Monster, CustomControl}
@@ -1,25 +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,getLinkedObjects, 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 {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";
17
20
 
18
21
  /**
19
22
  * @private
20
23
  * @type {symbol}
21
24
  */
22
- const optionsSymbol = Symbol.for(PROPERTY_KEY_OPTIONS);
25
+ const internalDataSymbol = Symbol.for(PROPERTY_KEY_INTERNALDATA);
23
26
 
24
27
  /**
25
28
  * @private
@@ -37,7 +40,6 @@ const initMethodSymbol = Symbol('initMethodSymbol');
37
40
  */
38
41
  const assembleMethodSymbol = Symbol('assembleMethodSymbol');
39
42
 
40
-
41
43
  /**
42
44
  * To define a new HTML element we need the power of CustomElement
43
45
  *
@@ -48,7 +50,7 @@ const assembleMethodSymbol = Symbol('assembleMethodSymbol');
48
50
  *
49
51
  * ```
50
52
  * <script type="module">
51
- * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.14.0/dist/modules/dom/customelement.js';
53
+ * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.15.3/dist/modules/dom/customelement.js';
52
54
  * console.log(new Monster.DOM.CustomElement())
53
55
  * </script>
54
56
  * ```
@@ -57,7 +59,7 @@ const assembleMethodSymbol = Symbol('assembleMethodSymbol');
57
59
  *
58
60
  * ```
59
61
  * <script type="module">
60
- * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.14.0/dist/modules/dom/customelement.js';
62
+ * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.15.3/dist/modules/dom/customelement.js';
61
63
  * console.log(new CustomElement())
62
64
  * </script>
63
65
  * ```
@@ -155,10 +157,21 @@ class CustomElement extends HTMLElement {
155
157
  */
156
158
  constructor() {
157
159
  super();
158
- this[optionsSymbol] = extend({}, this.defaults, getOptionsFromAttributes.call(this));
160
+ this[internalDataSymbol] = new ProxyObserver({'options': extend({}, this.defaults, getOptionsFromAttributes.call(this))});
161
+ initOptionObserver.call(this);
159
162
  this[initMethodSymbol]();
160
163
  }
161
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
+
162
175
  /**
163
176
  * | option | description |
164
177
  * |----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -190,6 +203,75 @@ class CustomElement extends HTMLElement {
190
203
  };
191
204
  }
192
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
+
193
275
  /**
194
276
  * nested options can be specified by path `a.b.c`
195
277
  *
@@ -202,7 +284,7 @@ class CustomElement extends HTMLElement {
202
284
  let value;
203
285
 
204
286
  try {
205
- value = new Pathfinder(this[optionsSymbol]).getVia(path);
287
+ value = new Pathfinder(this[internalDataSymbol].getRealSubject()['options']).getVia(path);
206
288
  } catch (e) {
207
289
 
208
290
  }
@@ -220,20 +302,27 @@ class CustomElement extends HTMLElement {
220
302
  * @since 1.14.0
221
303
  */
222
304
  setOption(path, value) {
305
+ new Pathfinder(this[internalDataSymbol].getSubject()['options']).setVia(path, value);
306
+ //this[internalDataSymbol].notifyObservers();
307
+ return this;
308
+ }
223
309
 
224
- // inform every element
225
- const updaters = getLinkedObjects(this, Symbol.for(OBJECTLINK_KEY_UPDATER));
310
+ /**
311
+ * @since 1.15.0
312
+ * @param {string|object} options
313
+ * @return {CustomElement}
314
+ */
315
+ setOptions(options) {
226
316
 
227
- for (const list of updaters) {
228
- for (const updater of list) {
229
- // reset value so that a change occurs
230
- new Pathfinder(this[optionsSymbol]).setVia(path, false);
231
- new Pathfinder(updater.getSubject()).setVia(path, value);
232
- }
317
+ if (isString(options)) {
318
+ options = parseOptionsJSON(options)
233
319
  }
234
320
 
235
- return this;
321
+ const self = this;
322
+ extend(self[internalDataSymbol].getSubject()['options'], self.defaults, options);
323
+ //this[internalDataSymbol].notifyObservers();
236
324
 
325
+ return self;
237
326
  }
238
327
 
239
328
  /**
@@ -275,8 +364,8 @@ class CustomElement extends HTMLElement {
275
364
  for (const [, element] of Object.entries(elements)) {
276
365
 
277
366
  if (!(element instanceof HTMLElement)) continue;
278
-
279
- const u = new Updater(element, this[optionsSymbol])
367
+ if ((element instanceof HTMLTemplateElement)) continue;
368
+ const u = new Updater(element, clone(self[internalDataSymbol].getRealSubject()['options']))
280
369
  updater.add(u);
281
370
 
282
371
  u.run().then(() => {
@@ -298,9 +387,7 @@ class CustomElement extends HTMLElement {
298
387
  connectedCallback() {
299
388
  let self = this;
300
389
  if (!hasObjectLink(self, objectLinkSymbol)) {
301
- setTimeout(() => {
302
- self[assembleMethodSymbol]()
303
- }, 0);
390
+ self[assembleMethodSymbol]()
304
391
  }
305
392
  }
306
393
 
@@ -326,58 +413,53 @@ class CustomElement extends HTMLElement {
326
413
 
327
414
  /**
328
415
  * Called when an observed attribute has been added, removed, updated, or replaced. Also called for initial
329
- * values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes property will receive this callback.
416
+ * values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes
417
+ * property will receive this callback.
330
418
  *
331
419
  * @param {string} attrName
332
420
  * @param {string} oldVal
333
421
  * @param {string} newVal
334
422
  * @return {void}
335
- * @since 1.7.0
423
+ * @since 1.15.0
336
424
  */
337
425
  attributeChangedCallback(attrName, oldVal, newVal) {
338
- }
426
+ const self = this;
339
427
 
340
- /**
341
- * There is no check on the name by this class. the developer is responsible for assigning an appropriate tag.
342
- * if the name is not valid, registerCustomElement() will issue an erro
343
- *
344
- * @link https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
345
- * @return {string}
346
- * @throws {Error} the method getTag must be overwritten by the derived class.
347
- * @since 1.7.0
348
- */
349
- static getTag() {
350
- throw new Error("the method getTag must be overwritten by the derived class.");
351
- }
428
+ if (attrName === ATTRIBUTE_OPTIONS) {
429
+ self.setOptions(newVal);
430
+ }
352
431
 
353
- /**
354
- * At this point a `CSSStyleSheet` object can be returned. If the environment does not
355
- * support a constructor, then an object can also be built using the following detour.
356
- *
357
- * If `undefined` is returned then the shadowRoot does not get a stylesheet.
358
- *
359
- * ```
360
- * const doc = document.implementation.createHTMLDocument('title');
361
- *
362
- * let style = doc.createElement("style");
363
- * style.innerHTML="p{color:red;}";
364
- *
365
- * // WebKit Hack
366
- * style.appendChild(document.createTextNode(""));
367
- * // Add the <style> element to the page
368
- * doc.head.appendChild(style);
369
- * return doc.styleSheets[0];
370
- * ;
371
- * ```
372
- *
373
- * @return {CSSStyleSheet|undefined}
374
- */
375
- static getCSSStyleSheet() {
376
- return undefined;
377
432
  }
378
433
 
379
434
  }
380
435
 
436
+ /**
437
+ * @since 1.15.0
438
+ * @private
439
+ */
440
+ function initOptionObserver() {
441
+ const self = this;
442
+
443
+ self.attachObserver(new Observer(function () {
444
+
445
+ // not initialised
446
+ if (!hasObjectLink(self, Symbol.for(OBJECTLINK_KEY_UPDATER))) {
447
+ return;
448
+ }
449
+ // inform every element
450
+ const updaters = getLinkedObjects(self, Symbol.for(OBJECTLINK_KEY_UPDATER));
451
+
452
+ for (const list of updaters) {
453
+ for (const updater of list) {
454
+ let d = clone(self[internalDataSymbol].getRealSubject()['options']);
455
+ Object.assign(updater.getSubject(), d);
456
+ }
457
+ }
458
+
459
+ }));
460
+
461
+ }
462
+
381
463
  /**
382
464
  * @private
383
465
  * @return {object}
@@ -386,11 +468,24 @@ class CustomElement extends HTMLElement {
386
468
  function getOptionsFromAttributes() {
387
469
  if (this.hasAttribute(ATTRIBUTE_OPTIONS)) {
388
470
  try {
389
- let obj = JSON.parse(this.getAttribute(ATTRIBUTE_OPTIONS))
471
+ return parseOptionsJSON(this.getAttribute(ATTRIBUTE_OPTIONS))
472
+ } catch (e) {
473
+ throw new Error('the options attribute ' + ATTRIBUTE_OPTIONS + ' does not contain a valid json definition (actual: ' + this.getAttribute(ATTRIBUTE_OPTIONS) + ').');
474
+ }
475
+ }
476
+
477
+ return {};
478
+ }
479
+
480
+
481
+ function parseOptionsJSON(data) {
482
+ if (isString(data)) {
483
+ try {
484
+ let obj = JSON.parse(data);
390
485
  validateObject(obj);
391
486
  return obj;
392
487
  } catch (e) {
393
- throw new Error('the options attribute ' + ATTRIBUTE_OPTIONS + ' does not contain a valid json definition (actual: ' + this.getAttribute(ATTRIBUTE_OPTIONS) + ').');
488
+ throw new Error('the options does not contain a valid json definition (actual: ' + data + ').');
394
489
  }
395
490
  }
396
491
 
@@ -476,5 +571,5 @@ function registerCustomElement(element) {
476
571
  getGlobalObject('customElements').define(element.getTag(), element);
477
572
  }
478
573
 
479
- Monster.assignToNamespace('Monster.DOM', CustomElement, registerCustomElement);
574
+ assignToNamespace('Monster.DOM', CustomElement, registerCustomElement);
480
575
  export {Monster, registerCustomElement, CustomElement, initMethodSymbol, assembleMethodSymbol}