Last active
October 9, 2018 21:50
-
-
Save PseudoSky/816cd61cf9978ec6aec2 to your computer and use it in GitHub Desktop.
Javascript function that will export all current css arrtibutes on a dom element
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Element.prototype.es = (function () { | |
// Mapping between tag names and css default values lookup tables. This allows to exclude default values in the result. | |
var defaultStylesByTagName = {}; | |
// Styles inherited from style sheets will not be rendered for elements with these tag names | |
var noStyleTags = {"BASE":true,"HEAD":true,"META":true,"NOFRAME":true,"NOSCRIPT":true,"PARAM":true,"SCRIPT":true,"STYLE":true,"TITLE":true}; | |
// This list determines which css default values lookup tables are precomputed at load time | |
// Lookup tables for other tag names will be automatically built at runtime if needed | |
var tagNames = ["A","ABBR","ADDRESS","AREA","ARTICLE","ASIDE","AUDIO","B","BASE","BDI","BDO","BLOCKQUOTE","BODY","BR","BUTTON","CANVAS","CAPTION","CENTER","CITE","CODE","COL","COLGROUP","COMMAND","DATALIST","DD","DEL","DETAILS","DFN","DIV","DL","DT","EM","EMBED","FIELDSET","FIGCAPTION","FIGURE","FONT","FOOTER","FORM","H1","H2","H3","H4","H5","H6","HEAD","HEADER","HGROUP","HR","HTML","I","IFRAME","IMG","INPUT","INS","KBD","KEYGEN","LABEL","LEGEND","LI","LINK","MAP","MARK","MATH","MENU","META","METER","NAV","NOBR","NOSCRIPT","OBJECT","OL","OPTION","OPTGROUP","OUTPUT","P","PARAM","PRE","PROGRESS","Q","RP","RT","RUBY","S","SAMP","SCRIPT","SECTION","SELECT","SMALL","SOURCE","SPAN","STRONG","STYLE","SUB","SUMMARY","SUP","SVG","TABLE","TBODY","TD","TEXTAREA","TFOOT","TH","THEAD","TIME","TITLE","TR","TRACK","U","UL","VAR","VIDEO","WBR"]; | |
// Precompute the lookup tables. | |
for (var i = 0; i < tagNames.length; i++) { | |
if(!noStyleTags[tagNames[i]]) { | |
defaultStylesByTagName[tagNames[i]] = computeDefaultStyleByTagName(tagNames[i]); | |
} | |
} | |
function computeDefaultStyleByTagName(tagName) { | |
var defaultStyle = {}; | |
var element = document.body.appendChild(document.createElement(tagName)); | |
var computedStyle = getComputedStyle(element); | |
for (var i = 0; i < computedStyle.length; i++) { | |
defaultStyle[computedStyle[i]] = computedStyle[computedStyle[i]]; | |
} | |
document.body.removeChild(element); | |
return defaultStyle; | |
} | |
function getDefaultStyleByTagName(tagName) { | |
tagName = tagName.toUpperCase(); | |
if (!defaultStylesByTagName[tagName]) { | |
defaultStylesByTagName[tagName] = computeDefaultStyleByTagName(tagName); | |
} | |
return defaultStylesByTagName[tagName]; | |
} | |
return function es() { | |
if (this.nodeType !== Node.ELEMENT_NODE) { | |
return -1; | |
// throw new TypeError("The es method only works on elements, not on " + this.nodeType + " nodes."); | |
} | |
if (noStyleTags[this.tagName]) { | |
return -1; | |
throw new TypeError("The es method does not work on " + this.tagName + " elements."); | |
} | |
var styles = {}; | |
var computedStyle = getComputedStyle(this); | |
var defaultStyle = getDefaultStyleByTagName(this.tagName); | |
for (var i = 0; i < computedStyle.length; i++) { | |
var cssPropName = computedStyle[i]; | |
if (computedStyle[cssPropName] !== defaultStyle[cssPropName]) { | |
styles[cssPropName] = computedStyle[cssPropName]; | |
} | |
} | |
var a = ["{"]; | |
for(var i in styles) { | |
a[a.length] = i + ": " + styles[i] + ";"; | |
} | |
a[a.length] = "}" | |
return a.join("\r\n"); | |
} | |
})(); | |
/* | |
Grabs a HTMLElement's computed style from the es() function above, | |
Creates a string from it compatible with the element's inline style attribute. | |
Then sets the elements style attribute to that string. | |
PARAM: | |
e => HTML Element | |
max => Int (terminal depth) | |
depth => Int current depth | |
*/ | |
function inline(e,max,depth){ | |
max=max || 0; | |
depth=depth || 0; | |
if(typeof e === typeof ''){ | |
console.info('Inline passed a selector') | |
ele = $$(e) | |
if (ele.length) { | |
return ele.forEach((d) => inline(d, max, depth)) | |
} | |
} | |
console.log((new Array(depth*2).join(' '))+e.nodeName); | |
if(e.es){ | |
style=e.es() | |
if(style!=-1){ // The style computed successfully | |
style=style.replace('{','').replace('}','').split("\n").join('') | |
e.setAttribute('style',style); | |
} | |
} | |
if(max>depth && e.children){ | |
e.childNodes.forEach(function(child){ | |
console.log('CHILD',child); | |
inline(child,max,depth+1); | |
}) | |
} | |
} | |
/* | |
Runs the inline function for all css capable elements, | |
Resulting in a page with complete css. | |
*/ | |
function inline_errything(){ | |
var all = document.body.getElementsByTagName("*"); | |
inline(document.getElementsByTagName("html")[0]) | |
inline(document.body); | |
for (var i=0, max=all.length; i < max; i++) { | |
inline(all[i]) | |
} | |
} | |
StyleExport = { | |
inline, | |
inline_errything, | |
} | |
//TODO: add pseudo selector simulation with set difference | |
/* | |
baseStyle = $$('#element')[0].es() | |
classLines = new Set(baseStyle.split('\n')) | |
$$('#element')[0].focus() | |
focusStyle = $$('#element')[0].es() | |
focusClass = focusStyle.split('\n').filter(line => !classLines.has(line)).join('\n') | |
baseClass = classLines.toJSON().join('\n') | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example On this page
Before
Pasted in
After
Not too sure yet why the highlighting goes away, but overall success.