开发者

What is causing this unexpected Javascript error?

开发者 https://www.devze.com 2023-04-02 18:43 出处:网络
This code is meant to add the style \'display: none\' to every element which does not have 开发者_JAVA技巧the class \'ShowThis\', or a descendant with that class:

This code is meant to add the style 'display: none' to every element which does not have 开发者_JAVA技巧the class 'ShowThis', or a descendant with that class:

var x = document.getElementsByTagName('*');
for(var i = x.length; i--;){
    x[i].style.display = 'none';
    if((' '+x[i].className+' ').indexOf(' ShowThis ') >= 0){
        var y = x[i];
        while(y){
            if(y.nodeType === 1){
                console.log(y.style.cssText);    // Outputs: "display: none;"
                console.log(y.style.display);    // Outputs: "none"
                y.style.display = 'block';
                console.log(y.style.display);    // Outputs: "block"
                console.log(y.style.cssText);    // Outputs: "display: block;"

                // ERROR here:
                    // Outputs the elements HTML (Chrome Console),
                    // But the style attribute isn't changed
                    // EX. <div style="display: none;">...</div>
                console.log(y);
            }
            y = y.parentNode;
        }
    }
}

Here's a JSFiddle: http://jsfiddle.net/Paulpro/wEq8X/

It works fine if you comment out if(y.nodeType === 1){ and the matching } (http://jsfiddle.net/Paulpro/wEq8X/1/), or if I change the if statement to if(y.nodeType) or if(true) which doesn't make any sense at all to me, since the program flow is entering that if statement (all the console.log's are executed) anyways.

I've tried changing the if statement to if(typeof y.style !== 'undefined') and it behaves incorrectly as well. (Exactly the same problem)

I need to test nodeType or style to prevent the error when it tries to access the document's style property, but testing either of them gives me this weird behaviour.

I can repro this in Chrome, Firefox, and IE.


Your code sets the containing block to "display: none". After that, it doesn't matter that the inner <div> is "display: block".

Your diagnostic technique of dumping out the element is flawed. If you use something like the Chrome debugger or Firebug, you'll see that your "ShowThis" element does indeed have "display: block" in its "style" attribute. However, it doesn't show up because all its parent elements (including the <body> tag) are still "display: none".

edit I think the problem is probably something that stems from the order in which the page elements appear in the "getElementsByTagName()" result. If you reach the parent elements after the child elements, then they'll be set to "display: none" after they've been set to "display: block".

edit again — confirmed. The elements are returned from "getElementsByTagName()" appear in reverse order that they appear in the HTML. Thus, the last element your code sees in the outer loop is the container <div> for the "ShowThis" <div>.

edit yet again oh dang I see - you're going backwards!! Durr. If you go forward through the node list, it should work.


You issue is that your outer loop that hides everything will hide the 'showthis' node's parents after you set then to display='block'. If you split the hiding and showing into two steps, it works fine.

var y, x = document.getElementsByTagName('*');
for(var i = 0, len = x.length; i < len; i++){
    x[i].style.display = 'none';
}
x = document.getElementsByClassName('ShowThis');
for(var i = 0, len = x.length; i < len; i++) {
    y = x[i];
    while(y){
        if(y.nodeType === 1){
            y.style.display = 'block';
        }
        y = y.parentNode;
    }
}

Also, just for the record, this type of thing is where jQuery is awesome.

jQuery('*').hide();
jQuery('.ShowThis').show().parents().show();
0

精彩评论

暂无评论...
验证码 换一张
取 消