Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript Firefox - Unable to query cssRules if @import is present in stylesheet- bug or expected behavior?

I am unable to query cssRules if @import is present in css stylesheet. Is it expected as per web standard? Or it's know limitation of Firefox?

Note: I am importing css file from same domain.

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

A parameter or an operation is not supported by the underlying object [Break On This Error] var style_rules = document.styleSheets[0].cssRules;

like image 398
P K Avatar asked Nov 25 '11 21:11

P K


People also ask

What is @import url in CSS?

The @import rule allows you to import a style sheet into another style sheet. The @import rule must be at the top of the document (but after any @charset declaration). The @import rule also supports media queries, so you can allow the import to be media-dependent.

What is the purpose of @import in CSS please Google it?

The @import CSS at-rule is used to import style rules from other stylesheets.

How do I import CSS file into another CSS?

Note: There are two different ways to import a CSS file into another using @import url(“style2. css”); or @import “style2. css”; or directly import any CSS file or multiple CSS file in the HTML file directly within <style>@import “style1.


1 Answers

The property document.styleSheets[0].cssRules is a CSSRuleList (apart from in IE6-8, where you should styleSheets[0].rules for the css rules and styleSheets[0].imports for the imports). This CSSRuleList has a certain number of CSSRules in the list. These rules can be of different types. For instance a @import CSSRule implements the CSSImportRule interface and a 'normal' style declaration CSSRule implements the CSSStyleRule interface. We can detect if a CSSRule is a @import css rule, by checking if rule.type == IMPORT_RULE, where IMPORT_RULE is 3. If it is a CSSImportRule, we can obtain its styleSheet property to obtain the css rules in the imported stylesheet and repeat the process described above.

The parsable textual representation of any CSSRule can be obtained by obtaining the cssText property: rule.cssText. In Internet Explorer 6-8 however, we have to use rule.style.cssText.

In other words, we can obtain all CSSRule's in the stylesheets (including its imports) using the following code. I've also put a working sample into a jsfiddle. Note that this code does not work in IE6-8. For this solution I suggest you to check my solution for another problem on 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);
    }
like image 184
dennisg Avatar answered Nov 04 '22 02:11

dennisg