Javascript Firefox-如果样式表中存在@import,则无法查询cssRules-错误或预期行为?

问题描述 投票:6回答:3

如果CSS样式表中存在@import,我将无法查询cssRules。是否符合网络标准?还是知道Firefox的局限性?

注意:我是从同一域导入css文件。

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

基础对象不支持参数或操作[中断此错误] var style_rules = document.styleSheets [0] .cssRules;

javascript css firefox browser
3个回答
3
投票

属性document.styleSheets [0] .cssRules是一个CSSRuleList(除了IE6-8中,对于CSS规则,您应该使用styleSheets [0] .rules,对于导入应使用styleSheets [0] .imports。)此CSSRuleList在列表中具有一定数量的CSSRules。这些规则可以是不同的类型。例如,@import CSSRule实现CSSImportRule接口,而'normal'样式声明CSSRule实现CSSStyleRule接口。通过检查rule.type == IMPORT_RULE,其中IMPORT_RULE为3,我们可以检测CSSRule是否为@import css规则。如果它为CSSImportRule,则可以获取其styleSheet属性,以在导入的样式表中获取css规则并重复该过程。如上所述。

任何CSSRule的可解析文本表示形式都可以通过获取cssText属性:rule.cssText获得。但是,在Internet Explorer 6-8中,我们必须使用rule.style.cssText

换句话说,我们可以使用以下代码获取样式表中的所有CSSRule(包括其导入)。我还将一个工作示例放入了jsfiddle中。请注意,此代码在IE6-8中不起作用。对于此解决方案,建议您检查我的解决方案是否有关于SO here的另一个问题。

/**
 * 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
投票

似乎工作正常,尽管我只对不存在的文件进行了测试。jsfiddle example working on Firefox 8

更新1:我想我发现了您为什么有问题。如果cssRule是导入文件,则必须解析其StyleSheet属性的cssRules。使用Firefox的Firebug插件很容易发现这一点。

这里是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属性。请使用我的示例自己检查一下,但请记住这一点:

如果尚未加载样式表,则此属性的值为null

您可能要延迟代码,直到加载此属性。


0
投票

丹尼斯和弗里德里希需要上一门阅读理解课程。如果document.styleSheets[0].cssRules失败,那么显然他们的代码也将分别在if (styleSheet.cssRules) {console.log(document.styleSheets[0].cssRules[0].styleSheet.cssRules[0].cssText);处失败。认真地说,发布您零思想的答案有什么用?

顺便说一句,我的来宾基于提供的有限信息猜测,您将收到DOMException'InvalidAccessError',因为在运行JavaScript代码时,样式表尚未从服务器完全转移到计算机上。

如果是这种情况,则需要处理拥有样式表的HTML元素的load事件。

try
{
  var rules = styleSheet.cssRules;
}
catch(x)
{
  if(x instanceof DOMException && x.name == "InvalidAccessError")
    styleSheet.ownerNode.addEventListener("load", functionToRunWhenItLoads);
}

您可以将以上代码用于您自己的目的。但是请注意,某些浏览器在样式表完成加载之前甚至不会将样式表添加到document.styleSheets,因此您可能仍然会错过这种方式。您可能需要处理window对象的load事件来处理这种情况,或者最好不要一开始就通过document.styleSheets

© www.soinside.com 2019 - 2024. All rights reserved.