0

I have a list of CSS classes defined in app.css as

.eventcolor-1{background:rgba(249, 115, 0);}
.eventcolor-2{background:rgba(14, 48, 71, 0.99);}
.eventcolor-3{background:rgba(16, 130, 140, 0.99);}
.eventcolor-4{background:rgba(41, 91, 167, 0.99);}
.eventcolor-5{background:rgba(148, 172, 60, 0.99)}
.eventcolor-6{background:rgba(252, 195, 20, 0.99);} 

In jQuery I need a method that will pull up all the .eventcolor-* currently available, and add them to an array.

The problem is, here's an accepted solution for this task: https://stackoverflow.com/a/18378434/1005607

function getClassNamesByPattern(pattern) {
    var pattern = "eventcolor-*";
    var selectors = {};

    for (var i = 0; i < document.styleSheets.length; i++) {
        var classes = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
        for (var x = 0; x < classes.length; x++) {
            if (undefined !== classes[x].selectorText && null !== classes[x].selectorText.match(new RegExp('\\.' + pattern.replace(/([^\s])\*/, '$1[^ ]+'), 'g'))) {
                selectors[classes[x].selectorText] = classes[x].selectorText;
            }
        }
    }

    return Object.keys(selectors);
}

But this throws a Security Error in Firefox, because I'm going through CSS's I don't need. I don't need to include everything in my app, just the custom file app.css.

SecurityError: The operation is insecure.

Is there a safe way to restrict the search to just a given CSS?

gene b.
  • 10,512
  • 21
  • 115
  • 227

2 Answers2

1

You can filter out stylesheet into loop by using StyleSheet.ownerNode property of the CSSStyleSheet objects, you're iterating by.

Considering that you're including your stylesheet as a <link> it may look like:

function getClassNamesByPattern(pattern) {
    var pattern = "eventcolor-*";
    var selectors = {};

    for (var i = 0; i < document.styleSheets.length; i++) {
        var stylesheet = document.styleSheets[i];
        if (typeof stylesheet.ownerNode !== 'undefined') {
            // This is stylesheet linked from external source
            var ownerNode = stylesheet.ownerNode;
            if (typeof ownerNode.tagName === 'string' && ownerNode.tagName.toLowerCase() === 'link' && ownerNode.rel === 'stylesheet') {
                // This is stylesheet linked through <link rel="stylesheet">
                var href = ownerNode.href;
                // Testing for filename match, you can update it to match your needs
                if (!href.match(/\/app\.css$/)) {
                    // Not inside our stylesheet - skip it
                    continue;
                }
            }
        }
        var classes = stylesheet.rules || stylesheet.cssRules;
        for (var x = 0; x < classes.length; x++) {
            if (undefined !== classes[x].selectorText && null !== classes[x].selectorText.match(new RegExp('\\.' + pattern.replace(/([^\s])\*/, '$1[^ ]+'), 'g'))) {
                selectors[classes[x].selectorText] = classes[x].selectorText;
            }
        }
    }

    return Object.keys(selectors);
}
Flying
  • 4,422
  • 2
  • 17
  • 25
  • Thanks. I also found that "document.styleSheets[i].href" holds the name of the current CSS, so I can check that directly. – gene b. Oct 29 '17 at 23:38
0

I also found this easy way:

document.styleSheets[i].href contains the name of the CSS currently being examined.

Thus, we can check document.styleSheets[i].href.indexOf("app.css") != -1

gene b.
  • 10,512
  • 21
  • 115
  • 227