decue 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/decue.js +56 -51
- package/dist/decue.min.js +1 -1
- package/examples.html +54 -0
- package/external.html +1 -0
- package/package.json +8 -4
- package/src/decue.js +56 -51
package/dist/decue.js
CHANGED
|
@@ -195,64 +195,67 @@ var decue = (function() {
|
|
|
195
195
|
throw `Invalid shadow DOM mode "${this._shadow}" for element "${elementName}". Must be one of "open", "closed" or "none".`;
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
198
|
+
if (!this._shadowRoot) {
|
|
199
|
+
this._shadowRoot = this._shadow === 'none' ? /** @type {HTMLElement} */ (this) : this.attachShadow({ mode: this._shadow, delegatesFocus: true });
|
|
200
|
+
|
|
201
|
+
const finalize = () => {
|
|
202
|
+
dbg('Finalizing...');
|
|
203
203
|
|
|
204
|
-
|
|
205
|
-
// Implement slotting manually when no shadow DOM in use
|
|
206
|
-
lightDOMSlotting(root, content);
|
|
207
|
-
dbg('Slots initialized');
|
|
208
|
-
}
|
|
204
|
+
const content = /** @type {DocumentFragment} */ (this._template.content.cloneNode(true));
|
|
209
205
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
206
|
+
if (this._shadow === 'none') {
|
|
207
|
+
// Implement slotting manually when no shadow DOM in use
|
|
208
|
+
lightDOMSlotting(this._shadowRoot, content);
|
|
209
|
+
dbg('Slots initialized');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// nodes having placeholder references, and thus need to be updated when attributes change.
|
|
213
|
+
/** @type {[Node,string,string][]} */
|
|
214
|
+
this._boundNodes = [];
|
|
215
|
+
|
|
216
|
+
// Find all placeholders in the attributes and text of template or element content.
|
|
217
|
+
[content, this].forEach(x =>
|
|
218
|
+
forEachPlaceholder(x, (node,attributeName,_) => this._boundNodes.push(node instanceof HTMLElement
|
|
219
|
+
? [node, node.getAttribute(attributeName), attributeName]
|
|
220
|
+
: [node, node.data, undefined])));
|
|
219
221
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
222
|
+
const ths = this;
|
|
223
|
+
// If there are attributes, which weren't yet observed statically, observe them dynamically with a MutationObserver.
|
|
224
|
+
const unobservedAttributes = this.getAttributeNames().filter(isNotBuiltinAttribute).filter(x => !observedAttrs.includes(x));
|
|
225
|
+
if (unobservedAttributes.length > 0 && this._boundNodes.length > 0) {
|
|
226
|
+
new MutationObserver(recs => recs.forEach(rec => {
|
|
227
|
+
if (unobservedAttributes.includes(rec.attributeName)) {
|
|
228
|
+
ths.attributeChangedCallback(rec.attributeName, rec.oldValue, (/** @type {HTMLElement} */ (rec.target)).getAttribute(rec.attributeName));
|
|
229
|
+
}
|
|
230
|
+
})).observe(this, { attributes: true });
|
|
231
|
+
this._decueMutationObserved = true;
|
|
232
|
+
if (debug) {
|
|
233
|
+
dbg('Observing attributes with MutationObserver: ' + unobservedAttributes.join(' '));
|
|
234
|
+
this.setAttribute('data-decue-mutation-observed-attributes', unobservedAttributes.join(' '));
|
|
227
235
|
}
|
|
228
|
-
})).observe(this, { attributes: true });
|
|
229
|
-
this._decueMutationObserved = true;
|
|
230
|
-
if (debug) {
|
|
231
|
-
dbg('Observing attributes with MutationObserver: ' + unobservedAttributes.join(' '));
|
|
232
|
-
this.setAttribute('data-decue-mutation-observed-attributes', unobservedAttributes.join(' '));
|
|
233
236
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
this._boundNodes.forEach(x => updatePlaceholders(ths, x));
|
|
237
|
+
if (debug && observedAttrs.length > 0) {
|
|
238
|
+
dbg('Observing attributes with observedAttributes: ' + observedAttrs.join(' '));
|
|
239
|
+
this.setAttribute('data-decue-observed-attributes', observedAttrs.join(' '));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
this._shadowRoot.append(content);
|
|
243
|
+
this._boundNodes.forEach(x => updatePlaceholders(ths, x));
|
|
242
244
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
+
fireEvent(this, 'connect');
|
|
246
|
+
};
|
|
245
247
|
|
|
246
|
-
|
|
247
|
-
finalize();
|
|
248
|
-
} else {
|
|
249
|
-
// predefined element. Finalize only after the children are parsed.
|
|
250
|
-
/** @type {MutationObserver} */
|
|
251
|
-
const observer = new MutationObserver(() => {
|
|
252
|
-
observer.disconnect();
|
|
248
|
+
if (template) {
|
|
253
249
|
finalize();
|
|
254
|
-
}
|
|
255
|
-
|
|
250
|
+
} else {
|
|
251
|
+
// predefined element. Finalize only after the children are parsed.
|
|
252
|
+
/** @type {MutationObserver} */
|
|
253
|
+
const observer = new MutationObserver(() => {
|
|
254
|
+
observer.disconnect();
|
|
255
|
+
finalize();
|
|
256
|
+
});
|
|
257
|
+
observer.observe(this.parentElement, { childList: true });
|
|
258
|
+
}
|
|
256
259
|
}
|
|
257
260
|
}
|
|
258
261
|
|
|
@@ -321,7 +324,9 @@ var decue = (function() {
|
|
|
321
324
|
.filter(obj => obj.getAttribute('type') === 'text/html')
|
|
322
325
|
.forEach(obj => {
|
|
323
326
|
obj.addEventListener('load', () => [...obj.contentDocument.getElementsByTagName('template')].forEach(processTemplate));
|
|
324
|
-
|
|
327
|
+
if (obj.contentDocument) {
|
|
328
|
+
[...obj.contentDocument.getElementsByTagName('template')].forEach(processTemplate);
|
|
329
|
+
}
|
|
325
330
|
});
|
|
326
331
|
});
|
|
327
332
|
|
package/dist/decue.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var decue=function(){const
|
|
1
|
+
var decue=function(){const o=document.currentScript.getAttribute("shadow")||"none";if(!["open","closed","none"].includes(o)){throw`Invalid default shadow DOM mode "${o}". Must be one of "open", "closed" or "none".`}const a=/{([a-zA-Z_0-9]+)((?:\|[.]?[a-zA-Z_0-9]+)*)}/g;const l=t=>!(t==="shadow"||t.startsWith("decue-"));const d=t=>{var e=t;while(e&&e.parentNode){if(e.parentNode===document){return true}else if(e.parentNode instanceof ShadowRoot){e=e.parentNode.host}else{e=e.parentNode}}return false};const n=i=>(t,e)=>{const o=e.startsWith(".")?e.substring(1):undefined;const s=window[e];if(!o&&!s){throw`Global function "${e}" not found. Make sure to include it (not deferred) before this element is created.`}return o?typeof t[o]==="function"?t[o]():t[o]:s.apply(i,[t])};const r=(s,i,t)=>t.replaceAll(a,(t,e,o)=>i.hasAttribute(e)?o.split("|").slice(1).reduce(n(s),i.getAttribute(e)):t);const c=(t,[e,o,s])=>{const i=r(e,t,o);if(e instanceof Text){if(i!==e.data){e.data=i}}else if(e instanceof HTMLElement){if(i!==e.getAttribute(s)){e.setAttribute(s,i)}}};const u=(t,o)=>{const e=document.createTreeWalker(t,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT);while(e.nextNode()){const s=e.currentNode;if(s instanceof Text){[...s.data.matchAll(a)].forEach(t=>o(s,undefined,t[1]))}else if(s instanceof HTMLElement){s.getAttributeNames().forEach(e=>[...s.getAttribute(e).matchAll(a)].forEach(t=>o(s,e,t[1])))}}};const h=(s,t)=>{t.querySelectorAll("slot[name]").forEach(t=>{const e=s.querySelectorAll(`:scope > [slot="${t.getAttribute("name")}"]`);const o=e.length>0?e:t.children;t.replaceWith.apply(t,o)});const e=t.querySelector("slot:not([name])");if(e){const o=[...s.childNodes].filter(t=>t.nodeType!==Node.ELEMENT_NODE||!t.hasAttribute("slot"));const i=o.length>0?o:e.children;e.replaceWith.apply(e,i)}};const s=(s,a,n,t,e)=>{const r=t=>s?console.log(a+": "+t):undefined;var i=e;if(n){u(n.content,(t,e,o)=>i.push(o))}i=[...new Set(i.filter(l))];window.customElements.define(a,class extends HTMLElement{static formAssociated=t;static observedAttributes=i;constructor(){super();this._template=n||[...document.getElementsByTagName("template")].find(t=>t.getAttribute("decue")===a);if(!this._template){throw`Template for "${a}" not found. Make sure it comes in the DOM before any corresponding custom element.`}if(!t&&this._template.hasAttribute("formAssociated")){throw`Cannot declare a predefined custom element "${a}" as formAssociated. Move it from elements="..." to formAssociated="...".`}const s=this;this.getAttributeNames().filter(t=>t.startsWith("decue-on:")).map(t=>t.substring("decue-on:".length)).forEach(t=>{const e=s.getAttribute("decue-on:"+t);const o=window[e];if(!o){throw`Global handler function "${e}" for event "${t}" not found.`}r("Registering event listener for event: "+t);s.addEventListener(t,o)});if(t){const i=this.attachInternals();var o=this.getAttribute("value");r("Making form-associated with value: "+o);Object.defineProperties(this,{internals:{value:i,writable:false},value:{get:()=>o,set:t=>{o=t;i.setFormValue(o);s.checkValidity()}},name:{get:()=>this.getAttribute("name")},form:{get:()=>i.form},labels:{get:()=>i.labels},validity:{get:()=>i.validity},validationMessage:{get:()=>i.validationMessage},willValidate:{get:()=>i.willValidate},setFormValue:{value:(t,e)=>i.setFormValue(o=t,e),writable:false},setValidity:{value:i.setValidity.bind(i),writable:false},checkValidity:{value:()=>{f(s,"checkvalidity");return i.checkValidity()},writable:false},reportValidity:{value:i.reportValidity.bind(i),writable:false}});this.value=o;if(!this.hasAttribute("tabindex")){this.tabIndex=0}}}connectedCallback(){this._shadow=this.getAttribute("shadow")||this._template.getAttribute("shadow")||o;if(!["open","closed","none"].includes(this._shadow)){throw`Invalid shadow DOM mode "${this._shadow}" for element "${a}". Must be one of "open", "closed" or "none".`}if(!this._shadowRoot){this._shadowRoot=this._shadow==="none"?this:this.attachShadow({mode:this._shadow,delegatesFocus:true});const t=()=>{r("Finalizing...");const t=this._template.content.cloneNode(true);if(this._shadow==="none"){h(this._shadowRoot,t);r("Slots initialized")}this._boundNodes=[];[t,this].forEach(t=>u(t,(t,e,o)=>this._boundNodes.push(t instanceof HTMLElement?[t,t.getAttribute(e),e]:[t,t.data,undefined])));const e=this;const o=this.getAttributeNames().filter(l).filter(t=>!i.includes(t));if(o.length>0&&this._boundNodes.length>0){new MutationObserver(t=>t.forEach(t=>{if(o.includes(t.attributeName)){e.attributeChangedCallback(t.attributeName,t.oldValue,t.target.getAttribute(t.attributeName))}})).observe(this,{attributes:true});this._decueMutationObserved=true;if(s){r("Observing attributes with MutationObserver: "+o.join(" "));this.setAttribute("data-decue-mutation-observed-attributes",o.join(" "))}}if(s&&i.length>0){r("Observing attributes with observedAttributes: "+i.join(" "));this.setAttribute("data-decue-observed-attributes",i.join(" "))}this._shadowRoot.append(t);this._boundNodes.forEach(t=>c(e,t));f(this,"connect")};if(n){t()}else{const e=new MutationObserver(()=>{e.disconnect();t()});e.observe(this.parentElement,{childList:true})}}}attributeChangedCallback(t,e,o){if(e!==o){if(t==="value"&&this.value!==o){this.value=o}if(this._boundNodes){const s=this._boundNodes.filter(([t,e])=>d(t));if(s.length!==this._boundNodes.length){this._boundNodes=s}const i=this;this._boundNodes.forEach(t=>c(i,t))}f(this,"attributechange",{name:t,oldValue:e,newValue:o})}}disconnectedCallback(){f(this,"disconnect")}adoptedCallback(){f(this,"adopt")}formAssociatedCallback(t){f(this,"formassociate",{form:t})}formDisabledCallback(t){f(this,"formdisable",{disabled:t})}formResetCallback(){f(this,"formreset")}formStateRestoreCallback(t,e){f(this,"formstaterestore",{state:t,mode:e})}})};const f=(t,e,o)=>{t.dispatchEvent(new CustomEvent(e,{detail:o||{},bubbles:true}))};const i=document.currentScript.hasAttribute("debug");[{attr:"elements",formAssociated:false},{attr:"form-associated",formAssociated:true}].forEach(({attr:t,formAssociated:o})=>{if(document.currentScript.hasAttribute(t)){document.currentScript.getAttribute(t).split(/\s+/).map(t=>t.split(/\[|]/)).forEach(([t,e])=>s(i,t,undefined,o,e?e.split(","):[]))}});const e=t=>{const e=t.getAttribute("decue");if(e&&!window.customElements.get(e)){s(i,e,t,t.hasAttribute("form-associated"),[])}};window.addEventListener("DOMContentLoaded",()=>{[...document.getElementsByTagName("template")].forEach(e);[...document.getElementsByTagName("object")].filter(t=>t.getAttribute("type")==="text/html").forEach(t=>{t.addEventListener("load",()=>[...t.contentDocument.getElementsByTagName("template")].forEach(e));if(t.contentDocument){[...t.contentDocument.getElementsByTagName("template")].forEach(e)}})});return{processTemplate:e,defineElement:s}}();
|
package/examples.html
CHANGED
|
@@ -45,6 +45,18 @@
|
|
|
45
45
|
document.querySelector('[data-modifyvalues]').addEventListener('click', () => {
|
|
46
46
|
document.querySelectorAll('[value]').forEach(x => {x.value = 'hello ' + x.value; x.dispatchEvent(new Event('change'));});
|
|
47
47
|
});
|
|
48
|
+
|
|
49
|
+
setTimeout(() => {
|
|
50
|
+
document.querySelectorAll('.remove-then-append nested-element-with-attribute').forEach(el => {
|
|
51
|
+
const parent = el.parentNode;
|
|
52
|
+
parent.removeChild(el);
|
|
53
|
+
parent.appendChild(el);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
document.querySelectorAll('.move nested-element-with-attribute').forEach(el => {
|
|
57
|
+
el.parentNode.moveBefore(el, null);
|
|
58
|
+
});
|
|
59
|
+
}, 1000);
|
|
48
60
|
});
|
|
49
61
|
</script>
|
|
50
62
|
<script src="src/decue.js" debug elements="predefined-element predefined-element-with-attributes predefined-element-with-slot"></script>
|
|
@@ -270,6 +282,48 @@
|
|
|
270
282
|
</fieldset>
|
|
271
283
|
</td>
|
|
272
284
|
</tr>
|
|
285
|
+
|
|
286
|
+
<tr>
|
|
287
|
+
<td>
|
|
288
|
+
<fieldset class="remove-then-append">
|
|
289
|
+
<legend>remove-then-append</legend>
|
|
290
|
+
<nested-element-with-attribute greetings="World!"></nested-element-with-attribute>
|
|
291
|
+
</fieldset>
|
|
292
|
+
</td>
|
|
293
|
+
<td>
|
|
294
|
+
<fieldset class="remove-then-append">
|
|
295
|
+
<legend>remove-then-append</legend>
|
|
296
|
+
<nested-element-with-attribute greetings="World!" shadow="open"></nested-element-with-attribute>
|
|
297
|
+
</fieldset>
|
|
298
|
+
</td>
|
|
299
|
+
<td>
|
|
300
|
+
<fieldset class="remove-then-append">
|
|
301
|
+
<legend>remove-then-append</legend>
|
|
302
|
+
<nested-element-with-attribute greetings="World!" shadow="closed"></nested-element-with-attribute>
|
|
303
|
+
</fieldset>
|
|
304
|
+
</td>
|
|
305
|
+
</tr>
|
|
306
|
+
|
|
307
|
+
<tr>
|
|
308
|
+
<td>
|
|
309
|
+
<fieldset class="move">
|
|
310
|
+
<legend>move</legend>
|
|
311
|
+
<nested-element-with-attribute greetings="World!"></nested-element-with-attribute>
|
|
312
|
+
</fieldset>
|
|
313
|
+
</td>
|
|
314
|
+
<td>
|
|
315
|
+
<fieldset class="move">
|
|
316
|
+
<legend>move</legend>
|
|
317
|
+
<nested-element-with-attribute greetings="World!" shadow="open"></nested-element-with-attribute>
|
|
318
|
+
</fieldset>
|
|
319
|
+
</td>
|
|
320
|
+
<td>
|
|
321
|
+
<fieldset class="move">
|
|
322
|
+
<legend>move</legend>
|
|
323
|
+
<nested-element-with-attribute greetings="World!" shadow="closed"></nested-element-with-attribute>
|
|
324
|
+
</fieldset>
|
|
325
|
+
</td>
|
|
326
|
+
</tr>
|
|
273
327
|
</table>
|
|
274
328
|
</main>
|
|
275
329
|
|
package/external.html
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "decue",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Declarative Custom Elements. Create simple web components with just HTML, parameterized with slots and attributes. With or without shadow-dom.",
|
|
5
5
|
"author": "Jyri-Matti Lähteenmäki <jyri-matti@lahteenmaki.net>",
|
|
6
|
-
"keywords": [
|
|
6
|
+
"keywords": [
|
|
7
|
+
"html",
|
|
8
|
+
"web-component",
|
|
9
|
+
"custom-element"
|
|
10
|
+
],
|
|
7
11
|
"license": "MIT",
|
|
8
12
|
"scripts": {
|
|
9
13
|
"test": "mocha-chrome test/index.html",
|
|
@@ -12,7 +16,7 @@
|
|
|
12
16
|
},
|
|
13
17
|
"repository": {
|
|
14
18
|
"type": "git",
|
|
15
|
-
"url": "
|
|
19
|
+
"url": "https://codeberg.org/jyri-matti/decue.git"
|
|
16
20
|
},
|
|
17
21
|
"devDependencies": {
|
|
18
22
|
"chai": "^4.3.6",
|
package/src/decue.js
CHANGED
|
@@ -195,64 +195,67 @@ var decue = (function() {
|
|
|
195
195
|
throw `Invalid shadow DOM mode "${this._shadow}" for element "${elementName}". Must be one of "open", "closed" or "none".`;
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
198
|
+
if (!this._shadowRoot) {
|
|
199
|
+
this._shadowRoot = this._shadow === 'none' ? /** @type {HTMLElement} */ (this) : this.attachShadow({ mode: this._shadow, delegatesFocus: true });
|
|
200
|
+
|
|
201
|
+
const finalize = () => {
|
|
202
|
+
dbg('Finalizing...');
|
|
203
203
|
|
|
204
|
-
|
|
205
|
-
// Implement slotting manually when no shadow DOM in use
|
|
206
|
-
lightDOMSlotting(root, content);
|
|
207
|
-
dbg('Slots initialized');
|
|
208
|
-
}
|
|
204
|
+
const content = /** @type {DocumentFragment} */ (this._template.content.cloneNode(true));
|
|
209
205
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
206
|
+
if (this._shadow === 'none') {
|
|
207
|
+
// Implement slotting manually when no shadow DOM in use
|
|
208
|
+
lightDOMSlotting(this._shadowRoot, content);
|
|
209
|
+
dbg('Slots initialized');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// nodes having placeholder references, and thus need to be updated when attributes change.
|
|
213
|
+
/** @type {[Node,string,string][]} */
|
|
214
|
+
this._boundNodes = [];
|
|
215
|
+
|
|
216
|
+
// Find all placeholders in the attributes and text of template or element content.
|
|
217
|
+
[content, this].forEach(x =>
|
|
218
|
+
forEachPlaceholder(x, (node,attributeName,_) => this._boundNodes.push(node instanceof HTMLElement
|
|
219
|
+
? [node, node.getAttribute(attributeName), attributeName]
|
|
220
|
+
: [node, node.data, undefined])));
|
|
219
221
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
222
|
+
const ths = this;
|
|
223
|
+
// If there are attributes, which weren't yet observed statically, observe them dynamically with a MutationObserver.
|
|
224
|
+
const unobservedAttributes = this.getAttributeNames().filter(isNotBuiltinAttribute).filter(x => !observedAttrs.includes(x));
|
|
225
|
+
if (unobservedAttributes.length > 0 && this._boundNodes.length > 0) {
|
|
226
|
+
new MutationObserver(recs => recs.forEach(rec => {
|
|
227
|
+
if (unobservedAttributes.includes(rec.attributeName)) {
|
|
228
|
+
ths.attributeChangedCallback(rec.attributeName, rec.oldValue, (/** @type {HTMLElement} */ (rec.target)).getAttribute(rec.attributeName));
|
|
229
|
+
}
|
|
230
|
+
})).observe(this, { attributes: true });
|
|
231
|
+
this._decueMutationObserved = true;
|
|
232
|
+
if (debug) {
|
|
233
|
+
dbg('Observing attributes with MutationObserver: ' + unobservedAttributes.join(' '));
|
|
234
|
+
this.setAttribute('data-decue-mutation-observed-attributes', unobservedAttributes.join(' '));
|
|
227
235
|
}
|
|
228
|
-
})).observe(this, { attributes: true });
|
|
229
|
-
this._decueMutationObserved = true;
|
|
230
|
-
if (debug) {
|
|
231
|
-
dbg('Observing attributes with MutationObserver: ' + unobservedAttributes.join(' '));
|
|
232
|
-
this.setAttribute('data-decue-mutation-observed-attributes', unobservedAttributes.join(' '));
|
|
233
236
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
this._boundNodes.forEach(x => updatePlaceholders(ths, x));
|
|
237
|
+
if (debug && observedAttrs.length > 0) {
|
|
238
|
+
dbg('Observing attributes with observedAttributes: ' + observedAttrs.join(' '));
|
|
239
|
+
this.setAttribute('data-decue-observed-attributes', observedAttrs.join(' '));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
this._shadowRoot.append(content);
|
|
243
|
+
this._boundNodes.forEach(x => updatePlaceholders(ths, x));
|
|
242
244
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
+
fireEvent(this, 'connect');
|
|
246
|
+
};
|
|
245
247
|
|
|
246
|
-
|
|
247
|
-
finalize();
|
|
248
|
-
} else {
|
|
249
|
-
// predefined element. Finalize only after the children are parsed.
|
|
250
|
-
/** @type {MutationObserver} */
|
|
251
|
-
const observer = new MutationObserver(() => {
|
|
252
|
-
observer.disconnect();
|
|
248
|
+
if (template) {
|
|
253
249
|
finalize();
|
|
254
|
-
}
|
|
255
|
-
|
|
250
|
+
} else {
|
|
251
|
+
// predefined element. Finalize only after the children are parsed.
|
|
252
|
+
/** @type {MutationObserver} */
|
|
253
|
+
const observer = new MutationObserver(() => {
|
|
254
|
+
observer.disconnect();
|
|
255
|
+
finalize();
|
|
256
|
+
});
|
|
257
|
+
observer.observe(this.parentElement, { childList: true });
|
|
258
|
+
}
|
|
256
259
|
}
|
|
257
260
|
}
|
|
258
261
|
|
|
@@ -321,7 +324,9 @@ var decue = (function() {
|
|
|
321
324
|
.filter(obj => obj.getAttribute('type') === 'text/html')
|
|
322
325
|
.forEach(obj => {
|
|
323
326
|
obj.addEventListener('load', () => [...obj.contentDocument.getElementsByTagName('template')].forEach(processTemplate));
|
|
324
|
-
|
|
327
|
+
if (obj.contentDocument) {
|
|
328
|
+
[...obj.contentDocument.getElementsByTagName('template')].forEach(processTemplate);
|
|
329
|
+
}
|
|
325
330
|
});
|
|
326
331
|
});
|
|
327
332
|
|