SO #20249222: get elements with pseudo-elements

Link: http://stackoverflow.com/questions/20249222/how-to-loop-over-all-elements-on-a-page-including-pseudo-elements/20286910

by Jordan

HTML

<p><span>Test</span></p>
<div><span></span></div>

CSS

p, p:after {
    content: ' (after) ';
}

p::before, span:before {
    content: ' (before) ';
}

div {
    font-weight: bold;
}
}

JavaScript

function getPseudoElementSelectors() {
    var matchPseudoSelector = /:{1,2}(after|before)/,
        found = { before: [], after: [] };
    
    if (!(document.styleSheets && document.styleSheets.length)) return found;
    
    return Array.from(document.styleSheets)
        .reduce(function(pseudoSelectors, sheet) {
            try {
                if (!sheet.cssRules) return pseudoSelectors;
                
                // Get an array of all individual selectors.
                var ruleSelectors = Array.from(sheet.cssRules)
                    .reduce(function(selectors, rule) {
                        return (rule && rule.selectorText)
                            ? selectors.concat(rule.selectorText.split(','))
                            : selectors;
                    }, []);
                
                // Construct a dictionary of rules with pseudo-elements.
                var rulePseudoSelectors = ruleSelectors.reduce(function(selectors, selector) {
                    
                    // Check if this selector has a pseudo-element.
                    if (matchPseudoSelector.test(selector)) {
                        var pseudoElement = matchPseudoSelector.exec(selector)[1],
                            cleanSelector = selector.replace(matchPseudoSelector, '').trim();
                        
                        selectors[pseudoElement].push(cleanSelector);
                    }
                    
                    return selectors;
                }, { before: [], after: [] });
                
                pseudoSelectors.before = pseudoSelectors.before.concat(rulePseudoSelectors.before);
                pseudoSelectors.after = pseudoSelectors.after.concat(rulePseudoSelectors.after);
            
            // Quietly handle errors from accessing cross-origin stylesheets.
            } catch (e) { if (console && console.warn) console.warn(e); }
            
            return pseudoSelectors;
                        
       ...