如果css样式表中存在@import,我无法查询cssRules。 它是否符合网络标准? 或者知道Firefox的限制?
注意:我从同一个域导入css文件。
var style_rules = document.styleSheets[0].cssRules;
console.log(style_rules);
底层对象不支持参数或操作 [打破此错误] var style_rules = document.styleSheets [0] .cssRules;
答案 0 :(得分:3)
属性document.styleSheets [0] .cssRules是一个CSSRuleList(除了在IE6-8中,你应该为css规则和styleSheets [0]设置styleSheets [0] .rules。进口)。此CSSRuleList在列表中具有一定数量的CSSRules。这些规则可以是不同类型的。例如,@ import CSSRule实现CSSImportRule接口和'普通'样式声明CSSRule实现CSSStyleRule接口。
我们可以检测CSSRule是否为@import css规则,检查是否为rule.type == IMPORT_RULE
,其中IMPORT_RULE为3.如果是CSSImportRule,我们可以获取其styleSheet属性以获取导入样式表中的css规则并重复上述过程。
可以通过获取cssText属性rule.cssText
来获取任何CSSRule的可解析文本表示。但是,在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);
}
答案 1 :(得分:0)
似乎工作正常,虽然我只测试了不存在的文件。 jsfiddle example working on Firefox 8
更新1: 我想我发现了你遇到问题的原因。如果cssRule是导入,则必须解析其StyleSheet属性的cssRules。使用Firebug Addon for 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: 根据{{3}},CSSImportRule对象最终具有styleSheet属性。请用我的例子自己检查一下,但请记住这一点:
如果尚未加载样式表,则此属性的值为null
您可能希望延迟代码,直到加载此属性。
答案 2 :(得分:-1)
丹尼斯和弗里德里希需要上一门阅读理解课程。如果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
。