forked from nytimes/svg-crowbar
-
Notifications
You must be signed in to change notification settings - Fork 0
/
svg-crowbar.min.js
1 lines (1 loc) · 10.2 KB
/
svg-crowbar.min.js
1
const crowbar_deps={_window:window,_document:document};const crowbar=function(_deps){const _doctype='<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';_prefix={svg:"http://www.w3.org/2000/svg",xlink:"http://www.w3.org/1999/xlink",xmlns:"http://www.w3.org/2000/xmlns/"};window.URL=window.URL||window.webkitURL;function _getEmtpySvgStyle(){const empty_svg=window.document.createElementNS(_prefix.svg,"svg");return window.getComputedStyle(empty_svg)}function _initialize(){const documents=[window.document];const iframes=document.querySelectorAll("iframe");const objects=document.querySelectorAll("object");const emptySvgDeclarationComputed=_getEmtpySvgStyle();let SVGSources=getSources(window.document,emptySvgDeclarationComputed);SVGSources=[...iframes,...objects].reduce(function(filtered,element){if(element.contentDocument){const newSources=getSources(element.contentDocument,emptySvgDeclarationComputed);filtered=filtered.concat(newSources)}return filtered},SVGSources);if(!SVGSources.length){window.alert("The SVG Crowbar couldn’t find any SVG nodes.");return}console.log(SVGSources);_createPopover(SVGSources)}function _createShowDiv(){}function _createPopover(sources){_cleanup();sources.forEach(function(s1){sources.forEach(function(s2){if(s1!==s2){if(Math.abs(s1.top-s2.top)<38&&Math.abs(s1.left-s2.left)<38){s2.top+=38;s2.left+=38}}})});const buttonsContainer=document.createElement("div");buttonsContainer.setAttribute("class","svg-crowbar");document.body.appendChild(buttonsContainer);buttonsContainer.classList.add("crowbar-container");buttonsContainer.style["z-index"]=999999;buttonsContainer.style.position="absolute";buttonsContainer.style.top=0;buttonsContainer.style.left=0;const background=document.createElement("div");background.setAttribute("class","svg-crowbar");document.body.appendChild(background);background.classList.add("crowbar-background");background.style.background="rgba(255, 255, 255, 0.7)";background.style["z-index"]=999998;background.style.position="fixed";background.style.left=0;background.style.top=0;background.style.width="100%";background.style.height="100%";const showDiv=document.createElement("div");showDiv.setAttribute("class","svg-crowbar");showDiv.setAttribute("id","showDiv");document.body.appendChild(showDiv);const showDivHeader=document.createElement("div");showDivHeader.setAttribute("class","showDiv-header");showDiv.appendChild(showDivHeader);showDivHeader.style.background="black";showDivHeader.style.color="white";showDivHeader.style["font-size"]="14px";showDivHeader.style["text-align"]="center";const showText=document.createTextNode("SVG Visualizer");const showCrossBtn=document.createElement("button");showCrossBtn.setAttribute("class","crowbar-show-cross");showCrossBtn.style.color="white";showCrossBtn.style.background="transparent";showCrossBtn.style["font-weight"]="bold";showCrossBtn.style.border="none";showCrossBtn.style.outline="none";showCrossBtn.style.float="right";showCrossBtn.style.margin="0px";showCrossBtn.style.cursor="pointer";showCrossBtn.style["text-align"]="center";showCrossBtn.innerHTML="✖";showDivHeader.appendChild(showText);showDivHeader.appendChild(showCrossBtn);showCrossBtn.onclick=function(e){e.target.parentElement.parentElement.style.display="none"};const showDivBody=document.createElement("div");showDivBody.setAttribute("class","showDiv-body");showDivBody.style.padding="5px";showDiv.appendChild(showDivBody);showDiv.classList.add("crowbar-show-div");showDiv.style["z-index"]=9999999;showDiv.style.position="absolute";showDiv.style.width="300px";showDiv.style["min-width"]="300px";showDiv.style["min-height"]="300px";showDiv.style.cursor="move";showDiv.style.border="4px solid black";showDiv.style.setProperty("background","rgba(255, 255, 255, 0.9)","important");showDiv.style.top=0;showDiv.style.left=0;showDiv.style.display="none";_dragElement(showDiv);sources.forEach(function(d,i){const buttonWrapper=document.createElement("div");buttonWrapper.setAttribute("class","svg-crowbar");buttonsContainer.appendChild(buttonWrapper);buttonWrapper.classList.add("crowbar-btn-wrapper");buttonWrapper.style.position="absolute";buttonWrapper.style.top=d.top+"px";buttonWrapper.style.left=d.left+"px";buttonWrapper.style.padding="4px";buttonWrapper.style["border-radius"]="3px";buttonWrapper.style.setProperty("color","white","important");buttonWrapper.style.setProperty("text-align","center","important");buttonWrapper.style["font-family"]="'Helvetica Neue'";buttonWrapper.style.setProperty("background","rgba(0, 0, 0, 0.8)","important");buttonWrapper.style["box-shadow"]="0px 4px 18px rgba(0, 0, 0, 0.4)";buttonWrapper.style.cursor="move";const buttonHeader=document.createElement("div");buttonHeader.setAttribute("class","showDiv-header");buttonWrapper.appendChild(buttonHeader);buttonHeader.style.color="white";buttonHeader.style["font-size"]="14px";buttonHeader.style["text-align"]="left";const buttonHeaderText=document.createTextNode("SVG #"+i+": "+(d.id?"#"+d.id:"")+(d.class?"."+d.class:""));const buttonCrossBtn=document.createElement("button");buttonCrossBtn.setAttribute("class","crowbar-show-cross");buttonCrossBtn.style.color="white";buttonCrossBtn.style.background="transparent";buttonCrossBtn.style["font-weight"]="bold";buttonCrossBtn.style.border="none";buttonCrossBtn.style.outline="none";buttonCrossBtn.style.float="right";buttonCrossBtn.style.margin="0px";buttonCrossBtn.style.cursor="pointer";buttonCrossBtn.style["text-align"]="center";buttonCrossBtn.innerHTML="✖";buttonHeader.appendChild(buttonHeaderText);buttonHeader.appendChild(buttonCrossBtn);const button=document.createElement("button");button.setAttribute("class","crowbar-download");buttonWrapper.appendChild(button);button.setAttribute("data-source-id",i);button.style.width="130px";button.style["font-size"]="12px";button.style["line-height"]="1.4em";button.style.margin="5px 0 0 0";button.style.setProperty("color","black","important");button.style.cursor="pointer";button.style.setProperty("background","rgba(255, 255, 255, 0.9)","important");button.textContent="Download";const cross=document.createElement("button");cross.setAttribute("class","crowbar-cross");buttonWrapper.appendChild(cross);cross.style["font-size"]="14px";cross.style.margin="5px 0 0 0";cross.style.setProperty("color","black","important");cross.style.cursor="pointer";cross.style.padding="5px";cross.style.setProperty("background","rgba(255, 255, 255, 0.9)","important");cross.innerHTML="✖";const show=document.createElement("button");show.setAttribute("class","crowbar-show");buttonWrapper.appendChild(show);show.style.width="40px";show.style["font-size"]="12px";show.style["line-height"]="1.4em";show.style.margin="5px 0 0 0";show.style.setProperty("color","black","important");show.style.cursor="pointer";show.style.setProperty("background","rgba(255, 255, 255, 0.9)","important");show.textContent="Show";_dragElement(buttonWrapper);button.onclick=function(){_download(d)};cross.onclick=function(e){e.target.parentElement.remove()};show.onclick=function(){const showDiv=document.querySelector("#showDiv");const showDivBody=document.querySelector("#showDiv > .showDiv-body");showDivBody.innerHTML="";showDivBody.appendChild(d.element);showDiv.style.display="block"}})}function _cleanup(){const crowbarElements=document.querySelectorAll(".svg-crowbar");[...crowbarElements].forEach(element=>{element.remove()})}function getSources(document,emptySvgDeclarationComputed){const svgInfo=[];const svgs=document.querySelectorAll("svg");[...svgs].forEach(svg=>{svg.setAttribute("version","1.1");svg.removeAttribute("xmlns");svg.removeAttribute("xlink");if(!svg.hasAttributeNS(_prefix.xmlns,"xmlns")){svg.setAttributeNS(_prefix.xmlns,"xmlns",_prefix.svg)}if(!svg.hasAttributeNS(_prefix.xmlns,"xmlns:xlink")){svg.setAttributeNS(_prefix.xmlns,"xmlns:xlink",_prefix.xlink)}setInlineStyles(svg,emptySvgDeclarationComputed);const source=(new XMLSerializer).serializeToString(svg);rect=svg.getBoundingClientRect();svgInfo.push({top:rect.top,left:rect.left,width:rect.width,height:rect.height,id:svg.getAttribute("id"),class:svg.getAttribute("class"),name:svg.getAttribute("name"),childElementCount:svg.childElementCount,source:[_doctype+source],element:svg.cloneNode(true)})});return svgInfo}function _download(source){let filename="untitled";if(source.name){filename=source.name}else if(source.id){filename=source.id}else if(source.class){filename=source.class}else if(window.document.title){filename=window.document.title.replace(/[^a-z0-9]/gi,"-").toLowerCase()}const url=window.URL.createObjectURL(new Blob(source.source,{type:"text/xml"}));const a=document.createElement("a");document.body.appendChild(a);a.setAttribute("class","svg-crowbar");a.setAttribute("download",filename+".svg");a.setAttribute("href",url);a.style.display="none";a.click();setTimeout(function(){window.URL.revokeObjectURL(url)},10)}function setInlineStyles(svg,emptySvgDeclarationComputed){function explicitlySetStyle(element){const cSSStyleDeclarationComputed=getComputedStyle(element);let i,len,key,value;let computedStyleStr="";for(i=0,len=cSSStyleDeclarationComputed.length;i<len;i++){key=cSSStyleDeclarationComputed[i];value=cSSStyleDeclarationComputed.getPropertyValue(key);if(value!==emptySvgDeclarationComputed.getPropertyValue(key)){computedStyleStr+=key+":"+value+";"}}element.setAttribute("style",computedStyleStr)}function traverse(obj){const tree=[];tree.push(obj);visit(obj);function visit(node){if(node&&node.hasChildNodes()){let child=node.firstChild;while(child){if(child.nodeType===1&&child.nodeName!="SCRIPT"){tree.push(child);visit(child)}child=child.nextSibling}}}return tree}const allElements=traverse(svg);let i=allElements.length;while(i--){explicitlySetStyle(allElements[i])}}function _dragElement(element){let pos1=0;let pos2=0;let pos3=0;let pos4=0;element.onmousedown=dragMouseDown;function dragMouseDown(e){e=e||window.event;e.preventDefault();pos3=e.clientX;pos4=e.clientY;document.onmouseup=closeDragElement;document.onmousemove=elementDrag}function elementDrag(e){e=e||window.event;e.preventDefault();pos1=pos3-e.clientX;pos2=pos4-e.clientY;pos3=e.clientX;pos4=e.clientY;element.style.top=element.offsetTop-pos2+"px";element.style.left=element.offsetLeft-pos1+"px"}function closeDragElement(){document.onmouseup=null;document.onmousemove=null}}return{initialize:_initialize}}(crowbar_deps);crowbar.initialize();