manuna
manuna

Reputation: 861

DOCTYPE breaks style.display

I have a (legacy) JS function, that shows or hides child nodes of argument element. It is used in mouseover and mouseout event handlers to show-hide img tags. The function looks like this:

function displayElem(elem, value, handlerRoot){
try{
    var display = 'inline';
    if(!value)
        display = 'none';
    if(handlerRoot)
        elem.style.display = display;
    var childs = elem.childNodes;
    for (i = 0; i < childs.length; i++){
        if(childs[i].nodeType == Node.ELEMENT_NODE){
            childs[i].style.display = display;
            alert("Node "+childs[i].tagName+" style set to " +childs[i].style.display);
        }
    }
}catch(e){
    alert('displayElem: ' + e);
}
}

Here, value and handlerRoot are boolean flags. This function works perfectly, if target html page has no doctype. Adding any doctype (strict or transitional) breaks this. Alert shows style has been set to the right value, but child elements are not displayed.
Would be good, if this function could work with any DOCTYPE.

Image (a child node of elem) is initialized like this (perhaps something is wrong here?):

var img = new Image();
img.style.cssText =
'background: transparent url("chrome://{appname}/content/dbutton.png") right top no-repeat;' +
'position: relative;' +
'height:18px;'+
'width:18px;'+
'display:none;';

Upvotes: 1

Views: 504

Answers (3)

manuna
manuna

Reputation: 861

Thanks to Álvaro G. Vicario. Though he didn't gave an exact answer, the direction was right. I've checked the page with w3c validator, and found that my Image objects were missing src attribute. Thus, adding img.src = "chrome://{appname}/content/dbutton.png"; helped.

Still, I'm not sure, why the original code author used background style instead of src... Perhaps, that would remain a mystery. :)

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074505

Update:

I wonder if when dealing with a document in standards mode (the document has a DOCTYPE), Firefox is inserting an implied element that it doesn't insert in backward-compat mode (no DOCTYPE), and so the image isn't an immediate child of elem but instead a child of this implied element that's then a child of elem; so you won't see the image in elem.childNodes. Walking through the code in a debugger is the best way to tell, but failing that, alert the tagName of each of the child nodes you're iterating through in the loop.

For example, with this markup:

<table id='theTable'>
    <tr><td>Hi there</td></tr>
</table>

...Firefox will insert a tbody element, so the DOM looks like this:

<table id='theTable'>
    <tbody>
        <tr><td>Hi there</td></tr>
    </tbody>
</table>

...but it won't be that specific example unless the DOCTYPE is a red herring, because I just tested and Firefox does that even in backward-compat mode. But perhaps you were testing two slightly different documents? Or perhaps it does it with some elements only in standards mode.


Original:

Not immediately seeing the problem, but I do see two issues:

  1. i isn't declared in the function, and so you're falling prey to the Horror of Implicit Globals. Since your alert is showing the correct value, I can't see why that would be the problem.
  2. url(..) in CSS doesn't use quotes. Yes they can, optionally.

Upvotes: 2

&#193;lvaro Gonz&#225;lez
&#193;lvaro Gonz&#225;lez

Reputation: 146460

JavaScript doesn't really work over plain HTML but on the DOM tree generated by the browser. Thus the DOCTYPE does not have a direct influence on JavaScript but on the way the browser handles invalid HTML and CSS.

I think the first step is to clean-up the HTML and make sure it's valid, esp. that tags are used in allowed places and properly nested. That will guarantee that the generated node tree is the same no matter the rendering mode.

You can also use your favourite browser tool (such as Firebug) the inspect the real tree and make sure nodes are placed where you think they are.

Upvotes: 2

Related Questions