Use a custom element to actually house the Ruffle

instance, even though we can't really upgrade `<object>` directly...
This commit is contained in:
David Wendt 2019-08-20 13:14:46 -06:00
parent 6f32fc022c
commit 2a2dbba21f
1 changed files with 38 additions and 15 deletions

View File

@ -5,26 +5,20 @@ ruffle_tmpl.innerHTML = `
<canvas id="player"></canvas> <canvas id="player"></canvas>
`; `;
class RuffleObjectShadow { class RuffleObjectShadow extends HTMLElement {
constructor(elem) { constructor() {
this.params = RuffleObjectShadow.params_of(elem); super();
this.oldelem = elem;
this.elem = document.createElement("div");
for (let attrib of this.oldelem.attributes) {
if (attrib.specified) {
this.elem.setAttribute(attrib.name, attrib.value);
}
}
this.shadow = this.elem.attachShadow({mode: 'closed'}); this.params = RuffleObjectShadow.params_of(this);
this.shadow = this.attachShadow({mode: 'closed'});
this.shadow.appendChild(ruffle_tmpl.content.cloneNode(true)); this.shadow.appendChild(ruffle_tmpl.content.cloneNode(true));
this.canvas = this.shadow.getElementById("player"); this.canvas = this.shadow.getElementById("player");
this.ruffle = null; this.ruffle = null;
}
//Swap elements around. connected() {
elem.parentElement.replaceChild(this.elem, elem);
//Kick off the SWF download. //Kick off the SWF download.
if (this.params.movie) { if (this.params.movie) {
fetch(this.params.movie).then(response => { fetch(this.params.movie).then(response => {
@ -57,10 +51,37 @@ class RuffleObjectShadow {
static wrap_tree(elem) { static wrap_tree(elem) {
for (let node of elem.getElementsByTagName("object")) { for (let node of elem.getElementsByTagName("object")) {
if (node.type === "application/x-shockwave-flash") { if (node.type === "application/x-shockwave-flash") {
new RuffleObjectShadow(node); RuffleObjectShadow.replace_native_object(node);
} }
} }
} }
static replace_native_object(elem) {
var ruffle_obj = document.createElement("ruffle-object");
for (let attrib of elem.attributes) {
if (attrib.specified) {
ruffle_obj.setAttribute(attrib.name, attrib.value);
}
}
for (let node of elem.children) {
ruffle_obj.appendChild(node);
}
//TODO: Preserve event handlers.
//Swap elements around.
//
//Unfortunately, this isn't entirely transparent: Sites that have
//manually created a Flash tag and want to communicate with it might
//hold a reference to the old, disconnected object. We need to intercept
//that kind of usage somehow.
//
//If JS tries to grab the object from the DOM again, then we're fine,
//and we can present ourselves as a perfectly normal object tag in every
//way except `nodeName`.
elem.parentElement.replaceChild(ruffle_obj, elem);
}
} }
const observer = new MutationObserver(function (mutationsList, observer) { const observer = new MutationObserver(function (mutationsList, observer) {
@ -73,3 +94,5 @@ const observer = new MutationObserver(function (mutationsList, observer) {
RuffleObjectShadow.wrap_tree(document); RuffleObjectShadow.wrap_tree(document);
observer.observe(document, { childList: true, subtree: true}); observer.observe(document, { childList: true, subtree: true});
window.customElements.define("ruffle-object", RuffleObjectShadow);