Недопустимый вызов процедуры или аргумент IE проблема при переборе document.styleSheets с использованием $ .each () - PullRequest
3 голосов
/ 18 февраля 2010

Я написал этот код, который перебирает все правила глобальных таблиц стилей и сохраняет их в массиве / объекте. Я использую этот словарь-объект позже, чтобы изменить глобальные правила, а не устанавливать стили для отдельных элементов.

Следующие коды ломаются в IE8, но отлично работают в Firefox3.7 и Chrome4.

var allRules;

$(function() {
    var fileRules;
    allRules = [];
    $.each(document.styleSheets, function() {
        // get rules for any browser (IE uses rules array)
        fileRules = this.cssRules || this.rules;
        $.each(fileRules, function() {
            allRules[this.selectorText] = this;
        });
    });
});

Я получаю Invalid procedure call or argument ошибку. Когда я пытаюсь его отладить, этот код успешно перебирает два файла таблицы стилей CSS с правилами, но когда повторение второго завершается, происходит сбой.

Я не могу найти ошибку в этом коде.

Ответы [ 3 ]

13 голосов
/ 18 февраля 2010

проблема

После тщательного тестирования я обнаружил, что document.styleSheets не является обычным массивом в IE. Вот почему он прерывает вызов $.each(), когда достигает конца.

Если мы посмотрим на саму функцию jQuery, у нее есть цикл for для перебора объекта, обладающего свойством length, ложно полагая, что это массив. document.styleSheets имеет свойство length, но это, очевидно, не массив. Поэтому, когда этот for цикл в $.each() выполняется:

for (var value = object[0];
     i < length && callback.call( value, i, value ) !== false;
     value = object[++i]){}

происходит сбой после итерации последнего элемента. Как мы можем видеть, этот цикл for не увеличивает i сам по себе, а увеличивает его при назначении нового значения для value.

Мы можем проверить это и вручную. Запишите эти две строки в адресную строку любого браузера:

javascript:var a=[1,2,3];alert(a[3]);void(0);
javascript:alert(document.styleSheets[document.styleSheets.length]);void(0);

Первый работает нормально во всех браузерах, но второй не работает в IE.

Решение

Мы должны переписать итерацию по таблицам стилей

var allRules;

$(function() {
    var fileRules;
    allRules = {};
    // can't use $.each() over document.styleSheets because it's not an array in IE
    for (var i = 0; i < document.styleSheets.length; i++)
    {
        fileRules = document.styleSheets[i].cssRules || document.styleSheets[i].rules;
        $.each(fileRules, function() {
            allRules[this.selectorText] = this;
        });
    }
});
0 голосов
/ 28 июня 2011

код истина:

var fileRules;
(function ($) {
    allRules = {};
    for (var i = 0; i < document.styleSheets.length; i++) {
        fileRules = document.styleSheets[i].cssRules || document.styleSheets[i].rules;
        $.each(fileRules, function () {
            allRules[this.selectorText] = this;
        })(jQuery);
    }
});
0 голосов
/ 18 февраля 2010

Может быть, само правило разбора не работает?Попробуйте поэкспериментировать с различными таблицами стилей и изменить порядок правил, чтобы убедиться, что по какой-то причине нет проблемы с анализом правила.

...