Stef
Stef

Reputation: 523

CSSRules is empty

I have this very simple HTML page, and I'm trying to get the CSSRules of #poulet, but when I'm accessing the documents.styleSheets[0].cssRules I get this error in Chrome v5.0.375.55:
Uncaught TypeError: Cannot read property 'length' of null

Here is what my code looks like:

HTML FILE

<!DOCTYPE html> 
<html lang="en"> 
<head>
<link rel="stylesheet" href="css/test.css" type="text/css" />
<script type="text/javascript" src="js/test.js"></script>
<title>Mozilla</title>
<script>
window.onload = function(){
    var test = findKeyframesRule('poulet');
    alert(test);
}
</script>
</head>
<body>
    <div id="poulet">
        allo
    </div>
</body>
</html>

JS FILE

function findKeyframesRule(rule)
{
    var ss = document.styleSheets;

    for (var i = 0; i < ss.length; ++i)
    {       
        for (var j = 0; j < ss[i].cssRules.length; ++j)
        {
            if (ss[i].cssRules[j].type == window.CSSRule.WEBKIT_KEYFRAMES_RULE && ss[i].cssRules[j].name == rule)
                return ss[i].cssRules[j];
        }
    }
    return null;
}

CSS FILE

html, body {
    background: #cccccc;
}

#poulet{
    border: 10px solid pink;
}

The files can be found here. I really need help on this one, please!!! D:

Upvotes: 4

Views: 11533

Answers (3)

kennebec
kennebec

Reputation: 104820

This method returns an array of rules that contain a given selector-

to work in correctly IE, the selector test has to be case insensitive.

Chrome 5 will work with either rules or cssRules, by the way.

function findRule(rule){
    var ss= document.styleSheets, L= ss.length, A= [], R, RL, ru;
    var rx= RegExp('\\b'+rule+'\\b','i');
    for(var i= 0; i < L; ++i){
        R= ss[i].cssRules || ss[i].rules,
        RL= R.length;
        while(RL){
            ru= R[--RL];
            if(rx.test(ru.selectorText)){
                A.unshift(ru.selectorText+'{'+ru.style.cssText+'}');
            }
        }
    }
    return A;
}

alert(findRule('body').join('\n\n'))

Note-may be of use to you-

If I run this in a directory on my c-drive I can't read any styleSheet's length or rules unless they are in the same directory as the page.

It runs fine when served via http- from localhost or the internet.

Upvotes: 2

Marcel Korpel
Marcel Korpel

Reputation: 21763

I found these errors in your script:

  1. You're testing for type being equal to window.CSSRule.WEBKIT_KEYFRAMES_RULE. That property has a value of 8, whereas the desired object has a type of 1. A quick look in the CSSRule object reveals that you probably want to compare with window.CSSRule.STYLE_RULE.

  2. I couldn't find a property name, but in the end found a property selectorText containing #poulet.

After corrections the script reads:

function findKeyframesRule(rule)
{
    var ss = document.styleSheets;

    for (var i = 0; i < ss.length; ++i)
    {
        for (var j = 0; j < ss[i].cssRules.length; ++j)
        {
            if (ss[i].cssRules[j].type == window.CSSRule.STYLE_RULE && ss[i].cssRules[j].selectorText == '#'+rule)
                return ss[i].cssRules[j];
        }
    }
    return null;
}

But beware of the problem I mentioned in a comment: this only works when protocol != "file:",

Upvotes: 3

Joel
Joel

Reputation: 19368

Chrome uses the rules[] array like IE.

document.styleSheets[0].rules.length

So modify your loop:

for (var i = 0; i < ss.length; ++i)
{       
    var rules = ss[i].cssRules;
    if (!rules)
        rules = ss[i].rules;

    for (var j = 0; j < rules.length; ++j)
    {
        if (rules[j].type == window.CSSRule.WEBKIT_KEYFRAMES_RULE && rules[j].name == rule)
            return rules[j];
    }
}

Upvotes: 0

Related Questions