Adding or Deleting a Rule

Find index of rule

To add a rule or delete one you want to know a rule’s index. You want to dynamically determine the numeric index of a rule in cross-browser

Let’s code a helper function findIndex().

  • It returns the loop variable i which will be the index of the desired rule.
  • When there is no rule in the style sheet, the return value will be undefined rather than null.

It returns undefined because findIndex() ought to return a number. Those are stored on the stack, and undefined conveys no value on the stack.

snippet
function findIndex(element, selector) {
    var sheet = element.sheet || element.styleSheet;
    var rules = sheet.cssRules || sheet.rules;
    selector = selector.toLowerCase()
    for (var i = rules.length - 1; i > -1; i--) {
        if (rules[i].selectorText && rules[i].selectorText.toLowerCase() === selector) {
            return i;
        }
    }
}

Find the numeric index of the rule with the "a#adidas" selector with findIndex()

findIndex(document.getElementById("spriteStyles"), "a#adidas");
Adding a Rule to a Style Sheet

With the numeric index of a rule, we can explore how to insert a rule into a style sheet.

Lets code the helper function insertRule().

This function has four parameters:

ParameterDescription
elementwill be a <link> or <style> Element node.
selectorwill be the text of the selector for the new rule, in other words, a string like "div#running li".
declarationswill be the text of the declaration block, minus the curly braces, such as a string like "top:135px; background-position:0 -81px".
indexcontains the text of the selector for the rule you want to insert the new rule before. So, that’s the selector string we will pass to findIndex(), which will then return a numeric index, or undefined.
function insertRule(element, selector, declarations, index) {
}

Now let’s move on to the body of our helper function.

  1. Assign either the DOM or Internet Explorer member that contains the CSSStyleSheet object to a local variable named sheet.
  2. Similarly, assign the DOM or Internet Explorer member that contains the CSSRuleList array-like object to one named rules.
  3. Let’s make the index parameter optional by way of a couple if statements. JavaScript will run the block of the first if statement in the event that we did pass a selector string for the value of index.
  4. When index is not passed, index defaults to undefined. Let’s overwrite that value with rules.length, which contains a number one greater than the total number of rules in the style sheet. Later, this numeric index will enable us to append the new rule to the very end of the style sheet.

So far we have this:

snippet
function insertRule(element, selector, declarations, index) {
    var sheet = element.sheet || element.styleSheet;
    var rules = sheet.cssRules || sheet.rules;
    if (typeof index === "string") {
        index = findIndex(element, index);
    }
    if (typeof index !== "number") {
        index = rules.length;
    }
}

Now sheet will contain either a DOM method named insertRule() or an Internet Explorer method named addRule().

When Firefox, Safari, or Opera is running our function, insertRule() will be defined. This method takes two parameters:

  • The full text of the rule, curly braces and all. So, we will cobble that together with the + operator.
  • The numeric index of the new rule.

For Internet Explorer to run. Its method, addRule(), takes three parameters:

The text for the selector, the text for the declarations, and the numeric index for where to insert the rule.

Simply pass in the values of selector, declarations, and index.

snippet
function insertRule(element, selector, declarations, index) {
    var sheet = element.sheet || element.styleSheet;
    var rules = sheet.cssRules || sheet.rules;
    if (typeof index === "string") {
        index = findIndex(element, index);
    }
    if (typeof index !== "number") {
        index = rules.length;
    }
    if (sheet.insertRule) {
        sheet.insertRule(selector + "{" + declarations + "}", index);
    } else if (sheet.addRule) {
        sheet.addRule(selector, declarations, index);
    }
}
Insert a rule with a index parameter.
insertRule(document.getElementById("spriteStyles"), "ul.blue a", "background-image:url(images/fuchsia.gif)", "ul.fuchsia a");
Insert a rule without a index parameter.
insertRule(document.getElementById("spriteStyles"), "ul.blue a", "background-image:url(images/green.gif)");
Deleting a Rule from a Style Sheet

Let’s code a helper function to delete a rule from a style sheet. Similar to insertRule() we will have Firefox, Safari, and Opera invoke the DOM method, deleteRule(), and Internet Explorer will invoke its proprietary one, removeRule().

The helper functions insertRule() and deleteRule() are methods of window.The function has two named arguments:

  • The first one, element, will be a <link> or <style> Element node.
  • The second one, selector, will be the text of the selector for the rule to delete.

The DOM and Internet Explorer functions for deleting a rule are methods of a CSSStyleSheet object, we need to save a reference to the one containing the rule to delete. Put that in a local variable named sheet. Then save the return value of passing element and selector to findIndex() to another local variable named index. If findIndex() return undefined instead of a number, we cannot delete a rule, So, write an if statement to abort deleteRule() in the event we have no numeric index to work with.

Thus far we have this:

function deleteRule(element, selector) {
    var sheet = element.sheet || element.styleSheet;
    var index = findIndex(element, selector);
    if (typeof index !== "number") {
        return;
    }
}

Both the DOM and Internet Explorer methods work with one parameter, the numeric index of the rule to delete.

snippet
function deleteRule(element, selector) {
    var sheet = element.sheet || element.styleSheet;
    var index = findIndex(element, selector);
    if (typeof index !== "number") {
        return;
    }
    if (sheet.deleteRule) {
        sheet.deleteRule(index);
    } else if (sheet.removeRule) {
        sheet.removeRule(index);
    }
}

We delete a rule just added with insertRule(). Those both have a selector of "ul.blue a". We pass "ul.blue a" to deleteRule().

deleteRule(document.getElementById("spriteStyles"), "ul.blue a");
Related Tutorial
Follow Us
https://www.facebook.com/Rookie-Nerd-638990322793530 https://twitter.com/RookieNerdTutor https://plus.google.com/b/117136517396468545840 #
Contents +