Skip to content

Instantly share code, notes, and snippets.

@PseudoSky
Last active October 9, 2018 21:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PseudoSky/816cd61cf9978ec6aec2 to your computer and use it in GitHub Desktop.
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
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')
*/
@PseudoSky
Copy link
Author

Example On this page

Before


screen shot 2016-02-10 at 1 02 52 am

Pasted in


screen shot 2016-02-10 at 1 03 12 am

After


screen shot 2016-02-10 at 1 03 33 am

Not too sure yet why the highlighting goes away, but overall success.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment