views:

643

answers:

7

I have a client who is embedding videos into his WordPress blog. The problem is they have a large CSS dropdown that sneaks behind the flash video. I understand that setting the video's wmode to opaque will fix this, but I obviously need this to apply to every video they upload and not have to go to the HTML to add this tag

Is there any way I can do this programatically?

A: 

Using jQuery, you could try this:

$(document).ready(function(){
    $("object").append('<param name="wmode" value="opaque">');
});

Not entirely sure if that would work, but it's worth a shot. Good luck!

inkedmn
That did in fact add it to every element, but for some reason did not work. I think it is because it is appending it at the end. Thanks for the idea though!
patricksweeney
+2  A: 

Since you seem to have abandoned this question I'll paste the answer here:

// makeObjectsOpaque() adds a <param> tag to each <object> tag
// analogous to <object ...><param name="wmode" value="opaque"></object>
// it seems unlikely that adding a <param> to an <object> dynamically after
// it has been rendered by the browser will actually apply the <param> value
// correctly; in other words, it *probably* WILL NOT WORK
function makeObjectsOpaque() {
    var elementToAppend = document.createElement('param');
    elementToAppend.setAttribute('name', 'wmode');
    elementToAppend.setAttribute('value', 'opaque');
    var objects = document.getElementsByTagName('object');
    for(var i = 0; i < objects.length; i++) {
        elementToAppend = elementToAppend.cloneNode(true);
        objects[i].appendChild(elementToAppend);
    }
}

// makeObjectsOpaque2() adds a 'wmode' attribute to each <object> tag
// this should be analogous to <object ... wmode="opaque"> in HTML
// THIS DOES NOT APPEAR TO BE WHAT YOU WANT TO DO ACCORDING TO
// THIS URL: http://kb2.adobe.com/cps/127/tn_12701.html
function makeObjectsOpaque2() {
    var objects = document.getElementsByTagName('object');
    for(var i = 0; i < objects.length; i++) {
        objects[i].setAttribute('wmode', 'opaque');
        // you can also try:
        // objects[i].wmode = 'opaque';
    }
}

// makeObjectsOpaque3() replaces every <object> tag on the page with
// a cloned copy, adding a <param> tag before replacing it
// analogous to replacing <object ...>...</object>
// with <object ...>...<param name="wmode" value="opaque"></object>
// this *may* cause the browser to re-render the <object> and apply
// the newly added <param>, or it may not
function makeObjectsOpaque3() {
    var elementToAppend = document.createElement('param');
    elementToAppend.setAttribute('name', 'wmode');
    elementToAppend.setAttribute('value', 'opaque');
    var objects = document.getElementsByTagName('object');
    for(var i = 0; i < objects.length; i++) {
        var newObject = objects[i].cloneNode(true);
        elementToAppend = elementToAppend.cloneNode(true);
        newObject.appendChild(elementToAppend);
        objects[i].parentNode.replaceChild(newObject, objects[i]);
    }
}

window.onload = makeObjectsOpaque3;

If there is already an onload event handler you'll have to do something like:

if(window.onload) {
    var onLoad = window.onload;
    window.onload = function() {
        onLoad();
        makeObjectsOpaque3();
    };
} else {
    window.onload = makeObjectsOpaque3;
}
Grant Wagner
how would I call it from the onload event? Just create a name for the function?
patricksweeney
@patricksweeney: I've edited my answer to demonstrate how to attach it to `onload`.
Grant Wagner
Thanks, but it still isn't working. It has successfully added to each time the tag appears, but it still doesn't work. If I add it manually, it does work though. Confused :(
patricksweeney
I've sort of figured out what's wrong. It needs to be in the <embed instead; so I need to add 'wmode="opaque" '. So now I have to figure out how to do that instead.
patricksweeney
@patricksweeney: You mean you need add an attribute to the `<object>` tag? I've edited my answer to demonstrate that.
Grant Wagner
It still doesn't work. I think it's because we are putting it in the object tag and not as a <param>. If you want to see the source, its animewire.com.
patricksweeney
@patricksweeney: `makeObjectsOpaque()` injects a `<param>` tag inside the `<object>` tag, analogous to `<object ...><param name="wmode" value="opaque"></object>`. `makeObjectsOpaque2()` adds a `wmode` attribute with an `opaque` value to the `<object>` tag, analogous to `<object ... wmode="opaque">`. The URL provided takes me to a Contact Us form with no JavaScript or `<object>` tags.
Grant Wagner
@patricksweeney: From the information I've gathered (http://kb2.adobe.com/cps/127/tn_12701.html), you want to add `<param name="wmode" value="opaque">` but adding the `<param>` tag *after* the page is loaded is unlikely to affect any existing rendered `<object>` tags (in other words, it won't work). Given that, I've added a third function that will replace any existing `<object>` tags on the page. This *might* work by re-rendering them and causing the `<param>` value to be effective. Then again, it might not.
Grant Wagner
Yea, still doesn't work. There HAS to be some way to do this. BTW, the URL is http://www.animewire.dbzseries.net/. Thanks for all your hard work!
patricksweeney
A: 

How about this. It sets it on the object and as a param (if the param already exists, it updates it; otherwise, it adds it).

var setWmode = function(wmode, object) {
    $(object || "object").each(function(i, node) {
     // Set wmode on the object
     node.setAttribute("wmode", wmode);

     // See if wmode already exists to avoid duplication param conflicts
     var currentWmode = $("param[name='wmode']", node);

     // If it already exists, make sure its the new wmode
     if ( currentWmode.length ) {
      currentWmode.attr("value", wmode);
     }
     // Otherwise, add it
     else {
      $(node).append('<param name="wmode" value="' + wmode + '">');
     }
    });
};

$(document).ready(function() {
    setWmode("opaque");
});
Justin Johnson
@Justin: My testing has shown that adding a `<param>` to an existing `<object>` tag which refers to the Adobe Flash Player does not actually accomplish anything. You have to clone the `<object>`, add the `<param>` node, then invoke `replaceChild()` on the parentNode to get it to render correctly.
Grant Wagner
+1  A: 

To avoid confusion with all the edits I've done to my previous answer, I'm creating a new answer with a fully tested and working sample page. It has been tested and is working in IE 6, 7 & 8, Opera 9.6 & 10, Safari 3 & 4, Google Chrome, but no version of Firefox I tested (2, 3 or 3.5):

<html>
<head><title>Opacity text</title></head>
<body>
<div style="color:Red;position:absolute;top:0px;left:0px;">
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<br>
</div>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" height="200" width="300">
    <param name="movie" value="http://freevideocoding.com/flvplayer.swf?file=http://www.freevideoediting.com/TVQvideos/Queen Demo--flv.flv&autoStart=false">
    <param name="bgcolor" value="#ffff00">
</object>
<!--
all you need to make this work is the script listed below.
everything else is just sample code to provide a demonstration
that the script shown below actually works
-->
<script type="text/javascript">
function makeObjectsOpaque_TestedAndWorking() {
    var elementToAppend = document.createElement('param');
    elementToAppend.setAttribute('name', 'wmode');
    elementToAppend.setAttribute('value', 'opaque');
    var objects = document.getElementsByTagName('object');
    for (var i = 0; i < objects.length; i++) {
        var newObject = objects[i].cloneNode(true);
        elementToAppend = elementToAppend.cloneNode(true);
        newObject.appendChild(elementToAppend);
        objects[i].parentNode.replaceChild(newObject, objects[i]);
    }
}
window.onload = makeObjectsOpaque_TestedAndWorking;
</script>
</body>
</html>
Grant Wagner
A: 

makeObjectsOpaque_TestedAndWorking from Grant works fine - at first - but here is what I experience: It works when I first load the page, but if I refresh the page or go to a new page and press Back, my Flash object loads on top of all other layers again. It makes no sense, but do you know a workaround? Do you experience this also?

A: 

For the record, it needs to be changed in TWO places: see here.

patricksweeney
A: 

I think the problem is that you need to create a wmode="opaque" attribute inside of the embed tag AS WELL AS add a param element with wmode set to "opaque." While Grant Wagner's code is effective at adding the wmode="opaque" as a param inside the object, it does not add it as an attribute in the embed tag. You need them both if you want this to work cross-browser, cross-platform. That might be why Grant Wagner is seeing it work, while patricksweeney is not.

Josh Fraser wrote a nice function that rewrites the embed tag to include the wmode attribute. soooooo I combined Grant Wagner's solution for adding the wmode param, and Josh Fraser's solution for adding a wmode attribute to the embed in one function, and it looks a little something like this:

 function fix_flash() {
    // loop through every embed tag on the site
    var embeds = document.getElementsByTagName('embed');
    for(i=0; i<embeds.length; i++)  {
        embed = embeds[i];
        var new_embed;
        // everything but Firefox & Konqueror
        if(embed.outerHTML) {
            var html = embed.outerHTML;
            // replace an existing wmode parameter
            if(html.match(/wmode\s*=\s*('|")[a-zA-Z]+('|")/i))
                new_embed = html.replace(/wmode\s*=\s*('|")window('|")/i,"wmode='opaque'");
            // add a new wmode parameter
            else 
                new_embed = html.replace(/<embed\s/i,"<embed wmode='opaque' ");
            // replace the old embed object with the fixed version
            embed.insertAdjacentHTML('beforeBegin',new_embed);
            embed.parentNode.removeChild(embed);
        } else {
            // cloneNode is buggy in some versions of Safari & Opera, but works fine in FF
            new_embed = embed.cloneNode(true);
            if(!new_embed.getAttribute('wmode') || new_embed.getAttribute('wmode').toLowerCase()=='window')
                new_embed.setAttribute('wmode','opaque');
            embed.parentNode.replaceChild(new_embed,embed);
        }
    }
    // loop through every object tag on the site
    var elementToAppend = document.createElement('param');
    elementToAppend.setAttribute('name', 'wmode');
    elementToAppend.setAttribute('value', 'opaque');
    var objects = document.getElementsByTagName('object');
    for (var i = 0; i < objects.length; i++) {
        var newObject = objects[i].cloneNode(true);
        elementToAppend = elementToAppend.cloneNode(true);
        newObject.appendChild(elementToAppend);
        objects[i].parentNode.replaceChild(newObject, objects[i]);
    }
}
window.onload = fix_flash;

It's a little bit of code, but it works very well, and it saved me from hours of pulling out my hair.

James