views:

54

answers:

4

What would be the regex I could use to completely remove a css rule from an inline stylesheet based on the selector that I provide, via javascript?

For example, I get the contents of the style tag and it contains a rule:

.some_class
{
    color: #FFF;
    font-style: italic;
}

If i provide the selector '.some_class' what is the correct regex/js method that will find any occurrence of that selector and remove it, its associated brackets, and all the properties/values within those brackets

A: 

Hi,

This should get you close - you might need to tweak for specific characters in your css name:value section.

.some_class\{([a-zA-Z0-9#]+:[a-zA-Z0-9#]+;\n)*\}

Enjoy!

Doug
thanks, ill give that a try :)
Bill Dami
this doesn't work on the example of Bill Dami
jigfox
Various things wrong here - you need to escape the `.` `{` and `}` characters in regex, the `{1}` after the colon is entirely unnecessary, and you're being both too explicit and too strict with accepted characters on both name and value side, and potential whitespace isn't correctly matched.
Peter Boughton
Ha Ha - Yes I agree with your comments Peter - but as my qualifier states "This should get you close"
Doug
A: 

I don't really understand what/why you're doing, but the existing expression is over-complex and looks wrong.

Here's a simple version:

^\s*\.some_class\s*\{[^}]*\}
Peter Boughton
+5  A: 

Consider correctly using the DOM API to achieve what you want, rather than a complex regular expression that may not work very well:

function deleteRule(selector) {
    // Get the collection of stylesheets and iterate over them
    var ss = document.styleSheets;

    // Exit if no stylesheets
    if (!ss.length)
        return;

    // Create an uppercase tagname version of our selector for IE
    var uSelector = selector.replace(/^[a-z]+|\s+[a-z]+/gi, function ($0) {
        return $0.toUpperCase();
    });

    // Create a map so we don't get SO's code block scrollbars involved
    var map = {};
    map[selector] = map[uSelector] = 1;

    // `deleteRule` for standards, `removeRule` for IE
    var del = "deleteRule" in ss[0] ? "deleteRule" : "removeRule";

    for (var a = 0, maxA = ss.length; a < maxA; a++) {
        // `cssRules` for standards, `rules` for IE
        var rules = ss[a].cssRules || ss[a].rules;

        for (var b = 0, maxB = rules.length; b < maxB; b++) {
            // Check for selector existence in our map
            if (rules[b].selectorText in map)
                ss[a][del](b);  // remove using our stored delete method
        }
    }
}

​ Bear in mind that browsers may reformat the stylesheet rule's selector to include whitespace (so body>div.selector becomes body > div.selector). You should try and be as consistent as possible with your whitespace in your CSS selectors. If you want to delete the rule from a specific stylesheet and not all stylesheets, eliminate the first for loop and specify the stylesheet object instead.

Example

Andy E
Slightly dodgy variable names, but definitely a better option than a (potentially fragile) regex solution.
Peter Boughton
@Peter: lol, yeah, they are a bit dodgy. I don't usually use variations of `i2` in subsequent for loops.
Andy E
Yeah this would definitely be a more robust and safer solution for what i am trying to accomplish, thank you :)
Bill Dami
one thing to keep in mind, IE returns element selectors (as well as most property names) capitalized, so if you are looking for a selector with an element base, like p.some_class, you'll need to look for P.some_class as well.
kennebec
@kennebec: thanks, I didn't realize IE did that. It seems all the browsers reformat selectors to include whitespace where necessary. I've updated the post with a solution that will work just as well in IE for those types of selectors.
Andy E
+1  A: 
var selector = ".some_class";
var pattern = new RegExp(selector.replace(/\./g, "\\.") + "\\s*{[^}]*?}", "gim");
$("style").html($("style").html().replace(pattern, ""));
serg
If you're using `new RegExp` syntax, I think you need to double escape the \ (so `\\s*`). Certainly you need to escape the `.` - not sure if JS supports the `\Q..\E` syntax, but that's an easy way if it does.
Peter Boughton
You are right and you are right. Thanks :)
serg