2

I have a script which adds a div to a page containing a full-screen Flash object, like this:

var myDiv= document.createElement("div");
myDiv.style.background = "red";
myDiv.style.width = "30px";
myDiv.style.height = "30px";
myDiv.style.position = "absolute";
myDiv.style.top = "0";
myDiv.style.left = "0";
document.body.appendChild(myDiv);

In Firefox (running on Greasemonkey), myDiv appears on top of the Flash object. In Chrome (running on Tampermonkey), it is added underneath. I can't seem to change this by setting z-index - it is ignored.

// code which apparently does nothing:
myDiv.style.zIndex = "999";
var swf_div = document.getElementById("swf_div");
if (swf_div) {
    swf_div.style.zIndex = "-999";
}

Is there any way I can get myDiv appearing on top of the Flash object in Chrome, considering that I don't own the host page and cannot set the wmode param of the Flash object? Why does it behave differently in FF vs Chrome?

ETA host page (glitch.com/game) source excerpt:

<body>
    ...
    <div id="client_div" style="width: 1680px; left: 0pt;">
        <object id="swf_div" width="100%" height="100%" type="application/x-shockwave-flash" data="http://c1.glitch.bz/swf/Boot_78793.swf" style="visibility: visible;">
            <param name="allowscriptaccess" value="always">
            <param name="allownetworking" value="all">
            <param name="wmode" value="direct">
            <param name="flashvars" value="--- auth tokens, omitted ---">
        </object>
    </div>
    ...
</body>
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
tuff
  • 4,895
  • 6
  • 26
  • 43
  • Link to the page in question. ... Also try changing the order of the nodes. Replace `document.body.appendChild(myDiv);` with: `var targ = document.querySelector ("body *"); /*1st child */ targ.parentNode.insertBefore (myDiv, targ);` – Brock Adams Jan 16 '12 at 02:20
  • The page is www.glitch.com/game, but it won't run unless you are a logged in player. I have added some source to my post above, it's what I see when I inspect the Flash object in Firebug. Tried your suggestion as well - myDiv does not show up on my target page, nor on other pages without Flash content. – tuff Jan 16 '12 at 18:53

2 Answers2

1

I figured it out, so I'll try to answer my own question...

First important point: userscripts can set params of a Flash object on the fly - I'd been led to believe that wasn't possible by Sam's comment in this question.

Second important point: the wmode value "opaque" should be used rather than "transparent" for performance reasons (source1, source2). Both allow html content to be drawn on top of the Flash object.

So my solution was to listen for when Flash objects are added to the page (or I think if you are targeting Flash objects which aren't added dynamically, you could just get them straightaway), find the wmode param of the one I want to change, clone it, and replace the original param with my clone:

// code to create and style myDiv, see original question

document.addEventListener("DOMNodeInserted", nodeInserted, false);

function nodeInserted(e) {
    if (e.target.id == "swf_div") { 

        var found = false;

        var params = e.target.getElementsByTagName("param");
        for (var i = 0; i < params.length; i++) {
            if (params[i].getAttribute("name") == "wmode") {
                var clone = params[i].cloneNode(true);
                clone.setAttribute("value", "opaque");
                params[i].parentNode.replaceChild(clone, params[i]);
                found = true;
                break;
            }
        }

        // in case swf_div doesn't already have a wmode param
        if (!found) {
            var clone = e.target.cloneNode(true); 
            var param = document.createElement("param");
            param.setAttribute("name", "wmode");
            param.setAttribute("value", "opaque");
            clone.appendChild(param);        
            e.target.parentNode.replaceChild(clone, e.target);
        }

        continueScript();
    }
}

function continueScript() {
    document.body.appendChild(myDiv);

    // do wonderful things
}

I still don't understand why the script requires a wmode change in Chrome but not in FF. But since that is the case, and wmode=opaque has a performance cost, I'll do a browser check before making the change. It would be very helpful to know which specific feature or rule controls this layering behaviour so that my check could be more precise.

Community
  • 1
  • 1
tuff
  • 4,895
  • 6
  • 26
  • 43
0

Which wmode are you using when you embed your SWF in the HTML? You will need to use wmode 'opaque' in order to stack HTML elements ontop of your flash element.

JonnyReeves
  • 6,119
  • 2
  • 26
  • 28
  • 1
    If a userscript is able to set params on an external Flash object, could you please explain how? Otherwise, it really looks like you've ignored my question. – tuff Jan 15 '12 at 19:51