Javascript Firefox - Невозможно запросить cssRules, если @import присутствует в таблице стилей - ошибка или ожидаемое поведение? - PullRequest
6 голосов
/ 26 ноября 2011

Я не могу запросить cssRules, если @import присутствует в таблице стилей css.Это ожидается в соответствии с веб-стандартом?Или это известное ограничение Firefox?

Примечание. Я импортирую файл CSS из того же домена.

var style_rules = document.styleSheets[0].cssRules;
console.log(style_rules);

Параметр или операция не поддерживается базовым объектом [Break On This Error] var style_rules = document.styleSheets [0] .cssRules;

Ответы [ 2 ]

3 голосов
/ 26 апреля 2012

Свойство document.styleSheets [0] .cssRules представляет собой CSSRuleList (кроме IE6-8, где вам нужно styleSheets [0] .rules для правил css и styleSheets [0] .imports. для импорта). Этот список CSSRuleList имеет определенное количество CSSRules в списке. Эти правила могут быть разных типов. Например, @import CSSRule реализует интерфейс CSSImportRule и «нормальное» объявление стиля CSSRule реализует интерфейс CSSStyleRule . Мы можем определить, является ли CSSRule правилом @import css, проверив, если rule.type == IMPORT_RULE, где IMPORT_RULE равен 3. Если это CSSImportRule, мы можем получить его свойство styleSheet для получения правил css в импортированной таблице стилей и повторить процесс описано выше.

Синтаксическое текстовое представление любого CSSRule может быть получено путем получения свойства cssText: rule.cssText. Однако в Internet Explorer 6-8 мы должны использовать rule.style.cssText.

Другими словами, мы можем получить все CSSRule в таблицах стилей (включая их импорт), используя следующий код. Я также поместил рабочий образец в jsfiddle . Обратите внимание, что этот код не работает в IE6-8. Для этого решения я предлагаю вам проверить мое решение для другой проблемы на SO здесь .

/**
 * Get the css rules of a stylesheet which apply to the htmlNode. Meaning its class
 * its id and its tag.
 * @param CSSStyleSheet styleSheet
 */
function getCssRules(styleSheet) {
    if ( !styleSheet )
        return null;

    var cssRules = new Array();
    if (styleSheet.cssRules) {
        var currentCssRules = styleSheet.cssRules;
        // Import statement are always at the top of the css file.
        for ( var i = 0; i < currentCssRules.length; i++ ) {
            // cssRules contains the import statements.
            // check if the rule is an import rule.
            if ( currentCssRules[i].type == 3 ) {
                // import the rules from the imported css file.
                var importCssRules = getCssRules(currentCssRules[i].styleSheet);
                if ( importCssRules != null ) {
                    // Add the rules from the import css file to the list of css rules.
                    cssRules = addToArray(cssRules, importCssRules);
                }
                // Remove the import css rule from the css rules.
                styleSheet.deleteRule(i);
            }
            else {
                // We found a rule that is not an CSSImportRule
                break;
            }
        }
        // After adding the import rules (lower priority than those in the current stylesheet),
        // add the rules in the current stylesheet.
        cssRules = addToArray(cssRules, currentCssRules);
    }


    return cssRules;
}

/**
 * Since a list of rules is returned, we cannot use concat. 
 * Just use old good push....
 * @param CSSRuleList cssRules
 * @param CSSRuleList cssRules
 */
function addToArray(cssRules, newRules) {
    for ( var i = 0; i < newRules.length; i++ ) {
        cssRules.push(newRules[i]);
    }
    return cssRules;
}

/**
 * Finds all CSS rules.
 */
function getCSSRules() {
    var cssRules = new Array();

    // Loop through the stylesheets in the html document.
    for ( var i = 0; i < document.styleSheets.length; i++ ) {
        var currentCssRules = getCssRules(document.styleSheets[i])
        if ( currentCssRules != null )
            cssRules.push.apply(cssRules, currentCssRules);
    }

    return cssRules;
}

// An array of all CSSRules.
var allCSSRules = getCSSRules();
    for ( var i = 0; i < allCSSRules.length; i++ ) {
        console.log(allCSSRules[i].cssText);
    }
0 голосов
/ 29 ноября 2011

Кажется, работает нормально, хотя я тестировал его только с несуществующими файлами. jsfiddle пример работы с Firefox 8

обновление 1: я думаю, я выяснил, почему у вас возникла проблема.Если cssRule является импортом, вы должны вместо этого проанализировать cssRules его свойства StyleSheet.Это было довольно легко заметить с помощью аддона Firebug для Firefox.

- это test.html

<html>
<head>
<style type="text/css">
@import 'test.css';
</style>
</head>
<body>
<div class="random5923">showing with border</div>
<script type="text/javascript">
console.log(document.styleSheets);
console.log(document.styleSheets[0].cssRules[0].styleSheet.cssRules[0].cssText);
</script>
</body>
</html>

и соответствующее обновление test.css

.random5923 {
    border : 1px solid black;
}

2: Согласно http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSImportRule объект CSSImportRule окончательно имеет свойство styleSheet.Пожалуйста, используйте мой пример, чтобы проверить это самостоятельно, но имейте это в виду:

Значение этого атрибута равно нулю, если таблица стилей еще не загружена

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...