Skip to content Skip to sidebar Skip to footer

Using Javascript To Dynamically Add Styles To Stylesheet But I Get A "cannot Read Property 'length' Of Undefined" Error

I am currently trying to make my own polyfill that will allow older browsers such as Internet Explorer the ability to read and execute media queries using traditional css selectors

Solution 1:

There are significant differences between the IE and W3C implementations of the styleSheets object, hopefully the following is explanatory enough to help:

function getStyleRules() {
    var rule, rules;
    var sheet, sheets = document.styleSheets;
    var ruleCssText = ['Rules:','',]

    for (var i=0, iLen=sheets.length; i<iLen; i++) {
      sheet = sheets[i];

      // Get the rules using:////        W3C model        IE model
      rules = sheet.cssRules || sheet.rules;

      for (var j=0, jLen=rules.length; j<jLen; j++) {
        rule = rules[j];

        // The selector is available here in both models,// but uppercase in IE so set to lower case
        alert('Selector: ' + rule.selectorText.toLowerCase());

        // Getting the actual rule text// W3C model - selector and ruleif (rule.cssText) {
          ruleCssText.push(rule.cssText);

        // IE model - rule only, doesn't include selector
        } elseif (rule.style) {
          ruleCssText.push(rule.style.cssText.toLowerCase());
        }
      }
      alert(ruleCssText.join('\n'));
    }
}

There is documentation on MSDN of the IE model, but I'm not sure if it still covers older IE or only the newer versions which may well use both models: styleSheet object, rule object

There is some Opera documentation here: Dynamic style - manipulating CSS with JavaScript

and also some information here: The styleSheet object, The CSS Rule object.

As with all web resources, take it with a serious amount of skepticism, look for other sources and test, test, test in as many browsers (especially older ones) as you can.

Running your code:

> TypeError: styleSheets[i].rules is undefined
> 
> for( a = 0; a < styleSheets[i].rules.length; a++ ) {

Here you are mixing the IE (rules) and W3C (cssRules) models. Better to just get the rules object once: -

var sheetRules = styleSheets[i].rules || styleSheets[i].cssRules;
  for( a = 0; a < sheetRules.length; a++ ) {

Then you have:

if ( sheetRules[a].type == 4 ) {

but the IE model doesn't implement a type property for the rules object (even though the MSDN documentation says it does, that's for the W3C model implemented by IE 9 and later).

Then:

>     mediaPart = sheetRules[a].media[0].split(' and ');

Note that media is a property of the sheet, not of a rule, so:

// Perhaps mediaParts (plural)?
      mediaPart = styleSheets[i].media;

And just to be nasty, the IE model has a media property with a type of string, but it's empty. You can get the text of it using:

styleSheets[0].cssText.replace(/\s+/g,' ').match(/@media.+}[^{]+}/)

.

>     // TypeError: mediaPart[1] is undefined
>     dimB = parseInt( mediaPart[1].replace(/[():A-Za-z$-]/g, "") );

Here you seem to be expecting "and" to be in the rule. You haven't provided an example of your rules, but if they are like:

@media screen, print { ... }

then media is a list of the media rules: media[0] is screen and media[1] is print, so you want to iterate over the media rules.

Anyhow, that's enough for now.

Post a Comment for "Using Javascript To Dynamically Add Styles To Stylesheet But I Get A "cannot Read Property 'length' Of Undefined" Error"