Created
April 21, 2019 09:40
-
-
Save obenjiro/0170e1a3badc90c90827136d3d1c8b53 to your computer and use it in GitHub Desktop.
HTML Clipper Fixed Version
This file contains 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
/* | |
HtmlClipper v0.1 | |
Made by Florentin Sardan | |
florentinwww (at) gmail.com | |
Project's page: | |
http://www.betterprogramming.com/htmlclipper.html | |
My portfolio: | |
http://www.betterprogramming.com | |
*/ | |
String.prototype.startsWith = function(str) {return (this.match("^"+str)==str);}; | |
String.prototype.endsWith = function(str) {return (this.match(str+"$")==str);}; | |
String.prototype.format = function(){ | |
var pattern = /\{\d+\}/g; | |
var args = arguments; | |
return this.replace(pattern, function(capture){ return args[capture.match(/\d+/)]; }); | |
}; | |
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g,""); }; | |
// var result = "Hello {0}! This is {1}.".format("world","foo bar"); | |
Array.prototype.contains = function(obj) { | |
var i = this.length; | |
while (i--) { | |
if (this[i].toLowerCase() == obj.toLowerCase()) { | |
return true; | |
} | |
} | |
return false; | |
}; | |
var flo = new function() { | |
var d = document; | |
var sessionCode = randomString(3); | |
var lastObj = []; | |
var activeObj = null; | |
var cachedStyles = {}; | |
var global = []; // temporary tests | |
var styleTpl = ".{0} { {1} }\n"; | |
var properties = ["opacity","filter","azimuth","background","background-attachment","background-color","background-image","background-position","background-repeat","border","border-collapse","border-color","border-spacing","border-style","border-top","border-right","border-bottom","border-left","border-top-color","border-right-color","border-bottom-color","border-left-color","border-top-style","border-right-style","border-bottom-style","border-left-style","border-top-width","border-right-width","border-bottom-width","border-left-width","border-width","bottom","caption-side","clear","clip","color","content","counter-increment","counter-reset","cue","cue-after","cue-before","cursor","direction","display","elevation","empty-cells","css-float","font","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","height","left","letter-spacing","line-height","list-style","list-style-image","list-style-position","list-style-type","margin","margin-top","margin-right","margin-bottom","margin-left","marker-offset","marks","max-height","max-width","min-height","min-width","orphans","outline","outline-color","outline-style","outline-width","overflow","padding","padding-top","padding-right","padding-bottom","padding-left","page","page-break-after","page-break-before","page-break-inside","pause","pause-after","pause-before","pitch","pitch-range","play-during","position","quotes","richness","right","size","speak","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","table-layout","text-align","text-decoration","text-indent","text-shadow","text-transform","top","unicode-bidi","vertical-align","visibility","voice-family","volume","white-space","widows","width","word-spacing","z-index"].sort(); | |
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
/* SHA-1 implementation in JavaScript (c) Chris Veness 2002-2009 */ | |
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
function sha1Hash(msg) { | |
// constants [§4.2.1] | |
var K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6]; | |
// PREPROCESSING | |
msg += String.fromCharCode(0x80); // add trailing '1' bit (+ 0's padding) to string [§5.1.1] | |
// convert string msg into 512-bit/16-integer blocks arrays of ints [§5.2.1] | |
var l = msg.length/4 + 2; // length (in 32-bit integers) of msg + ‘1’ + appended length | |
var N = Math.ceil(l/16); // number of 16-integer-blocks required to hold 'l' ints | |
var M = new Array(N); | |
for (var i=0; i<N; i++) { | |
M[i] = new Array(16); | |
for (var j=0; j<16; j++) { // encode 4 chars per integer, big-endian encoding | |
M[i][j] = (msg.charCodeAt(i*64+j*4)<<24) | (msg.charCodeAt(i*64+j*4+1)<<16) | | |
(msg.charCodeAt(i*64+j*4+2)<<8) | (msg.charCodeAt(i*64+j*4+3)); | |
} | |
} | |
// add length (in bits) into final pair of 32-bit integers (big-endian) [5.1.1] | |
// note: most significant word would be (len-1)*8 >>> 32, but since JS converts | |
// bitwise-op args to 32 bits, we need to simulate this by arithmetic operators | |
M[N-1][14] = ((msg.length-1)*8) / Math.pow(2, 32); M[N-1][14] = Math.floor(M[N-1][14]); | |
M[N-1][15] = ((msg.length-1)*8) & 0xffffffff; | |
// set initial hash value [§5.3.1] | |
var H0 = 0x67452301; | |
var H1 = 0xefcdab89; | |
var H2 = 0x98badcfe; | |
var H3 = 0x10325476; | |
var H4 = 0xc3d2e1f0; | |
// HASH COMPUTATION [§6.1.2] | |
var W = new Array(80); var a, b, c, d, e; | |
for (var i=0; i<N; i++) { | |
// 1 - prepare message schedule 'W' | |
for (var t=0; t<16; t++) W[t] = M[i][t]; | |
for (var t=16; t<80; t++) W[t] = ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1); | |
// 2 - initialise five working variables a, b, c, d, e with previous hash value | |
a = H0; b = H1; c = H2; d = H3; e = H4; | |
// 3 - main loop | |
for (var t=0; t<80; t++) { | |
var s = Math.floor(t/20); // seq for blocks of 'f' functions and 'K' constants | |
var T = (ROTL(a,5) + f(s,b,c,d) + e + K[s] + W[t]) & 0xffffffff; | |
e = d; | |
d = c; | |
c = ROTL(b, 30); | |
b = a; | |
a = T; | |
} | |
// 4 - compute the new intermediate hash value | |
H0 = (H0+a) & 0xffffffff; // note 'addition modulo 2^32' | |
H1 = (H1+b) & 0xffffffff; | |
H2 = (H2+c) & 0xffffffff; | |
H3 = (H3+d) & 0xffffffff; | |
H4 = (H4+e) & 0xffffffff; | |
} | |
return H0.toHexStr() + H1.toHexStr() + H2.toHexStr() + H3.toHexStr() + H4.toHexStr(); | |
} | |
// | |
// function 'f' [§4.1.1] | |
// | |
function f(s, x, y, z) { | |
switch (s) { | |
case 0: return (x & y) ^ (~x & z); // Ch() | |
case 1: return x ^ y ^ z; // Parity() | |
case 2: return (x & y) ^ (x & z) ^ (y & z); // Maj() | |
case 3: return x ^ y ^ z; // Parity() | |
} | |
} | |
// | |
// rotate left (circular left shift) value x by n positions [§3.2.5] | |
// | |
function ROTL(x, n) { | |
return (x<<n) | (x>>>(32-n)); | |
} | |
// | |
// extend Number class with a tailored hex-string method | |
// (note toString(16) is implementation-dependant, and | |
// in IE returns signed numbers when used on full words) | |
// | |
Number.prototype.toHexStr = function() { | |
var s="", v; | |
for (var i=7; i>=0; i--) { v = (this>>>(i*4)) & 0xf; s += v.toString(16); } | |
return s; | |
}; | |
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
function convertRGB(str) { | |
var start = str.indexOf('rgb('); | |
var end = str.indexOf(')', start); | |
if (start == -1 || end == -1) { | |
return str; | |
} | |
var col = str.slice(start + 4, end).replace(/ +/g, ''); | |
var rgbArray = col.split(','); | |
var colourStr = '#' + (rgbArray[0] << 16 | rgbArray[1] << 8 | rgbArray[2]).toString(16); | |
while (colourStr.length < 7) { | |
colourStr += '0'; | |
} | |
return str.substr(0, start) + colourStr + str.substring(end + 1); | |
}; | |
function unquoteXml (result) { | |
result = result.replace(/</g, "<"); | |
result = result.replace(/>/g, ">"); | |
result = result.replace(/"/g, "\""); | |
result = result.replace(/'/g, "'"); | |
return result; | |
} | |
function len(obj) { | |
var total = 0; | |
for(var key in obj) { | |
total +=1; | |
}; | |
return total; | |
}; | |
function getXPathForElement(el, xml) { | |
var xpath = ''; | |
var pos, tempitem2; | |
while(el !== xml.documentElement) { | |
pos = 0; | |
tempitem2 = el; | |
while(tempitem2) { | |
if (tempitem2.nodeType === 1 && tempitem2.nodeName === el.nodeName) { // If it is ELEMENT_NODE of the same name | |
pos += 1; | |
} | |
tempitem2 = tempitem2.previousSibling; | |
} | |
//xpath = "*[name()='"+el.nodeName+"']["+pos+']'+'/'+xpath; | |
xpath = el.nodeName+"["+pos+']'+'/'+xpath; | |
el = el.parentNode; | |
} | |
//xpath = '/*'+"[name()='"+xml.documentElement.nodeName+"']"+'/'+xpath; | |
xpath = '/'+xml.documentElement.nodeName+'/'+xpath; | |
xpath = xpath.replace(/\/$/, ''); | |
return xpath; | |
}; | |
function so_removeObj() { | |
activeObj.parentNode.removeChild(activeObj); | |
} | |
function so_cleanUp() { | |
var popup = d.getElementById('flo-popup'); | |
if (popup) | |
d.documentElement.removeChild(popup); | |
}; | |
function count(obj) { | |
var element_count = 0; | |
for (e in obj) { element_count++; } | |
return element_count; | |
}; | |
function so_showParentObj() { | |
if(activeObj.parentNode && activeObj.tagName != "HTML") { | |
change_active(activeObj.parentNode); | |
} | |
}; | |
function randomString(length) { | |
var length = length ? length : 10; | |
var chars = "abcdefghijklmnopqrstuvwxyz"; | |
var pass = ""; | |
for(var x=0;x<length;x++) { | |
var i = Math.floor(Math.random() * 26); | |
pass += chars.charAt(i); | |
} | |
return pass; | |
}; | |
function getView(node, doc) { | |
if (node && node.nodeType==1) { | |
var view = doc.defaultView ? doc.defaultView.getComputedStyle(node, null):node.currentStyle; | |
} | |
else { | |
var view = null; | |
} | |
return view; | |
}; | |
function getPopup() { | |
var popup = d.createElement("div"); | |
popup.setAttribute('id', 'flo-popup'); | |
popup.style.cssText='position: absolute;top: 10%;left: 10%;width: 80%;height: 80%;padding: 16px;border: 16px solid orange;background-color: white;z-index:10000000000;overflow: auto;'; | |
return popup; | |
}; | |
function getTextarea() { | |
var ta = d.createElement("textarea"); | |
ta.setAttribute('id', 'flo-textarea'); | |
ta.style.cssText='width:99%;height:200px'; | |
return ta; | |
}; | |
function getIframe() { | |
var iframe = d.createElement("iframe"); | |
iframe.src = "/"; | |
iframe.setAttribute('id', 'flo-iframe'); | |
iframe.style.width = '99%'; | |
iframe.style.height = '70%'; | |
iframe.style.background = '#FFF'; | |
/* | |
//idoc.open(); | |
idoc.write(htmlcontent); | |
idoc.close(); | |
*/ | |
return iframe; | |
}; | |
function getStyle(node, doc) { | |
// return all the style attributes of a node | |
var result = {}; | |
var ncs = getView(node, doc); | |
if (!ncs) return result; | |
for (var i=0; i<ncs.length; ++i) { | |
var e = ncs.item(i); // style name | |
if (e==undefined) continue; | |
if (e.startsWith('-moz-')) continue; | |
// TODO: enable this ? | |
//if (!properties.contains(e)) continue; | |
var v = ncs.getPropertyValue(e); // style value | |
/* | |
if (v.startsWith('rgb')) { | |
v = convertRGB(v); | |
} | |
*/ | |
result[e] = v; | |
} | |
return result; | |
}; | |
function unserializeStyle(str) { | |
var result = {}; | |
if (!str) return result; | |
var parts = str.split(' ; '); | |
//parts.pop(); // str ends with ; so parts[-1] will be empty | |
for (var i=0;i<parts.length;i++) { | |
if (!parts[i]) continue; | |
var ev = parts[i].split(' : '); | |
result[ev[0]] = ev[1]; | |
} | |
return result; | |
}; | |
function serializeStyle(obj) { | |
var result = ''; | |
for (var key in obj) { | |
result += key+" : "+obj[key]+" ; "; | |
} | |
return result.trim(); | |
}; | |
function getTargetNode(node) { | |
// given node, sets an attribute called "flo-style" on each child with the current style | |
var backupNode = node.cloneNode(true); | |
setStyleOnNode(node); | |
node.parentNode.replaceChild(backupNode, node); | |
delete backupNode; | |
return node; | |
}; | |
/* | |
function deleteAllStyles(doc) { | |
for (var i=0;i < doc.styleSheets.length;i++) { | |
var sstyle = doc.styleSheets.item(i); | |
var srules = sstyle.cssRules; | |
for(var j=0;j<srules.length;i++) { | |
sstyle.deleteRule(j); | |
} | |
} | |
} | |
*/ | |
function disableAllStyles(doc, how) { | |
if (how==null) how = true; | |
for (var i in doc.styleSheets.length) { | |
doc.styleSheets.item(i).disabled = how; | |
} | |
}; | |
function diffStyle(defaultStyle, nodeStyle) { | |
result = {}; | |
for (var key in nodeStyle) { | |
if ( defaultStyle[key]!=nodeStyle[key] ) { // key.match('^border\-.*?\-width$') || | |
result[key] = nodeStyle[key]; | |
} | |
} | |
return result; | |
} | |
function setStyleOnNode(node) { | |
var newStyle = getStyle(node, d); | |
var hash = sha1Hash(newStyle); | |
var nodeId = node.tagName.toLowerCase()+"-"+len(cachedStyles)+"-"+sessionCode; | |
cachedStyles[nodeId] = {'master':newStyle, 'style':newStyle, 'cls':nodeId, 'hash':hash}; // style, class name, style hash | |
node.setAttribute('flo-id', nodeId); // overwrite any old classes | |
for (var i=0, l=node.children.length;i<l;i++) { | |
setStyleOnNode(node.children.item(i)); | |
} | |
}; | |
function cleanIframeStyleNode(doc, node, dontfollow) { | |
// reads the final node style, removes it's class, reads the default style, compute the difference and update the styles cache | |
// later all the styles are rescribed | |
var nodeId = node.getAttribute('flo-id'); | |
if (nodeId==null) return false; | |
var cachedStyle = cachedStyles[nodeId]; | |
// remove existing class and style | |
node.removeAttribute('class'); | |
node.removeAttribute('style'); | |
//node.setAttribute('class', cachedStyle.cls); | |
var defaultStyle = getStyle(node, doc); | |
var floStyle = cachedStyle.master; | |
var diffObj = diffStyle(defaultStyle, floStyle); | |
function whatup(diffObj) { | |
cachedStyle.style = diffObj; | |
setClassForStyle(doc, cachedStyle); | |
replaceIframeStyle(doc, cachedStyle.cls, cachedStyle.style); | |
node.setAttribute('class', cachedStyle.cls); | |
} | |
if (len(diffObj)) { | |
whatup(diffObj); | |
var newStyle = getStyle(node, doc); | |
var diffObjNew = diffStyle(newStyle, floStyle); | |
// more differences ? | |
if (len(diffObjNew)) { | |
for (var key in diffObjNew) { | |
diffObj[key] = diffObjNew[key]; | |
} | |
whatup(diffObj); | |
} | |
} | |
else { | |
cachedStyle.style = null; | |
replaceIframeStyle(doc, cachedStyle.cls); | |
} | |
node.removeAttribute('flo-style'); | |
node.removeAttribute('flo-id'); | |
if (dontfollow==undefined) { | |
cleanIframeStyle(doc, node); | |
} | |
} | |
function cleanIframeStyle(doc, node) { | |
var children=node.children; | |
if (!children.length) return; | |
for (var i=0;i < children.length;i++) { | |
cleanIframeStyleNode(doc, children.item(i)); | |
} | |
} | |
function setClassForStyle(doc, cachedStyle) { | |
// TODO: need to fix this, only choose a style of a node which was already processed | |
for (var key in cachedStyles) { | |
if (cachedStyles[key].cls==cachedStyle.cls) return false; | |
if (serializeStyle(cachedStyles[key].style)==serializeStyle(cachedStyle.style)) { | |
replaceIframeStyle(doc, cachedStyle.cls); // remove unused class | |
cachedStyle.cls = cachedStyles[key].cls; | |
return true; | |
} | |
} | |
return false; | |
} | |
function replaceIframeStyle(doc, className, styleObj) { | |
var styleText = serializeStyle(styleObj); | |
// if cachedStyle is undefined, only delete the className rule | |
var sstyle = doc.styleSheets.item(1); | |
var srules = sstyle.cssRules; | |
for (var index=0;index<srules.length;index++) { | |
if (srules.item(index).selectorText=="."+className) { | |
sstyle.deleteRule(index); | |
if (styleText) { | |
sstyle.insertRule(styleTpl.format(className, styleText) , index); | |
} | |
} | |
} | |
} | |
function renewIframeStyles(doc) { | |
// TODO: remove old styles | |
var sstyle = doc.styleSheets.item(1); | |
var srules = sstyle.cssRules; | |
for (var key in cachedStyles) { | |
sstyle.insertRule(styleTpl.format(cachedStyles[key].cls, serializeStyle(cachedStyles[key].style)) , srules.length); | |
} | |
} | |
function getIframeWindow(iframeElement){ | |
return iframeElement.contentWindow || iframeElement.contentDocument.parentWindow; | |
} | |
function showStyle() { | |
clean_active(); | |
cachedStyles = {}; // clean style cache | |
// TODO: don't use global cachedStyles anymore | |
var node = activeObj; | |
var targetNode = getTargetNode(node); | |
var popup = getPopup(); | |
var iframe = getIframe(); | |
var textarea = getTextarea(); | |
d.documentElement.appendChild(popup); | |
popup.appendChild(iframe); | |
var iframewin = getIframeWindow(iframe); | |
var idoc = iframewin.document; | |
if(idoc == null) throw "Document not initialized"; | |
var tempNode = idoc.createElement('div'); | |
tempNode.appendChild(targetNode); | |
//var resetCss = '<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.0r4/build/reset/reset-min.css" />'+"\n"; | |
var xresetCss = '<style type="text/css">html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:\'\';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}body{text-align:center;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}'+ | |
'#yui-main .yui-b{position:static;}#yui-main,.yui-g .yui-u .yui-g{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}'+ | |
'.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-g .yui-u{width:48.1%;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}'+ | |
'.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}.yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#hd:after,#bd:after,#ft:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#hd,#bd,#ft,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;}</style>'; | |
var xresetCss = '<style type="text/css">html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;}body {line-height:1.5;}table {border-collapse:separate;border-spacing:0;}caption, th, td {text-align:left;font-weight:normal;}table, td, th {vertical-align:middle;}blockquote:before, blockquote:after, q:before, q:after {content:"";}blockquote, q {quotes:"" "";}a img {border:none;}</style>'; | |
var resetCss = '<style type="text/css"></style>'; | |
var tpl = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'+"\n"+ | |
'<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'+"\n"+ | |
resetCss+ | |
'<style type="text/css">'+"\n{0}\n</style>\n"+ | |
"</head><body>\n{1}\n</body></html>"; | |
idoc.write(tpl.format('', tempNode.innerHTML)); | |
//disableAllStyles(d, true); | |
renewIframeStyles(idoc); // append each style from cachedStyles to the iframe's stylesheets | |
cleanIframeStyle(idoc, idoc.body); // .children[0] (leave the parent node alone) | |
//disableAllStyles(d, false); | |
idoc.close(); | |
// read all styles | |
var cssText = ''; | |
var sheet=idoc.styleSheets.item(1); | |
var rules = sheet.cssRules; | |
for(var i=0;i<rules.length;i++) { | |
cssText += rules.item(i).cssText+"\n"; | |
} | |
textarea.value = tpl.format(cssText, idoc.body.innerHTML); | |
popup.appendChild(textarea); | |
}; | |
function clean_active() { | |
if (activeObj) activeObj.style.outline = ''; | |
el = d.getElementById('flo-xpath'); | |
if (el) el.parentNode.removeChild(el); | |
//activeObj.removeChild(activeObj.getElementById('xpath')); | |
}; | |
function change_active(newobj, undo) { | |
if (newobj) { | |
if (activeObj) { | |
clean_active(); | |
if (!undo) | |
lastObj.push(activeObj); | |
} | |
newobj.style.outline = '#f00 solid 2px'; | |
activeObj = newobj; | |
var tempNode = d.createElement('div'); | |
tempNode.setAttribute('id', 'flo-xpath'); | |
tempNode.style.cssText='background-color:yellow;font-size:10px;top:0px;left:0px;position:absolute;'; | |
tempNode.innerHTML = getXPathForElement(activeObj, d); | |
d.documentElement.appendChild(tempNode); | |
} | |
}; | |
function clickEvent(event) { | |
event.preventDefault(); | |
event.stopPropagation(); | |
var node = d.elementFromPoint(event.clientX, event.clientY) | |
// ignore click on my own elements | |
if (!node.getAttribute('id') || !node.getAttribute('id').startsWith('flo-')) { | |
change_active(node); | |
} | |
} | |
function so_exit() { | |
clean_active(); | |
d.removeEventListener('keydown', so_captureKeyDownEvent, false); | |
d.removeEventListener('click', clickEvent, false); | |
alert("HtmlClipper is Off !"); | |
} | |
function browser_supported() { | |
if(navigator.product == 'Gecko') | |
return true; | |
else | |
return false; | |
} | |
this.init = function() { | |
if(!browser_supported()) { | |
alert("HtmlClipper only works on Firefox or Chrome."); | |
return false; | |
} | |
d.addEventListener('keydown', so_captureKeyDownEvent, false); | |
d.addEventListener('click', clickEvent, true); | |
/* | |
d.addEventListener('mouseover', downEvent, false) | |
*/ | |
alert("HtmlClipper is On !\n\n" + | |
"Click anywhere to select an element.\n"+ | |
"type W to select the parent element\n"+ | |
"type Q to undo selection of parent element\n"+ | |
"type R to remove the selected element\n"+ | |
"type S to clip the selected element\n"+ | |
"type ESC to remove the clip window\n"+ | |
"type X to exit HtmlClipper\n" | |
) | |
}; | |
function so_captureKeyDownEvent(e) { | |
var keyCode = d.all?window.event.keyCode:e.keyCode; | |
switch(keyCode) { | |
case 27: // esc | |
so_cleanUp(); | |
break; | |
case 82: // R | |
so_removeObj(); | |
break; | |
case 83: // S | |
showStyle(); | |
//showStylePop(); | |
break; | |
case 81: // Q | |
change_active(lastObj.pop(), true); | |
break; | |
case 87: // W | |
so_showParentObj(); | |
break; | |
case 88: // x | |
so_exit(); | |
break; | |
} | |
}; | |
}; | |
flo.init(); | |
// TODO: parent/body background ? | |
// TODO: replace relative urls with absolute ones | |
// TODO: wrapper element must have full class | |
// TODO: a:hover | |
// TODO: add siblings |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment