]> source.dussan.org Git - svg.js.git/commitdiff
Reworked arrange module, <defs> always on top
authorwout <wout@impinc.co.uk>
Thu, 27 Jun 2013 15:36:26 +0000 (16:36 +0100)
committerwout <wout@impinc.co.uk>
Thu, 27 Jun 2013 15:36:26 +0000 (16:36 +0100)
17 files changed:
README.md
Rakefile
dist/svg.js
dist/svg.min.js
spec/index.html
spec/spec/arrange.js [new file with mode: 0644]
spec/spec/bbox.js
spec/spec/color.js
spec/spec/container.js
spec/spec/group.js [new file with mode: 0644]
spec/spec/svg.js
src/arrange.js
src/container.js
src/doc.js
src/group.js
src/instance.js [new file with mode: 0644]
src/svg.js

index d226f0745d5596d9d155af460bb3919996365f59..9ab8704d0bec02b4f7408c645050018a41a5a4f0 100644 (file)
--- a/README.md
+++ b/README.md
@@ -359,6 +359,12 @@ rect.style()
 // => 'cursor:pointer;fill:#f03;'
 ```
 
+Explicitly deleting individual style definitions works the same as with the `attr()` method:
+
+```javascript
+rect.style('cursor', null)
+```
+
 
 ### Move 
 Move the element to a given `x` and `y` position by its upper left corner:
@@ -853,6 +859,19 @@ Get the previous sibling:
 rect.previous()
 ```
 
+Insert an element before another:
+
+```javascript
+// inserts circle before rect
+rect.before(circle)
+```
+
+Insert an element after another:
+
+```javascript
+// inserts circle after rect
+rect.after(circle)
+```
 
 _This functionality requires the arrange.js module which is included in the default distribution._
 
index da0d350747f2d11d8678194c5f7c1eef786be6a8..ee9d27727967c17fda7be93d355fd82b78177594 100644 (file)
--- a/Rakefile
+++ b/Rakefile
@@ -1,7 +1,7 @@
-SVGJS_VERSION = '0.20'
+SVGJS_VERSION = '0.21'
 
 # all available modules in the correct loading order
-MODULES = %w[ svg regex default color number viewbox bbox rbox element container fx event group arrange defs mask clip pattern gradient doc shape rect ellipse line poly path plotable image text nested sugar ]
+MODULES = %w[ svg regex default color number viewbox bbox rbox element container fx event defs group arrange mask clip pattern gradient doc shape rect ellipse line poly path plotable image text nested sugar ]
 
 # how many bytes in a "kilobyte"
 KILO = 1024
index 6dc659586354a7005f8d83621485268e2869402d..4e13436a665353a4c061f0677a4a79f7ebd70e0e 100644 (file)
@@ -1,4 +1,4 @@
-/* svg.js v0.20-4-gb166969 - svg regex default color number viewbox bbox rbox element container fx event group arrange defs mask clip pattern gradient doc shape rect ellipse line poly path plotable image text nested sugar - svgjs.com/license */
+/* svg.js v0.21 - svg regex default color number viewbox bbox rbox element container fx event defs group arrange mask clip pattern gradient doc shape rect ellipse line poly path plotable image text nested sugar - svgjs.com/license */
 ;(function() {
 
   this.SVG = function(element) {
@@ -6,12 +6,6 @@
       return new SVG.Doc(element)
   }
   
-  // DEPRECATED!!! Use SVG() instead
-  this.svg = function(element) {
-    console.warn('WARNING: svg() is deprecated, please use SVG() instead.')
-    return SVG(element)
-  }
-  
   // Default namespaces
   SVG.ns = 'http://www.w3.org/2000/svg'
   SVG.xlink = 'http://www.w3.org/1999/xlink'
         this.node.insertBefore(element.node, this.node.childNodes[i] || null)
         element.parent = this
       }
+  
+      /* reposition defs */
+      if (this._defs) {
+        this.node.removeChild(this._defs.node)
+        this.node.appendChild(this._defs.node)
+      }
       
       return this
     }
         , children = this.children()
       
       for (i = 0, il = children.length; i < il; i++) {
-        if (children[i] instanceof SVG.Shape)
+        if (children[i] instanceof SVG.Element)
           block.apply(children[i], [i, children])
   
         if (deep && (children[i] instanceof SVG.Container))
       
       return this
     }
-    // Returns defs element
+    // Get defs
   , defs: function() {
-      return this._defs || (this._defs = this.put(new SVG.Defs, 0))
-    }
-    // Re-level defs to first positon in element stack
-  , level: function() {
-      return this.removeElement(this.defs()).put(this.defs(), 0)
+      return this.doc().defs()
     }
     // Get first child, skipping the defs node
   , first: function() {
         this.removeElement(this.children()[i])
   
       /* remove defs node */
-      if (this._defs) {
-        this._defs.remove()
-        delete this._defs
-      }
+      if (this._defs)
+        this._defs.clear()
   
       return this
     }
     }
   })
 
+  SVG.Defs = function() {
+    this.constructor.call(this, SVG.create('defs'))
+  }
+  
+  // Inherits from SVG.Container
+  SVG.Defs.prototype = new SVG.Container
+
   SVG.G = function() {
     this.constructor.call(this, SVG.create('g'))
   }
   , y: function(y) {
       return y == null ? this.trans.y : this.transform('y', y)
     }
-    // Get defs
-  , defs: function() {
-      return this.doc().defs()
-    }
-    
   })
   
   //
     }
     // Get the curent position siblings
   , position: function() {
-      return this.siblings().indexOf(this)
+      var siblings = this.siblings()
+  
+      return siblings.indexOf(this)
     }
     // Get the next element (will return null if there is none)
   , next: function() {
     }
     // Send given element one step forward
   , forward: function() {
-      return this.parent.removeElement(this).put(this, this.position() + 1)
+      var i = this.position()
+      return this.parent.removeElement(this).put(this, i + 1)
     }
     // Send given element one step backward
   , backward: function() {
-      this.parent.level()
-      
       var i = this.position()
       
-      if (i > 1)
+      if (i > 0)
         this.parent.removeElement(this).add(this, i - 1)
-      
+  
       return this
     }
     // Send given element all the way to the front
     }
     // Send given element all the way to the back
   , back: function() {
-      this.parent.level()
-      
       if (this.position() > 1)
         this.parent.removeElement(this).add(this, 0)
       
       return this
     }
-    
-  })
-
-  SVG.Defs = function() {
-    this.constructor.call(this, SVG.create('defs'))
-  }
+    // Inserts a given element before the targeted element
+  , before: function(element) {
+      element.remove()
   
-  // Inherits from SVG.Container
-  SVG.Defs.prototype = new SVG.Container
+      var i = this.position()
+      
+      this.parent.add(element, i)
+  
+      return this
+    }
+    // Insters a given element after the targeted element
+  , after: function(element) {
+      element.remove()
+      
+      var i = this.position()
+      
+      this.parent.add(element, i + 1)
+  
+      return this
+    }
+  
+  })
 
   SVG.Mask = function() {
     this.constructor.call(this, SVG.create('mask'))
     this.constructor
       .call(this, this.parent.nodeName == 'svg' ? this.parent : SVG.create('svg'))
     
-    /* set svg element attributes and create the <defs> node */
+    /* set svg element attributes */
     this
       .attr({ xmlns: SVG.ns, version: '1.1', width: '100%', height: '100%' })
       .attr('xlink', SVG.xlink, SVG.ns)
-      .defs()
+    
+    /* create the <defs> node */
+    this._defs = new SVG.Defs
+    this.node.appendChild(this._defs.node)
     
     /* ensure correct rendering */
     if (this.parent.nodeName != 'svg')
   // Inherits from SVG.Container
   SVG.Doc.prototype = new SVG.Container
   
-  
+  //
   SVG.extend(SVG.Doc, {
     // Hack for safari preventing text to be rendered in one line.
     // Basically it sets the position of the svg node to absolute
       return this
     }
   
+    // Creates and returns defs element
+  , defs: function() {
+      return this._defs
+    }
+  
     // Fix for possible sub-pixel offset. See:
     // https://bugzilla.mozilla.org/show_bug.cgi?id=608812
   , fixSubPixelOffset: function() {
index 5fada9c60d099137fd207ab54bdef58bb4e59346..df29cc4cc4d3f72d4473438d53d605af0b479cdc 100644 (file)
@@ -1 +1 @@
-!function(){if(this.SVG=function(t){return SVG.supported?new SVG.Doc(t):void 0},this.svg=function(t){return console.warn("WARNING: svg() is deprecated, please use SVG() instead."),SVG(t)},SVG.ns="http://www.w3.org/2000/svg",SVG.xlink="http://www.w3.org/1999/xlink",SVG.did=1e3,SVG.eid=function(t){return"Svgjs"+t.charAt(0).toUpperCase()+t.slice(1)+SVG.did++},SVG.create=function(t){var e=document.createElementNS(this.ns,t);return e.setAttribute("id",this.eid(t)),e},SVG.extend=function(){var t,e,i,n;for(t=[].slice.call(arguments),e=t.pop(),n=t.length-1;n>=0;n--)if(t[n])for(i in e)t[n].prototype[i]=e[i]},SVG.get=function(t){var e=document.getElementById(t);return e?e.instance:void 0},SVG.supported=function(){return!!document.createElementNS&&!!document.createElementNS(SVG.ns,"svg").createSVGRect}(),!SVG.supported)return!1;SVG.regex={test:function(t,e){return this[e].test(t)},unit:/^([\d\.]+)([a-z%]{0,2})$/,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isStyle:/^font|text|leading|cursor/,isBlank:/^(\s+)?$/,isNumber:/^-?[\d\.]+$/,isPercent:/^-?[\d\.]+%$/},SVG.defaults={matrix:"1,0,0,1,0,0",attrs:{"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000",stroke:"#000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000"},trans:function(){return{x:0,y:0,scaleX:1,scaleY:1,rotation:0,skewX:0,skewY:0,matrix:this.matrix,a:1,b:0,c:0,d:1,e:0,f:0}}},SVG.Color=function(t){var e;this.r=0,this.g=0,this.b=0,"string"==typeof t?SVG.regex.isRgb.test(t)?(e=SVG.regex.rgb.exec(t.replace(/\s/g,"")),this.r=parseInt(e[1]),this.g=parseInt(e[2]),this.b=parseInt(e[3])):SVG.regex.isHex.test(t)&&(e=SVG.regex.hex.exec(this._fullHex(t)),this.r=parseInt(e[1],16),this.g=parseInt(e[2],16),this.b=parseInt(e[3],16)):"object"==typeof t&&(this.r=t.r,this.g=t.g,this.b=t.b)},SVG.extend(SVG.Color,{toString:function(){return this.toHex()},toHex:function(){return"#"+this._compToHex(this.r)+this._compToHex(this.g)+this._compToHex(this.b)},toRgb:function(){return"rgb("+[this.r,this.g,this.b].join()+")"},brightness:function(){return.3*(this.r/255)+.59*(this.g/255)+.11*(this.b/255)},_fullHex:function(t){return 4==t.length?["#",t.substring(1,2),t.substring(1,2),t.substring(2,3),t.substring(2,3),t.substring(3,4),t.substring(3,4)].join(""):t},_compToHex:function(t){var e=t.toString(16);return 1==e.length?"0"+e:e}}),SVG.Color.test=function(t){return t+="",SVG.regex.isHex.test(t)||SVG.regex.isRgb.test(t)},SVG.Color.isRgb=function(t){return t&&"number"==typeof t.r},SVG.Number=function(t){switch(this.value=0,this.unit="",typeof t){case"number":this.value=t;break;case"string":var e=t.match(SVG.regex.unit);this.value=parseFloat(e[1]),"%"==e[2]&&(this.value/=100),this.unit=e[2];break;default:t instanceof SVG.Number&&(this.value=t.value,this.unit=t.unit)}},SVG.extend(SVG.Number,{toString:function(){return("%"==this.unit?~~(100*this.value):this.value)+this.unit},valueOf:function(){return this.value},to:function(t){return"string"==typeof t&&(this.unit=t),this},plus:function(t){return this.value=this+new SVG.Number(t),this},minus:function(t){return this.plus(-new SVG.Number(t))},times:function(t){return this.value=this*new SVG.Number(t),this},divide:function(t){return this.value=this/new SVG.Number(t),this}}),SVG.ViewBox=function(t){var e,i,n,s,r=t.bbox(),o=(t.attr("viewBox")||"").match(/-?[\d\.]+/g);this.x=r.x,this.y=r.y,this.width=t.node.offsetWidth||t.attr("width"),this.height=t.node.offsetHeight||t.attr("height"),o&&(e=parseFloat(o[0]),i=parseFloat(o[1]),n=parseFloat(o[2]),s=parseFloat(o[3]),this.zoom=this.width/this.height>n/s?this.height/s:this.width/n,this.x=e,this.y=i,this.width=n,this.height=s),this.zoom=this.zoom||1},SVG.extend(SVG.ViewBox,{toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}}),SVG.BBox=function(t){var e;if(this.x=0,this.y=0,this.width=0,this.height=0,t){try{e=t.node.getBBox()}catch(i){e={x:t.node.clientLeft,y:t.node.clientTop,width:t.node.clientWidth,height:t.node.clientHeight}}this.x=e.x+t.trans.x,this.y=e.y+t.trans.y,this.width=e.width*t.trans.scaleX,this.height=e.height*t.trans.scaleY}this.cx=this.x+this.width/2,this.cy=this.y+this.height/2},SVG.extend(SVG.BBox,{merge:function(t){var e=new SVG.BBox;return e.x=Math.min(this.x,t.x),e.y=Math.min(this.y,t.y),e.width=Math.max(this.x+this.width,t.x+t.width)-e.x,e.height=Math.max(this.y+this.height,t.y+t.height)-e.y,e.cx=e.x+e.width/2,e.cy=e.y+e.height/2,e}}),SVG.RBox=function(t){var e,i,n={};if(this.x=0,this.y=0,this.width=0,this.height=0,t){for(e=t.doc().parent,i=t.doc().viewbox().zoom,n=t.node.getBoundingClientRect(),this.x=n.left,this.y=n.top,this.x-=e.offsetLeft,this.y-=e.offsetTop;e=e.offsetParent;)this.x-=e.offsetLeft,this.y-=e.offsetTop;for(e=t;e=e.parent;)"svg"==e.type&&e.viewbox&&(i*=e.viewbox().zoom,this.x-=e.x()||0,this.y-=e.y()||0)}this.x/=i,this.y/=i,this.width=n.width/=i,this.height=n.height/=i,this.cx=this.x+this.width/2,this.cy=this.y+this.height/2},SVG.Element=function(t){this._stroke=SVG.defaults.attrs.stroke,this.styles={},this.trans=SVG.defaults.trans(),(this.node=t)&&(this.type=t.nodeName,this.node.instance=this)},SVG.extend(SVG.Element,{x:function(t){return t&&(t=new SVG.Number(t),t.value/=this.trans.scaleX),this.attr("x",t)},y:function(t){return t&&(t=new SVG.Number(t),t.value/=this.trans.scaleY),this.attr("y",t)},cx:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)},cy:function(t){return null==t?this.bbox().cy:this.y(t-this.bbox().height/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},size:function(t,e){return this.attr({width:new SVG.Number(t),height:new SVG.Number(e)})},clone:function(){var t,e,i=this.type;return t="rect"==i||"ellipse"==i?this.parent[i](0,0):"line"==i?this.parent[i](0,0,0,0):"image"==i?this.parent[i](this.src):"text"==i?this.parent[i](this.content):"path"==i?this.parent[i](this.attr("d")):"polyline"==i||"polygon"==i?this.parent[i](this.attr("points")):"g"==i?this.parent.group():this.parent[i](),e=this.attr(),delete e.id,t.attr(e),t.trans=this.trans,t.transform({})},remove:function(){return this.parent&&this.parent.removeElement(this),this},doc:function(t){return this._parent(t||SVG.Doc)},attr:function(t,e,i){if(null==t){for(t={},e=this.node.attributes,i=e.length-1;i>=0;i--)t[e[i].nodeName]=SVG.regex.test(e[i].nodeValue,"isNumber")?parseFloat(e[i].nodeValue):e[i].nodeValue;return t}if("object"==typeof t)for(e in t)this.attr(e,t[e]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return this._isStyle(t)?"text"==t?this.content:"leading"==t&&this.leading?this.leading():this.style(t):(e=this.node.getAttribute(t),null==e?SVG.defaults.attrs[t]:SVG.regex.test(e,"isNumber")?parseFloat(e):e);if("style"==t)return this.style(e);if("function"==typeof e.fill&&(e=e.fill()),"x"==t&&Array.isArray(this.lines))for(i=this.lines.length-1;i>=0;i--)this.lines[i].attr(t,e);"stroke-width"==t?this.attr("stroke",parseFloat(e)>0?this._stroke:null):"stroke"==t&&(this._stroke=e),(SVG.Color.test(e)||SVG.Color.isRgb(e))&&(e=new SVG.Color(e).toHex()),null!=i?this.node.setAttributeNS(i,t,e):this.node.setAttribute(t,e),this._isStyle(t)&&("text"==t?this.text(e):"leading"==t&&this.leading?this.leading(e):this.style(t,e),this.rebuild&&this.rebuild(t,e))}return this},transform:function(t,e){if(0==arguments.length)return this.trans;if("string"==typeof t){if(arguments.length<2)return this.trans[t];var i={};return i[t]=e,this.transform(i)}var i=[];t=this._parseMatrix(t);for(e in t)null!=t[e]&&(this.trans[e]=t[e]);return this.trans.matrix=this.trans.a+","+this.trans.b+","+this.trans.c+","+this.trans.d+","+this.trans.e+","+this.trans.f,t=this.trans,t.matrix!=SVG.defaults.matrix&&i.push("matrix("+t.matrix+")"),0!=t.rotation&&i.push("rotate("+t.rotation+","+(null==t.cx?this.bbox().cx:t.cx)+","+(null==t.cy?this.bbox().cy:t.cy)+")"),(1!=t.scaleX||1!=t.scaleY)&&i.push("scale("+t.scaleX+","+t.scaleY+")"),0!=t.skewX&&i.push("skewX("+t.skewX+")"),0!=t.skewY&&i.push("skewY("+t.skewY+")"),(0!=t.x||0!=t.y)&&i.push("translate("+t.x/t.scaleX+","+t.y/t.scaleY+")"),this._offset&&i.push("translate("+-this._offset.x+","+-this._offset.y+")"),0==i.length?this.node.removeAttribute("transform"):this.node.setAttribute("transform",i.join(" ")),this},style:function(t,e){if(0==arguments.length)return this.attr("style")||"";if(arguments.length<2)if("object"==typeof t)for(e in t)this.style(e,t[e]);else{if(!SVG.regex.isCss.test(t))return this.styles[t];t=t.split(";");for(var i=0;i<t.length;i++)e=t[i].split(":"),2==e.length&&this.style(e[0].replace(/\s+/g,""),e[1].replace(/^\s+/,"").replace(/\s+$/,""))}else null===e||SVG.regex.test(e,"isBlank")?delete this.styles[t]:this.styles[t]=e;t="";for(e in this.styles)t+=e+":"+this.styles[e]+";";return""==t?this.node.removeAttribute("style"):this.node.setAttribute("style",t),this},data:function(t,e,i){if(arguments.length<2)try{return JSON.parse(this.attr("data-"+t))}catch(n){return this.attr("data-"+t)}else this.attr("data-"+t,null===e?null:i===!0||"string"==typeof e||"number"==typeof e?e:JSON.stringify(e));return this},bbox:function(){return new SVG.BBox(this)},rbox:function(){return new SVG.RBox(this)},inside:function(t,e){var i=this.bbox();return t>i.x&&e>i.y&&t<i.x+i.width&&e<i.y+i.height},show:function(){return this.style("display","")},hide:function(){return this.style("display","none")},visible:function(){return"none"!=this.style("display")},_parent:function(t){for(var e=this;null!=e&&!(e instanceof t);)e=e.parent;return e},_isStyle:function(t){return"string"==typeof t?SVG.regex.test(t,"isStyle"):!1},_parseMatrix:function(t){if(t.matrix){var e=t.matrix.replace(/\s/g,"").split(",");6==e.length&&(t.a=parseFloat(e[0]),t.b=parseFloat(e[1]),t.c=parseFloat(e[2]),t.d=parseFloat(e[3]),t.e=parseFloat(e[4]),t.f=parseFloat(e[5]))}return t}}),SVG.Container=function(t){this.constructor.call(this,t)},SVG.Container.prototype=new SVG.Element,SVG.extend(SVG.Container,{children:function(){return this._children||(this._children=[])},add:function(t,e){if(!this.has(t)){if(e=null==e?this.children().length:e,t.parent){var i=t.parent.children().indexOf(t);t.parent.children().splice(i,1)}this.children().splice(e,0,t),this.node.insertBefore(t.node,this.node.childNodes[e]||null),t.parent=this}return this},put:function(t,e){return this.add(t,e),t},has:function(t){return this.children().indexOf(t)>=0},get:function(t){return this.children()[t]},each:function(t,e){var i,n,s=this.children();for(i=0,n=s.length;n>i;i++)s[i]instanceof SVG.Shape&&t.apply(s[i],[i,s]),e&&s[i]instanceof SVG.Container&&s[i].each(t,e);return this},removeElement:function(t){var e=this.children().indexOf(t);return this.children().splice(e,1),this.node.removeChild(t.node),t.parent=null,this},defs:function(){return this._defs||(this._defs=this.put(new SVG.Defs,0))},level:function(){return this.removeElement(this.defs()).put(this.defs(),0)},first:function(){return this.children()[0]instanceof SVG.Defs?this.children()[1]:this.children()[0]},last:function(){return this.children()[this.children().length-1]},viewbox:function(t){return 0==arguments.length?new SVG.ViewBox(this):(t=1==arguments.length?[t.x,t.y,t.width,t.height]:[].slice.call(arguments),this.attr("viewBox",t.join(" ")))},clear:function(){for(var t=this.children().length-1;t>=0;t--)this.removeElement(this.children()[t]);return this._defs&&(this._defs.remove(),delete this._defs),this}}),SVG.FX=function(t){this.target=t},SVG.extend(SVG.FX,{animate:function(t,e,i){var n,s,r,o,h=this.target,a=this;return"object"==typeof t&&(i=t.delay,e=t.ease,t=t.duration),t=null==t?1e3:t,e=e||"<>",a.to=function(t){var i;if(t=0>t?0:t>1?1:t,null==n){n=[];for(o in a.attrs)n.push(o)}if(null==s){s=[];for(o in a.trans)s.push(o)}if(null==r){r=[];for(o in a.styles)r.push(o)}for(t="<>"==e?-Math.cos(t*Math.PI)/2+.5:">"==e?Math.sin(t*Math.PI/2):"<"==e?-Math.cos(t*Math.PI/2)+1:"-"==e?t:"function"==typeof e?e(t):t,a._x?h.x(a._at(a._x,t)):a._cx&&h.cx(a._at(a._cx,t)),a._y?h.y(a._at(a._y,t)):a._cy&&h.cy(a._at(a._cy,t)),a._size&&h.size(a._at(a._size.width,t),a._at(a._size.height,t)),a._viewbox&&h.viewbox(a._at(a._viewbox.x,t),a._at(a._viewbox.y,t),a._at(a._viewbox.width,t),a._at(a._viewbox.height,t)),i=n.length-1;i>=0;i--)h.attr(n[i],a._at(a.attrs[n[i]],t));for(i=s.length-1;i>=0;i--)h.transform(s[i],a._at(a.trans[s[i]],t));for(i=r.length-1;i>=0;i--)h.style(r[i],a._at(a.styles[r[i]],t));a._during&&a._during.call(h,t,function(e,i){return a._at({from:e,to:i},t)})},"number"==typeof t&&(this.timeout=setTimeout(function(){var e=1e3/60,i=(new Date).getTime(),n=i+t;a.interval=setInterval(function(){var e=(new Date).getTime(),s=e>n?1:(e-i)/t;a.to(s),e>n&&(clearInterval(a.interval),a._after?a._after.apply(h,[a]):a.stop())},t>e?e:t)},i||0)),this},bbox:function(){return this.target.bbox()},attr:function(t,e){if("object"==typeof t)for(var i in t)this.attr(i,t[i]);else this.attrs[t]={from:this.target.attr(t),to:e};return this},transform:function(t,e){if(1==arguments.length){t=this.target._parseMatrix(t),delete t.matrix;for(e in t)this.trans[e]={from:this.target.trans[e],to:t[e]}}else{var i={};i[t]=e,this.transform(i)}return this},style:function(t,e){if("object"==typeof t)for(var i in t)this.style(i,t[i]);else this.styles[t]={from:this.target.style(t),to:e};return this},x:function(t){return this._x={from:this.target.x(),to:t},this},y:function(t){return this._y={from:this.target.y(),to:t},this},cx:function(t){return this._cx={from:this.target.cx(),to:t},this},cy:function(t){return this._cy={from:this.target.cy(),to:t},this},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},size:function(t,e){if(this.target instanceof SVG.Text)this.attr("font-size",t);else{var i=this.target.bbox();this._size={width:{from:i.width,to:t},height:{from:i.height,to:e}}}return this},viewbox:function(t,e,i,n){if(this.target instanceof SVG.Container){var s=this.target.viewbox();this._viewbox={x:{from:s.x,to:t},y:{from:s.y,to:e},width:{from:s.width,to:i},height:{from:s.height,to:n}}}return this},update:function(t){return this.target instanceof SVG.Stop&&(null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new SVG.Number(t.offset))),this},during:function(t){return this._during=t,this},after:function(t){return this._after=t,this},stop:function(){return clearTimeout(this.timeout),clearInterval(this.interval),this.attrs={},this.trans={},this.styles={},delete this._x,delete this._y,delete this._cx,delete this._cy,delete this._size,delete this._after,delete this._during,delete this._viewbox,this},_at:function(t,e){return"number"==typeof t.from?t.from+(t.to-t.from)*e:SVG.regex.unit.test(t.to)?new SVG.Number(t.to).minus(new SVG.Number(t.from)).times(e).plus(new SVG.Number(t.from)):t.to&&(t.to.r||SVG.Color.test(t.to))?this._color(t,e):1>e?t.from:t.to},_color:function(t,e){var i,n;return e=0>e?0:e>1?1:e,i=new SVG.Color(t.from),n=new SVG.Color(t.to),new SVG.Color({r:~~(i.r+(n.r-i.r)*e),g:~~(i.g+(n.g-i.g)*e),b:~~(i.b+(n.b-i.b)*e)}).toHex()}}),SVG.extend(SVG.Element,{animate:function(t,e,i){return(this.fx||(this.fx=new SVG.FX(this))).stop().animate(t,e,i)},stop:function(){return this.fx&&this.fx.stop(),this}}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","mouseenter","mouseleave","touchstart","touchend","touchmove","touchcancel"].forEach(function(t){SVG.Element.prototype[t]=function(e){var i=this;return this.node["on"+t]="function"==typeof e?function(){return e.apply(i,arguments)}:null,this}}),SVG.on=function(t,e,i){t.addEventListener?t.addEventListener(e,i,!1):t.attachEvent("on"+e,i)},SVG.off=function(t,e,i){t.removeEventListener?t.removeEventListener(e,i,!1):t.detachEvent("on"+e,i)},SVG.extend(SVG.Element,{on:function(t,e){return SVG.on(this.node,t,e),this},off:function(t,e){return SVG.off(this.node,t,e),this}}),SVG.G=function(){this.constructor.call(this,SVG.create("g"))},SVG.G.prototype=new SVG.Container,SVG.extend(SVG.G,{x:function(t){return null==t?this.trans.x:this.transform("x",t)},y:function(t){return null==t?this.trans.y:this.transform("y",t)},defs:function(){return this.doc().defs()}}),SVG.extend(SVG.Container,{group:function(){return this.put(new SVG.G)}}),SVG.extend(SVG.Element,{siblings:function(){return this.parent.children()},position:function(){return this.siblings().indexOf(this)},next:function(){return this.siblings()[this.position()+1]},previous:function(){return this.siblings()[this.position()-1]},forward:function(){return this.parent.removeElement(this).put(this,this.position()+1)},backward:function(){this.parent.level();var t=this.position();return t>1&&this.parent.removeElement(this).add(this,t-1),this},front:function(){return this.parent.removeElement(this).put(this)},back:function(){return this.parent.level(),this.position()>1&&this.parent.removeElement(this).add(this,0),this}}),SVG.Defs=function(){this.constructor.call(this,SVG.create("defs"))},SVG.Defs.prototype=new SVG.Container,SVG.Mask=function(){this.constructor.call(this,SVG.create("mask"))},SVG.Mask.prototype=new SVG.Container,SVG.extend(SVG.Element,{maskWith:function(t){return this.mask=t instanceof SVG.Mask?t:this.parent.mask().add(t),this.attr("mask","url(#"+this.mask.attr("id")+")")}}),SVG.extend(SVG.Container,{mask:function(){return this.defs().put(new SVG.Mask)}}),SVG.Clip=function(){this.constructor.call(this,SVG.create("clipPath"))},SVG.Clip.prototype=new SVG.Container,SVG.extend(SVG.Element,{clipWith:function(t){return this.clip=t instanceof SVG.Clip?t:this.parent.clip().add(t),this.attr("clip-path","url(#"+this.clip.attr("id")+")")}}),SVG.extend(SVG.Container,{clip:function(){return this.defs().put(new SVG.Clip)}}),SVG.Pattern=function(){this.constructor.call(this,SVG.create("pattern"))},SVG.Pattern.prototype=new SVG.Container,SVG.extend(SVG.Pattern,{fill:function(){return"url(#"+this.attr("id")+")"}}),SVG.extend(SVG.Defs,{pattern:function(t,e,i){var n=this.put(new SVG.Pattern);return i(n),n.attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),SVG.extend(SVG.Container,{pattern:function(t,e,i){return this.defs().pattern(t,e,i)}}),SVG.Gradient=function(t){this.constructor.call(this,SVG.create(t+"Gradient")),this.type=t},SVG.Gradient.prototype=new SVG.Container,SVG.extend(SVG.Gradient,{from:function(t,e){return"radial"==this.type?this.attr({fx:new SVG.Number(t),fy:new SVG.Number(e)}):this.attr({x1:new SVG.Number(t),y1:new SVG.Number(e)})},to:function(t,e){return"radial"==this.type?this.attr({cx:new SVG.Number(t),cy:new SVG.Number(e)}):this.attr({x2:new SVG.Number(t),y2:new SVG.Number(e)})},radius:function(t){return"radial"==this.type?this.attr({r:new SVG.Number(t)}):this},at:function(t){return this.put(new SVG.Stop(t))},update:function(t){return this.clear(),t(this),this},fill:function(){return"url(#"+this.attr("id")+")"}}),SVG.extend(SVG.Defs,{gradient:function(t,e){var i=this.put(new SVG.Gradient(t));return e(i),i}}),SVG.extend(SVG.Container,{gradient:function(t,e){return this.defs().gradient(t,e)}}),SVG.Stop=function(t){this.constructor.call(this,SVG.create("stop")),this.update(t)},SVG.Stop.prototype=new SVG.Element,SVG.extend(SVG.Stop,{update:function(t){return null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new SVG.Number(t.offset)),this}}),SVG.Doc=function(t){this.parent="string"==typeof t?document.getElementById(t):t,this.constructor.call(this,"svg"==this.parent.nodeName?this.parent:SVG.create("svg")),this.attr({xmlns:SVG.ns,version:"1.1",width:"100%",height:"100%"}).attr("xlink",SVG.xlink,SVG.ns).defs(),"svg"!=this.parent.nodeName&&this.stage()},SVG.Doc.prototype=new SVG.Container,SVG.extend(SVG.Doc,{stage:function(){var t,e=this,i=document.createElement("div");return i.style.cssText="position:relative;height:100%;",e.parent.appendChild(i),i.appendChild(e.node),t=function(){"complete"===document.readyState?(e.style("position:absolute;"),setTimeout(function(){e.style("position:relative;"),e.parent.removeChild(e.node.parentNode),e.node.parentNode.removeChild(e.node),e.parent.appendChild(e.node),e.fixSubPixelOffset(),SVG.on(window,"resize",function(){e.fixSubPixelOffset()})},5)):setTimeout(t,10)},t(),this},fixSubPixelOffset:function(){var t=this.node.getScreenCTM();this.style("left",-t.e%1+"px").style("top",-t.f%1+"px")}}),SVG.Shape=function(t){this.constructor.call(this,t)},SVG.Shape.prototype=new SVG.Element,SVG.Rect=function(){this.constructor.call(this,SVG.create("rect"))},SVG.Rect.prototype=new SVG.Shape,SVG.extend(SVG.Container,{rect:function(t,e){return this.put((new SVG.Rect).size(t,e))}}),SVG.Ellipse=function(){this.constructor.call(this,SVG.create("ellipse"))},SVG.Ellipse.prototype=new SVG.Shape,SVG.extend(SVG.Ellipse,{x:function(t){return null==t?this.cx()-this.attr("rx"):this.cx(t+this.attr("rx"))},y:function(t){return null==t?this.cy()-this.attr("ry"):this.cy(t+this.attr("ry"))},cx:function(t){return null==t?this.attr("cx"):this.attr("cx",new SVG.Number(t).divide(this.trans.scaleX))},cy:function(t){return null==t?this.attr("cy"):this.attr("cy",new SVG.Number(t).divide(this.trans.scaleY))},size:function(t,e){return this.attr({rx:new SVG.Number(t).divide(2),ry:new SVG.Number(e).divide(2)})}}),SVG.extend(SVG.Container,{circle:function(t){return this.ellipse(t,t)},ellipse:function(t,e){return this.put(new SVG.Ellipse).size(t,e).move(0,0)}}),SVG.Line=function(){this.constructor.call(this,SVG.create("line"))},SVG.Line.prototype=new SVG.Shape,SVG.extend(SVG.Line,{x:function(t){var e=this.bbox();return null==t?e.x:this.attr({x1:this.attr("x1")-e.x+t,x2:this.attr("x2")-e.x+t})},y:function(t){var e=this.bbox();return null==t?e.y:this.attr({y1:this.attr("y1")-e.y+t,y2:this.attr("y2")-e.y+t})},cx:function(t){var e=this.bbox().width/2;return null==t?this.x()+e:this.x(t-e)},cy:function(t){var e=this.bbox().height/2;return null==t?this.y()+e:this.y(t-e)},size:function(t,e){var i=this.bbox();return this.attr(this.attr("x1")<this.attr("x2")?"x2":"x1",i.x+t).attr(this.attr("y1")<this.attr("y2")?"y2":"y1",i.y+e)},plot:function(t,e,i,n){return this.attr({x1:t,y1:e,x2:i,y2:n})}}),SVG.extend(SVG.Container,{line:function(t,e,i,n){return this.put((new SVG.Line).plot(t,e,i,n))}}),SVG.Polyline=function(t){this.constructor.call(this,SVG.create("polyline")),this.unbiased=t},SVG.Polyline.prototype=new SVG.Shape,SVG.Polygon=function(t){this.constructor.call(this,SVG.create("polygon")),this.unbiased=t},SVG.Polygon.prototype=new SVG.Shape,SVG.extend(SVG.Polyline,SVG.Polygon,{_plot:function(t){if(Array.isArray(t)){var e,i,n=[];for(e=0,i=t.length;i>e;e++)n.push(t[e].join(","));t=n.length>0?n.join(" "):"0,0"}return this.attr("points",t||"0,0")}}),SVG.extend(SVG.Container,{polyline:function(t,e){return this.put(new SVG.Polyline(e)).plot(t)},polygon:function(t,e){return this.put(new SVG.Polygon(e)).plot(t)}}),SVG.Path=function(t){this.constructor.call(this,SVG.create("path")),this.unbiased=t},SVG.Path.prototype=new SVG.Shape,SVG.extend(SVG.Path,{_plot:function(t){return this.attr("d",t||"M0,0")}}),SVG.extend(SVG.Container,{path:function(t,e){return this.put(new SVG.Path(e)).plot(t)}}),SVG.extend(SVG.Polyline,SVG.Polygon,SVG.Path,{x:function(t){return null==t?this.bbox().x:this.transform("x",t)},y:function(t){return null==t?this.bbox().y:this.transform("y",t)},size:function(t,e){var i=t/this._offset.width;return this.transform({scaleX:i,scaleY:null!=e?e/this._offset.height:i})},plot:function(t){var e=this.trans.scaleX,i=this.trans.scaleY;return this._plot(t),this._offset=this.transform({scaleX:1,scaleY:1}).bbox(),this.unbiased?this._offset.x=this._offset.y=0:(this._offset.x-=this.trans.x,this._offset.y-=this.trans.y),this.transform({scaleX:e,scaleY:i})}}),SVG.Image=function(){this.constructor.call(this,SVG.create("image"))},SVG.Image.prototype=new SVG.Shape,SVG.extend(SVG.Image,{load:function(t){return t?this.attr("xlink:href",this.src=t,SVG.xlink):this}}),SVG.extend(SVG.Container,{image:function(t,e,i){return e=null!=e?e:100,this.put((new SVG.Image).load(t).size(e,null!=i?i:e))}});var t="size family weight stretch variant style".split(" ");SVG.Text=function(){this.constructor.call(this,SVG.create("text")),this.styles={"font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},this._leading=1.2,this._base=.276666666},SVG.Text.prototype=new SVG.Shape,SVG.extend(SVG.Text,{x:function(t,e){return null==t?e?this.attr("x"):this.bbox().x:(e||(e=this.style("text-anchor"),t="start"==e?t:"end"==e?t+this.bbox().width:t+this.bbox().width/2),this.attr("x",t))},cx:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)},cy:function(t,e){return null==t?this.bbox().cy:this.y(e?t:t-this.bbox().height/2)},move:function(t,e,i){return this.x(t,i).y(e)},center:function(t,e,i){return this.cx(t,i).cy(e,i)},text:function(t){if(null==t)return this.content;this.clear(),this.content=SVG.regex.isBlank.test(t)?"text":t;var e,i,n=t.split("\n");for(e=0,i=n.length;i>e;e++)this.tspan(n[e]);return this.attr("textLength",1).attr("textLength",null)},tspan:function(t){var e=(new SVG.TSpan).text(t);return this.node.appendChild(e.node),this.lines.push(e),e.attr("style",this.style())},size:function(t){return this.attr("font-size",t)},leading:function(t){return null==t?this._leading:(this._leading=t,this.rebuild("leading",t))},rebuild:function(){var t,e,i=this.styles["font-size"];for(t=0,e=this.lines.length;e>t;t++)this.lines[t].attr({dy:i*this._leading-(0==t?i*this._base:0),x:this.attr("x")||0,style:this.style()});return this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.lines=[],this}}),SVG.extend(SVG.Container,{text:function(t){return this.put((new SVG.Text).text(t))}}),SVG.TSpan=function(){this.constructor.call(this,SVG.create("tspan"))},SVG.TSpan.prototype=new SVG.Shape,SVG.extend(SVG.TSpan,{text:function(t){return this.node.appendChild(document.createTextNode(t)),this}}),SVG.Nested=function(){this.constructor.call(this,SVG.create("svg")),this.style("overflow","visible")},SVG.Nested.prototype=new SVG.Container,SVG.extend(SVG.Container,{nested:function(){return this.put(new SVG.Nested)}}),SVG._stroke=["color","width","opacity","linecap","linejoin","miterlimit","dasharray","dashoffset"],SVG._fill=["color","opacity","rule"];var e=function(t,e){return"color"==e?t:t+"-"+e};["fill","stroke"].forEach(function(t){var i={};i[t]=function(i){if("string"==typeof i||SVG.Color.isRgb(i)||i&&"function"==typeof i.fill)this.attr(t,i);else for(index=SVG["_"+t].length-1;index>=0;index--)null!=i[SVG["_"+t][index]]&&this.attr(e(t,SVG["_"+t][index]),i[SVG["_"+t][index]]);return this},SVG.extend(SVG.Shape,SVG.FX,i)}),SVG.extend(SVG.Element,SVG.FX,{rotate:function(t,e,i){return this.transform({rotation:t||0,cx:e,cy:i})},skew:function(t,e){return this.transform({skewX:t||0,skewY:e||0})},scale:function(t,e){return this.transform({scaleX:t,scaleY:null==e?t:e})},translate:function(t,e){return this.transform({x:t,y:e})},matrix:function(t){return this.transform({matrix:t})},opacity:function(t){return this.attr("opacity",t)}}),SVG.Text&&SVG.extend(SVG.Text,SVG.FX,{font:function(e){for(var i in e)"anchor"==i?this.attr("text-anchor",e[i]):t.indexOf(i)>-1?this.attr("font-"+i,e[i]):this.attr(i,e[i]);return this}})}.call(this);
\ No newline at end of file
+!function(){if(this.SVG=function(t){return SVG.supported?new SVG.Doc(t):void 0},SVG.ns="http://www.w3.org/2000/svg",SVG.xlink="http://www.w3.org/1999/xlink",SVG.did=1e3,SVG.eid=function(t){return"Svgjs"+t.charAt(0).toUpperCase()+t.slice(1)+SVG.did++},SVG.create=function(t){var e=document.createElementNS(this.ns,t);return e.setAttribute("id",this.eid(t)),e},SVG.extend=function(){var t,e,i,n;for(t=[].slice.call(arguments),e=t.pop(),n=t.length-1;n>=0;n--)if(t[n])for(i in e)t[n].prototype[i]=e[i]},SVG.get=function(t){var e=document.getElementById(t);return e?e.instance:void 0},SVG.supported=function(){return!!document.createElementNS&&!!document.createElementNS(SVG.ns,"svg").createSVGRect}(),!SVG.supported)return!1;SVG.regex={test:function(t,e){return this[e].test(t)},unit:/^([\d\.]+)([a-z%]{0,2})$/,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isStyle:/^font|text|leading|cursor/,isBlank:/^(\s+)?$/,isNumber:/^-?[\d\.]+$/,isPercent:/^-?[\d\.]+%$/},SVG.defaults={matrix:"1,0,0,1,0,0",attrs:{"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000",stroke:"#000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000"},trans:function(){return{x:0,y:0,scaleX:1,scaleY:1,rotation:0,skewX:0,skewY:0,matrix:this.matrix,a:1,b:0,c:0,d:1,e:0,f:0}}},SVG.Color=function(t){var e;this.r=0,this.g=0,this.b=0,"string"==typeof t?SVG.regex.isRgb.test(t)?(e=SVG.regex.rgb.exec(t.replace(/\s/g,"")),this.r=parseInt(e[1]),this.g=parseInt(e[2]),this.b=parseInt(e[3])):SVG.regex.isHex.test(t)&&(e=SVG.regex.hex.exec(this._fullHex(t)),this.r=parseInt(e[1],16),this.g=parseInt(e[2],16),this.b=parseInt(e[3],16)):"object"==typeof t&&(this.r=t.r,this.g=t.g,this.b=t.b)},SVG.extend(SVG.Color,{toString:function(){return this.toHex()},toHex:function(){return"#"+this._compToHex(this.r)+this._compToHex(this.g)+this._compToHex(this.b)},toRgb:function(){return"rgb("+[this.r,this.g,this.b].join()+")"},brightness:function(){return.3*(this.r/255)+.59*(this.g/255)+.11*(this.b/255)},_fullHex:function(t){return 4==t.length?["#",t.substring(1,2),t.substring(1,2),t.substring(2,3),t.substring(2,3),t.substring(3,4),t.substring(3,4)].join(""):t},_compToHex:function(t){var e=t.toString(16);return 1==e.length?"0"+e:e}}),SVG.Color.test=function(t){return t+="",SVG.regex.isHex.test(t)||SVG.regex.isRgb.test(t)},SVG.Color.isRgb=function(t){return t&&"number"==typeof t.r},SVG.Number=function(t){switch(this.value=0,this.unit="",typeof t){case"number":this.value=t;break;case"string":var e=t.match(SVG.regex.unit);this.value=parseFloat(e[1]),"%"==e[2]&&(this.value/=100),this.unit=e[2];break;default:t instanceof SVG.Number&&(this.value=t.value,this.unit=t.unit)}},SVG.extend(SVG.Number,{toString:function(){return("%"==this.unit?~~(100*this.value):this.value)+this.unit},valueOf:function(){return this.value},to:function(t){return"string"==typeof t&&(this.unit=t),this},plus:function(t){return this.value=this+new SVG.Number(t),this},minus:function(t){return this.plus(-new SVG.Number(t))},times:function(t){return this.value=this*new SVG.Number(t),this},divide:function(t){return this.value=this/new SVG.Number(t),this}}),SVG.ViewBox=function(t){var e,i,n,s,r=t.bbox(),o=(t.attr("viewBox")||"").match(/-?[\d\.]+/g);this.x=r.x,this.y=r.y,this.width=t.node.offsetWidth||t.attr("width"),this.height=t.node.offsetHeight||t.attr("height"),o&&(e=parseFloat(o[0]),i=parseFloat(o[1]),n=parseFloat(o[2]),s=parseFloat(o[3]),this.zoom=this.width/this.height>n/s?this.height/s:this.width/n,this.x=e,this.y=i,this.width=n,this.height=s),this.zoom=this.zoom||1},SVG.extend(SVG.ViewBox,{toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}}),SVG.BBox=function(t){var e;if(this.x=0,this.y=0,this.width=0,this.height=0,t){try{e=t.node.getBBox()}catch(i){e={x:t.node.clientLeft,y:t.node.clientTop,width:t.node.clientWidth,height:t.node.clientHeight}}this.x=e.x+t.trans.x,this.y=e.y+t.trans.y,this.width=e.width*t.trans.scaleX,this.height=e.height*t.trans.scaleY}this.cx=this.x+this.width/2,this.cy=this.y+this.height/2},SVG.extend(SVG.BBox,{merge:function(t){var e=new SVG.BBox;return e.x=Math.min(this.x,t.x),e.y=Math.min(this.y,t.y),e.width=Math.max(this.x+this.width,t.x+t.width)-e.x,e.height=Math.max(this.y+this.height,t.y+t.height)-e.y,e.cx=e.x+e.width/2,e.cy=e.y+e.height/2,e}}),SVG.RBox=function(t){var e,i,n={};if(this.x=0,this.y=0,this.width=0,this.height=0,t){for(e=t.doc().parent,i=t.doc().viewbox().zoom,n=t.node.getBoundingClientRect(),this.x=n.left,this.y=n.top,this.x-=e.offsetLeft,this.y-=e.offsetTop;e=e.offsetParent;)this.x-=e.offsetLeft,this.y-=e.offsetTop;for(e=t;e=e.parent;)"svg"==e.type&&e.viewbox&&(i*=e.viewbox().zoom,this.x-=e.x()||0,this.y-=e.y()||0)}this.x/=i,this.y/=i,this.width=n.width/=i,this.height=n.height/=i,this.cx=this.x+this.width/2,this.cy=this.y+this.height/2},SVG.Element=function(t){this._stroke=SVG.defaults.attrs.stroke,this.styles={},this.trans=SVG.defaults.trans(),(this.node=t)&&(this.type=t.nodeName,this.node.instance=this)},SVG.extend(SVG.Element,{x:function(t){return t&&(t=new SVG.Number(t),t.value/=this.trans.scaleX),this.attr("x",t)},y:function(t){return t&&(t=new SVG.Number(t),t.value/=this.trans.scaleY),this.attr("y",t)},cx:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)},cy:function(t){return null==t?this.bbox().cy:this.y(t-this.bbox().height/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},size:function(t,e){return this.attr({width:new SVG.Number(t),height:new SVG.Number(e)})},clone:function(){var t,e,i=this.type;return t="rect"==i||"ellipse"==i?this.parent[i](0,0):"line"==i?this.parent[i](0,0,0,0):"image"==i?this.parent[i](this.src):"text"==i?this.parent[i](this.content):"path"==i?this.parent[i](this.attr("d")):"polyline"==i||"polygon"==i?this.parent[i](this.attr("points")):"g"==i?this.parent.group():this.parent[i](),e=this.attr(),delete e.id,t.attr(e),t.trans=this.trans,t.transform({})},remove:function(){return this.parent&&this.parent.removeElement(this),this},doc:function(t){return this._parent(t||SVG.Doc)},attr:function(t,e,i){if(null==t){for(t={},e=this.node.attributes,i=e.length-1;i>=0;i--)t[e[i].nodeName]=SVG.regex.test(e[i].nodeValue,"isNumber")?parseFloat(e[i].nodeValue):e[i].nodeValue;return t}if("object"==typeof t)for(e in t)this.attr(e,t[e]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return this._isStyle(t)?"text"==t?this.content:"leading"==t&&this.leading?this.leading():this.style(t):(e=this.node.getAttribute(t),null==e?SVG.defaults.attrs[t]:SVG.regex.test(e,"isNumber")?parseFloat(e):e);if("style"==t)return this.style(e);if("function"==typeof e.fill&&(e=e.fill()),"x"==t&&Array.isArray(this.lines))for(i=this.lines.length-1;i>=0;i--)this.lines[i].attr(t,e);"stroke-width"==t?this.attr("stroke",parseFloat(e)>0?this._stroke:null):"stroke"==t&&(this._stroke=e),(SVG.Color.test(e)||SVG.Color.isRgb(e))&&(e=new SVG.Color(e).toHex()),null!=i?this.node.setAttributeNS(i,t,e):this.node.setAttribute(t,e),this._isStyle(t)&&("text"==t?this.text(e):"leading"==t&&this.leading?this.leading(e):this.style(t,e),this.rebuild&&this.rebuild(t,e))}return this},transform:function(t,e){if(0==arguments.length)return this.trans;if("string"==typeof t){if(arguments.length<2)return this.trans[t];var i={};return i[t]=e,this.transform(i)}var i=[];t=this._parseMatrix(t);for(e in t)null!=t[e]&&(this.trans[e]=t[e]);return this.trans.matrix=this.trans.a+","+this.trans.b+","+this.trans.c+","+this.trans.d+","+this.trans.e+","+this.trans.f,t=this.trans,t.matrix!=SVG.defaults.matrix&&i.push("matrix("+t.matrix+")"),0!=t.rotation&&i.push("rotate("+t.rotation+","+(null==t.cx?this.bbox().cx:t.cx)+","+(null==t.cy?this.bbox().cy:t.cy)+")"),(1!=t.scaleX||1!=t.scaleY)&&i.push("scale("+t.scaleX+","+t.scaleY+")"),0!=t.skewX&&i.push("skewX("+t.skewX+")"),0!=t.skewY&&i.push("skewY("+t.skewY+")"),(0!=t.x||0!=t.y)&&i.push("translate("+t.x/t.scaleX+","+t.y/t.scaleY+")"),this._offset&&i.push("translate("+-this._offset.x+","+-this._offset.y+")"),0==i.length?this.node.removeAttribute("transform"):this.node.setAttribute("transform",i.join(" ")),this},style:function(t,e){if(0==arguments.length)return this.attr("style")||"";if(arguments.length<2)if("object"==typeof t)for(e in t)this.style(e,t[e]);else{if(!SVG.regex.isCss.test(t))return this.styles[t];t=t.split(";");for(var i=0;i<t.length;i++)e=t[i].split(":"),2==e.length&&this.style(e[0].replace(/\s+/g,""),e[1].replace(/^\s+/,"").replace(/\s+$/,""))}else null===e||SVG.regex.test(e,"isBlank")?delete this.styles[t]:this.styles[t]=e;t="";for(e in this.styles)t+=e+":"+this.styles[e]+";";return""==t?this.node.removeAttribute("style"):this.node.setAttribute("style",t),this},data:function(t,e,i){if(arguments.length<2)try{return JSON.parse(this.attr("data-"+t))}catch(n){return this.attr("data-"+t)}else this.attr("data-"+t,null===e?null:i===!0||"string"==typeof e||"number"==typeof e?e:JSON.stringify(e));return this},bbox:function(){return new SVG.BBox(this)},rbox:function(){return new SVG.RBox(this)},inside:function(t,e){var i=this.bbox();return t>i.x&&e>i.y&&t<i.x+i.width&&e<i.y+i.height},show:function(){return this.style("display","")},hide:function(){return this.style("display","none")},visible:function(){return"none"!=this.style("display")},_parent:function(t){for(var e=this;null!=e&&!(e instanceof t);)e=e.parent;return e},_isStyle:function(t){return"string"==typeof t?SVG.regex.test(t,"isStyle"):!1},_parseMatrix:function(t){if(t.matrix){var e=t.matrix.replace(/\s/g,"").split(",");6==e.length&&(t.a=parseFloat(e[0]),t.b=parseFloat(e[1]),t.c=parseFloat(e[2]),t.d=parseFloat(e[3]),t.e=parseFloat(e[4]),t.f=parseFloat(e[5]))}return t}}),SVG.Container=function(t){this.constructor.call(this,t)},SVG.Container.prototype=new SVG.Element,SVG.extend(SVG.Container,{children:function(){return this._children||(this._children=[])},add:function(t,e){if(!this.has(t)){if(e=null==e?this.children().length:e,t.parent){var i=t.parent.children().indexOf(t);t.parent.children().splice(i,1)}this.children().splice(e,0,t),this.node.insertBefore(t.node,this.node.childNodes[e]||null),t.parent=this}return this._defs&&(this.node.removeChild(this._defs.node),this.node.appendChild(this._defs.node)),this},put:function(t,e){return this.add(t,e),t},has:function(t){return this.children().indexOf(t)>=0},get:function(t){return this.children()[t]},each:function(t,e){var i,n,s=this.children();for(i=0,n=s.length;n>i;i++)s[i]instanceof SVG.Element&&t.apply(s[i],[i,s]),e&&s[i]instanceof SVG.Container&&s[i].each(t,e);return this},removeElement:function(t){var e=this.children().indexOf(t);return this.children().splice(e,1),this.node.removeChild(t.node),t.parent=null,this},defs:function(){return this.doc().defs()},first:function(){return this.children()[0]instanceof SVG.Defs?this.children()[1]:this.children()[0]},last:function(){return this.children()[this.children().length-1]},viewbox:function(t){return 0==arguments.length?new SVG.ViewBox(this):(t=1==arguments.length?[t.x,t.y,t.width,t.height]:[].slice.call(arguments),this.attr("viewBox",t.join(" ")))},clear:function(){for(var t=this.children().length-1;t>=0;t--)this.removeElement(this.children()[t]);return this._defs&&this._defs.clear(),this}}),SVG.FX=function(t){this.target=t},SVG.extend(SVG.FX,{animate:function(t,e,i){var n,s,r,o,h=this.target,a=this;return"object"==typeof t&&(i=t.delay,e=t.ease,t=t.duration),t=null==t?1e3:t,e=e||"<>",a.to=function(t){var i;if(t=0>t?0:t>1?1:t,null==n){n=[];for(o in a.attrs)n.push(o)}if(null==s){s=[];for(o in a.trans)s.push(o)}if(null==r){r=[];for(o in a.styles)r.push(o)}for(t="<>"==e?-Math.cos(t*Math.PI)/2+.5:">"==e?Math.sin(t*Math.PI/2):"<"==e?-Math.cos(t*Math.PI/2)+1:"-"==e?t:"function"==typeof e?e(t):t,a._x?h.x(a._at(a._x,t)):a._cx&&h.cx(a._at(a._cx,t)),a._y?h.y(a._at(a._y,t)):a._cy&&h.cy(a._at(a._cy,t)),a._size&&h.size(a._at(a._size.width,t),a._at(a._size.height,t)),a._viewbox&&h.viewbox(a._at(a._viewbox.x,t),a._at(a._viewbox.y,t),a._at(a._viewbox.width,t),a._at(a._viewbox.height,t)),i=n.length-1;i>=0;i--)h.attr(n[i],a._at(a.attrs[n[i]],t));for(i=s.length-1;i>=0;i--)h.transform(s[i],a._at(a.trans[s[i]],t));for(i=r.length-1;i>=0;i--)h.style(r[i],a._at(a.styles[r[i]],t));a._during&&a._during.call(h,t,function(e,i){return a._at({from:e,to:i},t)})},"number"==typeof t&&(this.timeout=setTimeout(function(){var e=1e3/60,i=(new Date).getTime(),n=i+t;a.interval=setInterval(function(){var e=(new Date).getTime(),s=e>n?1:(e-i)/t;a.to(s),e>n&&(clearInterval(a.interval),a._after?a._after.apply(h,[a]):a.stop())},t>e?e:t)},i||0)),this},bbox:function(){return this.target.bbox()},attr:function(t,e){if("object"==typeof t)for(var i in t)this.attr(i,t[i]);else this.attrs[t]={from:this.target.attr(t),to:e};return this},transform:function(t,e){if(1==arguments.length){t=this.target._parseMatrix(t),delete t.matrix;for(e in t)this.trans[e]={from:this.target.trans[e],to:t[e]}}else{var i={};i[t]=e,this.transform(i)}return this},style:function(t,e){if("object"==typeof t)for(var i in t)this.style(i,t[i]);else this.styles[t]={from:this.target.style(t),to:e};return this},x:function(t){return this._x={from:this.target.x(),to:t},this},y:function(t){return this._y={from:this.target.y(),to:t},this},cx:function(t){return this._cx={from:this.target.cx(),to:t},this},cy:function(t){return this._cy={from:this.target.cy(),to:t},this},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},size:function(t,e){if(this.target instanceof SVG.Text)this.attr("font-size",t);else{var i=this.target.bbox();this._size={width:{from:i.width,to:t},height:{from:i.height,to:e}}}return this},viewbox:function(t,e,i,n){if(this.target instanceof SVG.Container){var s=this.target.viewbox();this._viewbox={x:{from:s.x,to:t},y:{from:s.y,to:e},width:{from:s.width,to:i},height:{from:s.height,to:n}}}return this},update:function(t){return this.target instanceof SVG.Stop&&(null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new SVG.Number(t.offset))),this},during:function(t){return this._during=t,this},after:function(t){return this._after=t,this},stop:function(){return clearTimeout(this.timeout),clearInterval(this.interval),this.attrs={},this.trans={},this.styles={},delete this._x,delete this._y,delete this._cx,delete this._cy,delete this._size,delete this._after,delete this._during,delete this._viewbox,this},_at:function(t,e){return"number"==typeof t.from?t.from+(t.to-t.from)*e:SVG.regex.unit.test(t.to)?new SVG.Number(t.to).minus(new SVG.Number(t.from)).times(e).plus(new SVG.Number(t.from)):t.to&&(t.to.r||SVG.Color.test(t.to))?this._color(t,e):1>e?t.from:t.to},_color:function(t,e){var i,n;return e=0>e?0:e>1?1:e,i=new SVG.Color(t.from),n=new SVG.Color(t.to),new SVG.Color({r:~~(i.r+(n.r-i.r)*e),g:~~(i.g+(n.g-i.g)*e),b:~~(i.b+(n.b-i.b)*e)}).toHex()}}),SVG.extend(SVG.Element,{animate:function(t,e,i){return(this.fx||(this.fx=new SVG.FX(this))).stop().animate(t,e,i)},stop:function(){return this.fx&&this.fx.stop(),this}}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","mouseenter","mouseleave","touchstart","touchend","touchmove","touchcancel"].forEach(function(t){SVG.Element.prototype[t]=function(e){var i=this;return this.node["on"+t]="function"==typeof e?function(){return e.apply(i,arguments)}:null,this}}),SVG.on=function(t,e,i){t.addEventListener?t.addEventListener(e,i,!1):t.attachEvent("on"+e,i)},SVG.off=function(t,e,i){t.removeEventListener?t.removeEventListener(e,i,!1):t.detachEvent("on"+e,i)},SVG.extend(SVG.Element,{on:function(t,e){return SVG.on(this.node,t,e),this},off:function(t,e){return SVG.off(this.node,t,e),this}}),SVG.Defs=function(){this.constructor.call(this,SVG.create("defs"))},SVG.Defs.prototype=new SVG.Container,SVG.G=function(){this.constructor.call(this,SVG.create("g"))},SVG.G.prototype=new SVG.Container,SVG.extend(SVG.G,{x:function(t){return null==t?this.trans.x:this.transform("x",t)},y:function(t){return null==t?this.trans.y:this.transform("y",t)}}),SVG.extend(SVG.Container,{group:function(){return this.put(new SVG.G)}}),SVG.extend(SVG.Element,{siblings:function(){return this.parent.children()},position:function(){var t=this.siblings();return t.indexOf(this)},next:function(){return this.siblings()[this.position()+1]},previous:function(){return this.siblings()[this.position()-1]},forward:function(){var t=this.position();return this.parent.removeElement(this).put(this,t+1)},backward:function(){var t=this.position();return t>0&&this.parent.removeElement(this).add(this,t-1),this},front:function(){return this.parent.removeElement(this).put(this)},back:function(){return this.position()>1&&this.parent.removeElement(this).add(this,0),this},before:function(t){t.remove();var e=this.position();return this.parent.add(t,e),this},after:function(t){t.remove();var e=this.position();return this.parent.add(t,e+1),this}}),SVG.Mask=function(){this.constructor.call(this,SVG.create("mask"))},SVG.Mask.prototype=new SVG.Container,SVG.extend(SVG.Element,{maskWith:function(t){return this.mask=t instanceof SVG.Mask?t:this.parent.mask().add(t),this.attr("mask","url(#"+this.mask.attr("id")+")")}}),SVG.extend(SVG.Container,{mask:function(){return this.defs().put(new SVG.Mask)}}),SVG.Clip=function(){this.constructor.call(this,SVG.create("clipPath"))},SVG.Clip.prototype=new SVG.Container,SVG.extend(SVG.Element,{clipWith:function(t){return this.clip=t instanceof SVG.Clip?t:this.parent.clip().add(t),this.attr("clip-path","url(#"+this.clip.attr("id")+")")}}),SVG.extend(SVG.Container,{clip:function(){return this.defs().put(new SVG.Clip)}}),SVG.Pattern=function(){this.constructor.call(this,SVG.create("pattern"))},SVG.Pattern.prototype=new SVG.Container,SVG.extend(SVG.Pattern,{fill:function(){return"url(#"+this.attr("id")+")"}}),SVG.extend(SVG.Defs,{pattern:function(t,e,i){var n=this.put(new SVG.Pattern);return i(n),n.attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),SVG.extend(SVG.Container,{pattern:function(t,e,i){return this.defs().pattern(t,e,i)}}),SVG.Gradient=function(t){this.constructor.call(this,SVG.create(t+"Gradient")),this.type=t},SVG.Gradient.prototype=new SVG.Container,SVG.extend(SVG.Gradient,{from:function(t,e){return"radial"==this.type?this.attr({fx:new SVG.Number(t),fy:new SVG.Number(e)}):this.attr({x1:new SVG.Number(t),y1:new SVG.Number(e)})},to:function(t,e){return"radial"==this.type?this.attr({cx:new SVG.Number(t),cy:new SVG.Number(e)}):this.attr({x2:new SVG.Number(t),y2:new SVG.Number(e)})},radius:function(t){return"radial"==this.type?this.attr({r:new SVG.Number(t)}):this},at:function(t){return this.put(new SVG.Stop(t))},update:function(t){return this.clear(),t(this),this},fill:function(){return"url(#"+this.attr("id")+")"}}),SVG.extend(SVG.Defs,{gradient:function(t,e){var i=this.put(new SVG.Gradient(t));return e(i),i}}),SVG.extend(SVG.Container,{gradient:function(t,e){return this.defs().gradient(t,e)}}),SVG.Stop=function(t){this.constructor.call(this,SVG.create("stop")),this.update(t)},SVG.Stop.prototype=new SVG.Element,SVG.extend(SVG.Stop,{update:function(t){return null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new SVG.Number(t.offset)),this}}),SVG.Doc=function(t){this.parent="string"==typeof t?document.getElementById(t):t,this.constructor.call(this,"svg"==this.parent.nodeName?this.parent:SVG.create("svg")),this.attr({xmlns:SVG.ns,version:"1.1",width:"100%",height:"100%"}).attr("xlink",SVG.xlink,SVG.ns),this._defs=new SVG.Defs,this.node.appendChild(this._defs.node),"svg"!=this.parent.nodeName&&this.stage()},SVG.Doc.prototype=new SVG.Container,SVG.extend(SVG.Doc,{stage:function(){var t,e=this,i=document.createElement("div");return i.style.cssText="position:relative;height:100%;",e.parent.appendChild(i),i.appendChild(e.node),t=function(){"complete"===document.readyState?(e.style("position:absolute;"),setTimeout(function(){e.style("position:relative;"),e.parent.removeChild(e.node.parentNode),e.node.parentNode.removeChild(e.node),e.parent.appendChild(e.node),e.fixSubPixelOffset(),SVG.on(window,"resize",function(){e.fixSubPixelOffset()})},5)):setTimeout(t,10)},t(),this},defs:function(){return this._defs},fixSubPixelOffset:function(){var t=this.node.getScreenCTM();this.style("left",-t.e%1+"px").style("top",-t.f%1+"px")}}),SVG.Shape=function(t){this.constructor.call(this,t)},SVG.Shape.prototype=new SVG.Element,SVG.Rect=function(){this.constructor.call(this,SVG.create("rect"))},SVG.Rect.prototype=new SVG.Shape,SVG.extend(SVG.Container,{rect:function(t,e){return this.put((new SVG.Rect).size(t,e))}}),SVG.Ellipse=function(){this.constructor.call(this,SVG.create("ellipse"))},SVG.Ellipse.prototype=new SVG.Shape,SVG.extend(SVG.Ellipse,{x:function(t){return null==t?this.cx()-this.attr("rx"):this.cx(t+this.attr("rx"))},y:function(t){return null==t?this.cy()-this.attr("ry"):this.cy(t+this.attr("ry"))},cx:function(t){return null==t?this.attr("cx"):this.attr("cx",new SVG.Number(t).divide(this.trans.scaleX))},cy:function(t){return null==t?this.attr("cy"):this.attr("cy",new SVG.Number(t).divide(this.trans.scaleY))},size:function(t,e){return this.attr({rx:new SVG.Number(t).divide(2),ry:new SVG.Number(e).divide(2)})}}),SVG.extend(SVG.Container,{circle:function(t){return this.ellipse(t,t)},ellipse:function(t,e){return this.put(new SVG.Ellipse).size(t,e).move(0,0)}}),SVG.Line=function(){this.constructor.call(this,SVG.create("line"))},SVG.Line.prototype=new SVG.Shape,SVG.extend(SVG.Line,{x:function(t){var e=this.bbox();return null==t?e.x:this.attr({x1:this.attr("x1")-e.x+t,x2:this.attr("x2")-e.x+t})},y:function(t){var e=this.bbox();return null==t?e.y:this.attr({y1:this.attr("y1")-e.y+t,y2:this.attr("y2")-e.y+t})},cx:function(t){var e=this.bbox().width/2;return null==t?this.x()+e:this.x(t-e)},cy:function(t){var e=this.bbox().height/2;return null==t?this.y()+e:this.y(t-e)},size:function(t,e){var i=this.bbox();return this.attr(this.attr("x1")<this.attr("x2")?"x2":"x1",i.x+t).attr(this.attr("y1")<this.attr("y2")?"y2":"y1",i.y+e)},plot:function(t,e,i,n){return this.attr({x1:t,y1:e,x2:i,y2:n})}}),SVG.extend(SVG.Container,{line:function(t,e,i,n){return this.put((new SVG.Line).plot(t,e,i,n))}}),SVG.Polyline=function(t){this.constructor.call(this,SVG.create("polyline")),this.unbiased=t},SVG.Polyline.prototype=new SVG.Shape,SVG.Polygon=function(t){this.constructor.call(this,SVG.create("polygon")),this.unbiased=t},SVG.Polygon.prototype=new SVG.Shape,SVG.extend(SVG.Polyline,SVG.Polygon,{_plot:function(t){if(Array.isArray(t)){var e,i,n=[];for(e=0,i=t.length;i>e;e++)n.push(t[e].join(","));t=n.length>0?n.join(" "):"0,0"}return this.attr("points",t||"0,0")}}),SVG.extend(SVG.Container,{polyline:function(t,e){return this.put(new SVG.Polyline(e)).plot(t)},polygon:function(t,e){return this.put(new SVG.Polygon(e)).plot(t)}}),SVG.Path=function(t){this.constructor.call(this,SVG.create("path")),this.unbiased=t},SVG.Path.prototype=new SVG.Shape,SVG.extend(SVG.Path,{_plot:function(t){return this.attr("d",t||"M0,0")}}),SVG.extend(SVG.Container,{path:function(t,e){return this.put(new SVG.Path(e)).plot(t)}}),SVG.extend(SVG.Polyline,SVG.Polygon,SVG.Path,{x:function(t){return null==t?this.bbox().x:this.transform("x",t)},y:function(t){return null==t?this.bbox().y:this.transform("y",t)},size:function(t,e){var i=t/this._offset.width;return this.transform({scaleX:i,scaleY:null!=e?e/this._offset.height:i})},plot:function(t){var e=this.trans.scaleX,i=this.trans.scaleY;return this._plot(t),this._offset=this.transform({scaleX:1,scaleY:1}).bbox(),this.unbiased?this._offset.x=this._offset.y=0:(this._offset.x-=this.trans.x,this._offset.y-=this.trans.y),this.transform({scaleX:e,scaleY:i})}}),SVG.Image=function(){this.constructor.call(this,SVG.create("image"))},SVG.Image.prototype=new SVG.Shape,SVG.extend(SVG.Image,{load:function(t){return t?this.attr("xlink:href",this.src=t,SVG.xlink):this}}),SVG.extend(SVG.Container,{image:function(t,e,i){return e=null!=e?e:100,this.put((new SVG.Image).load(t).size(e,null!=i?i:e))}});var t="size family weight stretch variant style".split(" ");SVG.Text=function(){this.constructor.call(this,SVG.create("text")),this.styles={"font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},this._leading=1.2,this._base=.276666666},SVG.Text.prototype=new SVG.Shape,SVG.extend(SVG.Text,{x:function(t,e){return null==t?e?this.attr("x"):this.bbox().x:(e||(e=this.style("text-anchor"),t="start"==e?t:"end"==e?t+this.bbox().width:t+this.bbox().width/2),this.attr("x",t))},cx:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)},cy:function(t,e){return null==t?this.bbox().cy:this.y(e?t:t-this.bbox().height/2)},move:function(t,e,i){return this.x(t,i).y(e)},center:function(t,e,i){return this.cx(t,i).cy(e,i)},text:function(t){if(null==t)return this.content;this.clear(),this.content=SVG.regex.isBlank.test(t)?"text":t;var e,i,n=t.split("\n");for(e=0,i=n.length;i>e;e++)this.tspan(n[e]);return this.attr("textLength",1).attr("textLength",null)},tspan:function(t){var e=(new SVG.TSpan).text(t);return this.node.appendChild(e.node),this.lines.push(e),e.attr("style",this.style())},size:function(t){return this.attr("font-size",t)},leading:function(t){return null==t?this._leading:(this._leading=t,this.rebuild("leading",t))},rebuild:function(){var t,e,i=this.styles["font-size"];for(t=0,e=this.lines.length;e>t;t++)this.lines[t].attr({dy:i*this._leading-(0==t?i*this._base:0),x:this.attr("x")||0,style:this.style()});return this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.lines=[],this}}),SVG.extend(SVG.Container,{text:function(t){return this.put((new SVG.Text).text(t))}}),SVG.TSpan=function(){this.constructor.call(this,SVG.create("tspan"))},SVG.TSpan.prototype=new SVG.Shape,SVG.extend(SVG.TSpan,{text:function(t){return this.node.appendChild(document.createTextNode(t)),this}}),SVG.Nested=function(){this.constructor.call(this,SVG.create("svg")),this.style("overflow","visible")},SVG.Nested.prototype=new SVG.Container,SVG.extend(SVG.Container,{nested:function(){return this.put(new SVG.Nested)}}),SVG._stroke=["color","width","opacity","linecap","linejoin","miterlimit","dasharray","dashoffset"],SVG._fill=["color","opacity","rule"];var e=function(t,e){return"color"==e?t:t+"-"+e};["fill","stroke"].forEach(function(t){var i={};i[t]=function(i){if("string"==typeof i||SVG.Color.isRgb(i)||i&&"function"==typeof i.fill)this.attr(t,i);else for(index=SVG["_"+t].length-1;index>=0;index--)null!=i[SVG["_"+t][index]]&&this.attr(e(t,SVG["_"+t][index]),i[SVG["_"+t][index]]);return this},SVG.extend(SVG.Shape,SVG.FX,i)}),SVG.extend(SVG.Element,SVG.FX,{rotate:function(t,e,i){return this.transform({rotation:t||0,cx:e,cy:i})},skew:function(t,e){return this.transform({skewX:t||0,skewY:e||0})},scale:function(t,e){return this.transform({scaleX:t,scaleY:null==e?t:e})},translate:function(t,e){return this.transform({x:t,y:e})},matrix:function(t){return this.transform({matrix:t})},opacity:function(t){return this.attr("opacity",t)}}),SVG.Text&&SVG.extend(SVG.Text,SVG.FX,{font:function(e){for(var i in e)"anchor"==i?this.attr("text-anchor",e[i]):t.indexOf(i)>-1?this.attr("font-"+i,e[i]):this.attr(i,e[i]);return this}})}.call(this);
\ No newline at end of file
index d4cf605658939c672997dde5f2f5b020832bdfd3..524bff794e2225935faa79621bd4adb4f8ad1ec2 100644 (file)
@@ -31,6 +31,7 @@
 <script type="text/javascript" src="spec/svg.js"></script>
 <script type="text/javascript" src="spec/container.js"></script>
 <script type="text/javascript" src="spec/element.js"></script>
+<script type="text/javascript" src="spec/arrange.js"></script>
 <script type="text/javascript" src="spec/bbox.js"></script>
 <script type="text/javascript" src="spec/rect.js"></script>
 <script type="text/javascript" src="spec/ellipse.js"></script>
@@ -41,6 +42,7 @@
 <script type="text/javascript" src="spec/image.js"></script>
 <script type="text/javascript" src="spec/text.js"></script>
 <script type="text/javascript" src="spec/doc.js"></script>
+<script type="text/javascript" src="spec/group.js"></script>
 <script type="text/javascript" src="spec/gradient.js"></script>
 <script type="text/javascript" src="spec/color.js"></script>
 <script type="text/javascript" src="spec/number.js"></script>
diff --git a/spec/spec/arrange.js b/spec/spec/arrange.js
new file mode 100644 (file)
index 0000000..195c322
--- /dev/null
@@ -0,0 +1,180 @@
+describe('Arrange', function() {
+  var e1, e2, e3
+
+  beforeEach(function() {
+    draw.clear()
+
+    e1 = draw.rect(100,100).move(10,10).attr('id', 'e1')
+    e2 = draw.ellipse(100,100).move(20,20).attr('id', 'e2')
+    e3 = draw.line(0,0,100,100).move(30,30).attr('id', 'e3')
+  })
+
+  describe('siblings()', function() {
+    it('returns all siblings of targeted element', function() {
+      expect(e1.siblings().length).toBe(3)
+      expect([e1,e2,e3]).toEqual(e2.siblings())
+    })
+  })
+
+  describe('position()', function() {
+    it('returns the index position within it\'s parent', function() {
+      expect(e1.siblings().length).toBe(3)
+      expect(e1.position()).toBe(0)
+      expect(e2.position()).toBe(1)
+      expect(e3.position()).toBe(2)
+    })
+  })
+
+  describe('next()', function() {
+    it('returns the next sibling within the parent element', function() {
+      expect(e1.next()).toBe(e2)
+      expect(e2.next()).toBe(e3)
+      expect(e3.next()).toBe(undefined)
+    })
+  })
+
+  describe('previous()', function() {
+    it('returns the previous sibling within the parent element', function() {
+      expect(e1.previous()).toBe(undefined)
+      expect(e2.previous()).toBe(e1)
+      expect(e3.previous()).toBe(e2)
+    })
+  })
+
+  describe('forward()', function() {
+    it('returns the element itself', function() {
+      expect(e1.forward()).toBe(e1)
+    })
+    it('moves the element one step forward within its parent', function() {
+      e1.forward()
+      expect(e1.position()).toBe(1)
+      expect(e2.position()).toBe(0)
+      expect(e3.position()).toBe(2)
+    })
+    it('keeps the last element at the same position', function() {
+      e3.forward()
+      expect(e3.position()).toBe(2)
+    })
+    it('keeps the defs on top of the stack', function() {
+      e3.forward()
+      expect(draw.node.childNodes[2]).toBe(e3.node)
+      expect(draw.node.childNodes[3]).toBe(draw.defs().node)
+    })
+  })
+
+  describe('backward()', function() {
+    it('returns the element itself', function() {
+      expect(e1.backward()).toBe(e1)
+    })
+    it('moves the element one step backwards within its parent', function() {
+      e3.backward()
+      expect(e1.position()).toBe(0)
+      expect(e2.position()).toBe(2)
+      expect(e3.position()).toBe(1)
+    })
+    it('keeps the first element at the same position', function() {
+      e3.backward()
+      expect(e1.position()).toBe(0)
+    })
+  })
+
+  describe('front()', function() {
+    it('returns the element itself', function() {
+      expect(e3.front()).toBe(e3)
+    })
+    it('moves the element to the top of the stack within its parent', function() {
+      e1.front()
+      expect(e1.position()).toBe(2)
+      expect(e2.position()).toBe(0)
+      expect(e3.position()).toBe(1)
+    })
+    it('keeps the last element at the same position', function() {
+      e3.front()
+      expect(e3.position()).toBe(2)
+    })
+    it('keeps the defs on top of the stack', function() {
+      e1.front()
+      expect(draw.node.childNodes[2]).toBe(e1.node)
+      expect(draw.node.childNodes[3]).toBe(draw.defs().node)
+    })
+  })
+
+  describe('back()', function() {
+    it('returns the element itself', function() {
+      expect(e3.back()).toBe(e3)
+    })
+    it('moves the element to the bottom of the stack within its parent', function() {
+      e3.back()
+      expect(e1.position()).toBe(1)
+      expect(e2.position()).toBe(2)
+      expect(e3.position()).toBe(0)
+    })
+    it('keeps the first element at the same position', function() {
+      e1.back()
+      expect(e1.position()).toBe(0)
+    })
+  })
+
+  describe('before()', function() {
+    it('returns the targeted element itself', function() {
+      expect(e3.before(e1)).toBe(e3)
+    })
+    it('inserts a given element before the targeted element', function() {
+      e3.before(e1)
+      expect(e1.position()).toBe(1)
+      expect(e2.position()).toBe(0)
+      expect(e3.position()).toBe(2)
+    })
+    it('moves elements between containers', function() {
+      var group = draw.group()
+        , e4 = group.rect(80,120)
+        , e5 = group.rect(80,120)
+        , e6 = group.rect(80,120)
+
+      e2.before(e5)
+      expect(e1.position()).toBe(0)
+      expect(e2.position()).toBe(2)
+      expect(e3.position()).toBe(3)
+      expect(e5.position()).toBe(1)
+    })
+  })
+
+  describe('after()', function() {
+    it('returns the targeted element itself', function() {
+      expect(e3.after(e1)).toBe(e3)
+    })
+    it('inserts a given element after the targeted element', function() {
+      e3.after(e1)
+      expect(e1.position()).toBe(2)
+      expect(e2.position()).toBe(0)
+      expect(e3.position()).toBe(1)
+    })
+    it('moves elements between containers', function() {
+      var group = draw.group()
+        , e4 = group.rect(80,120)
+        , e5 = group.rect(80,120)
+        , e6 = group.rect(80,120)
+
+      e2.after(e5)
+      expect(e1.position()).toBe(0)
+      expect(e2.position()).toBe(1)
+      expect(e3.position()).toBe(3)
+      expect(e5.position()).toBe(2)
+    })
+  })
+
+})
+
+
+
+
+
+
+
+
+
+
+
+
+
+
index 0218e42f96de2fa85edb33b5548bc019621eeac2..44c1eb861569420efd6800108c156b8f59828034 100644 (file)
@@ -4,7 +4,7 @@ describe('BBox', function() {
     draw.clear()
   })
   
-  it('should create a new instance without passing an element', function() {
+  it('creates a new instance without passing an element', function() {
     var box = new SVG.BBox
     expect(box.x).toBe(0)
     expect(box.y).toBe(0)
@@ -15,7 +15,7 @@ describe('BBox', function() {
   })
   
   describe('merge()', function() {
-    it('should merge various bounding boxes', function() {
+    it('merges various bounding boxes', function() {
       var box1 = draw.rect(100,100).move(50,50).bbox()
       var box2 = draw.rect(100,100).move(300,400).bbox()
       var box3 = draw.rect(100,100).move(500,100).bbox()
@@ -27,7 +27,7 @@ describe('BBox', function() {
       expect(merged.width).toBe(550)
       expect(merged.height).toBe(450)
     })
-    it('should return a new bbox instance', function() {
+    it('returns a new bbox instance', function() {
       var box1 = draw.rect(100,100).move(50,50).bbox()
       var box2 = draw.rect(100,100).move(300,400).bbox()
       var merged = box1.merge(box2)
index 19806008864a8aab3a0fd633a12592e60c450831..ca74bcadf59bf3639da67c0bea768e60abc97034 100644 (file)
@@ -1,20 +1,20 @@
 describe('Color', function() {
 
-       it('should correclty parse a rgb string', function() {
+       it('correclty parses a rgb string', function() {
                var color = new SVG.Color('rgb(255,0,128)')
                expect(color.r).toBe(255)
                expect(color.g).toBe(0)
                expect(color.b).toBe(128)
        })
        
-       it('should correclty parse a 3 digit hex string', function() {
+       it('correclty parses a 3 digit hex string', function() {
                var color = new SVG.Color('#f06')
                expect(color.r).toBe(255)
                expect(color.g).toBe(0)
                expect(color.b).toBe(102)
        })
 
-       it('should correclty parse a 6 digit hex string', function() {
+       it('correclty parses a 6 digit hex string', function() {
                var color = new SVG.Color('#0066ff')
                expect(color.r).toBe(0)
                expect(color.g).toBe(102)
index af07fd9842237d40577265302102174d5eb044ac..11727d75be81e78ced87fddcb14b65d6208a86db 100644 (file)
@@ -1,4 +1,8 @@
 describe('Container', function() {
+
+  beforeEach(function() {
+    draw.clear()
+  })
   
   describe('rect()', function() {
     it('should increase children by 1', function() {
@@ -186,11 +190,11 @@ describe('Container', function() {
       draw.clear()
       expect(draw.children().length).toBe(0)
     })
-    it('should create a new defs node', function() {
+    it('should keep the defs node', function() {
       var oldDefs = draw.defs()
       draw.rect(100,100).maskWith(draw.circle(100, 100))
       draw.clear()
-      expect(draw.defs()).not.toBe(oldDefs)
+      expect(draw.defs()).toBe(oldDefs)
     })
   })
   
@@ -205,7 +209,6 @@ describe('Container', function() {
       draw.each(function() {
         children.push(this.type)
       })
-      
       expect(children).toEqual(['rect', 'ellipse', 'polygon'])
     })
     it('should only include the its own children', function() {
diff --git a/spec/spec/group.js b/spec/spec/group.js
new file mode 100644 (file)
index 0000000..f0404fd
--- /dev/null
@@ -0,0 +1,74 @@
+describe('Group', function() {
+  var group
+
+  beforeEach(function() {
+    group = draw.group()
+    group.rect(100,100)
+  })
+  
+  afterEach(function() {
+    draw.clear()
+  })
+
+  describe('x()', function() {
+    it('returns the value of x without an argument', function() {
+      expect(group.x()).toBe(0)
+    })
+    it('sets the value of x with the first argument', function() {
+      group.x(123)
+      var box = group.bbox()
+      expect(box.x).toBe(123)
+    })
+  })
+  
+  describe('y()', function() {
+    it('returns the value of y without an argument', function() {
+      expect(group.y()).toBe(0)
+    })
+    it('sets the value of y with the first argument', function() {
+      group.y(345)
+      var box = group.bbox()
+      expect(box.y).toBe(345)
+    })
+  })
+  
+  describe('cx()', function() {
+    it('returns the value of cx without an argument', function() {
+      expect(group.cx()).toBe(50)
+    })
+    it('sets the value of cx with the first argument', function() {
+      group.cx(123)
+      var box = group.bbox()
+      expect(box.cx).toBe(123)
+    })
+  })
+  
+  describe('cy()', function() {
+    it('returns the value of cy without an argument', function() {
+      expect(group.cy()).toBe(50)
+    })
+    it('sets the value of cy with the first argument', function() {
+      group.cy(345)
+      var box = group.bbox()
+      expect(box.cy).toBe(345)
+    })
+  })
+
+  describe('move()', function() {
+    it('sets the x and y position', function() {
+      group.move(123,456)
+      expect(group.node.getAttribute('transform')).toBe('translate(123,456)')
+    })
+  })
+  
+  describe('center()', function() {
+    it('sets the cx and cy position', function() {
+      group.center(321,567)
+      var box = group.bbox()
+      expect(box.cx).toBe(321)
+      expect(box.cy).toBe(567)
+    })
+  })
+  
+
+})
\ No newline at end of file
index 1aecc315374f2af12205b0d9e5fac89765e68ae6..75f8a6d16e3fb73543f8ac419f907f337a1c6156 100644 (file)
@@ -13,27 +13,27 @@ describe('SVG', function() {
       wrapper.parentNode.removeChild(wrapper)
     })
     
-    it('should create a new svg canvas', function() {
+    it('creates a new svg canvas', function() {
       expect(canvas.type).toBe('svg')
     })
-    it('should create an instance of SVG.Doc', function() {
+    it('creates an instance of SVG.Doc', function() {
       expect(canvas instanceof SVG.Doc).toBe(true)
     })
   })
   
   describe('create()', function() {
-    it('should create an element with given node name and return it', function() {
+    it('creates an element with given node name and return it', function() {
       var element = SVG.create('rect')
       
       expect(element.nodeName).toBe('rect')
     })
-    it('should increase the global id sequence', function() {
+    it('increases the global id sequence', function() {
       var did = SVG.did
         , element = SVG.create('rect')
       
       expect(did + 1).toBe(SVG.did)
     })
-    it('should add a unique id containing the node name', function() {
+    it('adds a unique id containing the node name', function() {
       var did = SVG.did
         , element = SVG.create('rect')
       
@@ -42,7 +42,7 @@ describe('SVG', function() {
   })
   
   describe('extend()', function() {
-    it('should add all functions in the given object to the target object', function() {
+    it('adds all functions in the given object to the target object', function() {
       SVG.extend(SVG.Rect, {
         soft: function() {
           return this.opacity(0.2)
@@ -52,7 +52,7 @@ describe('SVG', function() {
       expect(typeof SVG.Rect.prototype.soft).toBe('function')
       expect(draw.rect(100,100).soft().attr('opacity')).toBe(0.2)
     })
-    it('should accept and extend multiple modules at once', function() {
+    it('accepts and extend multiple modules at once', function() {
       SVG.extend(SVG.Rect, SVG.Ellipse, SVG.Path, {
         soft: function() {
           return this.opacity(0.5)
@@ -66,7 +66,7 @@ describe('SVG', function() {
       expect(typeof SVG.Path.prototype.soft).toBe('function')
       expect(draw.path().soft().attr('opacity')).toBe(0.5)
     })
-    it('should ignone non existant objects', function() {
+    it('ignones non existant objects', function() {
       SVG.extend(SVG.Rect, SVG.Bogus, {
         soft: function() {
           return this.opacity(0.3)
@@ -80,12 +80,12 @@ describe('SVG', function() {
   })
   
   describe('get()', function() {
-    it('should get an element\'s instance by id', function() {
+    it('gets an element\'s instance by id', function() {
       var rect = draw.rect(111,333)
       
       expect(SVG.get(rect.attr('id'))).toBe(rect)
     })
-    it('should make have all the element\'s methods available', function() {
+    it('makes have all the element\'s methods available', function() {
       var element = draw.group()
         , got = SVG.get(element.attr('id'))
       
index 157c91c41a5dd02397e972e2b9159ef91cbfe401..13b4311cdf6e5e44688d46a29a60aab8959a762a 100644 (file)
@@ -8,7 +8,9 @@ SVG.extend(SVG.Element, {
   }
   // Get the curent position siblings
 , position: function() {
-    return this.siblings().indexOf(this)
+    var siblings = this.siblings()
+
+    return siblings.indexOf(this)
   }
   // Get the next element (will return null if there is none)
 , next: function() {
@@ -20,17 +22,16 @@ SVG.extend(SVG.Element, {
   }
   // Send given element one step forward
 , forward: function() {
-    return this.parent.removeElement(this).put(this, this.position() + 1)
+    var i = this.position()
+    return this.parent.removeElement(this).put(this, i + 1)
   }
   // Send given element one step backward
 , backward: function() {
-    this.parent.level()
-    
     var i = this.position()
     
-    if (i > 1)
+    if (i > 0)
       this.parent.removeElement(this).add(this, i - 1)
-    
+
     return this
   }
   // Send given element all the way to the front
@@ -39,12 +40,30 @@ SVG.extend(SVG.Element, {
   }
   // Send given element all the way to the back
 , back: function() {
-    this.parent.level()
-    
     if (this.position() > 1)
       this.parent.removeElement(this).add(this, 0)
     
     return this
   }
-  
+  // Inserts a given element before the targeted element
+, before: function(element) {
+    element.remove()
+
+    var i = this.position()
+    
+    this.parent.add(element, i)
+
+    return this
+  }
+  // Insters a given element after the targeted element
+, after: function(element) {
+    element.remove()
+    
+    var i = this.position()
+    
+    this.parent.add(element, i + 1)
+
+    return this
+  }
+
 })
\ No newline at end of file
index cb010f209aee599f73e549ee2999028b3ef1ef11..f928c543e61cbb5fa709f7f512e9875851d31aa7 100644 (file)
@@ -28,6 +28,12 @@ SVG.extend(SVG.Container, {
       this.node.insertBefore(element.node, this.node.childNodes[i] || null)
       element.parent = this
     }
+
+    /* reposition defs */
+    if (this._defs) {
+      this.node.removeChild(this._defs.node)
+      this.node.appendChild(this._defs.node)
+    }
     
     return this
   }
@@ -50,7 +56,7 @@ SVG.extend(SVG.Container, {
       , children = this.children()
     
     for (i = 0, il = children.length; i < il; i++) {
-      if (children[i] instanceof SVG.Shape)
+      if (children[i] instanceof SVG.Element)
         block.apply(children[i], [i, children])
 
       if (deep && (children[i] instanceof SVG.Container))
@@ -69,13 +75,9 @@ SVG.extend(SVG.Container, {
     
     return this
   }
-  // Returns defs element
+  // Get defs
 , defs: function() {
-    return this._defs || (this._defs = this.put(new SVG.Defs, 0))
-  }
-  // Re-level defs to first positon in element stack
-, level: function() {
-    return this.removeElement(this.defs()).put(this.defs(), 0)
+    return this.doc().defs()
   }
   // Get first child, skipping the defs node
 , first: function() {
@@ -105,10 +107,8 @@ SVG.extend(SVG.Container, {
       this.removeElement(this.children()[i])
 
     /* remove defs node */
-    if (this._defs) {
-      this._defs.remove()
-      delete this._defs
-    }
+    if (this._defs)
+      this._defs.clear()
 
     return this
   }
index faf89c5554616ea07913149a492e8adf55120e92..65545ebc6aeca8892f0b9e2d0f15d97d92ba79e6 100644 (file)
@@ -12,11 +12,14 @@ SVG.Doc = function(element) {
   this.constructor
     .call(this, this.parent.nodeName == 'svg' ? this.parent : SVG.create('svg'))
   
-  /* set svg element attributes and create the <defs> node */
+  /* set svg element attributes */
   this
     .attr({ xmlns: SVG.ns, version: '1.1', width: '100%', height: '100%' })
     .attr('xlink', SVG.xlink, SVG.ns)
-    .defs()
+  
+  /* create the <defs> node */
+  this._defs = new SVG.Defs
+  this.node.appendChild(this._defs.node)
   
   /* ensure correct rendering */
   if (this.parent.nodeName != 'svg')
@@ -26,7 +29,7 @@ SVG.Doc = function(element) {
 // Inherits from SVG.Container
 SVG.Doc.prototype = new SVG.Container
 
-
+//
 SVG.extend(SVG.Doc, {
   // Hack for safari preventing text to be rendered in one line.
   // Basically it sets the position of the svg node to absolute
@@ -76,6 +79,11 @@ SVG.extend(SVG.Doc, {
     return this
   }
 
+  // Creates and returns defs element
+, defs: function() {
+    return this._defs
+  }
+
   // Fix for possible sub-pixel offset. See:
   // https://bugzilla.mozilla.org/show_bug.cgi?id=608812
 , fixSubPixelOffset: function() {
index 118465760470d438b20eb17e23caef4db3253b68..84eed5417d5c38e445c8b1c117dd03984c1a5e41 100644 (file)
@@ -15,11 +15,6 @@ SVG.extend(SVG.G, {
 , y: function(y) {
     return y == null ? this.trans.y : this.transform('y', y)
   }
-  // Get defs
-, defs: function() {
-    return this.doc().defs()
-  }
-  
 })
 
 //
diff --git a/src/instance.js b/src/instance.js
new file mode 100644 (file)
index 0000000..086a019
--- /dev/null
@@ -0,0 +1,28 @@
+SVG.Use = function() {
+  this.constructor.call(this, SVG.create('use'))
+}
+
+// Inherit from SVG.Shape
+SVG.Use.prototype = new SVG.Element
+
+//
+SVG.extend(SVG.Use, {
+  
+  // (re)load image
+  load: function(url) {
+    return (url ? this.attr('xlink:href', (this.src = url), SVG.xlink) : this)
+  }
+  
+})
+
+//
+SVG.extend(SVG.Container, {
+  // Create a use element
+  use: function(element) {
+    if (element instanceof SVG.Element)
+      element = element.id
+
+    return this.put(new SVG.Use().)
+  }
+
+})
\ No newline at end of file
index 1de5c77ae4fb61f9019d3009dba376c4eb569d2c..1b820530f74af12e0e1f5b28f431471574a5f4cb 100644 (file)
@@ -12,12 +12,6 @@ this.SVG = function(element) {
     return new SVG.Doc(element)
 }
 
-// DEPRECATED!!! Use SVG() instead
-this.svg = function(element) {
-  console.warn('WARNING: svg() is deprecated, please use SVG() instead.')
-  return SVG(element)
-}
-
 // Default namespaces
 SVG.ns = 'http://www.w3.org/2000/svg'
 SVG.xlink = 'http://www.w3.org/1999/xlink'