-
-
Save PaulKinlan/6284142 to your computer and use it in GitHub Desktop.
(function() { | |
var CSSCriticalPath = function(w, d, opts) { | |
var opt = opts || {}; | |
var css = {}; | |
var pushCSS = function(r) { | |
if(!!css[r.selectorText] === false) css[r.selectorText] = {}; | |
var styles = r.style.cssText.split(/;(?![A-Za-z0-9])/); | |
for(var i = 0; i < styles.length; i++) { | |
if(!!styles[i] === false) continue; | |
var pair = styles[i].split(": "); | |
pair[0] = pair[0].trim(); | |
pair[1] = pair[1].trim(); | |
css[r.selectorText][pair[0]] = pair[1]; | |
} | |
}; | |
var parseTree = function() { | |
// Get a list of all the elements in the view. | |
var height = w.innerHeight; | |
var walker = d.createTreeWalker(d, NodeFilter.SHOW_ELEMENT, function(node) { return NodeFilter.FILTER_ACCEPT; }, true); | |
while(walker.nextNode()) { | |
var node = walker.currentNode; | |
var rect = node.getBoundingClientRect(); | |
if(rect.top < height || opt.scanFullPage) { | |
var rules = w.getMatchedCSSRules(node); | |
if(!!rules) { | |
for(var r = 0; r < rules.length; r++) { | |
pushCSS(rules[r]); | |
} | |
} | |
} | |
} | |
}; | |
this.generateCSS = function() { | |
var finalCSS = ""; | |
for(var k in css) { | |
finalCSS += k + " { "; | |
for(var j in css[k]) { | |
finalCSS += j + ": " + css[k][j] + "; "; | |
} | |
finalCSS += "}\n"; | |
} | |
return finalCSS; | |
}; | |
parseTree(); | |
}; | |
var cp = new CSSCriticalPath(window, document); | |
var css = cp.generateCSS(); | |
console.log(css); | |
})(); |
FWIW I also made a version of the bookmarklet, and I even accounted for some cases where the cssRules
or rules
property threw an error on access.
I get Uncaught TypeError: w.getMatchedCSSRules is not a function
, using Chrome
I get
Uncaught TypeError: w.getMatchedCSSRules is not a function
, using Chrome
My re-fashioning used a polyfill for that; getMatchedCSSRules
was never standardized, and it was removed from Chrome starting with version 63.
I was able to get it working by replacing getMatchedCSSRules
with the script below. However doesn't work if css is from a different domain.
var getCSS = function(el) {
var sheets = document.styleSheets, ret = [];
el.matches = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector
|| el.msMatchesSelector || el.oMatchesSelector;
for (var i in sheets) {
var rules;
try {
rules = sheets[i].rules;
} catch {
console.log("Error reading rules: ");
try{
rules = sheets[i].cssRules;
} catch {
console.log("Error reading cssRules: ");
}
}
```
this library is probably the way to go: https://www.brothercake.com/site/resources/scripts/cssutilities/
Your example script was not complete, but I imagine the rest of the way you'd do it is to test the element against each rule to see whether it matches.
got it! Now what I see is not wrapped in <style></style> tags, and I believe I am supposed to put what is wrapped in those style tags in the AO inline and defer css box. I don't want to crash my site (which I have managed to do before on things like this), so I want to be sure I have extracted the correct code to put in that AO field....