Что вызывает эту неожиданную ошибку Javascript? - PullRequest
4 голосов
/ 07 сентября 2011

Этот код предназначен для добавления стиля 'display: none' к каждому элементу, у которого нет класса 'ShowThis', или к потомку с этим классом:

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;
        }
    }
}

Вот JSFiddle: http://jsfiddle.net/Paulpro/wEq8X/

Работает нормально, если вы закомментируете if(y.nodeType === 1){ и соответствующий } (http://jsfiddle.net/Paulpro/wEq8X/1/), или если я изменю оператор if на if(y.nodeType) или if(true), который нене имеет никакого смысла для меня, поскольку поток программы вводит оператор if (все console.log выполняются) в любом случае.

Я попытался изменить оператор if на if(typeof y.style !== 'undefined'), и онтакже ведет себя некорректно. (Точно такая же проблема)

Мне нужно протестировать nodeType или стиль, чтобы предотвратить ошибку при попытке доступа к свойству стиля документа, но тестирование любого из них дает мне это странное поведение.

Я могу воспроизвести это в Chrome, Firefox и IE.

Ответы [ 2 ]

2 голосов
/ 07 сентября 2011

Ваш код устанавливает для блока , содержащего , значение "display: none". После этого не имеет значения, что внутренняя <div> является «display: block».

Ваша диагностическая техника выброса элемента неверна. Если вы используете что-то вроде отладчика Chrome или Firebug, вы увидите, что ваш элемент «ShowThis» действительно имеет «display: block» в своем атрибуте «style». Однако он не отображается, поскольку все его родительские элементы (включая тег <body>) по-прежнему "display: none".

edit Я думаю, что проблема, вероятно, связана с порядком, в котором элементы страницы появляются в результате "getElementsByTagName ()". Если вы достигнете родительских элементов после дочерних элементов, тогда им будет присвоено значение «display: none» после для них установлено значение «display: block».

изменить еще раз & mdash; подтверждено. Элементы, возвращаемые функцией «getElementsByTagName ()», отображаются в в обратном порядке , что и в HTML. Таким образом, последний элемент, который ваш код видит во внешнем цикле , является контейнером <div> для "ShowThis" <div>.

редактировать еще раз о черт, я вижу - вы идете назад !! Durr. Если вы идете вперед по списку узлов, он должен работать.

1 голос
/ 07 сентября 2011

У вас проблема в том, что ваш внешний цикл, который скрывает все, будет скрывать родителей «showthis» узла после того, как вы установите тогда display = «block».Если вы разделите скрытие и отображение на два шага, все будет работать нормально.

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;
    }
}

Кроме того, просто для записи, этот тип вещей - то, где jQuery является удивительным.

jQuery('*').hide();
jQuery('.ShowThis').show().parents().show();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...