@schukai/monster 1.12.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/CHANGELOG +40 -1
  2. package/README.md +5 -5
  3. package/dist/modules/constants.js +2 -0
  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 -0
  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 -0
  33. package/dist/modules/i18n/namespace.js +2 -0
  34. package/dist/modules/i18n/provider.js +2 -0
  35. package/dist/modules/i18n/providers/fetch.js +2 -0
  36. package/dist/modules/i18n/providers/namespace.js +2 -0
  37. package/dist/modules/i18n/translations.js +2 -0
  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 +1 -1
  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 -0
  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 +8692 -6669
  72. package/dist/monster.dev.js.map +1 -1
  73. package/dist/monster.js +3 -3
  74. package/package.json +1 -1
  75. package/source/constants.js +22 -0
  76. package/source/constraints/abstract.js +2 -2
  77. package/source/constraints/abstractoperator.js +3 -3
  78. package/source/constraints/andoperator.js +7 -7
  79. package/source/constraints/invalid.js +6 -6
  80. package/source/constraints/isarray.js +6 -6
  81. package/source/constraints/isobject.js +6 -6
  82. package/source/constraints/namespace.js +2 -0
  83. package/source/constraints/oroperator.js +8 -8
  84. package/source/constraints/valid.js +6 -6
  85. package/source/data/buildmap.js +15 -15
  86. package/source/data/diff.js +6 -6
  87. package/source/data/extend.js +55 -13
  88. package/source/data/namespace.js +2 -0
  89. package/source/data/pathfinder.js +6 -7
  90. package/source/data/pipe.js +5 -5
  91. package/source/data/transformer.js +6 -6
  92. package/source/dom/assembler.js +5 -5
  93. package/source/dom/attributes.js +89 -45
  94. package/source/dom/constants.js +8 -9
  95. package/source/dom/customcontrol.js +301 -0
  96. package/source/dom/customelement.js +149 -31
  97. package/source/dom/events.js +58 -8
  98. package/source/dom/locale.js +59 -0
  99. package/source/dom/namespace.js +2 -0
  100. package/source/dom/template.js +7 -7
  101. package/source/dom/theme.js +6 -6
  102. package/source/dom/updater.js +38 -11
  103. package/source/dom/util.js +10 -10
  104. package/source/i18n/locale.js +322 -0
  105. package/source/i18n/namespace.js +15 -0
  106. package/source/i18n/provider.js +58 -0
  107. package/source/i18n/providers/fetch.js +121 -0
  108. package/source/i18n/providers/namespace.js +15 -0
  109. package/source/i18n/translations.js +209 -0
  110. package/source/logging/handler/console.js +4 -4
  111. package/source/logging/handler.js +4 -4
  112. package/source/logging/logentry.js +4 -4
  113. package/source/logging/logger.js +4 -4
  114. package/source/logging/namespace.js +2 -0
  115. package/source/math/namespace.js +2 -0
  116. package/source/math/random.js +5 -5
  117. package/source/monster.js +26 -16
  118. package/source/namespace.js +10 -8
  119. package/source/text/formatter.js +4 -5
  120. package/source/text/namespace.js +1 -1
  121. package/source/types/base.js +4 -7
  122. package/source/types/basewithoptions.js +97 -0
  123. package/source/types/global.js +6 -6
  124. package/source/types/id.js +6 -6
  125. package/source/types/is.js +22 -22
  126. package/source/types/namespace.js +3 -1
  127. package/source/types/observer.js +5 -5
  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 +5 -5
  132. package/source/types/stack.js +11 -4
  133. package/source/types/tokenlist.js +4 -4
  134. package/source/types/typeof.js +5 -5
  135. package/source/types/uniquequeue.js +11 -4
  136. package/source/types/validate.js +22 -22
  137. package/source/types/version.js +9 -9
  138. package/source/util/clone.js +4 -4
  139. package/source/util/comparator.js +6 -6
  140. package/source/util/freeze.js +4 -4
  141. package/source/util/namespace.js +2 -0
  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/locale.js +44 -0
  148. package/test/cases/i18n/locale.js +80 -0
  149. package/test/cases/i18n/provider.js +15 -0
  150. package/test/cases/i18n/providers/fetch.js +65 -0
  151. package/test/cases/i18n/translations.js +57 -0
  152. package/test/cases/monster.js +3 -1
  153. package/test/cases/{util → text}/formatter.js +2 -0
  154. package/test/cases/types/basewithoptions.js +25 -0
  155. package/test/cases/types/proxyobserver.js +9 -0
  156. package/test/cases/{text → util}/clone.js +0 -0
  157. package/test/cases/{text → util}/comparator.js +0 -0
  158. package/test/util/jsdom.js +4 -0
  159. package/test/web/import.js +10 -3
  160. package/test/web/monster-dev.html +3 -3
  161. package/test/web/monster.html +3 -3
  162. package/test/web/test.html +3 -3
  163. package/test/web/tests.js +3 -3
@@ -0,0 +1,301 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * @author schukai GmbH
5
+ */
6
+ import {Monster, assignToNamespace} from '../namespace.js';
7
+ import {extend} from "../data/extend.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.0/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.0/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
+ * | option | description |
69
+ * |----------------|---------------------------------|
70
+ * | | |
71
+ *
72
+ * Derived classes can override and extend this method as follows.
73
+ *
74
+ * ```
75
+ * get defaults() {
76
+ * return extends{}, super.defaults, {
77
+ * myValue:true
78
+ * });
79
+ * }
80
+ * ```
81
+ *
82
+ * @see https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-face-example
83
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals
84
+ * @return {object}
85
+ * @since 1.14.0
86
+ */
87
+ get defaults() {
88
+ return extend({}, super.defaults);
89
+ }
90
+
91
+ /**
92
+ *
93
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals
94
+ * @since 1.14.0
95
+ * @return {boolean}
96
+ */
97
+ static get formAssociated() {
98
+ return true;
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
+ * ```
130
+ * // Use the control's name as the base name for submitted data
131
+ * const n = this.getAttribute('name');
132
+ * const entries = new FormData();
133
+ * entries.append(n + '-first-name', this.firstName_);
134
+ * entries.append(n + '-last-name', this.lastName_);
135
+ * this.setFormValue(entries);
136
+ * ```
137
+ *
138
+ * @param {File|string|FormData} value
139
+ * @param {File|string|FormData} state
140
+ * @since 1.14.0
141
+ * @return {undefined}
142
+ * @throws {DOMException} NotSupportedError
143
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
144
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setFormValue
145
+ */
146
+ setFormValue(value, state) {
147
+ getInternal.call(this).setFormValue(value, state);
148
+ }
149
+
150
+ /**
151
+ *
152
+ * @param {object} flags
153
+ * @param {string|undefined} message
154
+ * @param {HTMLElement} anchor
155
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setValidity
156
+ * @since 1.14.0
157
+ * @return {undefined}
158
+ * @throws {DOMException} NotSupportedError
159
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
160
+ */
161
+ setValidity(flags, message, anchor) {
162
+ getInternal.call(this).setValidity(flags, message, anchor);
163
+ }
164
+
165
+
166
+ /**
167
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
168
+ *
169
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/checkValidity
170
+ * @since 1.14.0
171
+ * @return {boolean}
172
+ * @throws {DOMException} NotSupportedError
173
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
174
+ */
175
+ checkValidity() {
176
+ return getInternal.call(this)?.checkValidity();
177
+ }
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/reportValidity
186
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
187
+ * @throws {DOMException} NotSupportedError
188
+ */
189
+ reportValidity() {
190
+ return getInternal.call(this)?.reportValidity();
191
+ }
192
+
193
+ /**
194
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
195
+ *
196
+ * @return {NodeList}
197
+ * @since 1.14.0
198
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/labels
199
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
200
+ */
201
+ get labels() {
202
+ return getInternal.call(this)?.labels;
203
+ }
204
+
205
+ /**
206
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
207
+ *
208
+ * @return {string|null}
209
+ */
210
+ get name() {
211
+ return this.getAttribute('name');
212
+ }
213
+
214
+ /**
215
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
216
+ *
217
+ * @return {string}
218
+ */
219
+ get type() {
220
+ return this.constructor.getTag();
221
+ }
222
+
223
+ /**
224
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
225
+ *
226
+ * @return {ValidityState}
227
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
228
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ValidityState
229
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/validity
230
+ */
231
+ get validity() {
232
+ return getInternal.call(this)?.validity;
233
+ }
234
+
235
+ /**
236
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
237
+ *
238
+ * @return {string}
239
+ * @since 1.14.0
240
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/validationMessage
241
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
242
+ */
243
+ get validationMessage() {
244
+ return getInternal.call(this)?.validationMessage;
245
+ }
246
+
247
+ /**
248
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
249
+ *
250
+ * @return {boolean}
251
+ * @since 1.14.0
252
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/willValidate
253
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
254
+ */
255
+ get willValidate() {
256
+ return getInternal.call(this)?.willValidate;
257
+ }
258
+
259
+ /**
260
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
261
+ *
262
+ * @return {CustomStateSet}
263
+ * @since 1.14.0
264
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/states
265
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
266
+ */
267
+ get states() {
268
+ return getInternal.call(this)?.states;
269
+ }
270
+
271
+ /**
272
+ * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
273
+ *
274
+ * @return {HTMLFontElement|null}
275
+ * @since 1.14.0
276
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/form
277
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
278
+ */
279
+ get form() {
280
+ return getInternal.call(this)?.form;
281
+ }
282
+
283
+ }
284
+
285
+ /**
286
+ * @private
287
+ * @return {object}
288
+ * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
289
+ */
290
+ function getInternal() {
291
+ const self = this;
292
+
293
+ if (!(internalSymbol in this)) {
294
+ throw new Error('ElementInternals is not supported and a polyfill is necessary');
295
+ }
296
+
297
+ return this[internalSymbol];
298
+ }
299
+
300
+ assignToNamespace('Monster.DOM', CustomControl);
301
+ export {Monster, CustomControl}
@@ -3,23 +3,27 @@
3
3
  /**
4
4
  * @author schukai GmbH
5
5
  */
6
-
7
- import {Monster, Updater} from "./updater.js";
6
+ import {Monster, assignToNamespace} from '../namespace.js';
7
+ import {Observer} from "../types/observer.js";
8
+ import {ProxyObserver} from "../types/proxyobserver.js";
9
+ import { Updater} from "./updater.js";
8
10
  import {extend} from "../data/extend.js";
11
+ import {clone} from "../util/clone.js";
9
12
  import {Pathfinder} from "../data/pathfinder.js";
10
- import {ATTRIBUTE_OPTIONS, OBJECTLINK_KEY_OPTIONS, OBJECTLINK_KEY_UPDATER} from "./constants.js";
13
+ import {ATTRIBUTE_OPTIONS, OBJECTLINK_KEY_UPDATER} from "./constants.js";
11
14
  import {findDocumentTemplate, Template} from "./template.js";
12
- import {addToObjectLink, hasObjectLink} from "./attributes.js";
15
+ import {addToObjectLink, getLinkedObjects, hasObjectLink} from "./attributes.js";
13
16
  import {getGlobalObject} from "../types/global.js";
14
17
  import {validateFunction, validateObject} from "../types/validate.js";
15
18
  import {isString} from "../types/is.js";
16
- import {getDocument} from "./util.js";
19
+ import {PROPERTY_KEY_INTERNALDATA} from "../constants.js";
17
20
 
18
21
  /**
19
22
  * @private
20
23
  * @type {symbol}
21
24
  */
22
- const optionsSymbol = Symbol.for(OBJECTLINK_KEY_OPTIONS);
25
+ const internalDataSymbol = Symbol.for(PROPERTY_KEY_INTERNALDATA);
26
+
23
27
  /**
24
28
  * @private
25
29
  * @type {symbol}
@@ -36,12 +40,6 @@ const initMethodSymbol = Symbol('initMethodSymbol');
36
40
  */
37
41
  const assembleMethodSymbol = Symbol('assembleMethodSymbol');
38
42
 
39
- /**
40
- * @private
41
- * @type {Document}
42
- */
43
- const document = getDocument();
44
-
45
43
  /**
46
44
  * To define a new HTML element we need the power of CustomElement
47
45
  *
@@ -52,7 +50,7 @@ const document = getDocument();
52
50
  *
53
51
  * ```
54
52
  * <script type="module">
55
- * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.12.0/dist/modules/dom/customelement.js';
53
+ * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.15.0/dist/modules/dom/customelement.js';
56
54
  * console.log(new Monster.DOM.CustomElement())
57
55
  * </script>
58
56
  * ```
@@ -61,7 +59,7 @@ const document = getDocument();
61
59
  *
62
60
  * ```
63
61
  * <script type="module">
64
- * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.12.0/dist/modules/dom/customelement.js';
62
+ * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.15.0/dist/modules/dom/customelement.js';
65
63
  * console.log(new CustomElement())
66
64
  * </script>
67
65
  * ```
@@ -159,15 +157,47 @@ class CustomElement extends HTMLElement {
159
157
  */
160
158
  constructor() {
161
159
  super();
162
- this[optionsSymbol] = extend({}, this.defaults, getOptionsFromAttributes.call(this));
160
+ this[internalDataSymbol] = new ProxyObserver({'options': extend({}, this.defaults, getOptionsFromAttributes.call(this))});
161
+ initOptionObserver.call(this);
163
162
  this[initMethodSymbol]();
164
163
  }
165
164
 
165
+ /**
166
+ * attach a new observer
167
+ *
168
+ * @param {Observer} observer
169
+ * @returns {CustomElement}
170
+ */
171
+ attachObserver(observer) {
172
+ this[internalDataSymbol].attachObserver(observer)
173
+ return this;
174
+ }
175
+
176
+ /**
177
+ * detach a observer
178
+ *
179
+ * @param {Observer} observer
180
+ * @returns {CustomElement}
181
+ */
182
+ detachObserver(observer) {
183
+ this[internalDataSymbol].detachObserver(observer)
184
+ return this;
185
+ }
186
+
187
+ /**
188
+ * @param {Observer} observer
189
+ * @returns {ProxyObserver}
190
+ */
191
+ containsObserver(observer) {
192
+ return this[internalDataSymbol].containsObserver(observer)
193
+ }
194
+
166
195
  /**
167
196
  * | option | description |
168
197
  * |----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
169
198
  * | shadowMode | `open` Elements of the shadow root are accessible from JavaScript outside the root, for example using. `close` Denies access to the node(s) of a closed shadow root from JavaScript outside it |
170
199
  * | delegatesFocus | A boolean that, when set to true, specifies behavior that mitigates custom element issues around focusability. When a non-focusable part of the shadow DOM is clicked, the first focusable part is given focus, and the shadow host is given any available :focus styling. |
200
+ * | templates.main | Main template |
171
201
  *
172
202
  * Derived classes can override and extend this method as follows.
173
203
  *
@@ -205,7 +235,7 @@ class CustomElement extends HTMLElement {
205
235
  let value;
206
236
 
207
237
  try {
208
- value = new Pathfinder(this[optionsSymbol]).getVia(path);
238
+ value = new Pathfinder(this[internalDataSymbol].getRealSubject()['options']).getVia(path);
209
239
  } catch (e) {
210
240
 
211
241
  }
@@ -214,6 +244,38 @@ class CustomElement extends HTMLElement {
214
244
  return value;
215
245
  }
216
246
 
247
+ /**
248
+ * Set option and inform elements
249
+ *
250
+ * @param {string} path
251
+ * @param {*} value
252
+ * @return {CustomElement}
253
+ * @since 1.14.0
254
+ */
255
+ setOption(path, value) {
256
+ new Pathfinder(this[internalDataSymbol].getSubject()['options']).setVia(path, value);
257
+ //this[internalDataSymbol].notifyObservers();
258
+ return this;
259
+ }
260
+
261
+ /**
262
+ * @since 1.15.0
263
+ * @param {string|object} options
264
+ * @return {CustomElement}
265
+ */
266
+ setOptions(options) {
267
+
268
+ if (isString(options)) {
269
+ options = parseOptionsJSON(options)
270
+ }
271
+
272
+ const self = this;
273
+ extend(self[internalDataSymbol].getSubject()['options'], self.defaults, options);
274
+ //this[internalDataSymbol].notifyObservers();
275
+
276
+ return self;
277
+ }
278
+
217
279
  /**
218
280
  *
219
281
  * @return {CustomElement}
@@ -253,8 +315,8 @@ class CustomElement extends HTMLElement {
253
315
  for (const [, element] of Object.entries(elements)) {
254
316
 
255
317
  if (!(element instanceof HTMLElement)) continue;
256
-
257
- const u = new Updater(element, this[optionsSymbol])
318
+ if ((element instanceof HTMLTemplateElement)) continue;
319
+ const u = new Updater(element, clone(self[internalDataSymbol].getRealSubject()['options']))
258
320
  updater.add(u);
259
321
 
260
322
  u.run().then(() => {
@@ -263,7 +325,6 @@ class CustomElement extends HTMLElement {
263
325
 
264
326
  }
265
327
 
266
-
267
328
  return this;
268
329
  }
269
330
 
@@ -303,22 +364,39 @@ class CustomElement extends HTMLElement {
303
364
 
304
365
  }
305
366
 
367
+ /**
368
+ * This method determines which attributes are to be monitored by `attributeChangedCallback()`.
369
+ *
370
+ * @return {string[]}
371
+ * @since 1.15.0
372
+ */
373
+ static get observedAttributes() {
374
+ return [ATTRIBUTE_OPTIONS];
375
+ }
376
+
306
377
  /**
307
378
  * Called when an observed attribute has been added, removed, updated, or replaced. Also called for initial
308
- * values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes property will receive this callback.
379
+ * values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes
380
+ * property will receive this callback.
309
381
  *
310
382
  * @param {string} attrName
311
383
  * @param {string} oldVal
312
384
  * @param {string} newVal
313
385
  * @return {void}
314
- * @since 1.7.0
386
+ * @since 1.15.0
315
387
  */
316
388
  attributeChangedCallback(attrName, oldVal, newVal) {
389
+ const self = this;
390
+
391
+ if (attrName === ATTRIBUTE_OPTIONS) {
392
+ self.setOptions(newVal);
393
+ }
394
+
317
395
  }
318
396
 
319
397
  /**
320
398
  * There is no check on the name by this class. the developer is responsible for assigning an appropriate tag.
321
- * if the name is not valid, registerCustomElement() will issue an erro
399
+ * if the name is not valid, registerCustomElement() will issue an error
322
400
  *
323
401
  * @link https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
324
402
  * @return {string}
@@ -330,25 +408,25 @@ class CustomElement extends HTMLElement {
330
408
  }
331
409
 
332
410
  /**
333
- * At this point a `CSSStyleSheet` object can be returned. If the environment does not
411
+ * At this point a `CSSStyleSheet` object can be returned. If the environment does not
334
412
  * support a constructor, then an object can also be built using the following detour.
335
- *
413
+ *
336
414
  * If `undefined` is returned then the shadowRoot does not get a stylesheet.
337
415
  *
338
416
  * ```
339
417
  * const doc = document.implementation.createHTMLDocument('title');
340
- *
418
+ *
341
419
  * let style = doc.createElement("style");
342
420
  * style.innerHTML="p{color:red;}";
343
- *
421
+ *
344
422
  * // WebKit Hack
345
423
  * style.appendChild(document.createTextNode(""));
346
424
  * // Add the <style> element to the page
347
425
  * doc.head.appendChild(style);
348
426
  * return doc.styleSheets[0];
349
- * ;
427
+ * ;
350
428
  * ```
351
- *
429
+ *
352
430
  * @return {CSSStyleSheet|undefined}
353
431
  */
354
432
  static getCSSStyleSheet() {
@@ -357,6 +435,33 @@ class CustomElement extends HTMLElement {
357
435
 
358
436
  }
359
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
+
360
465
  /**
361
466
  * @private
362
467
  * @return {object}
@@ -365,11 +470,24 @@ class CustomElement extends HTMLElement {
365
470
  function getOptionsFromAttributes() {
366
471
  if (this.hasAttribute(ATTRIBUTE_OPTIONS)) {
367
472
  try {
368
- 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);
369
487
  validateObject(obj);
370
488
  return obj;
371
489
  } catch (e) {
372
- 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 + ').');
373
491
  }
374
492
  }
375
493
 
@@ -455,5 +573,5 @@ function registerCustomElement(element) {
455
573
  getGlobalObject('customElements').define(element.getTag(), element);
456
574
  }
457
575
 
458
- Monster.assignToNamespace('Monster.DOM', CustomElement, registerCustomElement);
576
+ assignToNamespace('Monster.DOM', CustomElement, registerCustomElement);
459
577
  export {Monster, registerCustomElement, CustomElement, initMethodSymbol, assembleMethodSymbol}