Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing (global) CSS styles from Javascript

Tags:

javascript

css

related question with unsatisfactory answers: Changing CSS Values with Javascript

Here's what I want to do. I'd like to be able to set a page element's class to some value, and have the browser animate it, for instance a table td whose background will be set to rgb(255*(cos(time)*.5+.5),0,0).

I can easily do this for a single element by setting a timer. But I might want to have multiple elements have this property, and having to keep track of a timer for each one isn't a great idea.

So what I'd like to do is to be able to change a CSS value from javascript.

I am looking at the code here and it strikes me as being a bit too heavy-handed for me to use from a timer. From the looks of it, each call I make to a function like changecss has me appending an entire css rule to every single stylesheet. This is going to majorly pollute the stylesheets internally and will probably result in a runaway memory leak if I call it in a loop every 33ms.

So I'm looking for a solution that will let me zero in on the rgb color setting within the css entry corresponding to a particular class. And modify it. I don't actually need to retrieve the original setting in this case. Can this be done? I'd like to support IE9 if possible, though IE 6,7,8 already screws up my project so much that I've given up on them.

like image 588
Steven Lu Avatar asked Oct 05 '11 06:10

Steven Lu


1 Answers

That answer has the basics. As a general solution, you need to find the last occurence of the class in a style sheet (i.e. iterate over all the style sheets to find the last occurence of the class rule), then either add a new rule after that or modify the last rule.

If you know the class only exists once, you can just get the first occurence and modify that. Or if you know the class isn't in the style sheets at all, just add it anywhere (say to the last style sheet) and go from there.

You could easily animate it by storing a reference to the rule and change it over time with setTimeout.

For example, my library routine for changing a css rule is:

/* Replace the cssText for rule matching selectorText with value
** Changes all matching rules in all style sheets
*/
function modifyStyleRule(selectorText, value) {
  var sheets = document.styleSheets;
  var sheet, rules, rule;
  var i, j, k, l;

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

    // W3C model
    if (sheet.cssRules) {
      rules = sheet.cssRules;

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

        if (rule.selectorText == selectorText) {
          removeRule(sheet, rule);
          addRule(sheet, selectorText, value);
        }
      }

    // IE model
    } else if (sheet.rules) {
      rules = sheet.rules;

      for (k=0, kLen=rules.length; k<kLen; k++) {
        rule = rules[k];

        // An alternative is to just modify rule.style.cssText,
        // but this way keeps it consistent with W3C model
        if (rule.selectorText == selectorText) {
          removeRule(sheet, rule);
          addRule(sheet, selectorText, value);

          // Alternative
          // rule.style.cssText = value;
        }
      }
    }
  }
}

/* Remove rule from supplied sheet
*/
function removeRule(sheet, rule) {

  // W3C model
  if (typeof sheet.deleteRule == 'function') {
    sheet.deleteRule(rule);

  // IE model
  } else if (sheet.removeRule) {
    sheet.removeRule(rule);
  }
}

/* Add rule from supplied sheet
** Rule is added as last rule in sheet
*/
function addRule(sheet, selectorText, value) {

  // W3C model
  if (typeof sheet.insertRule == 'function') {
    sheet.insertRule(selectorText + ' {' + value + '}', sheet.cssRules.length);

  // IE model
  } else if (sheet.addRule) {
    sheet.addRule(selectorText, value, sheet.rules.length);
  }
}

To animate a change, call the function with the same selector but different values using setTimeout.

like image 159
RobG Avatar answered Sep 30 '22 11:09

RobG