1+ /*
2+ * @see https://github.com/NYTimes/svg-crowbar - A bit of used code from here, thanks to it's author.
3+ */
4+ var enableSVGDownload = function ( classView ) {
5+
6+ var 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">' ;
7+
8+ window . URL = ( window . URL || window . webkitURL ) ;
9+
10+ var prefix = {
11+ xmlns : "http://www.w3.org/2000/xmlns/" ,
12+ xlink : "http://www.w3.org/1999/xlink" ,
13+ svg : "http://www.w3.org/2000/svg"
14+ } ;
15+
16+ function getSources ( doc , emptySvgDeclarationComputed ) {
17+
18+ var svgInfo = [ ] ,
19+ svgs = doc . querySelectorAll ( "svg" ) ;
20+
21+ [ ] . forEach . call ( svgs , function ( svg ) {
22+
23+ var par = svg . parentNode ;
24+ svg = svg . cloneNode ( true ) ;
25+ par . appendChild ( svg ) ;
26+ var gGroup = svg . childNodes [ 0 ] ;
27+
28+ svg . setAttribute ( "version" , "1.1" ) ;
29+
30+ // removing attributes so they aren't doubled up
31+ svg . removeAttribute ( "xmlns" ) ;
32+ svg . removeAttribute ( "xlink" ) ;
33+
34+ // These are needed for the svg
35+ if ( ! svg . hasAttributeNS ( prefix . xmlns , "xmlns" ) ) {
36+ svg . setAttributeNS ( prefix . xmlns , "xmlns" , prefix . svg ) ;
37+ }
38+
39+ if ( ! svg . hasAttributeNS ( prefix . xmlns , "xmlns:xlink" ) ) {
40+ svg . setAttributeNS ( prefix . xmlns , "xmlns:xlink" , prefix . xlink ) ;
41+ }
42+
43+ svg . setAttribute ( "width" , gGroup . getBBox ( ) . width ) ;
44+ svg . setAttribute ( "height" , gGroup . getBBox ( ) . height ) ;
45+ gGroup . setAttribute ( "transform" , "" ) ;
46+
47+ setInlineStyles ( svg , emptySvgDeclarationComputed ) ;
48+
49+ var source = ( new XMLSerializer ( ) ) . serializeToString ( svg ) ;
50+ var rect = svg . getBoundingClientRect ( ) ;
51+ svgInfo . push ( {
52+ top : rect . top ,
53+ left : rect . left ,
54+ width : rect . width ,
55+ height : rect . height ,
56+ class : svg . getAttribute ( "class" ) ,
57+ id : svg . getAttribute ( "id" ) ,
58+ childElementCount : svg . childElementCount ,
59+ source : [ doctype + source ]
60+ } ) ;
61+
62+ par . removeChild ( svg ) ;
63+
64+ } ) ;
65+ return svgInfo ;
66+ }
67+
68+ document . getElementById ( "button.downloadSVG" ) . addEventListener ( "click" , function ( ) {
69+
70+ var emptySvg = window . document . createElementNS ( prefix . svg , 'svg' ) ,
71+ emptySvgDeclarationComputed = getComputedStyle ( emptySvg ) ,
72+ source = getSources ( document , emptySvgDeclarationComputed ) [ 0 ] ;
73+
74+ var filename = ( classView || { } ) . SELECTED_CLASS_NAME || "classDiagram" ;
75+
76+ var img = new Image ( ) ;
77+ var url = window . URL . createObjectURL ( new Blob ( source . source , { "type" : 'image/svg+xml;charset=utf-8' /*"text\/xml"*/ } ) ) ;
78+
79+ var canvas = document . createElement ( 'canvas' ) ;
80+ var ctx = canvas . getContext ( '2d' ) ;
81+ canvas . setAttribute ( "width" , source . width ) ;
82+ canvas . setAttribute ( "height" , source . height ) ;
83+ document . body . appendChild ( canvas ) ;
84+
85+ img . onload = function ( ) {
86+ ctx . drawImage ( img , 0 , 0 ) ;
87+ var dataURL = canvas . toDataURL ( "image/png" ) ;
88+ var a = document . createElement ( "a" ) ;
89+ a . setAttribute ( "download" , filename + ".png" ) ;
90+ a . setAttribute ( "href" , dataURL /*url*/ ) ;
91+ document . body . appendChild ( a ) ;
92+ a . click ( ) ;
93+ setTimeout ( function ( ) {
94+ a . parentNode . removeChild ( a ) ;
95+ canvas . parentNode . removeChild ( canvas ) ;
96+ window . URL . revokeObjectURL ( url ) ;
97+ } , 10 ) ;
98+ } ;
99+
100+ img . src = url ;
101+
102+ } ) ;
103+
104+ function setInlineStyles ( svg , emptySvgDeclarationComputed ) {
105+
106+ function explicitlySetStyle ( element ) {
107+ var cSSStyleDeclarationComputed = getComputedStyle ( element ) ;
108+ var i , len , key , value ;
109+ var computedStyleStr = "" ;
110+ for ( i = 0 , len = cSSStyleDeclarationComputed . length ; i < len ; i ++ ) {
111+ key = cSSStyleDeclarationComputed [ i ] ;
112+ value = cSSStyleDeclarationComputed . getPropertyValue ( key ) ;
113+ if ( value !== emptySvgDeclarationComputed . getPropertyValue ( key ) ) {
114+ computedStyleStr += key + ":" + value + ";" ;
115+ }
116+ }
117+ element . setAttribute ( 'style' , computedStyleStr ) ;
118+ }
119+ function traverse ( obj ) {
120+ var tree = [ ] ;
121+ tree . push ( obj ) ;
122+ visit ( obj ) ;
123+ function visit ( node ) {
124+ if ( node && node . hasChildNodes ( ) ) {
125+ var child = node . firstChild ;
126+ while ( child ) {
127+ if ( child . nodeType === 1 && child . nodeName != 'SCRIPT' ) {
128+ tree . push ( child ) ;
129+ visit ( child ) ;
130+ }
131+ child = child . nextSibling ;
132+ }
133+ }
134+ }
135+ return tree ;
136+ }
137+ // hardcode computed css styles inside svg
138+ var allElements = traverse ( svg ) ;
139+ var i = allElements . length ;
140+ while ( i -- ) {
141+ explicitlySetStyle ( allElements [ i ] ) ;
142+ }
143+ }
144+
145+
146+ } ;
0 commit comments