]> source.dussan.org Git - svg.js.git/commitdiff
Merge branch 'master' into 3.0.0
authorUlrich-Matthias Schäfer <ulima.ums@googlemail.com>
Sat, 22 Apr 2017 18:31:58 +0000 (20:31 +0200)
committerUlrich-Matthias Schäfer <ulima.ums@googlemail.com>
Sat, 22 Apr 2017 18:31:58 +0000 (20:31 +0200)
# Conflicts - all resolved:
# dist/svg.js
# dist/svg.min.js
# package.json
# spec/SpecRunner.html
# spec/spec/boxes.js
# spec/spec/element.js
# spec/spec/image.js
# spec/spec/svg.js
# src/boxes.js
# src/flatten.js
# src/image.js
# src/polyfill.js
# src/style.js
# src/svg.js

16 files changed:
1  2 
CHANGELOG.md
bench/runner.html
dist/svg.js
dist/svg.min.js
package.json
spec/SpecRunner.html
spec/spec/boxes.js
spec/spec/container.js
spec/spec/element.js
spec/spec/image.js
spec/spec/path.js
spec/spec/svg.js
spec/spec/text.js
src/boxes.js
src/fx.js
src/svg.js

diff --cc CHANGELOG.md
Simple merge
Simple merge
diff --cc dist/svg.js
index a71d957b24b8a7ced025743618bad78d959b5a4b,3263c193047915994636bbebac8ff56c73ccfac3..35ae5a16afc8caa350a745d7b620c8f37c035739
  /*!
  * svg.js - A lightweight library for manipulating and animating SVG.
- * @version 2.5.0
 -* @version 2.6.0
++* @version 3.0.0
  * https://svgdotjs.github.io/
  *
  * @copyright Wout Fierens <wout@mick-wout.com>
  * @license MIT
  *
- * BUILT: Sun Mar 19 2017 16:34:53 GMT+0100 (Mitteleuropäische Zeit)
 -* BUILT: Fri Apr 21 2017 12:48:06 GMT+0200 (Mitteleuropäische Sommerzeit)
++* BUILT: Sat Apr 22 2017 20:28:05 GMT+0200 (Mitteleuropäische Sommerzeit)
  */;
- (function(root, factory) {
-   if (typeof define === 'function' && define.amd) {
-     define(function(){
-       return factory(root, root.document)
-     })
-   } else if (typeof exports === 'object') {
-     module.exports = root.document ? factory(root, root.document) : function(w){ return factory(w, w.document) }
-   } else {
-     root.SVG = factory(root, root.document)
-   }
- }(typeof window !== "undefined" ? window : this, function(window, document) {
- // The main wrapping element
- var SVG = this.SVG = function(element) {
-   if (SVG.supported) {
-     element = new SVG.Doc(element)
-     if(!SVG.parser.draw)
-       SVG.prepare()
-     return element
-   }
- }
- // Default namespaces
- SVG.ns    = 'http://www.w3.org/2000/svg'
- SVG.xmlns = 'http://www.w3.org/2000/xmlns/'
- SVG.xlink = 'http://www.w3.org/1999/xlink'
- SVG.svgjs = 'http://svgjs.com/svgjs'
- // Svg support test
- SVG.supported = (function() {
-   return !! document.createElementNS &&
-          !! document.createElementNS(SVG.ns,'svg').createSVGRect
- })()
- // Don't bother to continue if SVG is not supported
- if (!SVG.supported) return false
- // Element id sequence
- SVG.did  = 1000
- // Get next named element id
- SVG.eid = function(name) {
-   return 'Svgjs' + capitalize(name) + (SVG.did++)
- }
- // Method for element creation
- SVG.create = function(name) {
-   // create element
-   var element = document.createElementNS(this.ns, name)
-   // apply unique id
-   element.setAttribute('id', this.eid(name))
-   return element
- }
- // Method for extending objects
- SVG.extend = function() {
-   var modules, methods, key, i
-   // Get list of modules
-   modules = [].slice.call(arguments)
-   // Get object with extensions
-   methods = modules.pop()
-   for (i = modules.length - 1; i >= 0; i--)
-     if (modules[i])
-       for (key in methods)
-         modules[i].prototype[key] = methods[key]
- }
- // Invent new element
- SVG.invent = function(config) {
-   // Create element initializer
-   var initializer = typeof config.create == 'function' ?
-     config.create :
-     function() {
-       this.constructor.call(this, SVG.create(config.create))
-     }
-   // Inherit prototype
-   if (config.inherit)
-     initializer.prototype = new config.inherit
-   // Extend with methods
-   if (config.extend)
-     SVG.extend(initializer, config.extend)
-   // Attach construct method to parent
-   if (config.construct)
-     SVG.extend(config.parent || SVG.Container, config.construct)
-   return initializer
- }
- // Adopt existing svg elements
- SVG.adopt = function(node) {
-   // check for presence of node
-   if (!node) return null
-   // make sure a node isn't already adopted
-   if (node.instance) return node.instance
-   // initialize variables
-   var element
-   // adopt with element-specific settings
-   if (node.nodeName == 'svg')
-     element = node.parentNode instanceof window.SVGElement ? new SVG.Nested : new SVG.Doc
-   else if (node.nodeName == 'linearGradient')
-     element = new SVG.Gradient('linear')
-   else if (node.nodeName == 'radialGradient')
-     element = new SVG.Gradient('radial')
-   else if (SVG[capitalize(node.nodeName)])
-     element = new SVG[capitalize(node.nodeName)]
-   else
-     element = new SVG.Element(node)
-   // ensure references
-   element.type  = node.nodeName
-   element.node  = node
-   node.instance = element
-   // SVG.Class specific preparations
-   if (element instanceof SVG.Doc)
-     element.namespace().defs()
-   // pull svgjs data from the dom (getAttributeNS doesn't work in html5)
-   element.setData(JSON.parse(node.getAttribute('svgjs:data')) || {})
-   return element
- }
- // Initialize parsing element
- SVG.prepare = function() {
-   // Select document body and create invisible svg element
-   var body = document.getElementsByTagName('body')[0]
-     , draw = (body ? new SVG.Doc(body) :  new SVG.Doc(document.documentElement).nested()).size(2, 0)
-   // Create parser object
-   SVG.parser = {
-     body: body || document.documentElement
-   , draw: draw.style({
-       opacity:0,
-       position:'absolute',
-       left:'-100%',
-       top:'-100%',
-       overflow:'hidden'
-     })
-   , poly: draw.polyline().node
-   , path: draw.path().node
-   , native: SVG.create('svg')
-   }
- }
- SVG.parser = {
-   native: SVG.create('svg')
- }
- document.addEventListener('DOMContentLoaded', function() {
-   if(!SVG.parser.draw)
-     SVG.prepare()
- }, false)
- // Storage for regular expressions
- SVG.regex = {
-   // Parse unit value
-   numberAndUnit:    /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i
-   // Parse hex value
- , hex:              /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i
-   // Parse rgb value
- , rgb:              /rgb\((\d+),(\d+),(\d+)\)/
-   // Parse reference id
- , reference:        /#([a-z0-9\-_]+)/i
-   // splits a transformation chain
- , transforms:       /\)\s*,?\s*/
-   // Whitespace
- , whitespace:       /\s/g
-   // Test hex value
- , isHex:            /^#[a-f0-9]{3,6}$/i
-   // Test rgb value
- , isRgb:            /^rgb\(/
-   // Test css declaration
- , isCss:            /[^:]+:[^;]+;?/
-   // Test for blank string
- , isBlank:          /^(\s+)?$/
-   // Test for numeric string
- , isNumber:         /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i
-   // Test for percent value
- , isPercent:        /^-?[\d\.]+%$/
-   // Test for image url
- , isImage:          /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i
-   // split at whitespace and comma
- , delimiter:        /[\s,]+/
-   // The following regex are used to parse the d attribute of a path
-   // Matches all hyphens which are not after an exponent
- , hyphen:           /([^e])\-/gi
-   // Replaces and tests for all path letters
- , pathLetters:      /[MLHVCSQTAZ]/gi
-   // yes we need this one, too
- , isPathLetter:     /[MLHVCSQTAZ]/i
-   // matches 0.154.23.45
- , numbersWithDots:  /((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi
-   // matches .
- , dots:             /\./g
- }
- SVG.utils = {
-   // Map function
-   map: function(array, block) {
-     var i
-       , il = array.length
-       , result = []
-     for (i = 0; i < il; i++)
-       result.push(block(array[i]))
-     return result
-   }
-   // Filter function
- , filter: function(array, block) {
-     var i
-       , il = array.length
-       , result = []
-     for (i = 0; i < il; i++)
-       if (block(array[i]))
-         result.push(array[i])
-     return result
-   }
-   // Degrees to radians
- , radians: function(d) {
-     return d % 360 * Math.PI / 180
-   }
-   // Radians to degrees
- , degrees: function(r) {
-     return r * 180 / Math.PI % 360
-   }
- , filterSVGElements: function(nodes) {
-     return this.filter( nodes, function(el) { return el instanceof window.SVGElement })
-   }
- }
- SVG.defaults = {
-   // Default attribute values
-   attrs: {
-     // fill and stroke
-     'fill-opacity':     1
-   , 'stroke-opacity':   1
-   , 'stroke-width':     0
-   , 'stroke-linejoin':  'miter'
-   , 'stroke-linecap':   'butt'
-   , fill:               '#000000'
-   , stroke:             '#000000'
-   , opacity:            1
-     // position
-   , x:                  0
-   , y:                  0
-   , cx:                 0
-   , cy:                 0
-     // size
-   , width:              0
-   , height:             0
-     // radius
-   , r:                  0
-   , rx:                 0
-   , ry:                 0
-     // gradient
-   , offset:             0
-   , 'stop-opacity':     1
-   , 'stop-color':       '#000000'
-     // text
-   , 'font-size':        16
-   , 'font-family':      'Helvetica, Arial, sans-serif'
-   , 'text-anchor':      'start'
-   }
- }
- // Module for color convertions
- SVG.Color = function(color) {
-   var match
-   // initialize defaults
-   this.r = 0
-   this.g = 0
-   this.b = 0
-   if(!color) return
-   // parse color
-   if (typeof color === 'string') {
-     if (SVG.regex.isRgb.test(color)) {
-       // get rgb values
-       match = SVG.regex.rgb.exec(color.replace(SVG.regex.whitespace,''))
-       // parse numeric values
-       this.r = parseInt(match[1])
-       this.g = parseInt(match[2])
-       this.b = parseInt(match[3])
-     } else if (SVG.regex.isHex.test(color)) {
-       // get hex values
-       match = SVG.regex.hex.exec(fullHex(color))
-       // parse numeric values
-       this.r = parseInt(match[1], 16)
-       this.g = parseInt(match[2], 16)
-       this.b = parseInt(match[3], 16)
-     }
-   } else if (typeof color === 'object') {
-     this.r = color.r
-     this.g = color.g
-     this.b = color.b
-   }
- }
- SVG.extend(SVG.Color, {
-   // Default to hex conversion
-   toString: function() {
-     return this.toHex()
-   }
-   // Build hex value
- , toHex: function() {
-     return '#'
-       + compToHex(this.r)
-       + compToHex(this.g)
-       + compToHex(this.b)
-   }
-   // Build rgb value
- , toRgb: function() {
-     return 'rgb(' + [this.r, this.g, this.b].join() + ')'
-   }
-   // Calculate true brightness
- , brightness: function() {
-     return (this.r / 255 * 0.30)
-          + (this.g / 255 * 0.59)
-          + (this.b / 255 * 0.11)
-   }
-   // Make color morphable
- , morph: function(color) {
-     this.destination = new SVG.Color(color)
-     return this
-   }
-   // Get morphed color at given position
- , at: function(pos) {
-     // make sure a destination is defined
-     if (!this.destination) return this
-     // normalise pos
-     pos = pos < 0 ? 0 : pos > 1 ? 1 : pos
-     // generate morphed color
-     return new SVG.Color({
-       r: ~~(this.r + (this.destination.r - this.r) * pos)
-     , g: ~~(this.g + (this.destination.g - this.g) * pos)
-     , b: ~~(this.b + (this.destination.b - this.b) * pos)
-     })
-   }
- })
- // Testers
- // Test if given value is a color string
- SVG.Color.test = function(color) {
-   color += ''
-   return SVG.regex.isHex.test(color)
-       || SVG.regex.isRgb.test(color)
- }
- // Test if given value is a rgb object
- SVG.Color.isRgb = function(color) {
-   return color && typeof color.r == 'number'
-                && typeof color.g == 'number'
-                && typeof color.b == 'number'
- }
- // Test if given value is a color
- SVG.Color.isColor = function(color) {
-   return SVG.Color.isRgb(color) || SVG.Color.test(color)
- }
- // Module for array conversion
- SVG.Array = function(array, fallback) {
-   array = (array || []).valueOf()
-   // if array is empty and fallback is provided, use fallback
-   if (array.length == 0 && fallback)
-     array = fallback.valueOf()
-   // parse array
-   this.value = this.parse(array)
- }
- SVG.extend(SVG.Array, {
-   // Make array morphable
-   morph: function(array) {
-     this.destination = this.parse(array)
-     // normalize length of arrays
-     if (this.value.length != this.destination.length) {
-       var lastValue       = this.value[this.value.length - 1]
-         , lastDestination = this.destination[this.destination.length - 1]
-       while(this.value.length > this.destination.length)
-         this.destination.push(lastDestination)
-       while(this.value.length < this.destination.length)
-         this.value.push(lastValue)
-     }
-     return this
-   }
-   // Clean up any duplicate points
- , settle: function() {
-     // find all unique values
-     for (var i = 0, il = this.value.length, seen = []; i < il; i++)
-       if (seen.indexOf(this.value[i]) == -1)
-         seen.push(this.value[i])
-     // set new value
-     return this.value = seen
-   }
-   // Get morphed array at given position
- , at: function(pos) {
-     // make sure a destination is defined
-     if (!this.destination) return this
-     // generate morphed array
-     for (var i = 0, il = this.value.length, array = []; i < il; i++)
-       array.push(this.value[i] + (this.destination[i] - this.value[i]) * pos)
-     return new SVG.Array(array)
-   }
-   // Convert array to string
- , toString: function() {
-     return this.value.join(' ')
-   }
-   // Real value
- , valueOf: function() {
-     return this.value
-   }
-   // Parse whitespace separated string
- , parse: function(array) {
-     array = array.valueOf()
-     // if already is an array, no need to parse it
-     if (Array.isArray(array)) return array
-     return array.trim().split(SVG.regex.delimiter).map(parseFloat)
-   }
-   // Reverse array
- , reverse: function() {
-     this.value.reverse()
-     return this
-   }
- , clone: function() {
-     var clone = new this.constructor()
-     clone.value = array_clone(this.value)
-     return clone
-   }
- })
- // Poly points array
- SVG.PointArray = function(array, fallback) {
-   SVG.Array.call(this, array, fallback || [[0,0]])
- }
- // Inherit from SVG.Array
- SVG.PointArray.prototype = new SVG.Array
- SVG.PointArray.prototype.constructor = SVG.PointArray
- SVG.extend(SVG.PointArray, {
-   // Convert array to string
-   toString: function() {
-     // convert to a poly point string
-     for (var i = 0, il = this.value.length, array = []; i < il; i++)
-       array.push(this.value[i].join(','))
-     return array.join(' ')
-   }
-   // Convert array to line object
- , toLine: function() {
-     return {
-       x1: this.value[0][0]
-     , y1: this.value[0][1]
-     , x2: this.value[1][0]
-     , y2: this.value[1][1]
-     }
-   }
-   // Get morphed array at given position
- , at: function(pos) {
-     // make sure a destination is defined
-     if (!this.destination) return this
-     // generate morphed point string
-     for (var i = 0, il = this.value.length, array = []; i < il; i++)
-       array.push([
-         this.value[i][0] + (this.destination[i][0] - this.value[i][0]) * pos
-       , this.value[i][1] + (this.destination[i][1] - this.value[i][1]) * pos
-       ])
-     return new SVG.PointArray(array)
-   }
-   // Parse point string and flat array
- , parse: function(array) {
-     var points = []
-     array = array.valueOf()
-     // if it is an array
-     if (Array.isArray(array)) {
-       // and it is not flat, there is no need to parse it
-       if(Array.isArray(array[0])) {
-         return array
-       }
-     } else { // Else, it is considered as a string
-       // parse points
-       array = array.trim().split(SVG.regex.delimiter).map(parseFloat)
-     }
-     // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints
-     // Odd number of coordinates is an error. In such cases, drop the last odd coordinate.
-     if (array.length % 2 !== 0) array.pop()
-     // wrap points in two-tuples and parse points as floats
-     for(var i = 0, len = array.length; i < len; i = i + 2)
-       points.push([ array[i], array[i+1] ])
-     return points
-   }
-   // Move point string
- , move: function(x, y) {
-     var box = this.bbox()
-     // get relative offset
-     x -= box.x
-     y -= box.y
-     // move every point
-     if (!isNaN(x) && !isNaN(y))
-       for (var i = this.value.length - 1; i >= 0; i--)
-         this.value[i] = [this.value[i][0] + x, this.value[i][1] + y]
-     return this
-   }
-   // Resize poly string
- , size: function(width, height) {
-     var i, box = this.bbox()
-     // recalculate position of all points according to new size
-     for (i = this.value.length - 1; i >= 0; i--) {
-       if(box.width) this.value[i][0] = ((this.value[i][0] - box.x) * width)  / box.width  + box.x
-       if(box.height) this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y
-     }
-     return this
-   }
-   // Get bounding box of points
- , bbox: function() {
-     SVG.parser.poly.setAttribute('points', this.toString())
-     return SVG.parser.poly.getBBox()
-   }
- })
- // Path points array
- SVG.PathArray = function(array, fallback) {
-   SVG.Array.call(this, array, fallback || [['M', 0, 0]])
- }
- // Inherit from SVG.Array
- SVG.PathArray.prototype = new SVG.Array
- SVG.PathArray.prototype.constructor = SVG.PathArray
- SVG.extend(SVG.PathArray, {
-   // Convert array to string
-   toString: function() {
-     return arrayToString(this.value)
-   }
-   // Move path string
- , move: function(x, y) {
-     // get bounding box of current situation
-     var box = this.bbox()
-     // get relative offset
-     x -= box.x
-     y -= box.y
-     if (!isNaN(x) && !isNaN(y)) {
-       // move every point
-       for (var l, i = this.value.length - 1; i >= 0; i--) {
-         l = this.value[i][0]
-         if (l == 'M' || l == 'L' || l == 'T')  {
-           this.value[i][1] += x
-           this.value[i][2] += y
-         } else if (l == 'H')  {
-           this.value[i][1] += x
-         } else if (l == 'V')  {
-           this.value[i][1] += y
-         } else if (l == 'C' || l == 'S' || l == 'Q')  {
-           this.value[i][1] += x
-           this.value[i][2] += y
-           this.value[i][3] += x
-           this.value[i][4] += y
-           if (l == 'C')  {
-             this.value[i][5] += x
-             this.value[i][6] += y
-           }
-         } else if (l == 'A')  {
-           this.value[i][6] += x
-           this.value[i][7] += y
-         }
-       }
-     }
-     return this
-   }
-   // Resize path string
- , size: function(width, height) {
-     // get bounding box of current situation
-     var i, l, box = this.bbox()
-     // recalculate position of all points according to new size
-     for (i = this.value.length - 1; i >= 0; i--) {
-       l = this.value[i][0]
-       if (l == 'M' || l == 'L' || l == 'T')  {
-         this.value[i][1] = ((this.value[i][1] - box.x) * width)  / box.width  + box.x
-         this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y
-       } else if (l == 'H')  {
-         this.value[i][1] = ((this.value[i][1] - box.x) * width)  / box.width  + box.x
-       } else if (l == 'V')  {
-         this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y
-       } else if (l == 'C' || l == 'S' || l == 'Q')  {
-         this.value[i][1] = ((this.value[i][1] - box.x) * width)  / box.width  + box.x
-         this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y
-         this.value[i][3] = ((this.value[i][3] - box.x) * width)  / box.width  + box.x
-         this.value[i][4] = ((this.value[i][4] - box.y) * height) / box.height + box.y
-         if (l == 'C')  {
-           this.value[i][5] = ((this.value[i][5] - box.x) * width)  / box.width  + box.x
-           this.value[i][6] = ((this.value[i][6] - box.y) * height) / box.height + box.y
-         }
-       } else if (l == 'A')  {
-         // resize radii
-         this.value[i][1] = (this.value[i][1] * width)  / box.width
-         this.value[i][2] = (this.value[i][2] * height) / box.height
-         // move position values
-         this.value[i][6] = ((this.value[i][6] - box.x) * width)  / box.width  + box.x
-         this.value[i][7] = ((this.value[i][7] - box.y) * height) / box.height + box.y
-       }
-     }
-     return this
-   }
-   // Test if the passed path array use the same path data commands as this path array
- , equalCommands: function(pathArray) {
-     var i, il, equalCommands
-     pathArray = new SVG.PathArray(pathArray)
-     equalCommands = this.value.length === pathArray.value.length
-     for(i = 0, il = this.value.length; equalCommands && i < il; i++) {
-       equalCommands = this.value[i][0] === pathArray.value[i][0]
-     }
-     return equalCommands
-   }
-   // Make path array morphable
- , morph: function(pathArray) {
-     pathArray = new SVG.PathArray(pathArray)
-     if(this.equalCommands(pathArray)) {
-       this.destination = pathArray
-     } else {
-       this.destination = null
-     }
-     return this
-   }
-   // Get morphed path array at given position
- , at: function(pos) {
-     // make sure a destination is defined
-     if (!this.destination) return this
-     var sourceArray = this.value
-       , destinationArray = this.destination.value
-       , array = [], pathArray = new SVG.PathArray()
-       , i, il, j, jl
-     // Animate has specified in the SVG spec
-     // See: https://www.w3.org/TR/SVG11/paths.html#PathElement
-     for (i = 0, il = sourceArray.length; i < il; i++) {
-       array[i] = [sourceArray[i][0]]
-       for(j = 1, jl = sourceArray[i].length; j < jl; j++) {
-         array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos
-       }
-       // For the two flags of the elliptical arc command, the SVG spec say:
-       // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true
-       // Elliptical arc command as an array followed by corresponding indexes:
-       // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y]
-       //   0    1   2        3                 4             5      6  7
-       if(array[i][0] === 'A') {
-         array[i][4] = +(array[i][4] != 0)
-         array[i][5] = +(array[i][5] != 0)
-       }
-     }
-     // Directly modify the value of a path array, this is done this way for performance
-     pathArray.value = array
-     return pathArray
-   }
-   // Absolutize and parse path to array
- , parse: function(array) {
-     // if it's already a patharray, no need to parse it
-     if (array instanceof SVG.PathArray) return array.valueOf()
-     // prepare for parsing
-     var i, x0, y0, s, seg, arr
-       , x = 0
-       , y = 0
-       , paramCnt = { 'M':2, 'L':2, 'H':1, 'V':1, 'C':6, 'S':4, 'Q':4, 'T':2, 'A':7 }
-     if(typeof array == 'string'){
-       array = array
-         .replace(SVG.regex.numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123
-         .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers
-         .replace(SVG.regex.hyphen, '$1 -')      // add space before hyphen
-         .trim()                                 // trim
-         .split(SVG.regex.delimiter)   // split into array
-     }else{
-       array = array.reduce(function(prev, curr){
-         return [].concat.apply(prev, curr)
-       }, [])
-     }
-     // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...]
-     var arr = []
-     do{
-       // Test if we have a path letter
-       if(SVG.regex.isPathLetter.test(array[0])){
-         s = array[0]
-         array.shift()
-       // If last letter was a move command and we got no new, it defaults to [L]ine
-       }else if(s == 'M'){
-         s = 'L'
-       }else if(s == 'm'){
-         s = 'l'
-       }
-       // add path letter as first element
-       seg = [s.toUpperCase()]
-       // push all necessary parameters to segment
-       for(i = 0; i < paramCnt[seg[0]]; ++i){
-         seg.push(parseFloat(array.shift()))
-       }
-       // upper case
-       if(s == seg[0]){
-         if(s == 'M' || s == 'L' || s == 'C' || s == 'Q' || s == 'S' || s == 'T'){
-           x = seg[paramCnt[seg[0]]-1]
-           y = seg[paramCnt[seg[0]]]
-         }else if(s == 'V'){
-           y = seg[1]
-         }else if(s == 'H'){
-           x = seg[1]
-         }else if(s == 'A'){
-           x = seg[6]
-           y = seg[7]
-         }
-       // lower case
-       }else{
-         // convert relative to absolute values
-         if(s == 'm' || s == 'l' || s == 'c' || s == 's' || s == 'q' || s == 't'){
-           seg[1] += x
-           seg[2] += y
-           if(seg[3] != null){
-             seg[3] += x
-             seg[4] += y
-           }
-           if(seg[5] != null){
-             seg[5] += x
-             seg[6] += y
-           }
-           // move pointer
-           x = seg[paramCnt[seg[0]]-1]
-           y = seg[paramCnt[seg[0]]]
-         }else if(s == 'v'){
-           seg[1] += y
-           y = seg[1]
-         }else if(s == 'h'){
-           seg[1] += x
-           x = seg[1]
-         }else if(s == 'a'){
-           seg[6] += x
-           seg[7] += y
-           x = seg[6]
-           y = seg[7]
-         }
-       }
-       if(seg[0] == 'M'){
-         x0 = x
-         y0 = y
-       }
-       if(seg[0] == 'Z'){
-         x = x0
-         y = y0
-       }
-       arr.push(seg)
-     }while(array.length)
-     return arr
-   }
-   // Get bounding box of path
- , bbox: function() {
-     SVG.parser.path.setAttribute('d', this.toString())
-     return SVG.parser.path.getBBox()
-   }
- })
- // Module for unit convertions
- SVG.Number = SVG.invent({
-   // Initialize
-   create: function(value, unit) {
-     // initialize defaults
-     this.value = 0
-     this.unit  = unit || ''
-     // parse value
-     if (typeof value === 'number') {
-       // ensure a valid numeric value
-       this.value = isNaN(value) ? 0 : !isFinite(value) ? (value < 0 ? -3.4e+38 : +3.4e+38) : value
-     } else if (typeof value === 'string') {
-       unit = value.match(SVG.regex.numberAndUnit)
-       if (unit) {
-         // make value numeric
-         this.value = parseFloat(unit[1])
-         // normalize
-         if (unit[5] == '%')
-           this.value /= 100
-         else if (unit[5] == 's')
-           this.value *= 1000
-         // store unit
-         this.unit = unit[5]
-       }
-     } else {
-       if (value instanceof SVG.Number) {
-         this.value = value.valueOf()
-         this.unit  = value.unit
-       }
-     }
-   }
-   // Add methods
- , extend: {
-     // Stringalize
-     toString: function() {
-       return (
-         this.unit == '%' ?
-           ~~(this.value * 1e8) / 1e6:
-         this.unit == 's' ?
-           this.value / 1e3 :
-           this.value
-       ) + this.unit
-     }
-   , toJSON: function() {
-       return this.toString()
-     }
-   , // Convert to primitive
-     valueOf: function() {
-       return this.value
-     }
-     // Add number
-   , plus: function(number) {
-       number = new SVG.Number(number)
-       return new SVG.Number(this + number, this.unit || number.unit)
-     }
-     // Subtract number
-   , minus: function(number) {
-       number = new SVG.Number(number)
-       return new SVG.Number(this - number, this.unit || number.unit)
-     }
-     // Multiply number
-   , times: function(number) {
-       number = new SVG.Number(number)
-       return new SVG.Number(this * number, this.unit || number.unit)
-     }
-     // Divide number
-   , divide: function(number) {
-       number = new SVG.Number(number)
-       return new SVG.Number(this / number, this.unit || number.unit)
-     }
-     // Convert to different unit
-   , to: function(unit) {
-       var number = new SVG.Number(this)
-       if (typeof unit === 'string')
-         number.unit = unit
-       return number
-     }
-     // Make number morphable
-   , morph: function(number) {
-       this.destination = new SVG.Number(number)
-       if(number.relative) {
-         this.destination.value += this.value
-       }
-       return this
-     }
-     // Get morphed number at given position
-   , at: function(pos) {
-       // Make sure a destination is defined
-       if (!this.destination) return this
-       // Generate new morphed number
-       return new SVG.Number(this.destination)
-           .minus(this)
-           .times(pos)
-           .plus(this)
-     }
-   }
- })
- SVG.Element = SVG.invent({
-   // Initialize node
-   create: function(node) {
-     // last fired event on node
-     this._event = null
-     // initialize data object
-     this.dom = {}
-     // create circular reference
-     if (this.node = node) {
-       this.type = node.nodeName
-       this.node.instance = this
-     }
-   }
-   // Add class methods
- , extend: {
-     // Move over x-axis
-     x: function(x) {
-       return this.attr('x', x)
-     }
-     // Move over y-axis
-   , y: function(y) {
-       return this.attr('y', y)
-     }
-     // Move by center over x-axis
-   , cx: function(x) {
-       return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2)
-     }
-     // Move by center over y-axis
-   , cy: function(y) {
-       return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2)
-     }
-     // Move element to given x and y values
-   , move: function(x, y) {
-       return this.x(x).y(y)
-     }
-     // Move element by its center
-   , center: function(x, y) {
-       return this.cx(x).cy(y)
-     }
-     // Set width of element
-   , width: function(width) {
-       return this.attr('width', width)
-     }
-     // Set height of element
-   , height: function(height) {
-       return this.attr('height', height)
-     }
-     // Set element size to given width and height
-   , size: function(width, height) {
-       var p = proportionalSize(this, width, height)
-       return this
-         .width(new SVG.Number(p.width))
-         .height(new SVG.Number(p.height))
-     }
-     // Clone element
-   , clone: function(parent, withData) {
-       // write dom data to the dom so the clone can pickup the data
-       this.writeDataToDom()
-       // clone element and assign new id
-       var clone = assignNewId(this.node.cloneNode(true))
-       // insert the clone in the given parent or after myself
-       if(parent) parent.add(clone)
-       else this.after(clone)
-       return clone
-     }
-     // Remove element
-   , remove: function() {
-       if (this.parent())
-         this.parent().removeElement(this)
-       return this
-     }
-     // Replace element
-   , replace: function(element) {
-       this.after(element).remove()
-       return element
-     }
-     // Add element to given container and return self
-   , addTo: function(parent) {
-       return parent.put(this)
-     }
-     // Add element to given container and return container
-   , putIn: function(parent) {
-       return parent.add(this)
-     }
-     // Get / set id
-   , id: function(id) {
-       return this.attr('id', id)
-     }
-     // Checks whether the given point inside the bounding box of the element
-   , inside: function(x, y) {
-       var box = this.bbox()
-       return x > box.x
-           && y > box.y
-           && x < box.x + box.width
-           && y < box.y + box.height
-     }
-     // Show element
-   , show: function() {
-       return this.style('display', '')
-     }
-     // Hide element
-   , hide: function() {
-       return this.style('display', 'none')
-     }
-     // Is element visible?
-   , visible: function() {
-       return this.style('display') != 'none'
-     }
-     // Return id on string conversion
-   , toString: function() {
-       return this.attr('id')
-     }
-     // Return array of classes on the node
-   , classes: function() {
-       var attr = this.attr('class')
-       return attr == null ? [] : attr.trim().split(SVG.regex.delimiter)
-     }
-     // Return true if class exists on the node, false otherwise
-   , hasClass: function(name) {
-       return this.classes().indexOf(name) != -1
-     }
-     // Add class to the node
-   , addClass: function(name) {
-       if (!this.hasClass(name)) {
-         var array = this.classes()
-         array.push(name)
-         this.attr('class', array.join(' '))
-       }
-       return this
-     }
-     // Remove class from the node
-   , removeClass: function(name) {
-       if (this.hasClass(name)) {
-         this.attr('class', this.classes().filter(function(c) {
-           return c != name
-         }).join(' '))
-       }
-       return this
-     }
-     // Toggle the presence of a class on the node
-   , toggleClass: function(name) {
-       return this.hasClass(name) ? this.removeClass(name) : this.addClass(name)
-     }
-     // Get referenced element form attribute value
-   , reference: function(attr) {
-       return SVG.get(this.attr(attr))
-     }
-     // Returns the parent element instance
-   , parent: function(type) {
-       var parent = this
-       // check for parent
-       if(!parent.node.parentNode) return null
-       // get parent element
-       parent = SVG.adopt(parent.node.parentNode)
-       if(!type) return parent
-       // loop trough ancestors if type is given
-       while(parent && parent.node instanceof window.SVGElement){
-         if(typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent
-         parent = SVG.adopt(parent.node.parentNode)
-       }
-     }
-     // Get parent document
-   , doc: function() {
-       return this instanceof SVG.Doc ? this : this.parent(SVG.Doc)
-     }
-     // return array of all ancestors of given type up to the root svg
-   , parents: function(type) {
-       var parents = [], parent = this
-       do{
-         parent = parent.parent(type)
-         if(!parent || !parent.node) break
-         parents.push(parent)
-       } while(parent.parent)
-       return parents
-     }
-     // matches the element vs a css selector
-   , matches: function(selector){
-       return matches(this.node, selector)
-     }
-     // Returns the svg node to call native svg methods on it
-   , native: function() {
-       return this.node
-     }
-     // Import raw svg
-   , svg: function(svg) {
-       var well, len
-       // act as a setter if svg is given
-       if (svg && this instanceof SVG.Parent) {
-         // create temporary holder
-         well = document.createElementNS(SVG.ns, 'svg')
-         // dump raw svg
-         well.innerHTML = svg
-         // transplant nodes
-         for (len = well.childNodes.length;len--;)
-           if(well.firstChild.nodeType != 1)
-             well.removeChild(well.firstChild)
-           else
-             this.node.appendChild(well.firstChild)
-       // otherwise act as a getter
-       } else {
-         return this.node.outerHTML
-       }
-       return this
-     }
-   // write svgjs data to the dom
-   , writeDataToDom: function() {
-       // dump variables recursively
-       if(this.is(SVG.Parent)){
-         this.each(function(){
-           this.writeDataToDom()
-         })
-       }
-       // remove previously set data
-       this.node.removeAttribute('svgjs:data')
-       if(Object.keys(this.dom).length)
-         this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)) // see #428
-       return this
-     }
-   // set given data to the elements data property
-   , setData: function(o){
-       this.dom = o
-       return this
-     }
-   , is: function(obj){
-       return is(this, obj)
-     }
-   }
- })
- SVG.easing = {
-   '-': function(pos){return pos}
- , '<>':function(pos){return -Math.cos(pos * Math.PI) / 2 + 0.5}
- , '>': function(pos){return  Math.sin(pos * Math.PI / 2)}
- , '<': function(pos){return -Math.cos(pos * Math.PI / 2) + 1}
- }
- SVG.morph = function(pos){
-   return function(from, to) {
-     return new SVG.MorphObj(from, to).at(pos)
-   }
- }
- SVG.Situation = SVG.invent({
-   create: function(o){
-     this.init = false
-     this.reversed = false
-     this.reversing = false
-     this.duration = new SVG.Number(o.duration).valueOf()
-     this.delay = new SVG.Number(o.delay).valueOf()
-     this.start = +new Date() + this.delay
-     this.finish = this.start + this.duration
-     this.ease = o.ease
-     // this.loop is incremented from 0 to this.loops
-     // it is also incremented when in an infinite loop (when this.loops is true)
-     this.loop = 0
-     this.loops = false
-     this.animations = {
-       // functionToCall: [list of morphable objects]
-       // e.g. move: [SVG.Number, SVG.Number]
-     }
-     this.attrs = {
-       // holds all attributes which are not represented from a function svg.js provides
-       // e.g. someAttr: SVG.Number
-     }
-     this.styles = {
-       // holds all styles which should be animated
-       // e.g. fill-color: SVG.Color
-     }
-     this.transforms = [
-       // holds all transformations as transformation objects
-       // e.g. [SVG.Rotate, SVG.Translate, SVG.Matrix]
-     ]
-     this.once = {
-       // functions to fire at a specific position
-       // e.g. "0.5": function foo(){}
-     }
-   }
- })
- SVG.FX = SVG.invent({
-   create: function(element) {
-     this._target = element
-     this.situations = []
-     this.active = false
-     this.situation = null
-     this.paused = false
-     this.lastPos = 0
-     this.pos = 0
-     // The absolute position of an animation is its position in the context of its complete duration (including delay and loops)
-     // When performing a delay, absPos is below 0 and when performing a loop, its value is above 1
-     this.absPos = 0
-     this._speed = 1
-   }
- , extend: {
-     /**
-      * sets or returns the target of this animation
-      * @param o object || number In case of Object it holds all parameters. In case of number its the duration of the animation
-      * @param ease function || string Function which should be used for easing or easing keyword
-      * @param delay Number indicating the delay before the animation starts
-      * @return target || this
-      */
-     animate: function(o, ease, delay){
-       if(typeof o == 'object'){
-         ease = o.ease
-         delay = o.delay
-         o = o.duration
-       }
-       var situation = new SVG.Situation({
-         duration: o || 1000,
-         delay: delay || 0,
-         ease: SVG.easing[ease || '-'] || ease
-       })
-       this.queue(situation)
-       return this
-     }
-     /**
-      * sets a delay before the next element of the queue is called
-      * @param delay Duration of delay in milliseconds
-      * @return this.target()
-      */
-   , delay: function(delay){
-       // The delay is performed by an empty situation with its duration
-       // attribute set to the duration of the delay
-       var situation = new SVG.Situation({
-         duration: delay,
-         delay: 0,
-         ease: SVG.easing['-']
-       })
-       return this.queue(situation)
-     }
-     /**
-      * sets or returns the target of this animation
-      * @param null || target SVG.Element which should be set as new target
-      * @return target || this
-      */
-   , target: function(target){
-       if(target && target instanceof SVG.Element){
-         this._target = target
-         return this
-       }
-       return this._target
-     }
-     // returns the absolute position at a given time
-   , timeToAbsPos: function(timestamp){
-       return (timestamp - this.situation.start) / (this.situation.duration/this._speed)
-     }
-     // returns the timestamp from a given absolute positon
-   , absPosToTime: function(absPos){
-       return this.situation.duration/this._speed * absPos + this.situation.start
-     }
-     // starts the animationloop
-   , startAnimFrame: function(){
-       this.stopAnimFrame()
-       this.animationFrame = requestAnimationFrame(function(){ this.step() }.bind(this))
-     }
-     // cancels the animationframe
-   , stopAnimFrame: function(){
-       cancelAnimationFrame(this.animationFrame)
-     }
-     // kicks off the animation - only does something when the queue is currently not active and at least one situation is set
-   , start: function(){
-       // dont start if already started
-       if(!this.active && this.situation){
-         this.active = true
-         this.startCurrent()
-       }
-       return this
-     }
-     // start the current situation
-   , startCurrent: function(){
-       this.situation.start = +new Date + this.situation.delay/this._speed
-       this.situation.finish = this.situation.start + this.situation.duration/this._speed
-       return this.initAnimations().step()
-     }
-     /**
-      * adds a function / Situation to the animation queue
-      * @param fn function / situation to add
-      * @return this
-      */
-   , queue: function(fn){
-       if(typeof fn == 'function' || fn instanceof SVG.Situation)
-         this.situations.push(fn)
-       if(!this.situation) this.situation = this.situations.shift()
-       return this
-     }
-     /**
-      * pulls next element from the queue and execute it
-      * @return this
-      */
-   , dequeue: function(){
-       // stop current animation
-       this.stop()
-       // get next animation from queue
-       this.situation = this.situations.shift()
-       if(this.situation){
-         if(this.situation instanceof SVG.Situation) {
-           this.start()
-         } else {
-           // If it is not a SVG.Situation, then it is a function, we execute it
-           this.situation.call(this)
-         }
-       }
-       return this
-     }
-     // updates all animations to the current state of the element
-     // this is important when one property could be changed from another property
-   , initAnimations: function() {
-       var i, source
-       var s = this.situation
-       if(s.init) return this
-       for(i in s.animations){
-         source = this.target()[i]()
-         // The condition is because some methods return a normal number instead
-         // of a SVG.Number
-         if(s.animations[i] instanceof SVG.Number)
-           source = new SVG.Number(source)
-         s.animations[i] = source.morph(s.animations[i])
-       }
-       for(i in s.attrs){
-         s.attrs[i] = new SVG.MorphObj(this.target().attr(i), s.attrs[i])
-       }
-       for(i in s.styles){
-         s.styles[i] = new SVG.MorphObj(this.target().style(i), s.styles[i])
-       }
-       s.initialTransformation = this.target().matrixify()
-       s.init = true
-       return this
-     }
-   , clearQueue: function(){
-       this.situations = []
-       return this
-     }
-   , clearCurrent: function(){
-       this.situation = null
-       return this
-     }
-     /** stops the animation immediately
-      * @param jumpToEnd A Boolean indicating whether to complete the current animation immediately.
-      * @param clearQueue A Boolean indicating whether to remove queued animation as well.
-      * @return this
-      */
-   , stop: function(jumpToEnd, clearQueue){
-       var active = this.active
-       this.active = false
-       if(clearQueue){
-         this.clearQueue()
-       }
-       if(jumpToEnd && this.situation){
-         // initialize the situation if it was not
-         !active && this.startCurrent()
-         this.atEnd()
-       }
-       this.stopAnimFrame()
-       return this.clearCurrent()
-     }
-     /** resets the element to the state where the current element has started
-      * @return this
-      */
-   , reset: function(){
-       if(this.situation){
-         var temp = this.situation
-         this.stop()
-         this.situation = temp
-         this.atStart()
-       }
-       return this
-     }
-     // Stop the currently-running animation, remove all queued animations, and complete all animations for the element.
-   , finish: function(){
-       this.stop(true, false)
-       while(this.dequeue().situation && this.stop(true, false));
-       this.clearQueue().clearCurrent()
-       return this
-     }
-     // set the internal animation pointer at the start position, before any loops, and updates the visualisation
-   , atStart: function() {
-       return this.at(0, true)
-     }
-     // set the internal animation pointer at the end position, after all the loops, and updates the visualisation
-   , atEnd: function() {
-       if (this.situation.loops === true) {
-         // If in a infinite loop, we end the current iteration
-         this.situation.loops = this.situation.loop + 1
-       }
-       if(typeof this.situation.loops == 'number') {
-         // If performing a finite number of loops, we go after all the loops
-         return this.at(this.situation.loops, true)
-       } else {
-         // If no loops, we just go at the end
-         return this.at(1, true)
-       }
-     }
-     // set the internal animation pointer to the specified position and updates the visualisation
-     // if isAbsPos is true, pos is treated as an absolute position
-   , at: function(pos, isAbsPos){
-       var durDivSpd = this.situation.duration/this._speed
-       this.absPos = pos
-       // If pos is not an absolute position, we convert it into one
-       if (!isAbsPos) {
-         if (this.situation.reversed) this.absPos = 1 - this.absPos
-         this.absPos += this.situation.loop
-       }
-       this.situation.start = +new Date - this.absPos * durDivSpd
-       this.situation.finish = this.situation.start + durDivSpd
-       return this.step(true)
-     }
-     /**
-      * sets or returns the speed of the animations
-      * @param speed null || Number The new speed of the animations
-      * @return Number || this
-      */
-   , speed: function(speed){
-       if (speed === 0) return this.pause()
-       if (speed) {
-         this._speed = speed
-         // We use an absolute position here so that speed can affect the delay before the animation
-         return this.at(this.absPos, true)
-       } else return this._speed
-     }
-     // Make loopable
-   , loop: function(times, reverse) {
-       var c = this.last()
-       // store total loops
-       c.loops = (times != null) ? times : true
-       c.loop = 0
-       if(reverse) c.reversing = true
-       return this
-     }
-     // pauses the animation
-   , pause: function(){
-       this.paused = true
-       this.stopAnimFrame()
-       return this
-     }
-     // unpause the animation
-   , play: function(){
-       if(!this.paused) return this
-       this.paused = false
-       // We use an absolute position here so that the delay before the animation can be paused
-       return this.at(this.absPos, true)
-     }
-     /**
-      * toggle or set the direction of the animation
-      * true sets direction to backwards while false sets it to forwards
-      * @param reversed Boolean indicating whether to reverse the animation or not (default: toggle the reverse status)
-      * @return this
-      */
-   , reverse: function(reversed){
-       var c = this.last()
-       if(typeof reversed == 'undefined') c.reversed = !c.reversed
-       else c.reversed = reversed
-       return this
-     }
-     /**
-      * returns a float from 0-1 indicating the progress of the current animation
-      * @param eased Boolean indicating whether the returned position should be eased or not
-      * @return number
-      */
-   , progress: function(easeIt){
-       return easeIt ? this.situation.ease(this.pos) : this.pos
-     }
-     /**
-      * adds a callback function which is called when the current animation is finished
-      * @param fn Function which should be executed as callback
-      * @return number
-      */
-   , after: function(fn){
-       var c = this.last()
-         , wrapper = function wrapper(e){
-             if(e.detail.situation == c){
-               fn.call(this, c)
-               this.off('finished.fx', wrapper) // prevent memory leak
-             }
-           }
-       this.target().on('finished.fx', wrapper)
-       return this._callStart()
-     }
-     // adds a callback which is called whenever one animation step is performed
-   , during: function(fn){
-       var c = this.last()
-         , wrapper = function(e){
-             if(e.detail.situation == c){
-               fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, c)
-             }
-           }
-       // see above
-       this.target().off('during.fx', wrapper).on('during.fx', wrapper)
-       this.after(function(){
-         this.off('during.fx', wrapper)
-       })
-       return this._callStart()
-     }
-     // calls after ALL animations in the queue are finished
-   , afterAll: function(fn){
-       var wrapper = function wrapper(e){
-             fn.call(this)
-             this.off('allfinished.fx', wrapper)
-           }
-       // see above
-       this.target().off('allfinished.fx', wrapper).on('allfinished.fx', wrapper)
-       return this._callStart()
-     }
-     // calls on every animation step for all animations
-   , duringAll: function(fn){
-       var wrapper = function(e){
-             fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, e.detail.situation)
-           }
-       this.target().off('during.fx', wrapper).on('during.fx', wrapper)
-       this.afterAll(function(){
-         this.off('during.fx', wrapper)
-       })
-       return this._callStart()
-     }
-   , last: function(){
-       return this.situations.length ? this.situations[this.situations.length-1] : this.situation
-     }
-     // adds one property to the animations
-   , add: function(method, args, type){
-       this.last()[type || 'animations'][method] = args
-       return this._callStart()
-     }
-     /** perform one step of the animation
-      *  @param ignoreTime Boolean indicating whether to ignore time and use position directly or recalculate position based on time
-      *  @return this
-      */
-   , step: function(ignoreTime){
-       // convert current time to an absolute position
-       if(!ignoreTime) this.absPos = this.timeToAbsPos(+new Date)
-       // This part convert an absolute position to a position
-       if(this.situation.loops !== false) {
-         var absPos, absPosInt, lastLoop
-         // If the absolute position is below 0, we just treat it as if it was 0
-         absPos = Math.max(this.absPos, 0)
-         absPosInt = Math.floor(absPos)
-         if(this.situation.loops === true || absPosInt < this.situation.loops) {
-           this.pos = absPos - absPosInt
-           lastLoop = this.situation.loop
-           this.situation.loop = absPosInt
-         } else {
-           this.absPos = this.situation.loops
-           this.pos = 1
-           // The -1 here is because we don't want to toggle reversed when all the loops have been completed
-           lastLoop = this.situation.loop - 1
-           this.situation.loop = this.situation.loops
-         }
-         if(this.situation.reversing) {
-           // Toggle reversed if an odd number of loops as occured since the last call of step
-           this.situation.reversed = this.situation.reversed != Boolean((this.situation.loop - lastLoop) % 2)
-         }
-       } else {
-         // If there are no loop, the absolute position must not be above 1
-         this.absPos = Math.min(this.absPos, 1)
-         this.pos = this.absPos
-       }
-       // while the absolute position can be below 0, the position must not be below 0
-       if(this.pos < 0) this.pos = 0
-       if(this.situation.reversed) this.pos = 1 - this.pos
-       // apply easing
-       var eased = this.situation.ease(this.pos)
-       // call once-callbacks
-       for(var i in this.situation.once){
-         if(i > this.lastPos && i <= eased){
-           this.situation.once[i].call(this.target(), this.pos, eased)
-           delete this.situation.once[i]
-         }
-       }
-       // fire during callback with position, eased position and current situation as parameter
-       if(this.active) this.target().fire('during', {pos: this.pos, eased: eased, fx: this, situation: this.situation})
-       // the user may call stop or finish in the during callback
-       // so make sure that we still have a valid situation
-       if(!this.situation){
-         return this
-       }
-       // apply the actual animation to every property
-       this.eachAt()
-       // do final code when situation is finished
-       if((this.pos == 1 && !this.situation.reversed) || (this.situation.reversed && this.pos == 0)){
-         // stop animation callback
-         this.stopAnimFrame()
-         // fire finished callback with current situation as parameter
-         this.target().fire('finished', {fx:this, situation: this.situation})
-         if(!this.situations.length){
-           this.target().fire('allfinished')
-           this.target().off('.fx') // there shouldnt be any binding left, but to make sure...
-           this.active = false
-         }
-         // start next animation
-         if(this.active) this.dequeue()
-         else this.clearCurrent()
-       }else if(!this.paused && this.active){
-         // we continue animating when we are not at the end
-         this.startAnimFrame()
-       }
-       // save last eased position for once callback triggering
-       this.lastPos = eased
-       return this
-     }
-     // calculates the step for every property and calls block with it
-   , eachAt: function(){
-       var i, at, self = this, target = this.target(), s = this.situation
-       // apply animations which can be called trough a method
-       for(i in s.animations){
-         at = [].concat(s.animations[i]).map(function(el){
-           return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
-         })
-         target[i].apply(target, at)
-       }
-       // apply animation which has to be applied with attr()
-       for(i in s.attrs){
-         at = [i].concat(s.attrs[i]).map(function(el){
-           return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
-         })
-         target.attr.apply(target, at)
-       }
-       // apply animation which has to be applied with style()
-       for(i in s.styles){
-         at = [i].concat(s.styles[i]).map(function(el){
-           return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
-         })
-         target.style.apply(target, at)
-       }
-       // animate initialTransformation which has to be chained
-       if(s.transforms.length){
-         // get initial initialTransformation
-         at = s.initialTransformation
-         for(i = 0, len = s.transforms.length; i < len; i++){
-           // get next transformation in chain
-           var a = s.transforms[i]
-           // multiply matrix directly
-           if(a instanceof SVG.Matrix){
-             if(a.relative){
-               at = at.multiply(new SVG.Matrix().morph(a).at(s.ease(this.pos)))
-             }else{
-               at = at.morph(a).at(s.ease(this.pos))
-             }
-             continue
-           }
-           // when transformation is absolute we have to reset the needed transformation first
-           if(!a.relative)
-             a.undo(at.extract())
-           // and reapply it after
-           at = at.multiply(a.at(s.ease(this.pos)))
-         }
-         // set new matrix on element
-         target.matrix(at)
-       }
-       return this
-     }
-     // adds an once-callback which is called at a specific position and never again
-   , once: function(pos, fn, isEased){
-       if(!isEased)pos = this.situation.ease(pos)
-       this.situation.once[pos] = fn
-       return this
-     }
-   , _callStart: function() {
-       setTimeout(function(){this.start()}.bind(this), 0)
-       return this
-     }
-   }
- , parent: SVG.Element
-   // Add method to parent elements
- , construct: {
-     // Get fx module or create a new one, then animate with given duration and ease
-     animate: function(o, ease, delay) {
-       return (this.fx || (this.fx = new SVG.FX(this))).animate(o, ease, delay)
-     }
-   , delay: function(delay){
-       return (this.fx || (this.fx = new SVG.FX(this))).delay(delay)
-     }
-   , stop: function(jumpToEnd, clearQueue) {
-       if (this.fx)
-         this.fx.stop(jumpToEnd, clearQueue)
-       return this
-     }
-   , finish: function() {
-       if (this.fx)
-         this.fx.finish()
-       return this
-     }
-     // Pause current animation
-   , pause: function() {
-       if (this.fx)
-         this.fx.pause()
-       return this
-     }
-     // Play paused current animation
-   , play: function() {
-       if (this.fx)
-         this.fx.play()
-       return this
-     }
-     // Set/Get the speed of the animations
-   , speed: function(speed) {
-       if (this.fx)
-         if (speed == null)
-           return this.fx.speed()
-         else
-           this.fx.speed(speed)
-       return this
-     }
-   }
- })
- // MorphObj is used whenever no morphable object is given
- SVG.MorphObj = SVG.invent({
-   create: function(from, to){
-     // prepare color for morphing
-     if(SVG.Color.isColor(to)) return new SVG.Color(from).morph(to)
-     // prepare number for morphing
-     if(SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to)
-     // prepare for plain morphing
-     this.value = from
-     this.destination = to
-   }
- , extend: {
-     at: function(pos, real){
-       return real < 1 ? this.value : this.destination
-     },
-     valueOf: function(){
-       return this.value
-     }
-   }
- })
- SVG.extend(SVG.FX, {
-   // Add animatable attributes
-   attr: function(a, v, relative) {
-     // apply attributes individually
-     if (typeof a == 'object') {
-       for (var key in a)
-         this.attr(key, a[key])
-     } else {
-       this.add(a, v, 'attrs')
-     }
-     return this
-   }
-   // Add animatable styles
- , style: function(s, v) {
-     if (typeof s == 'object')
-       for (var key in s)
-         this.style(key, s[key])
-     else
-       this.add(s, v, 'styles')
-     return this
-   }
-   // Animatable x-axis
- , x: function(x, relative) {
-     if(this.target() instanceof SVG.G){
-       this.transform({x:x}, relative)
-       return this
-     }
-     var num = new SVG.Number(x)
-     num.relative = relative
-     return this.add('x', num)
-   }
-   // Animatable y-axis
- , y: function(y, relative) {
-     if(this.target() instanceof SVG.G){
-       this.transform({y:y}, relative)
-       return this
-     }
-     var num = new SVG.Number(y)
-     num.relative = relative
-     return this.add('y', num)
-   }
-   // Animatable center x-axis
- , cx: function(x) {
-     return this.add('cx', new SVG.Number(x))
-   }
-   // Animatable center y-axis
- , cy: function(y) {
-     return this.add('cy', new SVG.Number(y))
-   }
-   // Add animatable move
- , move: function(x, y) {
-     return this.x(x).y(y)
-   }
-   // Add animatable center
- , center: function(x, y) {
-     return this.cx(x).cy(y)
-   }
-   // Add animatable size
- , size: function(width, height) {
-     if (this.target() instanceof SVG.Text) {
-       // animate font size for Text elements
-       this.attr('font-size', width)
-     } else {
-       // animate bbox based size for all other elements
-       var box
-       if(!width || !height){
-         box = this.target().bbox()
-       }
-       if(!width){
-         width = box.width / box.height  * height
-       }
-       if(!height){
-         height = box.height / box.width  * width
-       }
-       this.add('width' , new SVG.Number(width))
-           .add('height', new SVG.Number(height))
-     }
-     return this
-   }
-   // Add animatable plot
- , plot: function() {
-     // We use arguments here since SVG.Line's plot method can be passed 4 parameters
-     return this.add('plot', arguments.length > 1 ? [].slice.call(arguments) : arguments[0])
-   }
-   // Add leading method
- , leading: function(value) {
-     return this.target().leading ?
-       this.add('leading', new SVG.Number(value)) :
-       this
-   }
-   // Add animatable viewbox
- , viewbox: function(x, y, width, height) {
-     if (this.target() instanceof SVG.Container) {
-       this.add('viewbox', new SVG.Box(x, y, width, height))
-     }
-     return this
-   }
- , update: function(o) {
-     if (this.target() instanceof SVG.Stop) {
-       if (typeof o == 'number' || o instanceof SVG.Number) {
-         return this.update({
-           offset:  arguments[0]
-         , color:   arguments[1]
-         , opacity: arguments[2]
-         })
-       }
-       if (o.opacity != null) this.attr('stop-opacity', o.opacity)
-       if (o.color   != null) this.attr('stop-color', o.color)
-       if (o.offset  != null) this.attr('offset', o.offset)
-     }
-     return this
-   }
- })
- SVG.Matrix = SVG.invent({
-   // Initialize
-   create: function(source) {
-     var i, base = arrayToMatrix([1, 0, 0, 1, 0, 0])
-     // ensure source as object
-     source = source instanceof SVG.Element ?
-       source.matrixify() :
-     typeof source === 'string' ?
-       arrayToMatrix(source.split(SVG.regex.delimiter).map(parseFloat)) :
-     arguments.length == 6 ?
-       arrayToMatrix([].slice.call(arguments)) :
-     Array.isArray(source) ?
-       arrayToMatrix(source) :
-     typeof source === 'object' ?
-       source : base
-     // merge source
-     for (i = abcdef.length - 1; i >= 0; --i)
-       this[abcdef[i]] = source && typeof source[abcdef[i]] === 'number' ?
-         source[abcdef[i]] : base[abcdef[i]]
-   }
-   // Add methods
- , extend: {
-     // Extract individual transformations
-     extract: function() {
-       // find delta transform points
-       var px    = deltaTransformPoint(this, 0, 1)
-         , py    = deltaTransformPoint(this, 1, 0)
-         , skewX = 180 / Math.PI * Math.atan2(px.y, px.x) - 90
-       return {
-         // translation
-         x:        this.e
-       , y:        this.f
-       , transformedX:(this.e * Math.cos(skewX * Math.PI / 180) + this.f * Math.sin(skewX * Math.PI / 180)) / Math.sqrt(this.a * this.a + this.b * this.b)
-       , transformedY:(this.f * Math.cos(skewX * Math.PI / 180) + this.e * Math.sin(-skewX * Math.PI / 180)) / Math.sqrt(this.c * this.c + this.d * this.d)
-         // skew
-       , skewX:    -skewX
-       , skewY:    180 / Math.PI * Math.atan2(py.y, py.x)
-         // scale
-       , scaleX:   Math.sqrt(this.a * this.a + this.b * this.b)
-       , scaleY:   Math.sqrt(this.c * this.c + this.d * this.d)
-         // rotation
-       , rotation: skewX
-       , a: this.a
-       , b: this.b
-       , c: this.c
-       , d: this.d
-       , e: this.e
-       , f: this.f
-       , matrix: new SVG.Matrix(this)
-       }
-     }
-     // Clone matrix
-   , clone: function() {
-       return new SVG.Matrix(this)
-     }
-     // Morph one matrix into another
-   , morph: function(matrix) {
-       // store new destination
-       this.destination = new SVG.Matrix(matrix)
-       return this
-     }
-     // Get morphed matrix at a given position
-   , at: function(pos) {
-       // make sure a destination is defined
-       if (!this.destination) return this
-       // calculate morphed matrix at a given position
-       var matrix = new SVG.Matrix({
-         a: this.a + (this.destination.a - this.a) * pos
-       , b: this.b + (this.destination.b - this.b) * pos
-       , c: this.c + (this.destination.c - this.c) * pos
-       , d: this.d + (this.destination.d - this.d) * pos
-       , e: this.e + (this.destination.e - this.e) * pos
-       , f: this.f + (this.destination.f - this.f) * pos
-       })
-       return matrix
-     }
-     // Multiplies by given matrix
-   , multiply: function(matrix) {
-       return new SVG.Matrix(this.native().multiply(parseMatrix(matrix).native()))
-     }
-     // Inverses matrix
-   , inverse: function() {
-       return new SVG.Matrix(this.native().inverse())
-     }
-     // Translate matrix
-   , translate: function(x, y) {
-       return new SVG.Matrix(this.native().translate(x || 0, y || 0))
-     }
-     // Scale matrix
-   , scale: function(x, y, cx, cy) {
-       // support uniformal scale
-       if (arguments.length == 1) {
-         y = x
-       } else if (arguments.length == 3) {
-         cy = cx
-         cx = y
-         y = x
-       }
-       return this.around(cx, cy, new SVG.Matrix(x, 0, 0, y, 0, 0))
-     }
-     // Rotate matrix
-   , rotate: function(r, cx, cy) {
-       // convert degrees to radians
-       r = SVG.utils.radians(r)
-       return this.around(cx, cy, new SVG.Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0))
-     }
-     // Flip matrix on x or y, at a given offset
-   , flip: function(a, o) {
-       o = typeof a == 'number' ? a : o
-       return a == 'x' ?
-           this.scale(-1, 1, o, 0) :
-         a == 'y' ?
-           this.scale(1, -1, 0, o) :
-           this.scale(-1, -1, o, o)
-     }
-     // Skew
-   , skew: function(x, y, cx, cy) {
-       // support uniformal skew
-       if (arguments.length == 1) {
-         y = x
-       } else if (arguments.length == 3) {
-         cy = cx
-         cx = y
-         y = x
-       }
-       // convert degrees to radians
-       x = SVG.utils.radians(x)
-       y = SVG.utils.radians(y)
-       return this.around(cx, cy, new SVG.Matrix(1, Math.tan(y), Math.tan(x), 1, 0, 0))
-     }
-     // SkewX
-   , skewX: function(x, cx, cy) {
-       return this.skew(x, 0, cx, cy)
-     }
-     // SkewY
-   , skewY: function(y, cx, cy) {
-       return this.skew(0, y, cx, cy)
-     }
-     // Transform around a center point
-   , around: function(cx, cy, matrix) {
-       return this
-         .multiply(new SVG.Matrix(1, 0, 0, 1, cx || 0, cy || 0))
-         .multiply(matrix)
-         .multiply(new SVG.Matrix(1, 0, 0, 1, -cx || 0, -cy || 0))
-     }
-     // Convert to native SVGMatrix
-   , native: function() {
-       // create new matrix
-       var matrix = SVG.parser.native.createSVGMatrix()
-       // update with current values
-       for (var i = abcdef.length - 1; i >= 0; i--)
-         matrix[abcdef[i]] = this[abcdef[i]]
-       return matrix
-     }
-     // Convert matrix to string
-   , toString: function() {
-       return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'
-     }
-   }
-   // Define parent
- , parent: SVG.Element
-   // Add parent method
- , construct: {
-     // Get current matrix
-     ctm: function() {
-       return new SVG.Matrix(this.node.getCTM())
-     },
-     // Get current screen matrix
-     screenCTM: function() {
-       /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537
-          This is needed because FF does not return the transformation matrix
-          for the inner coordinate system when getScreenCTM() is called on nested svgs.
-          However all other Browsers do that */
-       if(this instanceof SVG.Nested) {
-         var rect = this.rect(1,1)
-         var m = rect.node.getScreenCTM()
-         rect.remove()
-         return new SVG.Matrix(m)
-       }
-       return new SVG.Matrix(this.node.getScreenCTM())
-     }
-   }
- })
- SVG.Point = SVG.invent({
-   // Initialize
-   create: function(x,y) {
-     var i, source, base = {x:0, y:0}
-     // ensure source as object
-     source = Array.isArray(x) ?
-       {x:x[0], y:x[1]} :
-     typeof x === 'object' ?
-       {x:x.x, y:x.y} :
-     x != null ?
-       {x:x, y:(y != null ? y : x)} : base // If y has no value, then x is used has its value
-     // merge source
-     this.x = source.x
-     this.y = source.y
-   }
-   // Add methods
- , extend: {
-     // Clone point
-     clone: function() {
-       return new SVG.Point(this)
-     }
-     // Morph one point into another
-   , morph: function(x, y) {
-       // store new destination
-       this.destination = new SVG.Point(x, y)
-       return this
-     }
-     // Get morphed point at a given position
-   , at: function(pos) {
-       // make sure a destination is defined
-       if (!this.destination) return this
-       // calculate morphed matrix at a given position
-       var point = new SVG.Point({
-         x: this.x + (this.destination.x - this.x) * pos
-       , y: this.y + (this.destination.y - this.y) * pos
-       })
-       return point
-     }
-     // Convert to native SVGPoint
-   , native: function() {
-       // create new point
-       var point = SVG.parser.native.createSVGPoint()
-       // update with current values
-       point.x = this.x
-       point.y = this.y
-       return point
-     }
-     // transform point with matrix
-   , transform: function(matrix) {
-       return new SVG.Point(this.native().matrixTransform(matrix.native()))
-     }
-   }
- })
- SVG.extend(SVG.Element, {
-   // Get point
-   point: function(x, y) {
-     return new SVG.Point(x,y).transform(this.screenCTM().inverse());
-   }
- })
- SVG.extend(SVG.Element, {
-   // Set svg element attribute
-   attr: function(a, v, n) {
-     // act as full getter
-     if (a == null) {
-       // get an object of attributes
-       a = {}
-       v = this.node.attributes
-       for (n = v.length - 1; n >= 0; n--)
-         a[v[n].nodeName] = SVG.regex.isNumber.test(v[n].nodeValue) ? parseFloat(v[n].nodeValue) : v[n].nodeValue
-       return a
-     } else if (typeof a == 'object') {
-       // apply every attribute individually if an object is passed
-       for (v in a) this.attr(v, a[v])
-     } else if (v === null) {
-         // remove value
-         this.node.removeAttribute(a)
-     } else if (v == null) {
-       // act as a getter if the first and only argument is not an object
-       v = this.node.getAttribute(a)
-       return v == null ?
-         SVG.defaults.attrs[a] :
-       SVG.regex.isNumber.test(v) ?
-         parseFloat(v) : v
-     } else {
-       // convert image fill and stroke to patterns
-       if (a == 'fill' || a == 'stroke') {
-         if (SVG.regex.isImage.test(v))
-           v = this.doc().defs().image(v)
-         if (v instanceof SVG.Image)
-           v = this.doc().defs().pattern(0, 0, function() {
-             this.add(v)
-           })
-       }
-       // ensure correct numeric values (also accepts NaN and Infinity)
-       if (typeof v === 'number')
-         v = new SVG.Number(v)
-       // ensure full hex color
-       else if (SVG.Color.isColor(v))
-         v = new SVG.Color(v)
-       // parse array values
-       else if (Array.isArray(v))
-         v = new SVG.Array(v)
-       // if the passed attribute is leading...
-       if (a == 'leading') {
-         // ... call the leading method instead
-         if (this.leading)
-           this.leading(v)
-       } else {
-         // set given attribute on node
-         typeof n === 'string' ?
-           this.node.setAttributeNS(n, a, v.toString()) :
-           this.node.setAttribute(a, v.toString())
-       }
-       // rebuild if required
-       if (this.rebuild && (a == 'font-size' || a == 'x'))
-         this.rebuild(a, v)
-     }
-     return this
-   }
- })
- SVG.extend(SVG.Element, {
-   // Add transformations
-   transform: function(o, relative) {
-     // get target in case of the fx module, otherwise reference this
-     var target = this
-       , matrix
-     // act as a getter
-     if (typeof o !== 'object') {
-       // get current matrix
-       matrix = new SVG.Matrix(target).extract()
-       return typeof o === 'string' ? matrix[o] : matrix
-     }
-     // get current matrix
-     matrix = new SVG.Matrix(target)
-     // ensure relative flag
-     relative = !!relative || !!o.relative
-     // act on matrix
-     if (o.a != null) {
-       matrix = relative ?
-         // relative
-         matrix.multiply(new SVG.Matrix(o)) :
-         // absolute
-         new SVG.Matrix(o)
-     // act on rotation
-     } else if (o.rotation != null) {
-       // ensure centre point
-       ensureCentre(o, target)
-       // apply transformation
-       matrix = relative ?
-         // relative
-         matrix.rotate(o.rotation, o.cx, o.cy) :
-         // absolute
-         matrix.rotate(o.rotation - matrix.extract().rotation, o.cx, o.cy)
-     // act on scale
-     } else if (o.scale != null || o.scaleX != null || o.scaleY != null) {
-       // ensure centre point
-       ensureCentre(o, target)
-       // ensure scale values on both axes
-       o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1
-       o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1
-       if (!relative) {
-         // absolute; multiply inversed values
-         var e = matrix.extract()
-         o.scaleX = o.scaleX * 1 / e.scaleX
-         o.scaleY = o.scaleY * 1 / e.scaleY
-       }
-       matrix = matrix.scale(o.scaleX, o.scaleY, o.cx, o.cy)
-     // act on skew
-     } else if (o.skew != null || o.skewX != null || o.skewY != null) {
-       // ensure centre point
-       ensureCentre(o, target)
-       // ensure skew values on both axes
-       o.skewX = o.skew != null ? o.skew : o.skewX != null ? o.skewX : 0
-       o.skewY = o.skew != null ? o.skew : o.skewY != null ? o.skewY : 0
-       if (!relative) {
-         // absolute; reset skew values
-         var e = matrix.extract()
-         matrix = matrix.multiply(new SVG.Matrix().skew(e.skewX, e.skewY, o.cx, o.cy).inverse())
-       }
-       matrix = matrix.skew(o.skewX, o.skewY, o.cx, o.cy)
-     // act on flip
-     } else if (o.flip) {
-       matrix = matrix.flip(
-         o.flip
-       , o.offset == null ? target.bbox()['c' + o.flip] : o.offset
-       )
-     // act on translate
-     } else if (o.x != null || o.y != null) {
-       if (relative) {
-         // relative
-         matrix = matrix.translate(o.x, o.y)
-       } else {
-         // absolute
-         if (o.x != null) matrix.e = o.x
-         if (o.y != null) matrix.f = o.y
-       }
-     }
-     return this.attr('transform', matrix)
-   }
- })
- SVG.extend(SVG.FX, {
-   transform: function(o, relative) {
-     // get target in case of the fx module, otherwise reference this
-     var target = this.target()
-       , matrix
-     // act as a getter
-     if (typeof o !== 'object') {
-       // get current matrix
-       matrix = new SVG.Matrix(target).extract()
-       return typeof o === 'string' ? matrix[o] : matrix
-     }
-     // ensure relative flag
-     relative = !!relative || !!o.relative
-     // act on matrix
-     if (o.a != null) {
-       matrix = new SVG.Matrix(o)
-     // act on rotation
-     } else if (o.rotation != null) {
-       // ensure centre point
-       ensureCentre(o, target)
-       // apply transformation
-       matrix = new SVG.Rotate(o.rotation, o.cx, o.cy)
-     // act on scale
-     } else if (o.scale != null || o.scaleX != null || o.scaleY != null) {
-       // ensure centre point
-       ensureCentre(o, target)
-       // ensure scale values on both axes
-       o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1
-       o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1
-       matrix = new SVG.Scale(o.scaleX, o.scaleY, o.cx, o.cy)
-     // act on skew
-     } else if (o.skewX != null || o.skewY != null) {
-       // ensure centre point
-       ensureCentre(o, target)
-       // ensure skew values on both axes
-       o.skewX = o.skewX != null ? o.skewX : 0
-       o.skewY = o.skewY != null ? o.skewY : 0
-       matrix = new SVG.Skew(o.skewX, o.skewY, o.cx, o.cy)
-     // act on flip
-     } else if (o.flip) {
-       matrix = new SVG.Matrix().flip(
-         o.flip
-       , o.offset == null ? target.bbox()['c' + o.flip] : o.offset
-       )
-     // act on translate
-     } else if (o.x != null || o.y != null) {
-       matrix = new SVG.Translate(o.x, o.y)
-     }
-     if(!matrix) return this
-     matrix.relative = relative
-     this.last().transforms.push(matrix)
-     return this._callStart()
-   }
- })
- SVG.extend(SVG.Element, {
-   // Reset all transformations
-   untransform: function() {
-     return this.attr('transform', null)
-   },
-   // merge the whole transformation chain into one matrix and returns it
-   matrixify: function() {
-     var matrix = (this.attr('transform') || '')
-       // split transformations
-       .split(SVG.regex.transforms).slice(0,-1).map(function(str){
-         // generate key => value pairs
-         var kv = str.trim().split('(')
-         return [kv[0], kv[1].split(SVG.regex.delimiter).map(function(str){ return parseFloat(str) })]
-       })
-       // merge every transformation into one matrix
-       .reduce(function(matrix, transform){
-         if(transform[0] == 'matrix') return matrix.multiply(arrayToMatrix(transform[1]))
-         return matrix[transform[0]].apply(matrix, transform[1])
-       }, new SVG.Matrix())
-     return matrix
-   },
-   // add an element to another parent without changing the visual representation on the screen
-   toParent: function(parent) {
-     if(this == parent) return this
-     var ctm = this.screenCTM()
-     var pCtm = parent.screenCTM().inverse()
-     this.addTo(parent).untransform().transform(pCtm.multiply(ctm))
-     return this
-   },
-   // same as above with parent equals root-svg
-   toDoc: function() {
-     return this.toParent(this.doc())
-   }
- })
- SVG.Transformation = SVG.invent({
-   create: function(source, inversed){
-     if(arguments.length > 1 && typeof inversed != 'boolean'){
-       return this.constructor.call(this, [].slice.call(arguments))
-     }
-     if(Array.isArray(source)){
-       for(var i = 0, len = this.arguments.length; i < len; ++i){
-         this[this.arguments[i]] = source[i]
-       }
-     } else if(typeof source == 'object'){
-       for(var i = 0, len = this.arguments.length; i < len; ++i){
-         this[this.arguments[i]] = source[this.arguments[i]]
-       }
-     }
-     this.inversed = false
-     if(inversed === true){
-       this.inversed = true
-     }
-   }
- , extend: {
-     arguments: []
-   , method: ''
-   , at: function(pos){
-       var params = []
-       for(var i = 0, len = this.arguments.length; i < len; ++i){
-         params.push(this[this.arguments[i]])
-       }
-       var m = this._undo || new SVG.Matrix()
-       m = new SVG.Matrix().morph(SVG.Matrix.prototype[this.method].apply(m, params)).at(pos)
-       return this.inversed ? m.inverse() : m
-     }
-   , undo: function(o){
-       for(var i = 0, len = this.arguments.length; i < len; ++i){
-         o[this.arguments[i]] = typeof this[this.arguments[i]] == 'undefined' ? 0 : o[this.arguments[i]]
-       }
-       // The method SVG.Matrix.extract which was used before calling this
-       // method to obtain a value for the parameter o doesn't return a cx and
-       // a cy so we use the ones that were provided to this object at its creation
-       o.cx = this.cx
-       o.cy = this.cy
-       this._undo = new SVG[capitalize(this.method)](o, true).at(1)
-       return this
-     }
-   }
- })
- SVG.Translate = SVG.invent({
-   parent: SVG.Matrix
- , inherit: SVG.Transformation
- , create: function(source, inversed){
-     this.constructor.apply(this, [].slice.call(arguments))
-   }
- , extend: {
-     arguments: ['transformedX', 'transformedY']
-   , method: 'translate'
-   }
- })
- SVG.Rotate = SVG.invent({
-   parent: SVG.Matrix
- , inherit: SVG.Transformation
- , create: function(source, inversed){
-     this.constructor.apply(this, [].slice.call(arguments))
-   }
- , extend: {
-     arguments: ['rotation', 'cx', 'cy']
-   , method: 'rotate'
-   , at: function(pos){
-       var m = new SVG.Matrix().rotate(new SVG.Number().morph(this.rotation - (this._undo ? this._undo.rotation : 0)).at(pos), this.cx, this.cy)
-       return this.inversed ? m.inverse() : m
-     }
-   , undo: function(o){
-       this._undo = o
-     }
-   }
- })
- SVG.Scale = SVG.invent({
-   parent: SVG.Matrix
- , inherit: SVG.Transformation
- , create: function(source, inversed){
-     this.constructor.apply(this, [].slice.call(arguments))
-   }
- , extend: {
-     arguments: ['scaleX', 'scaleY', 'cx', 'cy']
-   , method: 'scale'
-   }
- })
- SVG.Skew = SVG.invent({
-   parent: SVG.Matrix
- , inherit: SVG.Transformation
- , create: function(source, inversed){
-     this.constructor.apply(this, [].slice.call(arguments))
-   }
- , extend: {
-     arguments: ['skewX', 'skewY', 'cx', 'cy']
-   , method: 'skew'
-   }
- })
- SVG.extend(SVG.Element, {
-   // Dynamic style generator
-   style: function(s, v) {
-     if (arguments.length == 0) {
-       // get full style
-       return this.node.style.cssText || ''
-     } else if (arguments.length < 2) {
-       // apply every style individually if an object is passed
-       if (typeof s == 'object') {
-         for (v in s) this.style(v, s[v])
-       } else {
-         // act as a getter if the first and only argument is not an object
-         return this.node.style[camelCase(s)]
-       }
-     } else {
-       this.node.style[camelCase(s)] = v === null || SVG.regex.isBlank.test(v) ? '' : v
-     }
-     return this
-   }
- })
- SVG.Parent = SVG.invent({
-   // Initialize node
-   create: function(element) {
-     this.constructor.call(this, element)
-   }
-   // Inherit from
- , inherit: SVG.Element
-   // Add class methods
- , extend: {
-     // Returns all child elements
-     children: function() {
-       return SVG.utils.map(SVG.utils.filterSVGElements(this.node.childNodes), function(node) {
-         return SVG.adopt(node)
-       })
-     }
-     // Add given element at a position
-   , add: function(element, i) {
-       if (i == null)
-         this.node.appendChild(element.node)
-       else if (element.node != this.node.childNodes[i])
-         this.node.insertBefore(element.node, this.node.childNodes[i])
-       return this
-     }
-     // Basically does the same as `add()` but returns the added element instead
-   , put: function(element, i) {
-       this.add(element, i)
-       return element
-     }
-     // Checks if the given element is a child
-   , has: function(element) {
-       return this.index(element) >= 0
-     }
-     // Gets index of given element
-   , index: function(element) {
-       return [].slice.call(this.node.childNodes).indexOf(element.node)
-     }
-     // Get a element at the given index
-   , get: function(i) {
-       return SVG.adopt(this.node.childNodes[i])
-     }
-     // Get first child
-   , first: function() {
-       return this.get(0)
-     }
-     // Get the last child
-   , last: function() {
-       return this.get(this.node.childNodes.length - 1)
-     }
-     // Iterates over all children and invokes a given block
-   , each: function(block, deep) {
-       var i, il
-         , children = this.children()
-       for (i = 0, il = children.length; i < il; i++) {
-         if (children[i] instanceof SVG.Element)
-           block.apply(children[i], [i, children])
-         if (deep && (children[i] instanceof SVG.Container))
-           children[i].each(block, deep)
-       }
-       return this
-     }
-     // Remove a given child
-   , removeElement: function(element) {
-       this.node.removeChild(element.node)
-       return this
-     }
-     // Remove all elements in this container
-   , clear: function() {
-       // remove children
-       while(this.node.hasChildNodes())
-         this.node.removeChild(this.node.lastChild)
-       // remove defs reference
-       delete this._defs
-       return this
-     }
-   , // Get defs
-     defs: function() {
-       return this.doc().defs()
-     }
-   }
- })
- SVG.extend(SVG.Parent, {
-   flatten: function(parent) {
-     if(this instanceof SVG.Defs) return this
-     parent = parent || (this instanceof SVG.Doc ? this : this.parent(SVG.Parent))
-     this.each(function(){
-       if(this instanceof SVG.Defs) return this
-       if(this instanceof SVG.Parent) return this.flatten(parent)
-       return this.toParent(parent)
-     })
-     // we need this so that SVG.Doc does not get removed
-     this.node.firstChild || this.remove()
-     return this
-   }
- })
- SVG.Container = SVG.invent({
-   // Initialize node
-   create: function(element) {
-     this.constructor.call(this, element)
-   }
-   // Inherit from
- , inherit: SVG.Parent
- })
- // Add events to elements
- ;[  'click'
-   , 'dblclick'
-   , 'mousedown'
-   , 'mouseup'
-   , 'mouseover'
-   , 'mouseout'
-   , 'mousemove'
-   // , 'mouseenter' -> not supported by IE
-   // , 'mouseleave' -> not supported by IE
-   , 'touchstart'
-   , 'touchmove'
-   , 'touchleave'
-   , 'touchend'
-   , 'touchcancel' ].forEach(function(event) {
-   // add event to SVG.Element
-   SVG.Element.prototype[event] = function(f) {
-     var self = this
-     // bind event to element rather than element node
-     this.node['on' + event] = typeof f == 'function' ?
-       function() { return f.apply(self, arguments) } : null
-     return this
-   }
- })
- // Initialize listeners stack
- SVG.listeners = []
- SVG.handlerMap = []
- SVG.listenerId = 0
- // Add event binder in the SVG namespace
- SVG.on = function(node, event, listener, binding) {
-   // create listener, get object-index
-   var l     = listener.bind(binding || node.instance || node)
-     , index = (SVG.handlerMap.indexOf(node) + 1 || SVG.handlerMap.push(node)) - 1
-     , ev    = event.split('.')[0]
-     , ns    = event.split('.')[1] || '*'
-   // ensure valid object
-   SVG.listeners[index]         = SVG.listeners[index]         || {}
-   SVG.listeners[index][ev]     = SVG.listeners[index][ev]     || {}
-   SVG.listeners[index][ev][ns] = SVG.listeners[index][ev][ns] || {}
-   if(!listener._svgjsListenerId)
-     listener._svgjsListenerId = ++SVG.listenerId
-   // reference listener
-   SVG.listeners[index][ev][ns][listener._svgjsListenerId] = l
-   // add listener
-   node.addEventListener(ev, l, false)
- }
- // Add event unbinder in the SVG namespace
- SVG.off = function(node, event, listener) {
-   var index = SVG.handlerMap.indexOf(node)
-     , ev    = event && event.split('.')[0]
-     , ns    = event && event.split('.')[1]
-   if(index == -1) return
-   if (listener) {
-     if(typeof listener == 'function') listener = listener._svgjsListenerId
-     if(!listener) return
-     // remove listener reference
-     if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns || '*']) {
-       // remove listener
-       node.removeEventListener(ev, SVG.listeners[index][ev][ns || '*'][listener], false)
-       delete SVG.listeners[index][ev][ns || '*'][listener]
-     }
-   } else if (ns && ev) {
-     // remove all listeners for a namespaced event
-     if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns]) {
-       for (listener in SVG.listeners[index][ev][ns])
-         SVG.off(node, [ev, ns].join('.'), listener)
-       delete SVG.listeners[index][ev][ns]
-     }
-   } else if (ns){
-     // remove all listeners for a specific namespace
-     for(event in SVG.listeners[index]){
-         for(namespace in SVG.listeners[index][event]){
-             if(ns === namespace){
-                 SVG.off(node, [event, ns].join('.'))
-             }
-         }
-     }
-   } else if (ev) {
-     // remove all listeners for the event
-     if (SVG.listeners[index][ev]) {
-       for (namespace in SVG.listeners[index][ev])
-         SVG.off(node, [ev, namespace].join('.'))
-       delete SVG.listeners[index][ev]
-     }
-   } else {
-     // remove all listeners on a given node
-     for (event in SVG.listeners[index])
-       SVG.off(node, event)
-     delete SVG.listeners[index]
-     delete SVG.handlerMap[index]
-   }
- }
- //
- SVG.extend(SVG.Element, {
-   // Bind given event to listener
-   on: function(event, listener, binding) {
-     SVG.on(this.node, event, listener, binding)
-     return this
-   }
-   // Unbind event from listener
- , off: function(event, listener) {
-     SVG.off(this.node, event, listener)
-     return this
-   }
-   // Fire given event
- , fire: function(event, data) {
-     // Dispatch event
-     if(event instanceof window.Event){
-         this.node.dispatchEvent(event)
-     }else{
-         this.node.dispatchEvent(event = new window.CustomEvent(event, {detail:data, cancelable: true}))
-     }
-     this._event = event
-     return this
-   }
- , event: function() {
-     return this._event
-   }
- })
- SVG.Defs = SVG.invent({
-   // Initialize node
-   create: 'defs'
-   // Inherit from
- , inherit: SVG.Container
- })
- SVG.G = SVG.invent({
-   // Initialize node
-   create: 'g'
-   // Inherit from
- , inherit: SVG.Container
-   // Add class methods
- , extend: {
-     // Move over x-axis
-     x: function(x) {
-       return x == null ? this.transform('x') : this.transform({ x: x - this.x() }, true)
-     }
-     // Move over y-axis
-   , y: function(y) {
-       return y == null ? this.transform('y') : this.transform({ y: y - this.y() }, true)
-     }
-     // Move by center over x-axis
-   , cx: function(x) {
-       return x == null ? this.gbox().cx : this.x(x - this.gbox().width / 2)
-     }
-     // Move by center over y-axis
-   , cy: function(y) {
-       return y == null ? this.gbox().cy : this.y(y - this.gbox().height / 2)
-     }
-   , gbox: function() {
-       var bbox  = this.bbox()
-         , trans = this.transform()
-       bbox.x  += trans.x
-       bbox.x2 += trans.x
-       bbox.cx += trans.x
-       bbox.y  += trans.y
-       bbox.y2 += trans.y
-       bbox.cy += trans.y
-       return bbox
-     }
-   }
-   // Add parent method
- , construct: {
-     // Create a group element
-     group: function() {
-       return this.put(new SVG.G)
-     }
-   }
- })
- // ### This module adds backward / forward functionality to elements.
- //
- SVG.extend(SVG.Element, {
-   // Get all siblings, including myself
-   siblings: function() {
-     return this.parent().children()
-   }
-   // Get the curent position siblings
- , position: function() {
-     return this.parent().index(this)
-   }
-   // Get the next element (will return null if there is none)
- , next: function() {
-     return this.siblings()[this.position() + 1]
-   }
-   // Get the next element (will return null if there is none)
- , previous: function() {
-     return this.siblings()[this.position() - 1]
-   }
-   // Send given element one step forward
- , forward: function() {
-     var i = this.position() + 1
-       , p = this.parent()
-     // move node one step forward
-     p.removeElement(this).add(this, i)
-     // make sure defs node is always at the top
-     if (p instanceof SVG.Doc)
-       p.node.appendChild(p.defs().node)
-     return this
-   }
-   // Send given element one step backward
- , backward: function() {
-     var i = this.position()
-     if (i > 0)
-       this.parent().removeElement(this).add(this, i - 1)
-     return this
-   }
-   // Send given element all the way to the front
- , front: function() {
-     var p = this.parent()
-     // Move node forward
-     p.node.appendChild(this.node)
-     // Make sure defs node is always at the top
-     if (p instanceof SVG.Doc)
-       p.node.appendChild(p.defs().node)
-     return this
-   }
-   // Send given element all the way to the back
- , back: function() {
-     if (this.position() > 0)
-       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
-   }
- })
- SVG.Mask = SVG.invent({
-   // Initialize node
-   create: 'mask'
-   // Inherit from
- , inherit: SVG.Container
-   // Add class methods
- , extend: {
-     // Unmask all masked elements and remove itself
-     remove: function() {
-       // unmask all targets
-       this.targets().forEach(function(el) {
-         el.unmask()
-       })
-       // remove mask from parent
-       return SVG.Element.prototype.remove.call(this)
-     }
-   , targets: function() {
-       return SVG.select('svg [mask*="' +this.id() +'"]')
-     }
-   }
-   // Add parent method
- , construct: {
-     // Create masking element
-     mask: function() {
-       return this.defs().put(new SVG.Mask)
-     }
-   }
- })
- SVG.extend(SVG.Element, {
-   // Distribute mask to svg element
-   maskWith: function(element) {
-     // use given mask or create a new one
-     var masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element)
-     // apply mask
-     return this.attr('mask', 'url("#' + masker.attr('id') + '")')
-   }
-   // Unmask element
- , unmask: function() {
-     return this.attr('mask', null)
-   }
- , masker: function() {
-     return this.reference('mask')
-   }
- })
- SVG.ClipPath = SVG.invent({
-   // Initialize node
-   create: 'clipPath'
-   // Inherit from
- , inherit: SVG.Container
-   // Add class methods
- , extend: {
-     // Unclip all clipped elements and remove itself
-     remove: function() {
-       // unclip all targets
-       this.targets().forEach(function(el) {
-         el.unclip()
-       })
-       // remove clipPath from parent
-       return SVG.Element.prototype.remove.call(this)
-     }
-   , targets: function() {
-       return SVG.select('svg [clip-path*="' +this.id() +'"]')
-     }
-   }
-   // Add parent method
- , construct: {
-     // Create clipping element
-     clip: function() {
-       return this.defs().put(new SVG.ClipPath)
-     }
-   }
- })
- //
- SVG.extend(SVG.Element, {
-   // Distribute clipPath to svg element
-   clipWith: function(element) {
-     // use given clip or create a new one
-     var clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element)
-     // apply mask
-     return this.attr('clip-path', 'url("#' + clipper.attr('id') + '")')
-   }
-   // Unclip element
- , unclip: function() {
-     return this.attr('clip-path', null)
-   }
- , clipper: function() {
-     return this.reference('clip-path')
-   }
- })
- SVG.Gradient = SVG.invent({
-   // Initialize node
-   create: function(type) {
-     this.constructor.call(this, SVG.create(type + 'Gradient'))
-   }
-   // Inherit from
- , inherit: SVG.Container
-   // Add class methods
- , extend: {
-     // Add a color stop
-     at: function(offset, color, opacity) {
-       return this.put(new SVG.Stop).update(offset, color, opacity)
-     }
-     // Update gradient
-   , update: function(block) {
-       // remove all stops
-       this.clear()
-       // invoke passed block
-       if (typeof block == 'function')
-         block.call(this, this)
-       return this
-     }
-     // Return the fill id
-   , fill: function() {
-       return 'url(#' + this.id() + ')'
-     }
-     // Alias string convertion to fill
-   , toString: function() {
-       return this.fill()
-     }
-     // custom attr to handle transform
-   , attr: function(a, b, c) {
-       if(a == 'transform') a = 'gradientTransform'
-       return SVG.Container.prototype.attr.call(this, a, b, c)
-     }
-   }
-   // Add parent method
- , construct: {
-     // Create gradient element in defs
-     gradient: function(type, block) {
-       return this.defs().gradient(type, block)
-     }
-   }
- })
- // Add animatable methods to both gradient and fx module
- SVG.extend(SVG.Gradient, SVG.FX, {
-   // From position
-   from: function(x, y) {
-     return (this._target || this).type == 'radialGradient' ?
-       this.attr({ fx: new SVG.Number(x), fy: new SVG.Number(y) }) :
-       this.attr({ x1: new SVG.Number(x), y1: new SVG.Number(y) })
-   }
-   // To position
- , to: function(x, y) {
-     return (this._target || this).type == 'radialGradient' ?
-       this.attr({ cx: new SVG.Number(x), cy: new SVG.Number(y) }) :
-       this.attr({ x2: new SVG.Number(x), y2: new SVG.Number(y) })
-   }
- })
- // Base gradient generation
- SVG.extend(SVG.Defs, {
-   // define gradient
-   gradient: function(type, block) {
-     return this.put(new SVG.Gradient(type)).update(block)
-   }
- })
- SVG.Stop = SVG.invent({
-   // Initialize node
-   create: 'stop'
-   // Inherit from
- , inherit: SVG.Element
-   // Add class methods
- , extend: {
-     // add color stops
-     update: function(o) {
-       if (typeof o == 'number' || o instanceof SVG.Number) {
-         o = {
-           offset:  arguments[0]
-         , color:   arguments[1]
-         , opacity: arguments[2]
-         }
-       }
-       // set attributes
-       if (o.opacity != null) this.attr('stop-opacity', o.opacity)
-       if (o.color   != null) this.attr('stop-color', o.color)
-       if (o.offset  != null) this.attr('offset', new SVG.Number(o.offset))
-       return this
-     }
-   }
- })
- SVG.Pattern = SVG.invent({
-   // Initialize node
-   create: 'pattern'
-   // Inherit from
- , inherit: SVG.Container
-   // Add class methods
- , extend: {
-     // Return the fill id
-     fill: function() {
-       return 'url(#' + this.id() + ')'
-     }
-     // Update pattern by rebuilding
-   , update: function(block) {
-       // remove content
-       this.clear()
-       // invoke passed block
-       if (typeof block == 'function')
-         block.call(this, this)
-       return this
-     }
-     // Alias string convertion to fill
-   , toString: function() {
-       return this.fill()
-     }
-     // custom attr to handle transform
-   , attr: function(a, b, c) {
-       if(a == 'transform') a = 'patternTransform'
-       return SVG.Container.prototype.attr.call(this, a, b, c)
-     }
-   }
-   // Add parent method
- , construct: {
-     // Create pattern element in defs
-     pattern: function(width, height, block) {
-       return this.defs().pattern(width, height, block)
-     }
-   }
- })
- SVG.extend(SVG.Defs, {
-   // Define gradient
-   pattern: function(width, height, block) {
-     return this.put(new SVG.Pattern).update(block).attr({
-       x:            0
-     , y:            0
-     , width:        width
-     , height:       height
-     , patternUnits: 'userSpaceOnUse'
-     })
-   }
- })
- SVG.Doc = SVG.invent({
-   // Initialize node
-   create: function(element) {
-     if (element) {
-       // ensure the presence of a dom element
-       element = typeof element == 'string' ?
-         document.getElementById(element) :
-         element
-       // If the target is an svg element, use that element as the main wrapper.
-       // This allows svg.js to work with svg documents as well.
-       if (element.nodeName == 'svg') {
-         this.constructor.call(this, element)
-       } else {
-         this.constructor.call(this, SVG.create('svg'))
-         element.appendChild(this.node)
-         this.size('100%', '100%')
-       }
-       // set svg element attributes and ensure defs node
-       this.namespace().defs()
-     }
-   }
-   // Inherit from
- , inherit: SVG.Container
-   // Add class methods
- , extend: {
-     // Add namespaces
-     namespace: function() {
-       return this
-         .attr({ xmlns: SVG.ns, version: '1.1' })
-         .attr('xmlns:xlink', SVG.xlink, SVG.xmlns)
-         .attr('xmlns:svgjs', SVG.svgjs, SVG.xmlns)
-     }
-     // Creates and returns defs element
-   , defs: function() {
-       if (!this._defs) {
-         var defs
-         // Find or create a defs element in this instance
-         if (defs = this.node.getElementsByTagName('defs')[0])
-           this._defs = SVG.adopt(defs)
-         else
-           this._defs = new SVG.Defs
-         // Make sure the defs node is at the end of the stack
-         this.node.appendChild(this._defs.node)
-       }
-       return this._defs
-     }
-     // custom parent method
-   , parent: function() {
-       return this.node.parentNode.nodeName == '#document' ? null : this.node.parentNode
-     }
-     // Fix for possible sub-pixel offset. See:
-     // https://bugzilla.mozilla.org/show_bug.cgi?id=608812
-   , spof: function(spof) {
-       var pos = this.node.getScreenCTM()
-       if (pos)
-         this
-           .style('left', (-pos.e % 1) + 'px')
-           .style('top',  (-pos.f % 1) + 'px')
-       return this
-     }
-       // Removes the doc from the DOM
-   , remove: function() {
-       if(this.parent()) {
-         this.parent().removeChild(this.node);
-       }
-       return this;
-     }
-   }
- })
- SVG.Shape = SVG.invent({
-   // Initialize node
-   create: function(element) {
-     this.constructor.call(this, element)
-   }
-   // Inherit from
- , inherit: SVG.Element
- })
- SVG.Bare = SVG.invent({
-   // Initialize
-   create: function(element, inherit) {
-     // construct element
-     this.constructor.call(this, SVG.create(element))
-     // inherit custom methods
-     if (inherit)
-       for (var method in inherit.prototype)
-         if (typeof inherit.prototype[method] === 'function')
-           this[method] = inherit.prototype[method]
-   }
-   // Inherit from
- , inherit: SVG.Element
-   // Add methods
- , extend: {
-     // Insert some plain text
-     words: function(text) {
-       // remove contents
-       while (this.node.hasChildNodes())
-         this.node.removeChild(this.node.lastChild)
-       // create text node
-       this.node.appendChild(document.createTextNode(text))
-       return this
-     }
-   }
- })
- SVG.extend(SVG.Parent, {
-   // Create an element that is not described by SVG.js
-   element: function(element, inherit) {
-     return this.put(new SVG.Bare(element, inherit))
-   }
- })
- SVG.Symbol = SVG.invent({
-   // Initialize node
-   create: 'symbol'
-   // Inherit from
- , inherit: SVG.Container
- , construct: {
-     // create symbol
-     symbol: function() {
-       return this.put(new SVG.Symbol)
-     }
-   }
- })
- SVG.Use = SVG.invent({
-   // Initialize node
-   create: 'use'
-   // Inherit from
- , inherit: SVG.Shape
-   // Add class methods
- , extend: {
-     // Use element as a reference
-     element: function(element, file) {
-       // Set lined element
-       return this.attr('href', (file || '') + '#' + element, SVG.xlink)
-     }
-   }
-   // Add parent method
- , construct: {
-     // Create a use element
-     use: function(element, file) {
-       return this.put(new SVG.Use).element(element, file)
-     }
-   }
- })
- SVG.Rect = SVG.invent({
-   // Initialize node
-   create: 'rect'
-   // Inherit from
- , inherit: SVG.Shape
-   // Add parent method
- , construct: {
-     // Create a rect element
-     rect: function(width, height) {
-       return this.put(new SVG.Rect()).size(width, height)
-     }
-   }
- })
- SVG.Circle = SVG.invent({
-   // Initialize node
-   create: 'circle'
-   // Inherit from
- , inherit: SVG.Shape
-   // Add parent method
- , construct: {
-     // Create circle element, based on ellipse
-     circle: function(size) {
-       return this.put(new SVG.Circle).rx(new SVG.Number(size).divide(2)).move(0, 0)
-     }
-   }
- })
- SVG.extend(SVG.Circle, SVG.FX, {
-   // Radius x value
-   rx: function(rx) {
-     return this.attr('r', rx)
-   }
-   // Alias radius x value
- , ry: function(ry) {
-     return this.rx(ry)
-   }
- })
- SVG.Ellipse = SVG.invent({
-   // Initialize node
-   create: 'ellipse'
-   // Inherit from
- , inherit: SVG.Shape
-   // Add parent method
- , construct: {
-     // Create an ellipse
-     ellipse: function(width, height) {
-       return this.put(new SVG.Ellipse).size(width, height).move(0, 0)
-     }
-   }
- })
- SVG.extend(SVG.Ellipse, SVG.Rect, SVG.FX, {
-   // Radius x value
-   rx: function(rx) {
-     return this.attr('rx', rx)
-   }
-   // Radius y value
- , ry: function(ry) {
-     return this.attr('ry', ry)
-   }
- })
- // Add common method
- SVG.extend(SVG.Circle, SVG.Ellipse, {
-     // Move over x-axis
-     x: function(x) {
-       return x == null ? this.cx() - this.rx() : this.cx(x + this.rx())
-     }
-     // Move over y-axis
-   , y: function(y) {
-       return y == null ? this.cy() - this.ry() : this.cy(y + this.ry())
-     }
-     // Move by center over x-axis
-   , cx: function(x) {
-       return x == null ? this.attr('cx') : this.attr('cx', x)
-     }
-     // Move by center over y-axis
-   , cy: function(y) {
-       return y == null ? this.attr('cy') : this.attr('cy', y)
-     }
-     // Set width of element
-   , width: function(width) {
-       return width == null ? this.rx() * 2 : this.rx(new SVG.Number(width).divide(2))
-     }
-     // Set height of element
-   , height: function(height) {
-       return height == null ? this.ry() * 2 : this.ry(new SVG.Number(height).divide(2))
-     }
-     // Custom size function
-   , size: function(width, height) {
-       var p = proportionalSize(this, width, height)
-       return this
-         .rx(new SVG.Number(p.width).divide(2))
-         .ry(new SVG.Number(p.height).divide(2))
-     }
- })
- SVG.Line = SVG.invent({
-   // Initialize node
-   create: 'line'
-   // Inherit from
- , inherit: SVG.Shape
-   // Add class methods
- , extend: {
-     // Get array
-     array: function() {
-       return new SVG.PointArray([
-         [ this.attr('x1'), this.attr('y1') ]
-       , [ this.attr('x2'), this.attr('y2') ]
-       ])
-     }
-     // Overwrite native plot() method
-   , plot: function(x1, y1, x2, y2) {
-       if (x1 == null)
-         return this.array()
-       else if (typeof y1 !== 'undefined')
-         x1 = { x1: x1, y1: y1, x2: x2, y2: y2 }
-       else
-         x1 = new SVG.PointArray(x1).toLine()
-       return this.attr(x1)
-     }
-     // Move by left top corner
-   , move: function(x, y) {
-       return this.attr(this.array().move(x, y).toLine())
-     }
-     // Set element size to given width and height
-   , size: function(width, height) {
-       var p = proportionalSize(this, width, height)
-       return this.attr(this.array().size(p.width, p.height).toLine())
-     }
-   }
-   // Add parent method
- , construct: {
-     // Create a line element
-     line: function(x1, y1, x2, y2) {
-       // make sure plot is called as a setter
-       // x1 is not necessarily a number, it can also be an array, a string and a SVG.PointArray
-       return SVG.Line.prototype.plot.apply(
-         this.put(new SVG.Line)
-       , x1 != null ? [x1, y1, x2, y2] : [0, 0, 0, 0]
-       )
-     }
-   }
- })
- SVG.Polyline = SVG.invent({
-   // Initialize node
-   create: 'polyline'
-   // Inherit from
- , inherit: SVG.Shape
-   // Add parent method
- , construct: {
-     // Create a wrapped polyline element
-     polyline: function(p) {
-       // make sure plot is called as a setter
-       return this.put(new SVG.Polyline).plot(p || new SVG.PointArray)
-     }
-   }
- })
- SVG.Polygon = SVG.invent({
-   // Initialize node
-   create: 'polygon'
-   // Inherit from
- , inherit: SVG.Shape
-   // Add parent method
- , construct: {
-     // Create a wrapped polygon element
-     polygon: function(p) {
-       // make sure plot is called as a setter
-       return this.put(new SVG.Polygon).plot(p || new SVG.PointArray)
-     }
-   }
- })
- // Add polygon-specific functions
- SVG.extend(SVG.Polyline, SVG.Polygon, {
-   // Get array
-   array: function() {
-     return this._array || (this._array = new SVG.PointArray(this.attr('points')))
-   }
-   // Plot new path
- , plot: function(p) {
-     return (p == null) ?
-       this.array() :
-       this.attr('points', (this._array = new SVG.PointArray(p)))
-   }
-   // Move by left top corner
- , move: function(x, y) {
-     return this.attr('points', this.array().move(x, y))
-   }
-   // Set element size to given width and height
- , size: function(width, height) {
-     var p = proportionalSize(this, width, height)
-     return this.attr('points', this.array().size(p.width, p.height))
-   }
- })
- // unify all point to point elements
- SVG.extend(SVG.Line, SVG.Polyline, SVG.Polygon, {
-   // Define morphable array
-   morphArray:  SVG.PointArray
-   // Move by left top corner over x-axis
- , x: function(x) {
-     return x == null ? this.bbox().x : this.move(x, this.bbox().y)
-   }
-   // Move by left top corner over y-axis
- , y: function(y) {
-     return y == null ? this.bbox().y : this.move(this.bbox().x, y)
-   }
-   // Set width of element
- , width: function(width) {
-     var b = this.bbox()
-     return width == null ? b.width : this.size(width, b.height)
-   }
-   // Set height of element
- , height: function(height) {
-     var b = this.bbox()
-     return height == null ? b.height : this.size(b.width, height)
-   }
- })
- SVG.Path = SVG.invent({
-   // Initialize node
-   create: 'path'
-   // Inherit from
- , inherit: SVG.Shape
-   // Add class methods
- , extend: {
-     // Define morphable array
-     morphArray:  SVG.PathArray
-     // Get array
-   , array: function() {
-       return this._array || (this._array = new SVG.PathArray(this.attr('d')))
-     }
-     // Plot new poly points
-   , plot: function(p) {
-       return (p == null) ?
-         this.array() :
-         this.attr('d', (this._array = new SVG.PathArray(p)))
-     }
-     // Move by left top corner
-   , move: function(x, y) {
-       return this.attr('d', this.array().move(x, y))
-     }
-     // Move by left top corner over x-axis
-   , x: function(x) {
-       return x == null ? this.bbox().x : this.move(x, this.bbox().y)
-     }
-     // Move by left top corner over y-axis
-   , y: function(y) {
-       return y == null ? this.bbox().y : this.move(this.bbox().x, y)
-     }
-     // Set element size to given width and height
-   , size: function(width, height) {
-       var p = proportionalSize(this, width, height)
-       return this.attr('d', this.array().size(p.width, p.height))
-     }
-     // Set width of element
-   , width: function(width) {
-       return width == null ? this.bbox().width : this.size(width, this.bbox().height)
-     }
-     // Set height of element
-   , height: function(height) {
-       return height == null ? this.bbox().height : this.size(this.bbox().width, height)
-     }
-   }
-   // Add parent method
- , construct: {
-     // Create a wrapped path element
-     path: function(d) {
-       // make sure plot is called as a setter
-       return this.put(new SVG.Path).plot(d || new SVG.PathArray)
-     }
-   }
- })
- SVG.Image = SVG.invent({
-   // Initialize node
-   create: 'image'
-   // Inherit from
- , inherit: SVG.Shape
-   // Add class methods
- , extend: {
-     // (re)load image
-     load: function(url, callback) {
-       if (!url) return this
-       var img = new window.Image()
-       SVG.on(img, 'load', function(e) {
-         var p = this.parent()
-         // ensure image size
-         if (this.width() == 0 && this.height() == 0)
-           this.size(img.width, img.height)
-         if(p instanceof SVG.Pattern) {
-           // ensure pattern size if not set
-           if (p.width() == 0 && p.height() == 0)
-             p.size(this.width(), this.height())
-         }
-         if(typeof callback == 'function') {
-           callback.call(this, {
-             width:  img.width
-           , height: img.height
-           , ratio:  img.width / img.height
-           , url:    url
-           })
-         }
-       }, this)
-       return this.attr('href', (img.src = url), SVG.xlink)
-     }
-   }
-   // Add parent method
- , construct: {
-     // create image element, load image and set its size
-     image: function(source, callback) {
-       return this.put(new SVG.Image).size(0, 0).load(source, callback)
-     }
-   }
- })
- SVG.Text = SVG.invent({
-   // Initialize node
-   create: function() {
-     this.constructor.call(this, SVG.create('text'))
-     this.dom.leading = new SVG.Number(1.3)    // store leading value for rebuilding
-     this._rebuild = true                      // enable automatic updating of dy values
-     this._build   = false                     // disable build mode for adding multiple lines
-     // set default font
-     this.attr('font-family', SVG.defaults.attrs['font-family'])
-   }
-   // Inherit from
- , inherit: SVG.Parent
-   // Add class methods
- , extend: {
-     // Move over x-axis
-     x: function(x) {
-       // act as getter
-       if (x == null)
-         return this.attr('x')
-       return this.attr('x', x)
-     }
-     // Move over y-axis
-   , y: function(y) {
-       var oy = this.attr('y')
-         , o  = typeof oy === 'number' ? oy - this.bbox().y : 0
-       // act as getter
-       if (y == null)
-         return typeof oy === 'number' ? oy - o : oy
-       return this.attr('y', typeof y === 'number' ? y + o : y)
-     }
-     // Move center over x-axis
-   , cx: function(x) {
-       return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2)
-     }
-     // Move center over y-axis
-   , cy: function(y) {
-       return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2)
-     }
-     // Set the text content
-   , text: function(text) {
-       // act as getter
-       if (typeof text === 'undefined'){
-         var text = ''
-         var children = this.node.childNodes
-         for(var i = 0, len = children.length; i < len; ++i){
-           // add newline if its not the first child and newLined is set to true
-           if(i != 0 && children[i].nodeType != 3 && SVG.adopt(children[i]).dom.newLined == true){
-             text += '\n'
-           }
-           // add content of this node
-           text += children[i].textContent
-         }
-         return text
-       }
-       // remove existing content
-       this.clear().build(true)
-       if (typeof text === 'function') {
-         // call block
-         text.call(this, this)
-       } else {
-         // store text and make sure text is not blank
-         text = text.split('\n')
-         // build new lines
-         for (var i = 0, il = text.length; i < il; i++)
-           this.tspan(text[i]).newLine()
-       }
-       // disable build mode and rebuild lines
-       return this.build(false).rebuild()
-     }
-     // Set font size
-   , size: function(size) {
-       return this.attr('font-size', size).rebuild()
-     }
-     // Set / get leading
-   , leading: function(value) {
-       // act as getter
-       if (value == null)
-         return this.dom.leading
-       // act as setter
-       this.dom.leading = new SVG.Number(value)
-       return this.rebuild()
-     }
-     // Rebuild appearance type
-   , rebuild: function(rebuild) {
-       // store new rebuild flag if given
-       if (typeof rebuild == 'boolean')
-         this._rebuild = rebuild
-       // define position of all lines
-       if (this._rebuild) {
-         var self = this
-           , blankLineOffset = 0
-           , dy = this.dom.leading * new SVG.Number(this.attr('font-size'))
-         this.each(function() {
-           if (this.dom.newLined) {
-             if (!self.textPath())
-               this.attr('x', self.attr('x'))
-             if(this.text() == '\n') {
-               blankLineOffset += dy
-             }else{
-               this.attr('dy', dy + blankLineOffset)
-               blankLineOffset = 0
-             }
-           }
-         })
-         this.fire('rebuild')
-       }
-       return this
-     }
-     // Enable / disable build mode
-   , build: function(build) {
-       this._build = !!build
-       return this
-     }
-     // overwrite method from parent to set data properly
-   , setData: function(o){
-       this.dom = o
-       this.dom.leading = new SVG.Number(o.leading || 1.3)
-       return this
-     }
-   }
-   // Add parent method
- , construct: {
-     // Create text element
-     text: function(text) {
-       return this.put(new SVG.Text).text(text)
-     }
-     // Create plain text element
-   , plain: function(text) {
-       return this.put(new SVG.Text).plain(text)
-     }
-   }
- })
- SVG.Tspan = SVG.invent({
-   // Initialize node
-   create: 'tspan'
-   // Inherit from
- , inherit: SVG.Parent
-   // Add class methods
- , extend: {
-     // Set text content
-     text: function(text) {
-       if(text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '')
-       typeof text === 'function' ? text.call(this, this) : this.plain(text)
-       return this
-     }
-     // Shortcut dx
-   , dx: function(dx) {
-       return this.attr('dx', dx)
-     }
-     // Shortcut dy
-   , dy: function(dy) {
-       return this.attr('dy', dy)
-     }
-     // Create new line
-   , newLine: function() {
-       // fetch text parent
-       var t = this.parent(SVG.Text)
-       // mark new line
-       this.dom.newLined = true
-       // apply new hy¡n
-       return this.dy(t.dom.leading * t.attr('font-size')).attr('x', t.x())
-     }
-   }
- })
- SVG.extend(SVG.Text, SVG.Tspan, {
-   // Create plain text node
-   plain: function(text) {
-     // clear if build mode is disabled
-     if (this._build === false)
-       this.clear()
-     // create text node
-     this.node.appendChild(document.createTextNode(text))
-     return this
-   }
-   // Create a tspan
- , tspan: function(text) {
-     var node  = (this.textPath && this.textPath() || this).node
-       , tspan = new SVG.Tspan
-     // clear if build mode is disabled
-     if (this._build === false)
-       this.clear()
-     // add new tspan
-     node.appendChild(tspan.node)
-     return tspan.text(text)
-   }
-   // Get length of text element
- , length: function() {
-     return this.node.getComputedTextLength()
-   }
- })
- SVG.TextPath = SVG.invent({
-   // Initialize node
-   create: 'textPath'
-   // Inherit from
- , inherit: SVG.Parent
-   // Define parent class
- , parent: SVG.Text
-   // Add parent method
- , construct: {
-     // Create path for text to run on
-     path: function(d) {
-       // create textPath element
-       var path  = new SVG.TextPath
-         , track = this.doc().defs().path(d)
-       // move lines to textpath
-       while (this.node.hasChildNodes())
-         path.node.appendChild(this.node.firstChild)
-       // add textPath element as child node
-       this.node.appendChild(path.node)
-       // link textPath to path and add content
-       path.attr('href', '#' + track, SVG.xlink)
-       return this
-     }
-     // return the array of the path track element
-   , array: function() {
-       var track = this.track()
-       return track ? track.array() : null
-     }
-     // Plot path if any
-   , plot: function(d) {
-       var track = this.track()
-         , pathArray = null
-       if (track) {
-         pathArray = track.plot(d)
-       }
-       return (d == null) ? pathArray : this
-     }
-     // Get the path track element
-   , track: function() {
-       var path = this.textPath()
-       if (path)
-         return path.reference('href')
-     }
-     // Get the textPath child
-   , textPath: function() {
-       if (this.node.firstChild && this.node.firstChild.nodeName == 'textPath')
-         return SVG.adopt(this.node.firstChild)
-     }
-   }
+ (function(root, factory) {\r
+   /* istanbul ignore next */\r
+   if (typeof define === 'function' && define.amd) {\r
+     define(function(){\r
+       return factory(root, root.document)\r
+     })\r
+   } else if (typeof exports === 'object') {\r
+     module.exports = root.document ? factory(root, root.document) : function(w){ return factory(w, w.document) }\r
+   } else {\r
+     root.SVG = factory(root, root.document)\r
+   }\r
+ }(typeof window !== "undefined" ? window : this, function(window, document) {\r
\r
+ // The main wrapping element\r
+ var SVG = this.SVG = function(element) {\r
+   if (SVG.supported) {\r
+     element = new SVG.Doc(element)\r
\r
+     if(!SVG.parser.draw)\r
+       SVG.prepare()\r
\r
+     return element\r
+   }\r
+ }\r
\r
+ // Default namespaces\r
+ SVG.ns    = 'http://www.w3.org/2000/svg'\r
+ SVG.xmlns = 'http://www.w3.org/2000/xmlns/'\r
+ SVG.xlink = 'http://www.w3.org/1999/xlink'\r
+ SVG.svgjs = 'http://svgjs.com/svgjs'\r
\r
+ // Svg support test\r
+ SVG.supported = (function() {\r
+   return !! document.createElementNS &&\r
+          !! document.createElementNS(SVG.ns,'svg').createSVGRect\r
+ })()\r
\r
+ // Don't bother to continue if SVG is not supported\r
+ if (!SVG.supported) return false\r
\r
+ // Element id sequence\r
+ SVG.did  = 1000\r
\r
+ // Get next named element id\r
+ SVG.eid = function(name) {\r
+   return 'Svgjs' + capitalize(name) + (SVG.did++)\r
+ }\r
\r
+ // Method for element creation\r
+ SVG.create = function(name) {\r
+   // create element\r
+   var element = document.createElementNS(this.ns, name)\r
\r
+   // apply unique id\r
+   element.setAttribute('id', this.eid(name))\r
\r
+   return element\r
+ }\r
\r
+ // Method for extending objects\r
+ SVG.extend = function() {\r
+   var modules, methods, key, i\r
\r
+   // Get list of modules\r
+   modules = [].slice.call(arguments)\r
\r
+   // Get object with extensions\r
+   methods = modules.pop()\r
\r
+   for (i = modules.length - 1; i >= 0; i--)\r
+     if (modules[i])\r
+       for (key in methods)\r
+         modules[i].prototype[key] = methods[key]\r
 -\r
 -  // Make sure SVG.Set inherits any newly added methods\r
 -  if (SVG.Set && SVG.Set.inherit)\r
 -    SVG.Set.inherit()\r
+ }\r
\r
+ // Invent new element\r
+ SVG.invent = function(config) {\r
+   // Create element initializer\r
+   var initializer = typeof config.create == 'function' ?\r
+     config.create :\r
+     function() {\r
+       this.constructor.call(this, SVG.create(config.create))\r
+     }\r
\r
+   // Inherit prototype\r
+   if (config.inherit)\r
+     initializer.prototype = new config.inherit\r
\r
+   // Extend with methods\r
+   if (config.extend)\r
+     SVG.extend(initializer, config.extend)\r
\r
+   // Attach construct method to parent\r
+   if (config.construct)\r
+     SVG.extend(config.parent || SVG.Container, config.construct)\r
\r
+   return initializer\r
+ }\r
\r
+ // Adopt existing svg elements\r
+ SVG.adopt = function(node) {\r
+   // check for presence of node\r
+   if (!node) return null\r
\r
+   // make sure a node isn't already adopted\r
+   if (node.instance) return node.instance\r
\r
+   // initialize variables\r
+   var element\r
\r
+   // adopt with element-specific settings\r
+   if (node.nodeName == 'svg')\r
+     element = node.parentNode instanceof window.SVGElement ? new SVG.Nested : new SVG.Doc\r
+   else if (node.nodeName == 'linearGradient')\r
+     element = new SVG.Gradient('linear')\r
+   else if (node.nodeName == 'radialGradient')\r
+     element = new SVG.Gradient('radial')\r
+   else if (SVG[capitalize(node.nodeName)])\r
+     element = new SVG[capitalize(node.nodeName)]\r
+   else\r
+     element = new SVG.Element(node)\r
\r
+   // ensure references\r
+   element.type  = node.nodeName\r
+   element.node  = node\r
+   node.instance = element\r
\r
+   // SVG.Class specific preparations\r
+   if (element instanceof SVG.Doc)\r
+     element.namespace().defs()\r
\r
+   // pull svgjs data from the dom (getAttributeNS doesn't work in html5)\r
+   element.setData(JSON.parse(node.getAttribute('svgjs:data')) || {})\r
\r
+   return element\r
+ }\r
\r
+ // Initialize parsing element\r
+ SVG.prepare = function() {\r
+   // Select document body and create invisible svg element\r
+   var body = document.getElementsByTagName('body')[0]\r
+     , draw = (body ? new SVG.Doc(body) : SVG.adopt(document.documentElement).nested()).size(2, 0)\r
\r
+   // Create parser object\r
+   SVG.parser = {\r
+     body: body || document.documentElement\r
 -  , draw: draw.style('opacity:0;position:absolute;left:-100%;top:-100%;overflow:hidden').node\r
++  , draw: draw.style({\r
++      opacity:0,\r
++      position:'absolute',\r
++      left:'-100%',\r
++      top:'-100%',\r
++      overflow:'hidden'\r
++    }).node\r
+   , poly: draw.polyline().node\r
+   , path: draw.path().node\r
+   , native: SVG.create('svg')\r
+   }\r
+ }\r
\r
+ SVG.parser = {\r
+   native: SVG.create('svg')\r
+ }\r
\r
+ document.addEventListener('DOMContentLoaded', function() {\r
+   if(!SVG.parser.draw)\r
+     SVG.prepare()\r
+ }, false)\r
+ // Storage for regular expressions\r
+ SVG.regex = {\r
+   // Parse unit value\r
+   numberAndUnit:    /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i\r
\r
+   // Parse hex value\r
+ , hex:              /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i\r
\r
+   // Parse rgb value\r
+ , rgb:              /rgb\((\d+),(\d+),(\d+)\)/\r
\r
+   // Parse reference id\r
+ , reference:        /#([a-z0-9\-_]+)/i\r
\r
+   // splits a transformation chain\r
+ , transforms:       /\)\s*,?\s*/\r
\r
+   // Whitespace\r
+ , whitespace:       /\s/g\r
\r
+   // Test hex value\r
+ , isHex:            /^#[a-f0-9]{3,6}$/i\r
\r
+   // Test rgb value\r
+ , isRgb:            /^rgb\(/\r
\r
+   // Test css declaration\r
+ , isCss:            /[^:]+:[^;]+;?/\r
\r
+   // Test for blank string\r
+ , isBlank:          /^(\s+)?$/\r
\r
+   // Test for numeric string\r
+ , isNumber:         /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i\r
\r
+   // Test for percent value\r
+ , isPercent:        /^-?[\d\.]+%$/\r
\r
+   // Test for image url\r
+ , isImage:          /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i\r
\r
+   // split at whitespace and comma\r
+ , delimiter:        /[\s,]+/\r
\r
+   // The following regex are used to parse the d attribute of a path\r
\r
+   // Matches all hyphens which are not after an exponent\r
+ , hyphen:           /([^e])\-/gi\r
\r
+   // Replaces and tests for all path letters\r
+ , pathLetters:      /[MLHVCSQTAZ]/gi\r
\r
+   // yes we need this one, too\r
+ , isPathLetter:     /[MLHVCSQTAZ]/i\r
\r
+   // matches 0.154.23.45\r
+ , numbersWithDots:  /((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi\r
\r
+   // matches .\r
+ , dots:             /\./g\r
+ }\r
+ SVG.utils = {\r
+   // Map function\r
+   map: function(array, block) {\r
+     var i\r
+       , il = array.length\r
+       , result = []\r
\r
+     for (i = 0; i < il; i++)\r
+       result.push(block(array[i]))\r
\r
+     return result\r
+   }\r
\r
+   // Filter function\r
+ , filter: function(array, block) {\r
+     var i\r
+       , il = array.length\r
+       , result = []\r
\r
+     for (i = 0; i < il; i++)\r
+       if (block(array[i]))\r
+         result.push(array[i])\r
\r
+     return result\r
+   }\r
\r
+   // Degrees to radians\r
+ , radians: function(d) {\r
+     return d % 360 * Math.PI / 180\r
+   }\r
\r
+   // Radians to degrees\r
+ , degrees: function(r) {\r
+     return r * 180 / Math.PI % 360\r
+   }\r
\r
+ , filterSVGElements: function(nodes) {\r
+     return this.filter( nodes, function(el) { return el instanceof window.SVGElement })\r
+   }\r
\r
+ }
\r
+ SVG.defaults = {\r
+   // Default attribute values\r
+   attrs: {\r
+     // fill and stroke\r
+     'fill-opacity':     1\r
+   , 'stroke-opacity':   1\r
+   , 'stroke-width':     0\r
+   , 'stroke-linejoin':  'miter'\r
+   , 'stroke-linecap':   'butt'\r
+   , fill:               '#000000'\r
+   , stroke:             '#000000'\r
+   , opacity:            1\r
+     // position\r
+   , x:                  0\r
+   , y:                  0\r
+   , cx:                 0\r
+   , cy:                 0\r
+     // size\r
+   , width:              0\r
+   , height:             0\r
+     // radius\r
+   , r:                  0\r
+   , rx:                 0\r
+   , ry:                 0\r
+     // gradient\r
+   , offset:             0\r
+   , 'stop-opacity':     1\r
+   , 'stop-color':       '#000000'\r
+     // text\r
+   , 'font-size':        16\r
+   , 'font-family':      'Helvetica, Arial, sans-serif'\r
+   , 'text-anchor':      'start'\r
+   }\r
\r
+ }
+ // Module for color convertions\r
+ SVG.Color = function(color) {\r
+   var match\r
\r
+   // initialize defaults\r
+   this.r = 0\r
+   this.g = 0\r
+   this.b = 0\r
\r
+   if(!color) return\r
\r
+   // parse color\r
+   if (typeof color === 'string') {\r
+     if (SVG.regex.isRgb.test(color)) {\r
+       // get rgb values\r
+       match = SVG.regex.rgb.exec(color.replace(SVG.regex.whitespace,''))\r
\r
+       // parse numeric values\r
+       this.r = parseInt(match[1])\r
+       this.g = parseInt(match[2])\r
+       this.b = parseInt(match[3])\r
\r
+     } else if (SVG.regex.isHex.test(color)) {\r
+       // get hex values\r
+       match = SVG.regex.hex.exec(fullHex(color))\r
\r
+       // parse numeric values\r
+       this.r = parseInt(match[1], 16)\r
+       this.g = parseInt(match[2], 16)\r
+       this.b = parseInt(match[3], 16)\r
\r
+     }\r
\r
+   } else if (typeof color === 'object') {\r
+     this.r = color.r\r
+     this.g = color.g\r
+     this.b = color.b\r
\r
+   }\r
\r
+ }\r
\r
+ SVG.extend(SVG.Color, {\r
+   // Default to hex conversion\r
+   toString: function() {\r
+     return this.toHex()\r
+   }\r
+   // Build hex value\r
+ , toHex: function() {\r
+     return '#'\r
+       + compToHex(this.r)\r
+       + compToHex(this.g)\r
+       + compToHex(this.b)\r
+   }\r
+   // Build rgb value\r
+ , toRgb: function() {\r
+     return 'rgb(' + [this.r, this.g, this.b].join() + ')'\r
+   }\r
+   // Calculate true brightness\r
+ , brightness: function() {\r
+     return (this.r / 255 * 0.30)\r
+          + (this.g / 255 * 0.59)\r
+          + (this.b / 255 * 0.11)\r
+   }\r
+   // Make color morphable\r
+ , morph: function(color) {\r
+     this.destination = new SVG.Color(color)\r
\r
+     return this\r
+   }\r
+   // Get morphed color at given position\r
+ , at: function(pos) {\r
+     // make sure a destination is defined\r
+     if (!this.destination) return this\r
\r
+     // normalise pos\r
+     pos = pos < 0 ? 0 : pos > 1 ? 1 : pos\r
\r
+     // generate morphed color\r
+     return new SVG.Color({\r
+       r: ~~(this.r + (this.destination.r - this.r) * pos)\r
+     , g: ~~(this.g + (this.destination.g - this.g) * pos)\r
+     , b: ~~(this.b + (this.destination.b - this.b) * pos)\r
+     })\r
+   }\r
\r
+ })\r
\r
+ // Testers\r
\r
+ // Test if given value is a color string\r
+ SVG.Color.test = function(color) {\r
+   color += ''\r
+   return SVG.regex.isHex.test(color)\r
+       || SVG.regex.isRgb.test(color)\r
+ }\r
\r
+ // Test if given value is a rgb object\r
+ SVG.Color.isRgb = function(color) {\r
+   return color && typeof color.r == 'number'\r
+                && typeof color.g == 'number'\r
+                && typeof color.b == 'number'\r
+ }\r
\r
+ // Test if given value is a color\r
+ SVG.Color.isColor = function(color) {\r
+   return SVG.Color.isRgb(color) || SVG.Color.test(color)\r
+ }
+ // Module for array conversion\r
+ SVG.Array = function(array, fallback) {\r
+   array = (array || []).valueOf()\r
\r
+   // if array is empty and fallback is provided, use fallback\r
+   if (array.length == 0 && fallback)\r
+     array = fallback.valueOf()\r
\r
+   // parse array\r
+   this.value = this.parse(array)\r
+ }\r
\r
+ SVG.extend(SVG.Array, {\r
+   // Make array morphable\r
+   morph: function(array) {\r
+     this.destination = this.parse(array)\r
\r
+     // normalize length of arrays\r
+     if (this.value.length != this.destination.length) {\r
+       var lastValue       = this.value[this.value.length - 1]\r
+         , lastDestination = this.destination[this.destination.length - 1]\r
\r
+       while(this.value.length > this.destination.length)\r
+         this.destination.push(lastDestination)\r
+       while(this.value.length < this.destination.length)\r
+         this.value.push(lastValue)\r
+     }\r
\r
+     return this\r
+   }\r
+   // Clean up any duplicate points\r
+ , settle: function() {\r
+     // find all unique values\r
+     for (var i = 0, il = this.value.length, seen = []; i < il; i++)\r
+       if (seen.indexOf(this.value[i]) == -1)\r
+         seen.push(this.value[i])\r
\r
+     // set new value\r
+     return this.value = seen\r
+   }\r
+   // Get morphed array at given position\r
+ , at: function(pos) {\r
+     // make sure a destination is defined\r
+     if (!this.destination) return this\r
\r
+     // generate morphed array\r
+     for (var i = 0, il = this.value.length, array = []; i < il; i++)\r
+       array.push(this.value[i] + (this.destination[i] - this.value[i]) * pos)\r
\r
+     return new SVG.Array(array)\r
+   }\r
+   // Convert array to string\r
+ , toString: function() {\r
+     return this.value.join(' ')\r
+   }\r
+   // Real value\r
+ , valueOf: function() {\r
+     return this.value\r
+   }\r
+   // Parse whitespace separated string\r
+ , parse: function(array) {\r
+     array = array.valueOf()\r
\r
+     // if already is an array, no need to parse it\r
+     if (Array.isArray(array)) return array\r
\r
 -    return this.split(array)\r
 -  }\r
 -  // Strip unnecessary whitespace\r
 -, split: function(string) {\r
 -    return string.trim().split(SVG.regex.delimiter).map(parseFloat)\r
++    return array.trim().split(SVG.regex.delimiter).map(parseFloat)\r
+   }\r
+   // Reverse array\r
+ , reverse: function() {\r
+     this.value.reverse()\r
\r
+     return this\r
+   }\r
+ , clone: function() {\r
+     var clone = new this.constructor()\r
+     clone.value = array_clone(this.value)\r
+     return clone\r
+   }\r
  })
- SVG.Nested = SVG.invent({
-   // Initialize node
-   create: function() {
-     this.constructor.call(this, SVG.create('svg'))
-     this.style('overflow', 'visible')
-   }
-   // Inherit from
- , inherit: SVG.Container
-   // Add parent method
- , construct: {
-     // Create nested svg document
-     nested: function() {
-       return this.put(new SVG.Nested)
-     }
-   }
+ // Poly points array\r
+ SVG.PointArray = function(array, fallback) {\r
+   SVG.Array.call(this, array, fallback || [[0,0]])\r
+ }\r
\r
+ // Inherit from SVG.Array\r
+ SVG.PointArray.prototype = new SVG.Array\r
+ SVG.PointArray.prototype.constructor = SVG.PointArray\r
\r
+ SVG.extend(SVG.PointArray, {\r
+   // Convert array to string\r
+   toString: function() {\r
+     // convert to a poly point string\r
+     for (var i = 0, il = this.value.length, array = []; i < il; i++)\r
+       array.push(this.value[i].join(','))\r
\r
+     return array.join(' ')\r
+   }\r
+   // Convert array to line object\r
+ , toLine: function() {\r
+     return {\r
+       x1: this.value[0][0]\r
+     , y1: this.value[0][1]\r
+     , x2: this.value[1][0]\r
+     , y2: this.value[1][1]\r
+     }\r
+   }\r
+   // Get morphed array at given position\r
+ , at: function(pos) {\r
+     // make sure a destination is defined\r
+     if (!this.destination) return this\r
\r
+     // generate morphed point string\r
+     for (var i = 0, il = this.value.length, array = []; i < il; i++)\r
+       array.push([\r
+         this.value[i][0] + (this.destination[i][0] - this.value[i][0]) * pos\r
+       , this.value[i][1] + (this.destination[i][1] - this.value[i][1]) * pos\r
+       ])\r
\r
+     return new SVG.PointArray(array)\r
+   }\r
+   // Parse point string and flat array\r
+ , parse: function(array) {\r
+     var points = []\r
\r
+     array = array.valueOf()\r
\r
+     // if it is an array\r
+     if (Array.isArray(array)) {\r
+       // and it is not flat, there is no need to parse it\r
+       if(Array.isArray(array[0])) {\r
+         return array\r
+       }\r
+     } else { // Else, it is considered as a string\r
+       // parse points\r
+       array = array.trim().split(SVG.regex.delimiter).map(parseFloat)\r
+     }\r
\r
+     // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints\r
+     // Odd number of coordinates is an error. In such cases, drop the last odd coordinate.\r
+     if (array.length % 2 !== 0) array.pop()\r
\r
+     // wrap points in two-tuples and parse points as floats\r
+     for(var i = 0, len = array.length; i < len; i = i + 2)\r
+       points.push([ array[i], array[i+1] ])\r
\r
+     return points\r
+   }\r
+   // Move point string\r
+ , move: function(x, y) {\r
+     var box = this.bbox()\r
\r
+     // get relative offset\r
+     x -= box.x\r
+     y -= box.y\r
\r
+     // move every point\r
+     if (!isNaN(x) && !isNaN(y))\r
+       for (var i = this.value.length - 1; i >= 0; i--)\r
+         this.value[i] = [this.value[i][0] + x, this.value[i][1] + y]\r
\r
+     return this\r
+   }\r
+   // Resize poly string\r
+ , size: function(width, height) {\r
+     var i, box = this.bbox()\r
\r
+     // recalculate position of all points according to new size\r
+     for (i = this.value.length - 1; i >= 0; i--) {\r
+       if(box.width) this.value[i][0] = ((this.value[i][0] - box.x) * width)  / box.width  + box.x\r
+       if(box.height) this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y\r
+     }\r
\r
+     return this\r
+   }\r
+   // Get bounding box of points\r
+ , bbox: function() {\r
+     SVG.parser.poly.setAttribute('points', this.toString())\r
\r
+     return SVG.parser.poly.getBBox()\r
+   }\r
+ })\r
+ var pathHandlers = {\r
+   M: function(c, p, p0) {\r
+     p.x = p0.x = c[0]\r
+     p.y = p0.y = c[1]\r
\r
+     return ['M', p.x, p.y]\r
+   },\r
+   L: function(c, p) {\r
+     p.x = c[0]\r
+     p.y = c[1]\r
+     return ['L', c[0], c[1]]\r
+   },\r
+   H: function(c, p) {\r
+     p.x = c[0]\r
+     return ['H', c[0]]\r
+   },\r
+   V: function(c, p) {\r
+     p.y = c[0]\r
+     return ['V', c[0]]\r
+   },\r
+   C: function(c, p) {\r
+     p.x = c[4]\r
+     p.y = c[5]\r
+     return ['C', c[0], c[1], c[2], c[3], c[4], c[5]]\r
+   },\r
+   S: function(c, p) {\r
+     p.x = c[2]\r
+     p.y = c[3]\r
+     return ['S', c[0], c[1], c[2], c[3]]\r
+   },\r
+   Q: function(c, p) {\r
+     p.x = c[2]\r
+     p.y = c[3]\r
+     return ['Q', c[0], c[1], c[2], c[3]]\r
+   },\r
+   T: function(c, p) {\r
+     p.x = c[0]\r
+     p.y = c[1]\r
+     return ['T', c[0], c[1]]\r
+   },\r
+   Z: function(c, p, p0) {\r
+     p.x = p0.x\r
+     p.y = p0.y\r
+     return ['Z']\r
+   },\r
+   A: function(c, p) {\r
+     p.x = c[5]\r
+     p.y = c[6]\r
+     return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]]\r
+   }\r
+ }\r
\r
+ var mlhvqtcsa = 'mlhvqtcsaz'.split('')\r
\r
+ for(var i = 0, il = mlhvqtcsa.length; i < il; ++i){\r
+   pathHandlers[mlhvqtcsa[i]] = (function(i){\r
+     return function(c, p, p0) {\r
+       if(i == 'H') c[0] = c[0] + p.x\r
+       else if(i == 'V') c[0] = c[0] + p.y\r
+       else if(i == 'A'){\r
+         c[5] = c[5] + p.x,\r
+         c[6] = c[6] + p.y\r
+       }\r
+       else\r
+         for(var j = 0, jl = c.length; j < jl; ++j) {\r
+           c[j] = c[j] + (j%2 ? p.y : p.x)\r
+         }\r
\r
+       return pathHandlers[i](c, p, p0)\r
+     }\r
+   })(mlhvqtcsa[i].toUpperCase())\r
+ }\r
\r
+ // Path points array\r
+ SVG.PathArray = function(array, fallback) {\r
+   SVG.Array.call(this, array, fallback || [['M', 0, 0]])\r
+ }\r
\r
+ // Inherit from SVG.Array\r
+ SVG.PathArray.prototype = new SVG.Array\r
+ SVG.PathArray.prototype.constructor = SVG.PathArray\r
\r
+ SVG.extend(SVG.PathArray, {\r
+   // Convert array to string\r
+   toString: function() {\r
+     return arrayToString(this.value)\r
+   }\r
+   // Move path string\r
+ , move: function(x, y) {\r
+     // get bounding box of current situation\r
+     var box = this.bbox()\r
\r
+     // get relative offset\r
+     x -= box.x\r
+     y -= box.y\r
\r
+     if (!isNaN(x) && !isNaN(y)) {\r
+       // move every point\r
+       for (var l, i = this.value.length - 1; i >= 0; i--) {\r
+         l = this.value[i][0]\r
\r
+         if (l == 'M' || l == 'L' || l == 'T')  {\r
+           this.value[i][1] += x\r
+           this.value[i][2] += y\r
\r
+         } else if (l == 'H')  {\r
+           this.value[i][1] += x\r
\r
+         } else if (l == 'V')  {\r
+           this.value[i][1] += y\r
\r
+         } else if (l == 'C' || l == 'S' || l == 'Q')  {\r
+           this.value[i][1] += x\r
+           this.value[i][2] += y\r
+           this.value[i][3] += x\r
+           this.value[i][4] += y\r
\r
+           if (l == 'C')  {\r
+             this.value[i][5] += x\r
+             this.value[i][6] += y\r
+           }\r
\r
+         } else if (l == 'A')  {\r
+           this.value[i][6] += x\r
+           this.value[i][7] += y\r
+         }\r
\r
+       }\r
+     }\r
\r
+     return this\r
+   }\r
+   // Resize path string\r
+ , size: function(width, height) {\r
+     // get bounding box of current situation\r
+     var i, l, box = this.bbox()\r
\r
+     // recalculate position of all points according to new size\r
+     for (i = this.value.length - 1; i >= 0; i--) {\r
+       l = this.value[i][0]\r
\r
+       if (l == 'M' || l == 'L' || l == 'T')  {\r
+         this.value[i][1] = ((this.value[i][1] - box.x) * width)  / box.width  + box.x\r
+         this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y\r
\r
+       } else if (l == 'H')  {\r
+         this.value[i][1] = ((this.value[i][1] - box.x) * width)  / box.width  + box.x\r
\r
+       } else if (l == 'V')  {\r
+         this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y\r
\r
+       } else if (l == 'C' || l == 'S' || l == 'Q')  {\r
+         this.value[i][1] = ((this.value[i][1] - box.x) * width)  / box.width  + box.x\r
+         this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y\r
+         this.value[i][3] = ((this.value[i][3] - box.x) * width)  / box.width  + box.x\r
+         this.value[i][4] = ((this.value[i][4] - box.y) * height) / box.height + box.y\r
\r
+         if (l == 'C')  {\r
+           this.value[i][5] = ((this.value[i][5] - box.x) * width)  / box.width  + box.x\r
+           this.value[i][6] = ((this.value[i][6] - box.y) * height) / box.height + box.y\r
+         }\r
\r
+       } else if (l == 'A')  {\r
+         // resize radii\r
+         this.value[i][1] = (this.value[i][1] * width)  / box.width\r
+         this.value[i][2] = (this.value[i][2] * height) / box.height\r
\r
+         // move position values\r
+         this.value[i][6] = ((this.value[i][6] - box.x) * width)  / box.width  + box.x\r
+         this.value[i][7] = ((this.value[i][7] - box.y) * height) / box.height + box.y\r
+       }\r
\r
+     }\r
\r
+     return this\r
+   }\r
+   // Test if the passed path array use the same path data commands as this path array\r
+ , equalCommands: function(pathArray) {\r
+     var i, il, equalCommands\r
\r
+     pathArray = new SVG.PathArray(pathArray)\r
\r
+     equalCommands = this.value.length === pathArray.value.length\r
+     for(i = 0, il = this.value.length; equalCommands && i < il; i++) {\r
+       equalCommands = this.value[i][0] === pathArray.value[i][0]\r
+     }\r
\r
+     return equalCommands\r
+   }\r
+   // Make path array morphable\r
+ , morph: function(pathArray) {\r
+     pathArray = new SVG.PathArray(pathArray)\r
\r
+     if(this.equalCommands(pathArray)) {\r
+       this.destination = pathArray\r
+     } else {\r
+       this.destination = null\r
+     }\r
\r
+     return this\r
+   }\r
+   // Get morphed path array at given position\r
+ , at: function(pos) {\r
+     // make sure a destination is defined\r
+     if (!this.destination) return this\r
\r
+     var sourceArray = this.value\r
+       , destinationArray = this.destination.value\r
+       , array = [], pathArray = new SVG.PathArray()\r
+       , i, il, j, jl\r
\r
+     // Animate has specified in the SVG spec\r
+     // See: https://www.w3.org/TR/SVG11/paths.html#PathElement\r
+     for (i = 0, il = sourceArray.length; i < il; i++) {\r
+       array[i] = [sourceArray[i][0]]\r
+       for(j = 1, jl = sourceArray[i].length; j < jl; j++) {\r
+         array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos\r
+       }\r
+       // For the two flags of the elliptical arc command, the SVG spec say:\r
+       // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true\r
+       // Elliptical arc command as an array followed by corresponding indexes:\r
+       // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y]\r
+       //   0    1   2        3                 4             5      6  7\r
+       if(array[i][0] === 'A') {\r
+         array[i][4] = +(array[i][4] != 0)\r
+         array[i][5] = +(array[i][5] != 0)\r
+       }\r
+     }\r
\r
+     // Directly modify the value of a path array, this is done this way for performance\r
+     pathArray.value = array\r
+     return pathArray\r
+   }\r
+   // Absolutize and parse path to array\r
+ , parse: function(array) {\r
+     // if it's already a patharray, no need to parse it\r
+     if (array instanceof SVG.PathArray) return array.valueOf()\r
\r
+     // prepare for parsing\r
+     var i, x0, y0, s, seg, arr\r
+       , x = 0\r
+       , y = 0\r
+       , paramCnt = { 'M':2, 'L':2, 'H':1, 'V':1, 'C':6, 'S':4, 'Q':4, 'T':2, 'A':7 }\r
\r
+     if(typeof array == 'string'){\r
\r
+       array = array\r
+         .replace(SVG.regex.numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123\r
+         .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers\r
+         .replace(SVG.regex.hyphen, '$1 -')      // add space before hyphen\r
+         .trim()                                 // trim\r
+         .split(SVG.regex.delimiter)   // split into array\r
\r
+     }else{\r
+       array = array.reduce(function(prev, curr){\r
+         return [].concat.call(prev, curr)\r
+       }, [])\r
+     }\r
\r
+     // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...]\r
+     var arr = []\r
+       , p = new SVG.Point()\r
+       , p0 = new SVG.Point()\r
+       , index = 0\r
+       , len = array.length\r
\r
+     do{\r
+       // Test if we have a path letter\r
+       if(SVG.regex.isPathLetter.test(array[index])){\r
+         s = array[index]\r
+         ++index\r
+       // If last letter was a move command and we got no new, it defaults to [L]ine\r
+       }else if(s == 'M'){\r
+         s = 'L'\r
+       }else if(s == 'm'){\r
+         s = 'l'\r
+       }\r
\r
+       arr.push(pathHandlers[s].call(null,\r
+           array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat),\r
+           p, p0\r
+         )\r
+       )\r
\r
+     }while(len > index)\r
\r
+     return arr\r
\r
+   }\r
+   // Get bounding box of path\r
+ , bbox: function() {\r
+     SVG.parser.path.setAttribute('d', this.toString())\r
\r
+     return SVG.parser.path.getBBox()\r
+   }\r
\r
+ })\r
+ // Module for unit convertions\r
+ SVG.Number = SVG.invent({\r
+   // Initialize\r
+   create: function(value, unit) {\r
+     // initialize defaults\r
+     this.value = 0\r
+     this.unit  = unit || ''\r
\r
+     // parse value\r
+     if (typeof value === 'number') {\r
+       // ensure a valid numeric value\r
+       this.value = isNaN(value) ? 0 : !isFinite(value) ? (value < 0 ? -3.4e+38 : +3.4e+38) : value\r
\r
+     } else if (typeof value === 'string') {\r
+       unit = value.match(SVG.regex.numberAndUnit)\r
\r
+       if (unit) {\r
+         // make value numeric\r
+         this.value = parseFloat(unit[1])\r
\r
+         // normalize\r
+         if (unit[5] == '%')\r
+           this.value /= 100\r
+         else if (unit[5] == 's')\r
+           this.value *= 1000\r
\r
+         // store unit\r
+         this.unit = unit[5]\r
+       }\r
\r
+     } else {\r
+       if (value instanceof SVG.Number) {\r
+         this.value = value.valueOf()\r
+         this.unit  = value.unit\r
+       }\r
+     }\r
\r
+   }\r
+   // Add methods\r
+ , extend: {\r
+     // Stringalize\r
+     toString: function() {\r
+       return (\r
+         this.unit == '%' ?\r
+           ~~(this.value * 1e8) / 1e6:\r
+         this.unit == 's' ?\r
+           this.value / 1e3 :\r
+           this.value\r
+       ) + this.unit\r
+     }\r
+   , toJSON: function() {\r
+       return this.toString()\r
+     }\r
+   , // Convert to primitive\r
+     valueOf: function() {\r
+       return this.value\r
+     }\r
+     // Add number\r
+   , plus: function(number) {\r
+       number = new SVG.Number(number)\r
+       return new SVG.Number(this + number, this.unit || number.unit)\r
+     }\r
+     // Subtract number\r
+   , minus: function(number) {\r
+       number = new SVG.Number(number)\r
+       return new SVG.Number(this - number, this.unit || number.unit)\r
+     }\r
+     // Multiply number\r
+   , times: function(number) {\r
+       number = new SVG.Number(number)\r
+       return new SVG.Number(this * number, this.unit || number.unit)\r
+     }\r
+     // Divide number\r
+   , divide: function(number) {\r
+       number = new SVG.Number(number)\r
+       return new SVG.Number(this / number, this.unit || number.unit)\r
+     }\r
+     // Convert to different unit\r
+   , to: function(unit) {\r
+       var number = new SVG.Number(this)\r
\r
+       if (typeof unit === 'string')\r
+         number.unit = unit\r
\r
+       return number\r
+     }\r
+     // Make number morphable\r
+   , morph: function(number) {\r
+       this.destination = new SVG.Number(number)\r
\r
+       if(number.relative) {\r
+         this.destination.value += this.value\r
+       }\r
\r
+       return this\r
+     }\r
+     // Get morphed number at given position\r
+   , at: function(pos) {\r
+       // Make sure a destination is defined\r
+       if (!this.destination) return this\r
\r
+       // Generate new morphed number\r
+       return new SVG.Number(this.destination)\r
+           .minus(this)\r
+           .times(pos)\r
+           .plus(this)\r
+     }\r
\r
+   }\r
+ })\r
\r
+ SVG.Element = SVG.invent({\r
+   // Initialize node\r
+   create: function(node) {\r
 -    // make stroke value accessible dynamically\r
 -    this._stroke = SVG.defaults.attrs.stroke\r
++    // last fired event on node\r
+     this._event = null\r
\r
+     // initialize data object\r
+     this.dom = {}\r
\r
+     // create circular reference\r
+     if (this.node = node) {\r
+       this.type = node.nodeName\r
+       this.node.instance = this\r
 -\r
 -      // store current attribute value\r
 -      this._stroke = node.getAttribute('stroke') || this._stroke\r
+     }\r
+   }\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Move over x-axis\r
+     x: function(x) {\r
+       return this.attr('x', x)\r
+     }\r
+     // Move over y-axis\r
+   , y: function(y) {\r
+       return this.attr('y', y)\r
+     }\r
+     // Move by center over x-axis\r
+   , cx: function(x) {\r
+       return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2)\r
+     }\r
+     // Move by center over y-axis\r
+   , cy: function(y) {\r
+       return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2)\r
+     }\r
+     // Move element to given x and y values\r
+   , move: function(x, y) {\r
+       return this.x(x).y(y)\r
+     }\r
+     // Move element by its center\r
+   , center: function(x, y) {\r
+       return this.cx(x).cy(y)\r
+     }\r
+     // Set width of element\r
+   , width: function(width) {\r
+       return this.attr('width', width)\r
+     }\r
+     // Set height of element\r
+   , height: function(height) {\r
+       return this.attr('height', height)\r
+     }\r
+     // Set element size to given width and height\r
+   , size: function(width, height) {\r
+       var p = proportionalSize(this, width, height)\r
\r
+       return this\r
+         .width(new SVG.Number(p.width))\r
+         .height(new SVG.Number(p.height))\r
+     }\r
+     // Clone element\r
+   , clone: function(parent, withData) {\r
+       // write dom data to the dom so the clone can pickup the data\r
+       this.writeDataToDom()\r
\r
+       // clone element and assign new id\r
+       var clone = assignNewId(this.node.cloneNode(true))\r
\r
+       // insert the clone in the given parent or after myself\r
+       if(parent) parent.add(clone)\r
+       else this.after(clone)\r
\r
+       return clone\r
+     }\r
+     // Remove element\r
+   , remove: function() {\r
+       if (this.parent())\r
+         this.parent().removeElement(this)\r
\r
+       return this\r
+     }\r
+     // Replace element\r
+   , replace: function(element) {\r
+       this.after(element).remove()\r
\r
+       return element\r
+     }\r
+     // Add element to given container and return self\r
+   , addTo: function(parent) {\r
+       return parent.put(this)\r
+     }\r
+     // Add element to given container and return container\r
+   , putIn: function(parent) {\r
+       return parent.add(this)\r
+     }\r
+     // Get / set id\r
+   , id: function(id) {\r
+       return this.attr('id', id)\r
+     }\r
+     // Checks whether the given point inside the bounding box of the element\r
+   , inside: function(x, y) {\r
+       var box = this.bbox()\r
\r
+       return x > box.x\r
+           && y > box.y\r
+           && x < box.x + box.width\r
+           && y < box.y + box.height\r
+     }\r
+     // Show element\r
+   , show: function() {\r
+       return this.style('display', '')\r
+     }\r
+     // Hide element\r
+   , hide: function() {\r
+       return this.style('display', 'none')\r
+     }\r
+     // Is element visible?\r
+   , visible: function() {\r
+       return this.style('display') != 'none'\r
+     }\r
+     // Return id on string conversion\r
+   , toString: function() {\r
+       return this.attr('id')\r
+     }\r
+     // Return array of classes on the node\r
+   , classes: function() {\r
+       var attr = this.attr('class')\r
\r
+       return attr == null ? [] : attr.trim().split(SVG.regex.delimiter)\r
+     }\r
+     // Return true if class exists on the node, false otherwise\r
+   , hasClass: function(name) {\r
+       return this.classes().indexOf(name) != -1\r
+     }\r
+     // Add class to the node\r
+   , addClass: function(name) {\r
+       if (!this.hasClass(name)) {\r
+         var array = this.classes()\r
+         array.push(name)\r
+         this.attr('class', array.join(' '))\r
+       }\r
\r
+       return this\r
+     }\r
+     // Remove class from the node\r
+   , removeClass: function(name) {\r
+       if (this.hasClass(name)) {\r
+         this.attr('class', this.classes().filter(function(c) {\r
+           return c != name\r
+         }).join(' '))\r
+       }\r
\r
+       return this\r
+     }\r
+     // Toggle the presence of a class on the node\r
+   , toggleClass: function(name) {\r
+       return this.hasClass(name) ? this.removeClass(name) : this.addClass(name)\r
+     }\r
+     // Get referenced element form attribute value\r
+   , reference: function(attr) {\r
+       return SVG.get(this.attr(attr))\r
+     }\r
+     // Returns the parent element instance\r
+   , parent: function(type) {\r
+       var parent = this\r
\r
+       // check for parent\r
+       if(!parent.node.parentNode) return null\r
\r
+       // get parent element\r
+       parent = SVG.adopt(parent.node.parentNode)\r
\r
+       if(!type) return parent\r
\r
+       // loop trough ancestors if type is given\r
+       while(parent && parent.node instanceof window.SVGElement){\r
+         if(typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent\r
+         parent = SVG.adopt(parent.node.parentNode)\r
+       }\r
+     }\r
+     // Get parent document\r
+   , doc: function() {\r
+       return this instanceof SVG.Doc ? this : this.parent(SVG.Doc)\r
+     }\r
+     // return array of all ancestors of given type up to the root svg\r
+   , parents: function(type) {\r
+       var parents = [], parent = this\r
\r
+       do{\r
+         parent = parent.parent(type)\r
+         if(!parent || !parent.node) break\r
\r
+         parents.push(parent)\r
+       } while(parent.parent)\r
\r
+       return parents\r
+     }\r
+     // matches the element vs a css selector\r
+   , matches: function(selector){\r
+       return matches(this.node, selector)\r
+     }\r
+     // Returns the svg node to call native svg methods on it\r
+   , native: function() {\r
+       return this.node\r
+     }\r
+     // Import raw svg\r
+   , svg: function(svg) {\r
 -      // create temporary holder\r
 -      var well = document.createElement('svg')\r
++      var well, len\r
\r
+       // act as a setter if svg is given\r
+       if (svg && this instanceof SVG.Parent) {\r
++\r
++        // create temporary holder\r
++        well = document.createElementNS(SVG.ns, 'svg')\r
+         // dump raw svg\r
 -        well.innerHTML = '<svg>' + svg.replace(/\n/, '').replace(/<(\w+)([^<]+?)\/>/g, '<$1$2></$1>') + '</svg>'\r
++        well.innerHTML = svg\r
\r
+         // transplant nodes\r
 -        for (var i = 0, il = well.firstChild.childNodes.length; i < il; i++)\r
 -          this.node.appendChild(well.firstChild.firstChild)\r
++        for (len = well.childNodes.length;len--;)\r
++          if(well.firstChild.nodeType != 1)\r
++            well.removeChild(well.firstChild)\r
++          else\r
++            this.node.appendChild(well.firstChild)\r
\r
+       // otherwise act as a getter\r
+       } else {\r
 -        // create a wrapping svg element in case of partial content\r
 -        well.appendChild(svg = document.createElement('svg'))\r
 -\r
 -        // write svgjs data to the dom\r
 -        this.writeDataToDom()\r
 -\r
 -        // insert a copy of this node\r
 -        svg.appendChild(this.node.cloneNode(true))\r
 -\r
 -        // return target element\r
 -        return well.innerHTML.replace(/^<svg>/, '').replace(/<\/svg>$/, '')\r
++        return this.node.outerHTML\r
+       }\r
\r
+       return this\r
+     }\r
+   // write svgjs data to the dom\r
+   , writeDataToDom: function() {\r
\r
+       // dump variables recursively\r
 -      if(this.each || this.lines){\r
 -        var fn = this.each ? this : this.lines();\r
 -        fn.each(function(){\r
++      if(this.is(SVG.Parent)){\r
++        this.each(function(){\r
+           this.writeDataToDom()\r
+         })\r
+       }\r
\r
+       // remove previously set data\r
+       this.node.removeAttribute('svgjs:data')\r
\r
+       if(Object.keys(this.dom).length)\r
+         this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)) // see #428\r
\r
+       return this\r
+     }\r
+   // set given data to the elements data property\r
+   , setData: function(o){\r
+       this.dom = o\r
+       return this\r
+     }\r
+   , is: function(obj){\r
+       return is(this, obj)\r
+     }\r
+   }\r
+ })\r
+ SVG.easing = {\r
+   '-': function(pos){return pos}\r
+ , '<>':function(pos){return -Math.cos(pos * Math.PI) / 2 + 0.5}\r
+ , '>': function(pos){return  Math.sin(pos * Math.PI / 2)}\r
+ , '<': function(pos){return -Math.cos(pos * Math.PI / 2) + 1}\r
+ }\r
\r
+ SVG.morph = function(pos){\r
+   return function(from, to) {\r
+     return new SVG.MorphObj(from, to).at(pos)\r
+   }\r
+ }\r
\r
+ SVG.Situation = SVG.invent({\r
\r
+   create: function(o){\r
+     this.init = false\r
+     this.reversed = false\r
+     this.reversing = false\r
\r
+     this.duration = new SVG.Number(o.duration).valueOf()\r
+     this.delay = new SVG.Number(o.delay).valueOf()\r
\r
+     this.start = +new Date() + this.delay\r
+     this.finish = this.start + this.duration\r
+     this.ease = o.ease\r
\r
+     // this.loop is incremented from 0 to this.loops\r
+     // it is also incremented when in an infinite loop (when this.loops is true)\r
+     this.loop = 0\r
+     this.loops = false\r
\r
+     this.animations = {\r
+       // functionToCall: [list of morphable objects]\r
+       // e.g. move: [SVG.Number, SVG.Number]\r
+     }\r
\r
+     this.attrs = {\r
+       // holds all attributes which are not represented from a function svg.js provides\r
+       // e.g. someAttr: SVG.Number\r
+     }\r
\r
+     this.styles = {\r
+       // holds all styles which should be animated\r
+       // e.g. fill-color: SVG.Color\r
+     }\r
\r
+     this.transforms = [\r
+       // holds all transformations as transformation objects\r
+       // e.g. [SVG.Rotate, SVG.Translate, SVG.Matrix]\r
+     ]\r
\r
+     this.once = {\r
+       // functions to fire at a specific position\r
+       // e.g. "0.5": function foo(){}\r
+     }\r
\r
+   }\r
\r
+ })\r
\r
\r
+ SVG.FX = SVG.invent({\r
\r
+   create: function(element) {\r
+     this._target = element\r
+     this.situations = []\r
+     this.active = false\r
+     this.situation = null\r
+     this.paused = false\r
+     this.lastPos = 0\r
+     this.pos = 0\r
+     // The absolute position of an animation is its position in the context of its complete duration (including delay and loops)\r
+     // When performing a delay, absPos is below 0 and when performing a loop, its value is above 1\r
+     this.absPos = 0\r
+     this._speed = 1\r
+   }\r
\r
+ , extend: {\r
\r
+     /**\r
+      * sets or returns the target of this animation\r
+      * @param o object || number In case of Object it holds all parameters. In case of number its the duration of the animation\r
+      * @param ease function || string Function which should be used for easing or easing keyword\r
+      * @param delay Number indicating the delay before the animation starts\r
+      * @return target || this\r
+      */\r
+     animate: function(o, ease, delay){\r
\r
+       if(typeof o == 'object'){\r
+         ease = o.ease\r
+         delay = o.delay\r
+         o = o.duration\r
+       }\r
\r
+       var situation = new SVG.Situation({\r
+         duration: o || 1000,\r
+         delay: delay || 0,\r
+         ease: SVG.easing[ease || '-'] || ease\r
+       })\r
\r
+       this.queue(situation)\r
\r
+       return this\r
+     }\r
\r
+     /**\r
+      * sets a delay before the next element of the queue is called\r
+      * @param delay Duration of delay in milliseconds\r
+      * @return this.target()\r
+      */\r
+   , delay: function(delay){\r
+       // The delay is performed by an empty situation with its duration\r
+       // attribute set to the duration of the delay\r
+       var situation = new SVG.Situation({\r
+         duration: delay,\r
+         delay: 0,\r
+         ease: SVG.easing['-']\r
+       })\r
\r
+       return this.queue(situation)\r
+     }\r
\r
+     /**\r
+      * sets or returns the target of this animation\r
+      * @param null || target SVG.Element which should be set as new target\r
+      * @return target || this\r
+      */\r
+   , target: function(target){\r
+       if(target && target instanceof SVG.Element){\r
+         this._target = target\r
+         return this\r
+       }\r
\r
+       return this._target\r
+     }\r
\r
+     // returns the absolute position at a given time\r
+   , timeToAbsPos: function(timestamp){\r
+       return (timestamp - this.situation.start) / (this.situation.duration/this._speed)\r
+     }\r
\r
+     // returns the timestamp from a given absolute positon\r
+   , absPosToTime: function(absPos){\r
+       return this.situation.duration/this._speed * absPos + this.situation.start\r
+     }\r
\r
+     // starts the animationloop\r
+   , startAnimFrame: function(){\r
+       this.stopAnimFrame()\r
+       this.animationFrame = window.requestAnimationFrame(function(){ this.step() }.bind(this))\r
+     }\r
\r
+     // cancels the animationframe\r
+   , stopAnimFrame: function(){\r
+       window.cancelAnimationFrame(this.animationFrame)\r
+     }\r
\r
+     // kicks off the animation - only does something when the queue is currently not active and at least one situation is set\r
+   , start: function(){\r
+       // dont start if already started\r
+       if(!this.active && this.situation){\r
+         this.active = true\r
+         this.startCurrent()\r
+       }\r
\r
+       return this\r
+     }\r
\r
+     // start the current situation\r
+   , startCurrent: function(){\r
+       this.situation.start = +new Date + this.situation.delay/this._speed\r
+       this.situation.finish = this.situation.start + this.situation.duration/this._speed\r
+       return this.initAnimations().step()\r
+     }\r
\r
+     /**\r
+      * adds a function / Situation to the animation queue\r
+      * @param fn function / situation to add\r
+      * @return this\r
+      */\r
+   , queue: function(fn){\r
+       if(typeof fn == 'function' || fn instanceof SVG.Situation)\r
+         this.situations.push(fn)\r
\r
+       if(!this.situation) this.situation = this.situations.shift()\r
\r
+       return this\r
+     }\r
\r
+     /**\r
+      * pulls next element from the queue and execute it\r
+      * @return this\r
+      */\r
+   , dequeue: function(){\r
+       // stop current animation\r
+       this.stop()\r
\r
+       // get next animation from queue\r
+       this.situation = this.situations.shift()\r
\r
+       if(this.situation){\r
+         if(this.situation instanceof SVG.Situation) {\r
+           this.start()\r
+         } else {\r
+           // If it is not a SVG.Situation, then it is a function, we execute it\r
+           this.situation.call(this)\r
+         }\r
+       }\r
\r
+       return this\r
+     }\r
\r
+     // updates all animations to the current state of the element\r
+     // this is important when one property could be changed from another property\r
+   , initAnimations: function() {\r
+       var i, source\r
+       var s = this.situation\r
\r
+       if(s.init) return this\r
\r
+       for(i in s.animations){\r
+         source = this.target()[i]()\r
\r
+         // The condition is because some methods return a normal number instead\r
+         // of a SVG.Number\r
+         if(s.animations[i] instanceof SVG.Number)\r
+           source = new SVG.Number(source)\r
\r
+         s.animations[i] = source.morph(s.animations[i])\r
+       }\r
\r
+       for(i in s.attrs){\r
+         s.attrs[i] = new SVG.MorphObj(this.target().attr(i), s.attrs[i])\r
+       }\r
\r
+       for(i in s.styles){\r
+         s.styles[i] = new SVG.MorphObj(this.target().style(i), s.styles[i])\r
+       }\r
\r
+       s.initialTransformation = this.target().matrixify()\r
\r
+       s.init = true\r
+       return this\r
+     }\r
+   , clearQueue: function(){\r
+       this.situations = []\r
+       return this\r
+     }\r
+   , clearCurrent: function(){\r
+       this.situation = null\r
+       return this\r
+     }\r
+     /** stops the animation immediately\r
+      * @param jumpToEnd A Boolean indicating whether to complete the current animation immediately.\r
+      * @param clearQueue A Boolean indicating whether to remove queued animation as well.\r
+      * @return this\r
+      */\r
+   , stop: function(jumpToEnd, clearQueue){\r
+       var active = this.active\r
+       this.active = false\r
\r
+       if(clearQueue){\r
+         this.clearQueue()\r
+       }\r
\r
+       if(jumpToEnd && this.situation){\r
+         // initialize the situation if it was not\r
+         !active && this.startCurrent()\r
+         this.atEnd()\r
+       }\r
\r
+       this.stopAnimFrame()\r
\r
+       return this.clearCurrent()\r
+     }\r
\r
+     /** resets the element to the state where the current element has started\r
+      * @return this\r
+      */\r
+   , reset: function(){\r
+       if(this.situation){\r
+         var temp = this.situation\r
+         this.stop()\r
+         this.situation = temp\r
+         this.atStart()\r
+       }\r
+       return this\r
+     }\r
\r
+     // Stop the currently-running animation, remove all queued animations, and complete all animations for the element.\r
+   , finish: function(){\r
\r
+       this.stop(true, false)\r
\r
+       while(this.dequeue().situation && this.stop(true, false));\r
\r
+       this.clearQueue().clearCurrent()\r
\r
+       return this\r
+     }\r
\r
+     // set the internal animation pointer at the start position, before any loops, and updates the visualisation\r
+   , atStart: function() {\r
+       return this.at(0, true)\r
+     }\r
\r
+     // set the internal animation pointer at the end position, after all the loops, and updates the visualisation\r
+   , atEnd: function() {\r
+       if (this.situation.loops === true) {\r
+         // If in a infinite loop, we end the current iteration\r
+         this.situation.loops = this.situation.loop + 1\r
+       }\r
\r
+       if(typeof this.situation.loops == 'number') {\r
+         // If performing a finite number of loops, we go after all the loops\r
+         return this.at(this.situation.loops, true)\r
+       } else {\r
+         // If no loops, we just go at the end\r
+         return this.at(1, true)\r
+       }\r
+     }\r
\r
+     // set the internal animation pointer to the specified position and updates the visualisation\r
+     // if isAbsPos is true, pos is treated as an absolute position\r
+   , at: function(pos, isAbsPos){\r
+       var durDivSpd = this.situation.duration/this._speed\r
\r
+       this.absPos = pos\r
+       // If pos is not an absolute position, we convert it into one\r
+       if (!isAbsPos) {\r
+         if (this.situation.reversed) this.absPos = 1 - this.absPos\r
+         this.absPos += this.situation.loop\r
+       }\r
\r
+       this.situation.start = +new Date - this.absPos * durDivSpd\r
+       this.situation.finish = this.situation.start + durDivSpd\r
\r
+       return this.step(true)\r
+     }\r
\r
+     /**\r
+      * sets or returns the speed of the animations\r
+      * @param speed null || Number The new speed of the animations\r
+      * @return Number || this\r
+      */\r
+   , speed: function(speed){\r
+       if (speed === 0) return this.pause()\r
\r
+       if (speed) {\r
+         this._speed = speed\r
+         // We use an absolute position here so that speed can affect the delay before the animation\r
+         return this.at(this.absPos, true)\r
+       } else return this._speed\r
+     }\r
\r
+     // Make loopable\r
+   , loop: function(times, reverse) {\r
+       var c = this.last()\r
\r
+       // store total loops\r
+       c.loops = (times != null) ? times : true\r
+       c.loop = 0\r
\r
+       if(reverse) c.reversing = true\r
+       return this\r
+     }\r
\r
+     // pauses the animation\r
+   , pause: function(){\r
+       this.paused = true\r
+       this.stopAnimFrame()\r
\r
+       return this\r
+     }\r
\r
+     // unpause the animation\r
+   , play: function(){\r
+       if(!this.paused) return this\r
+       this.paused = false\r
+       // We use an absolute position here so that the delay before the animation can be paused\r
+       return this.at(this.absPos, true)\r
+     }\r
\r
+     /**\r
+      * toggle or set the direction of the animation\r
+      * true sets direction to backwards while false sets it to forwards\r
+      * @param reversed Boolean indicating whether to reverse the animation or not (default: toggle the reverse status)\r
+      * @return this\r
+      */\r
+   , reverse: function(reversed){\r
+       var c = this.last()\r
\r
+       if(typeof reversed == 'undefined') c.reversed = !c.reversed\r
+       else c.reversed = reversed\r
\r
+       return this\r
+     }\r
\r
\r
+     /**\r
+      * returns a float from 0-1 indicating the progress of the current animation\r
+      * @param eased Boolean indicating whether the returned position should be eased or not\r
+      * @return number\r
+      */\r
+   , progress: function(easeIt){\r
+       return easeIt ? this.situation.ease(this.pos) : this.pos\r
+     }\r
\r
+     /**\r
+      * adds a callback function which is called when the current animation is finished\r
+      * @param fn Function which should be executed as callback\r
+      * @return number\r
+      */\r
+   , after: function(fn){\r
+       var c = this.last()\r
+         , wrapper = function wrapper(e){\r
+             if(e.detail.situation == c){\r
+               fn.call(this, c)\r
+               this.off('finished.fx', wrapper) // prevent memory leak\r
+             }\r
+           }\r
\r
+       this.target().on('finished.fx', wrapper)\r
\r
+       return this._callStart()\r
+     }\r
\r
+     // adds a callback which is called whenever one animation step is performed\r
+   , during: function(fn){\r
+       var c = this.last()\r
+         , wrapper = function(e){\r
+             if(e.detail.situation == c){\r
+               fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, c)\r
+             }\r
+           }\r
\r
+       // see above\r
+       this.target().off('during.fx', wrapper).on('during.fx', wrapper)\r
\r
+       this.after(function(){\r
+         this.off('during.fx', wrapper)\r
+       })\r
\r
+       return this._callStart()\r
+     }\r
\r
+     // calls after ALL animations in the queue are finished\r
+   , afterAll: function(fn){\r
+       var wrapper = function wrapper(e){\r
+             fn.call(this)\r
+             this.off('allfinished.fx', wrapper)\r
+           }\r
\r
+       // see above\r
+       this.target().off('allfinished.fx', wrapper).on('allfinished.fx', wrapper)\r
\r
+       return this._callStart()\r
+     }\r
\r
+     // calls on every animation step for all animations\r
+   , duringAll: function(fn){\r
+       var wrapper = function(e){\r
+             fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, e.detail.situation)\r
+           }\r
\r
+       this.target().off('during.fx', wrapper).on('during.fx', wrapper)\r
\r
+       this.afterAll(function(){\r
+         this.off('during.fx', wrapper)\r
+       })\r
\r
+       return this._callStart()\r
+     }\r
\r
+   , last: function(){\r
+       return this.situations.length ? this.situations[this.situations.length-1] : this.situation\r
+     }\r
\r
+     // adds one property to the animations\r
+   , add: function(method, args, type){\r
+       this.last()[type || 'animations'][method] = args\r
+       return this._callStart()\r
+     }\r
\r
+     /** perform one step of the animation\r
+      *  @param ignoreTime Boolean indicating whether to ignore time and use position directly or recalculate position based on time\r
+      *  @return this\r
+      */\r
+   , step: function(ignoreTime){\r
\r
+       // convert current time to an absolute position\r
+       if(!ignoreTime) this.absPos = this.timeToAbsPos(+new Date)\r
\r
+       // This part convert an absolute position to a position\r
+       if(this.situation.loops !== false) {\r
+         var absPos, absPosInt, lastLoop\r
\r
+         // If the absolute position is below 0, we just treat it as if it was 0\r
+         absPos = Math.max(this.absPos, 0)\r
+         absPosInt = Math.floor(absPos)\r
\r
+         if(this.situation.loops === true || absPosInt < this.situation.loops) {\r
+           this.pos = absPos - absPosInt\r
+           lastLoop = this.situation.loop\r
+           this.situation.loop = absPosInt\r
+         } else {\r
+           this.absPos = this.situation.loops\r
+           this.pos = 1\r
+           // The -1 here is because we don't want to toggle reversed when all the loops have been completed\r
+           lastLoop = this.situation.loop - 1\r
+           this.situation.loop = this.situation.loops\r
+         }\r
\r
+         if(this.situation.reversing) {\r
+           // Toggle reversed if an odd number of loops as occured since the last call of step\r
+           this.situation.reversed = this.situation.reversed != Boolean((this.situation.loop - lastLoop) % 2)\r
+         }\r
\r
+       } else {\r
+         // If there are no loop, the absolute position must not be above 1\r
+         this.absPos = Math.min(this.absPos, 1)\r
+         this.pos = this.absPos\r
+       }\r
\r
+       // while the absolute position can be below 0, the position must not be below 0\r
+       if(this.pos < 0) this.pos = 0\r
\r
+       if(this.situation.reversed) this.pos = 1 - this.pos\r
\r
\r
+       // apply easing\r
+       var eased = this.situation.ease(this.pos)\r
\r
+       // call once-callbacks\r
+       for(var i in this.situation.once){\r
+         if(i > this.lastPos && i <= eased){\r
+           this.situation.once[i].call(this.target(), this.pos, eased)\r
+           delete this.situation.once[i]\r
+         }\r
+       }\r
\r
+       // fire during callback with position, eased position and current situation as parameter\r
+       if(this.active) this.target().fire('during', {pos: this.pos, eased: eased, fx: this, situation: this.situation})\r
\r
+       // the user may call stop or finish in the during callback\r
+       // so make sure that we still have a valid situation\r
+       if(!this.situation){\r
+         return this\r
+       }\r
\r
+       // apply the actual animation to every property\r
+       this.eachAt()\r
\r
+       // do final code when situation is finished\r
+       if((this.pos == 1 && !this.situation.reversed) || (this.situation.reversed && this.pos == 0)){\r
\r
+         // stop animation callback\r
+         this.stopAnimFrame()\r
\r
+         // fire finished callback with current situation as parameter\r
+         this.target().fire('finished', {fx:this, situation: this.situation})\r
\r
+         if(!this.situations.length){\r
+           this.target().fire('allfinished')\r
+           this.target().off('.fx') // there shouldnt be any binding left, but to make sure...\r
+           this.active = false\r
+         }\r
\r
+         // start next animation\r
+         if(this.active) this.dequeue()\r
+         else this.clearCurrent()\r
\r
+       }else if(!this.paused && this.active){\r
+         // we continue animating when we are not at the end\r
+         this.startAnimFrame()\r
+       }\r
\r
+       // save last eased position for once callback triggering\r
+       this.lastPos = eased\r
+       return this\r
\r
+     }\r
\r
+     // calculates the step for every property and calls block with it\r
+   , eachAt: function(){\r
+       var i, len, at, self = this, target = this.target(), s = this.situation\r
\r
+       // apply animations which can be called trough a method\r
+       for(i in s.animations){\r
\r
+         at = [].concat(s.animations[i]).map(function(el){\r
+           return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el\r
+         })\r
\r
+         target[i].apply(target, at)\r
\r
+       }\r
\r
+       // apply animation which has to be applied with attr()\r
+       for(i in s.attrs){\r
\r
+         at = [i].concat(s.attrs[i]).map(function(el){\r
+           return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el\r
+         })\r
\r
+         target.attr.apply(target, at)\r
\r
+       }\r
\r
+       // apply animation which has to be applied with style()\r
+       for(i in s.styles){\r
\r
+         at = [i].concat(s.styles[i]).map(function(el){\r
+           return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el\r
+         })\r
\r
+         target.style.apply(target, at)\r
\r
+       }\r
\r
+       // animate initialTransformation which has to be chained\r
+       if(s.transforms.length){\r
\r
+         // get initial initialTransformation\r
+         at = s.initialTransformation\r
+         for(i = 0, len = s.transforms.length; i < len; i++){\r
\r
+           // get next transformation in chain\r
+           var a = s.transforms[i]\r
\r
+           // multiply matrix directly\r
+           if(a instanceof SVG.Matrix){\r
\r
+             if(a.relative){\r
+               at = at.multiply(new SVG.Matrix().morph(a).at(s.ease(this.pos)))\r
+             }else{\r
+               at = at.morph(a).at(s.ease(this.pos))\r
+             }\r
+             continue\r
+           }\r
\r
+           // when transformation is absolute we have to reset the needed transformation first\r
+           if(!a.relative)\r
+             a.undo(at.extract())\r
\r
+           // and reapply it after\r
+           at = at.multiply(a.at(s.ease(this.pos)))\r
\r
+         }\r
\r
+         // set new matrix on element\r
+         target.matrix(at)\r
+       }\r
\r
+       return this\r
\r
+     }\r
\r
\r
+     // adds an once-callback which is called at a specific position and never again\r
+   , once: function(pos, fn, isEased){\r
\r
+       if(!isEased)pos = this.situation.ease(pos)\r
\r
+       this.situation.once[pos] = fn\r
\r
+       return this\r
+     }\r
\r
+   , _callStart: function() {\r
+       setTimeout(function(){this.start()}.bind(this), 0)\r
+       return this\r
+     }\r
\r
+   }\r
\r
+ , parent: SVG.Element\r
\r
+   // Add method to parent elements\r
+ , construct: {\r
+     // Get fx module or create a new one, then animate with given duration and ease\r
+     animate: function(o, ease, delay) {\r
+       return (this.fx || (this.fx = new SVG.FX(this))).animate(o, ease, delay)\r
+     }\r
+   , delay: function(delay){\r
+       return (this.fx || (this.fx = new SVG.FX(this))).delay(delay)\r
+     }\r
+   , stop: function(jumpToEnd, clearQueue) {\r
+       if (this.fx)\r
+         this.fx.stop(jumpToEnd, clearQueue)\r
\r
+       return this\r
+     }\r
+   , finish: function() {\r
+       if (this.fx)\r
+         this.fx.finish()\r
\r
+       return this\r
+     }\r
+     // Pause current animation\r
+   , pause: function() {\r
+       if (this.fx)\r
+         this.fx.pause()\r
\r
+       return this\r
+     }\r
+     // Play paused current animation\r
+   , play: function() {\r
+       if (this.fx)\r
+         this.fx.play()\r
\r
+       return this\r
+     }\r
+     // Set/Get the speed of the animations\r
+   , speed: function(speed) {\r
+       if (this.fx)\r
+         if (speed == null)\r
+           return this.fx.speed()\r
+         else\r
+           this.fx.speed(speed)\r
\r
+       return this\r
+     }\r
+   }\r
\r
+ })\r
\r
+ // MorphObj is used whenever no morphable object is given\r
+ SVG.MorphObj = SVG.invent({\r
\r
+   create: function(from, to){\r
+     // prepare color for morphing\r
+     if(SVG.Color.isColor(to)) return new SVG.Color(from).morph(to)\r
+     // prepare number for morphing\r
+     if(SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to)\r
\r
+     // prepare for plain morphing\r
+     this.value = from\r
+     this.destination = to\r
+   }\r
\r
+ , extend: {\r
+     at: function(pos, real){\r
+       return real < 1 ? this.value : this.destination\r
+     },\r
\r
+     valueOf: function(){\r
+       return this.value\r
+     }\r
+   }\r
\r
+ })\r
\r
+ SVG.extend(SVG.FX, {\r
+   // Add animatable attributes\r
+   attr: function(a, v, relative) {\r
+     // apply attributes individually\r
+     if (typeof a == 'object') {\r
+       for (var key in a)\r
+         this.attr(key, a[key])\r
\r
+     } else {\r
+       this.add(a, v, 'attrs')\r
+     }\r
\r
+     return this\r
+   }\r
+   // Add animatable styles\r
+ , style: function(s, v) {\r
+     if (typeof s == 'object')\r
+       for (var key in s)\r
+         this.style(key, s[key])\r
\r
+     else\r
+       this.add(s, v, 'styles')\r
\r
+     return this\r
+   }\r
+   // Animatable x-axis\r
+ , x: function(x, relative) {\r
+     if(this.target() instanceof SVG.G){\r
+       this.transform({x:x}, relative)\r
+       return this\r
+     }\r
\r
+     var num = new SVG.Number(x)\r
+     num.relative = relative\r
+     return this.add('x', num)\r
+   }\r
+   // Animatable y-axis\r
+ , y: function(y, relative) {\r
+     if(this.target() instanceof SVG.G){\r
+       this.transform({y:y}, relative)\r
+       return this\r
+     }\r
\r
+     var num = new SVG.Number(y)\r
+     num.relative = relative\r
+     return this.add('y', num)\r
+   }\r
+   // Animatable center x-axis\r
+ , cx: function(x) {\r
+     return this.add('cx', new SVG.Number(x))\r
+   }\r
+   // Animatable center y-axis\r
+ , cy: function(y) {\r
+     return this.add('cy', new SVG.Number(y))\r
+   }\r
+   // Add animatable move\r
+ , move: function(x, y) {\r
+     return this.x(x).y(y)\r
+   }\r
+   // Add animatable center\r
+ , center: function(x, y) {\r
+     return this.cx(x).cy(y)\r
+   }\r
+   // Add animatable size\r
+ , size: function(width, height) {\r
+     if (this.target() instanceof SVG.Text) {\r
+       // animate font size for Text elements\r
+       this.attr('font-size', width)\r
\r
+     } else {\r
+       // animate bbox based size for all other elements\r
+       var box\r
\r
+       if(!width || !height){\r
+         box = this.target().bbox()\r
+       }\r
\r
+       if(!width){\r
+         width = box.width / box.height  * height\r
+       }\r
\r
+       if(!height){\r
+         height = box.height / box.width  * width\r
+       }\r
\r
+       this.add('width' , new SVG.Number(width))\r
+           .add('height', new SVG.Number(height))\r
\r
+     }\r
\r
+     return this\r
+   }\r
+   // Add animatable plot\r
+ , plot: function() {\r
+     // We use arguments here since SVG.Line's plot method can be passed 4 parameters\r
+     return this.add('plot', arguments.length > 1 ? [].slice.call(arguments) : arguments[0])\r
+   }\r
+   // Add leading method\r
+ , leading: function(value) {\r
+     return this.target().leading ?\r
+       this.add('leading', new SVG.Number(value)) :\r
+       this\r
+   }\r
+   // Add animatable viewbox\r
+ , viewbox: function(x, y, width, height) {\r
+     if (this.target() instanceof SVG.Container) {\r
 -      this.add('viewbox', new SVG.ViewBox(x, y, width, height))\r
++      this.add('viewbox', new SVG.Box(x, y, width, height))\r
+     }\r
\r
+     return this\r
+   }\r
+ , update: function(o) {\r
+     if (this.target() instanceof SVG.Stop) {\r
+       if (typeof o == 'number' || o instanceof SVG.Number) {\r
+         return this.update({\r
+           offset:  arguments[0]\r
+         , color:   arguments[1]\r
+         , opacity: arguments[2]\r
+         })\r
+       }\r
\r
+       if (o.opacity != null) this.attr('stop-opacity', o.opacity)\r
+       if (o.color   != null) this.attr('stop-color', o.color)\r
+       if (o.offset  != null) this.attr('offset', o.offset)\r
+     }\r
\r
+     return this\r
+   }\r
+ })\r
 -SVG.Box = SVG.invent({\r
 -  create: function(x, y, width, height) {\r
 -    if (typeof x == 'object' && !(x instanceof SVG.Element)) {\r
 -      // chromes getBoundingClientRect has no x and y property\r
 -      return SVG.Box.call(this, x.left != null ? x.left : x.x , x.top != null ? x.top : x.y, x.width, x.height)\r
 -    } else if (arguments.length == 4) {\r
 -      this.x = x\r
 -      this.y = y\r
 -      this.width = width\r
 -      this.height = height\r
 -    }\r
 -\r
 -    // add center, right, bottom...\r
 -    fullBox(this)\r
 -  }\r
 -, extend: {\r
 -    // Merge rect box with another, return a new instance\r
 -    merge: function(box) {\r
 -      var b = new this.constructor()\r
 -\r
 -      // merge boxes\r
 -      b.x      = Math.min(this.x, box.x)\r
 -      b.y      = Math.min(this.y, box.y)\r
 -      b.width  = Math.max(this.x + this.width,  box.x + box.width)  - b.x\r
 -      b.height = Math.max(this.y + this.height, box.y + box.height) - b.y\r
 -\r
 -      return fullBox(b)\r
 -    }\r
 -\r
 -  , transform: function(m) {\r
 -      var xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, p, bbox\r
 -\r
 -      var pts = [\r
 -        new SVG.Point(this.x, this.y),\r
 -        new SVG.Point(this.x2, this.y),\r
 -        new SVG.Point(this.x, this.y2),\r
 -        new SVG.Point(this.x2, this.y2)\r
 -      ]\r
 -\r
 -      pts.forEach(function(p) {\r
 -        p = p.transform(m)\r
 -        xMin = Math.min(xMin,p.x)\r
 -        xMax = Math.max(xMax,p.x)\r
 -        yMin = Math.min(yMin,p.y)\r
 -        yMax = Math.max(yMax,p.y)\r
 -      })\r
 -\r
 -      bbox = new this.constructor()\r
 -      bbox.x = xMin\r
 -      bbox.width = xMax-xMin\r
 -      bbox.y = yMin\r
 -      bbox.height = yMax-yMin\r
 -\r
 -      fullBox(bbox)\r
 -\r
 -      return bbox\r
 -    }\r
 -  }\r
 -})\r
 -\r
 -SVG.BBox = SVG.invent({\r
 -  // Initialize\r
 -  create: function(element) {\r
 -    SVG.Box.apply(this, [].slice.call(arguments))\r
 -\r
 -    // get values if element is given\r
 -    if (element instanceof SVG.Element) {\r
 -      var box\r
 -\r
 -      // yes this is ugly, but Firefox can be a bitch when it comes to elements that are not yet rendered\r
 -      try {\r
 -\r
 -        if (!document.documentElement.contains){\r
 -          // This is IE - it does not support contains() for top-level SVGs\r
 -          var topParent = element.node\r
 -          while (topParent.parentNode){\r
 -            topParent = topParent.parentNode\r
 -          }\r
 -          if (topParent != document) throw new Exception('Element not in the dom')\r
 -        } else {\r
 -          // the element is NOT in the dom, throw error\r
 -          if(!document.documentElement.contains(element.node)) throw new Exception('Element not in the dom')\r
 -        }\r
 -\r
 -        // find native bbox\r
 -        box = element.node.getBBox()\r
 -      } catch(e) {\r
 -        if(element instanceof SVG.Shape){\r
 -          var clone = element.clone(SVG.parser.draw.instance).show()\r
 -          box = clone.node.getBBox()\r
 -          clone.remove()\r
 -        }else{\r
 -          box = {\r
 -            x:      element.node.clientLeft\r
 -          , y:      element.node.clientTop\r
 -          , width:  element.node.clientWidth\r
 -          , height: element.node.clientHeight\r
 -          }\r
 -        }\r
 -      }\r
 -\r
 -      SVG.Box.call(this, box)\r
 -    }\r
 -\r
 -  }\r
 -\r
 -  // Define ancestor\r
 -, inherit: SVG.Box\r
 -\r
 -  // Define Parent\r
 -, parent: SVG.Element\r
 -\r
 -  // Constructor\r
 -, construct: {\r
 -    // Get bounding box\r
 -    bbox: function() {\r
 -      return new SVG.BBox(this)\r
 -    }\r
 -  }\r
 -\r
 -})\r
 -\r
 -SVG.BBox.prototype.constructor = SVG.BBox\r
 -\r
 -\r
 -SVG.extend(SVG.Element, {\r
 -  tbox: function(){\r
 -    console.warn('Use of TBox is deprecated and mapped to RBox. Use .rbox() instead.')\r
 -    return this.rbox(this.doc())\r
 -  }\r
 -})\r
 -\r
 -SVG.RBox = SVG.invent({\r
 -  // Initialize\r
 -  create: function(element) {\r
 -    SVG.Box.apply(this, [].slice.call(arguments))\r
 -\r
 -    if (element instanceof SVG.Element) {\r
 -      SVG.Box.call(this, element.node.getBoundingClientRect())\r
 -    }\r
 -  }\r
 -\r
 -, inherit: SVG.Box\r
 -\r
 -  // define Parent\r
 -, parent: SVG.Element\r
 -\r
 -, extend: {\r
 -    addOffset: function() {\r
 -      // offset by window scroll position, because getBoundingClientRect changes when window is scrolled\r
 -      this.x += window.pageXOffset\r
 -      this.y += window.pageYOffset\r
 -      return this\r
 -    }\r
 -  }\r
 -\r
 -  // Constructor\r
 -, construct: {\r
 -    // Get rect box\r
 -    rbox: function(el) {\r
 -      if (el) return new SVG.RBox(this).transform(el.screenCTM().inverse())\r
 -      return new SVG.RBox(this).addOffset()\r
 -    }\r
 -  }\r
 -\r
 -})\r
 -\r
 -SVG.RBox.prototype.constructor = SVG.RBox\r
 -
+ SVG.Matrix = SVG.invent({\r
+   // Initialize\r
+   create: function(source) {\r
+     var i, base = arrayToMatrix([1, 0, 0, 1, 0, 0])\r
\r
+     // ensure source as object\r
+     source = source instanceof SVG.Element ?\r
+       source.matrixify() :\r
+     typeof source === 'string' ?\r
+       arrayToMatrix(source.split(SVG.regex.delimiter).map(parseFloat)) :\r
+     arguments.length == 6 ?\r
+       arrayToMatrix([].slice.call(arguments)) :\r
+     Array.isArray(source) ?\r
+       arrayToMatrix(source) :\r
+     typeof source === 'object' ?\r
+       source : base\r
\r
+     // merge source\r
+     for (i = abcdef.length - 1; i >= 0; --i)\r
+       this[abcdef[i]] = source && typeof source[abcdef[i]] === 'number' ?\r
+         source[abcdef[i]] : base[abcdef[i]]\r
+   }\r
\r
+   // Add methods\r
+ , extend: {\r
+     // Extract individual transformations\r
+     extract: function() {\r
+       // find delta transform points\r
+       var px    = deltaTransformPoint(this, 0, 1)\r
+         , py    = deltaTransformPoint(this, 1, 0)\r
+         , skewX = 180 / Math.PI * Math.atan2(px.y, px.x) - 90\r
\r
+       return {\r
+         // translation\r
+         x:        this.e\r
+       , y:        this.f\r
+       , transformedX:(this.e * Math.cos(skewX * Math.PI / 180) + this.f * Math.sin(skewX * Math.PI / 180)) / Math.sqrt(this.a * this.a + this.b * this.b)\r
+       , transformedY:(this.f * Math.cos(skewX * Math.PI / 180) + this.e * Math.sin(-skewX * Math.PI / 180)) / Math.sqrt(this.c * this.c + this.d * this.d)\r
+         // skew\r
+       , skewX:    -skewX\r
+       , skewY:    180 / Math.PI * Math.atan2(py.y, py.x)\r
+         // scale\r
+       , scaleX:   Math.sqrt(this.a * this.a + this.b * this.b)\r
+       , scaleY:   Math.sqrt(this.c * this.c + this.d * this.d)\r
+         // rotation\r
+       , rotation: skewX\r
+       , a: this.a\r
+       , b: this.b\r
+       , c: this.c\r
+       , d: this.d\r
+       , e: this.e\r
+       , f: this.f\r
+       , matrix: new SVG.Matrix(this)\r
+       }\r
+     }\r
+     // Clone matrix\r
+   , clone: function() {\r
+       return new SVG.Matrix(this)\r
+     }\r
+     // Morph one matrix into another\r
+   , morph: function(matrix) {\r
+       // store new destination\r
+       this.destination = new SVG.Matrix(matrix)\r
\r
+       return this\r
+     }\r
+     // Get morphed matrix at a given position\r
+   , at: function(pos) {\r
+       // make sure a destination is defined\r
+       if (!this.destination) return this\r
\r
+       // calculate morphed matrix at a given position\r
+       var matrix = new SVG.Matrix({\r
+         a: this.a + (this.destination.a - this.a) * pos\r
+       , b: this.b + (this.destination.b - this.b) * pos\r
+       , c: this.c + (this.destination.c - this.c) * pos\r
+       , d: this.d + (this.destination.d - this.d) * pos\r
+       , e: this.e + (this.destination.e - this.e) * pos\r
+       , f: this.f + (this.destination.f - this.f) * pos\r
+       })\r
\r
+       return matrix\r
+     }\r
+     // Multiplies by given matrix\r
+   , multiply: function(matrix) {\r
+       return new SVG.Matrix(this.native().multiply(parseMatrix(matrix).native()))\r
+     }\r
+     // Inverses matrix\r
+   , inverse: function() {\r
+       return new SVG.Matrix(this.native().inverse())\r
+     }\r
+     // Translate matrix\r
+   , translate: function(x, y) {\r
+       return new SVG.Matrix(this.native().translate(x || 0, y || 0))\r
+     }\r
+     // Scale matrix\r
+   , scale: function(x, y, cx, cy) {\r
+       // support uniformal scale\r
+       if (arguments.length == 1) {\r
+         y = x\r
+       } else if (arguments.length == 3) {\r
+         cy = cx\r
+         cx = y\r
+         y = x\r
+       }\r
\r
+       return this.around(cx, cy, new SVG.Matrix(x, 0, 0, y, 0, 0))\r
+     }\r
+     // Rotate matrix\r
+   , rotate: function(r, cx, cy) {\r
+       // convert degrees to radians\r
+       r = SVG.utils.radians(r)\r
\r
+       return this.around(cx, cy, new SVG.Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0))\r
+     }\r
+     // Flip matrix on x or y, at a given offset\r
+   , flip: function(a, o) {\r
+       return a == 'x' ?\r
+           this.scale(-1, 1, o, 0) :\r
+         a == 'y' ?\r
+           this.scale(1, -1, 0, o) :\r
+           this.scale(-1, -1, a, o != null ? o : a)\r
+     }\r
+     // Skew\r
+   , skew: function(x, y, cx, cy) {\r
+       // support uniformal skew\r
+       if (arguments.length == 1) {\r
+         y = x\r
+       } else if (arguments.length == 3) {\r
+         cy = cx\r
+         cx = y\r
+         y = x\r
+       }\r
\r
+       // convert degrees to radians\r
+       x = SVG.utils.radians(x)\r
+       y = SVG.utils.radians(y)\r
\r
+       return this.around(cx, cy, new SVG.Matrix(1, Math.tan(y), Math.tan(x), 1, 0, 0))\r
+     }\r
+     // SkewX\r
+   , skewX: function(x, cx, cy) {\r
+       return this.skew(x, 0, cx, cy)\r
+     }\r
+     // SkewY\r
+   , skewY: function(y, cx, cy) {\r
+       return this.skew(0, y, cx, cy)\r
+     }\r
+     // Transform around a center point\r
+   , around: function(cx, cy, matrix) {\r
+       return this\r
+         .multiply(new SVG.Matrix(1, 0, 0, 1, cx || 0, cy || 0))\r
+         .multiply(matrix)\r
+         .multiply(new SVG.Matrix(1, 0, 0, 1, -cx || 0, -cy || 0))\r
+     }\r
+     // Convert to native SVGMatrix\r
+   , native: function() {\r
+       // create new matrix\r
+       var matrix = SVG.parser.native.createSVGMatrix()\r
\r
+       // update with current values\r
+       for (var i = abcdef.length - 1; i >= 0; i--)\r
+         matrix[abcdef[i]] = this[abcdef[i]]\r
\r
+       return matrix\r
+     }\r
+     // Convert matrix to string\r
+   , toString: function() {\r
+       return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'\r
+     }\r
+   }\r
\r
+   // Define parent\r
+ , parent: SVG.Element\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Get current matrix\r
+     ctm: function() {\r
+       return new SVG.Matrix(this.node.getCTM())\r
+     },\r
+     // Get current screen matrix\r
+     screenCTM: function() {\r
+       /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537\r
+          This is needed because FF does not return the transformation matrix\r
+          for the inner coordinate system when getScreenCTM() is called on nested svgs.\r
+          However all other Browsers do that */\r
+       if(this instanceof SVG.Nested) {\r
+         var rect = this.rect(1,1)\r
+         var m = rect.node.getScreenCTM()\r
+         rect.remove()\r
+         return new SVG.Matrix(m)\r
+       }\r
+       return new SVG.Matrix(this.node.getScreenCTM())\r
+     }\r
\r
+   }\r
\r
+ })\r
+ SVG.Point = SVG.invent({\r
+   // Initialize\r
+   create: function(x,y) {\r
+     var i, source, base = {x:0, y:0}\r
\r
+     // ensure source as object\r
+     source = Array.isArray(x) ?\r
+       {x:x[0], y:x[1]} :\r
+     typeof x === 'object' ?\r
+       {x:x.x, y:x.y} :\r
+     x != null ?\r
+       {x:x, y:(y != null ? y : x)} : base // If y has no value, then x is used has its value\r
\r
+     // merge source\r
+     this.x = source.x\r
+     this.y = source.y\r
+   }\r
\r
+   // Add methods\r
+ , extend: {\r
+     // Clone point\r
+     clone: function() {\r
+       return new SVG.Point(this)\r
+     }\r
+     // Morph one point into another\r
+   , morph: function(x, y) {\r
+       // store new destination\r
+       this.destination = new SVG.Point(x, y)\r
\r
+       return this\r
+     }\r
+     // Get morphed point at a given position\r
+   , at: function(pos) {\r
+       // make sure a destination is defined\r
+       if (!this.destination) return this\r
\r
+       // calculate morphed matrix at a given position\r
+       var point = new SVG.Point({\r
+         x: this.x + (this.destination.x - this.x) * pos\r
+       , y: this.y + (this.destination.y - this.y) * pos\r
+       })\r
\r
+       return point\r
+     }\r
+     // Convert to native SVGPoint\r
+   , native: function() {\r
+       // create new point\r
+       var point = SVG.parser.native.createSVGPoint()\r
\r
+       // update with current values\r
+       point.x = this.x\r
+       point.y = this.y\r
\r
+       return point\r
+     }\r
+     // transform point with matrix\r
+   , transform: function(matrix) {\r
+       return new SVG.Point(this.native().matrixTransform(matrix.native()))\r
+     }\r
\r
+   }\r
\r
+ })\r
\r
+ SVG.extend(SVG.Element, {\r
\r
+   // Get point\r
+   point: function(x, y) {\r
+     return new SVG.Point(x,y).transform(this.screenCTM().inverse());\r
+   }\r
\r
+ })\r
+ SVG.extend(SVG.Element, {\r
+   // Set svg element attribute\r
+   attr: function(a, v, n) {\r
+     // act as full getter\r
+     if (a == null) {\r
+       // get an object of attributes\r
+       a = {}\r
+       v = this.node.attributes\r
+       for (n = v.length - 1; n >= 0; n--)\r
+         a[v[n].nodeName] = SVG.regex.isNumber.test(v[n].nodeValue) ? parseFloat(v[n].nodeValue) : v[n].nodeValue\r
\r
+       return a\r
\r
+     } else if (typeof a == 'object') {\r
+       // apply every attribute individually if an object is passed\r
+       for (v in a) this.attr(v, a[v])\r
\r
+     } else if (v === null) {\r
+         // remove value\r
+         this.node.removeAttribute(a)\r
\r
+     } else if (v == null) {\r
+       // act as a getter if the first and only argument is not an object\r
+       v = this.node.getAttribute(a)\r
+       return v == null ?\r
+         SVG.defaults.attrs[a] :\r
+       SVG.regex.isNumber.test(v) ?\r
+         parseFloat(v) : v\r
\r
+     } else {\r
 -      // BUG FIX: some browsers will render a stroke if a color is given even though stroke width is 0\r
 -      if (a == 'stroke-width')\r
 -        this.attr('stroke', parseFloat(v) > 0 ? this._stroke : null)\r
 -      else if (a == 'stroke')\r
 -        this._stroke = v\r
\r
+       // convert image fill and stroke to patterns\r
+       if (a == 'fill' || a == 'stroke') {\r
+         if (SVG.regex.isImage.test(v))\r
 -          v = this.doc().defs().image(v, 0, 0)\r
++          v = this.doc().defs().image(v)\r
\r
+         if (v instanceof SVG.Image)\r
+           v = this.doc().defs().pattern(0, 0, function() {\r
+             this.add(v)\r
+           })\r
+       }\r
\r
+       // ensure correct numeric values (also accepts NaN and Infinity)\r
+       if (typeof v === 'number')\r
+         v = new SVG.Number(v)\r
\r
+       // ensure full hex color\r
+       else if (SVG.Color.isColor(v))\r
+         v = new SVG.Color(v)\r
\r
+       // parse array values\r
+       else if (Array.isArray(v))\r
+         v = new SVG.Array(v)\r
\r
+       // if the passed attribute is leading...\r
+       if (a == 'leading') {\r
+         // ... call the leading method instead\r
+         if (this.leading)\r
+           this.leading(v)\r
+       } else {\r
+         // set given attribute on node\r
+         typeof n === 'string' ?\r
+           this.node.setAttributeNS(n, a, v.toString()) :\r
+           this.node.setAttribute(a, v.toString())\r
+       }\r
\r
+       // rebuild if required\r
+       if (this.rebuild && (a == 'font-size' || a == 'x'))\r
+         this.rebuild(a, v)\r
+     }\r
\r
+     return this\r
+   }\r
  })
- SVG.A = SVG.invent({
-   // Initialize node
-   create: 'a'
-   // Inherit from
- , inherit: SVG.Container
-   // Add class methods
- , extend: {
-     // Link url
-     to: function(url) {
-       return this.attr('href', url, SVG.xlink)
-     }
-     // Link show attribute
-   , show: function(target) {
-       return this.attr('show', target, SVG.xlink)
-     }
-     // Link target attribute
-   , target: function(target) {
-       return this.attr('target', target)
-     }
-   }
-   // Add parent method
- , construct: {
-     // Create a hyperlink element
-     link: function(url) {
-       return this.put(new SVG.A).to(url)
-     }
-   }
+ SVG.extend(SVG.Element, {\r
+   // Add transformations\r
+   transform: function(o, relative) {\r
+     // get target in case of the fx module, otherwise reference this\r
+     var target = this\r
+       , matrix, bbox\r
\r
+     // act as a getter\r
+     if (typeof o !== 'object') {\r
+       // get current matrix\r
+       matrix = new SVG.Matrix(target).extract()\r
\r
+       return typeof o === 'string' ? matrix[o] : matrix\r
+     }\r
\r
+     // get current matrix\r
+     matrix = new SVG.Matrix(target)\r
\r
+     // ensure relative flag\r
+     relative = !!relative || !!o.relative\r
\r
+     // act on matrix\r
+     if (o.a != null) {\r
+       matrix = relative ?\r
+         // relative\r
+         matrix.multiply(new SVG.Matrix(o)) :\r
+         // absolute\r
+         new SVG.Matrix(o)\r
\r
+     // act on rotation\r
+     } else if (o.rotation != null) {\r
+       // ensure centre point\r
+       ensureCentre(o, target)\r
\r
+       // apply transformation\r
+       matrix = relative ?\r
+         // relative\r
+         matrix.rotate(o.rotation, o.cx, o.cy) :\r
+         // absolute\r
+         matrix.rotate(o.rotation - matrix.extract().rotation, o.cx, o.cy)\r
\r
+     // act on scale\r
+     } else if (o.scale != null || o.scaleX != null || o.scaleY != null) {\r
+       // ensure centre point\r
+       ensureCentre(o, target)\r
\r
+       // ensure scale values on both axes\r
+       o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1\r
+       o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1\r
\r
+       if (!relative) {\r
+         // absolute; multiply inversed values\r
+         var e = matrix.extract()\r
+         o.scaleX = o.scaleX * 1 / e.scaleX\r
+         o.scaleY = o.scaleY * 1 / e.scaleY\r
+       }\r
\r
+       matrix = matrix.scale(o.scaleX, o.scaleY, o.cx, o.cy)\r
\r
+     // act on skew\r
+     } else if (o.skew != null || o.skewX != null || o.skewY != null) {\r
+       // ensure centre point\r
+       ensureCentre(o, target)\r
\r
+       // ensure skew values on both axes\r
+       o.skewX = o.skew != null ? o.skew : o.skewX != null ? o.skewX : 0\r
+       o.skewY = o.skew != null ? o.skew : o.skewY != null ? o.skewY : 0\r
\r
+       if (!relative) {\r
+         // absolute; reset skew values\r
+         var e = matrix.extract()\r
+         matrix = matrix.multiply(new SVG.Matrix().skew(e.skewX, e.skewY, o.cx, o.cy).inverse())\r
+       }\r
\r
+       matrix = matrix.skew(o.skewX, o.skewY, o.cx, o.cy)\r
\r
+     // act on flip\r
+     } else if (o.flip) {\r
+       if(o.flip == 'x' || o.flip == 'y') {\r
+         o.offset = o.offset == null ? target.bbox()['c' + o.flip] : o.offset\r
+       } else {\r
+         if(o.offset == null) {\r
+           bbox = target.bbox()\r
+           o.flip = bbox.cx\r
+           o.offset = bbox.cy\r
+         } else {\r
+           o.flip = o.offset\r
+         }\r
+       }\r
\r
+       matrix = new SVG.Matrix().flip(o.flip, o.offset)\r
\r
+     // act on translate\r
+     } else if (o.x != null || o.y != null) {\r
+       if (relative) {\r
+         // relative\r
+         matrix = matrix.translate(o.x, o.y)\r
+       } else {\r
+         // absolute\r
+         if (o.x != null) matrix.e = o.x\r
+         if (o.y != null) matrix.f = o.y\r
+       }\r
+     }\r
\r
+     return this.attr('transform', matrix)\r
+   }\r
+ })\r
\r
+ SVG.extend(SVG.FX, {\r
+   transform: function(o, relative) {\r
+     // get target in case of the fx module, otherwise reference this\r
+     var target = this.target()\r
+       , matrix, bbox\r
\r
+     // act as a getter\r
+     if (typeof o !== 'object') {\r
+       // get current matrix\r
+       matrix = new SVG.Matrix(target).extract()\r
\r
+       return typeof o === 'string' ? matrix[o] : matrix\r
+     }\r
\r
+     // ensure relative flag\r
+     relative = !!relative || !!o.relative\r
\r
+     // act on matrix\r
+     if (o.a != null) {\r
+       matrix = new SVG.Matrix(o)\r
\r
+     // act on rotation\r
+     } else if (o.rotation != null) {\r
+       // ensure centre point\r
+       ensureCentre(o, target)\r
\r
+       // apply transformation\r
+       matrix = new SVG.Rotate(o.rotation, o.cx, o.cy)\r
\r
+     // act on scale\r
+     } else if (o.scale != null || o.scaleX != null || o.scaleY != null) {\r
+       // ensure centre point\r
+       ensureCentre(o, target)\r
\r
+       // ensure scale values on both axes\r
+       o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1\r
+       o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1\r
\r
+       matrix = new SVG.Scale(o.scaleX, o.scaleY, o.cx, o.cy)\r
\r
+     // act on skew\r
+     } else if (o.skewX != null || o.skewY != null) {\r
+       // ensure centre point\r
+       ensureCentre(o, target)\r
\r
+       // ensure skew values on both axes\r
+       o.skewX = o.skewX != null ? o.skewX : 0\r
+       o.skewY = o.skewY != null ? o.skewY : 0\r
\r
+       matrix = new SVG.Skew(o.skewX, o.skewY, o.cx, o.cy)\r
\r
+     // act on flip\r
+     } else if (o.flip) {\r
+       if(o.flip == 'x' || o.flip == 'y') {\r
+         o.offset = o.offset == null ? target.bbox()['c' + o.flip] : o.offset\r
+       } else {\r
+         if(o.offset == null) {\r
+           bbox = target.bbox()\r
+           o.flip = bbox.cx\r
+           o.offset = bbox.cy\r
+         } else {\r
+           o.flip = o.offset\r
+         }\r
+       }\r
\r
+       matrix = new SVG.Matrix().flip(o.flip, o.offset)\r
\r
+     // act on translate\r
+     } else if (o.x != null || o.y != null) {\r
+       matrix = new SVG.Translate(o.x, o.y)\r
+     }\r
\r
+     if(!matrix) return this\r
\r
+     matrix.relative = relative\r
\r
+     this.last().transforms.push(matrix)\r
\r
+     return this._callStart()\r
+   }\r
+ })\r
\r
+ SVG.extend(SVG.Element, {\r
+   // Reset all transformations\r
+   untransform: function() {\r
+     return this.attr('transform', null)\r
+   },\r
+   // merge the whole transformation chain into one matrix and returns it\r
+   matrixify: function() {\r
\r
+     var matrix = (this.attr('transform') || '')\r
+       // split transformations\r
+       .split(SVG.regex.transforms).slice(0,-1).map(function(str){\r
+         // generate key => value pairs\r
+         var kv = str.trim().split('(')\r
+         return [kv[0], kv[1].split(SVG.regex.delimiter).map(function(str){ return parseFloat(str) })]\r
+       })\r
+       // merge every transformation into one matrix\r
+       .reduce(function(matrix, transform){\r
\r
+         if(transform[0] == 'matrix') return matrix.multiply(arrayToMatrix(transform[1]))\r
+         return matrix[transform[0]].apply(matrix, transform[1])\r
\r
+       }, new SVG.Matrix())\r
\r
+     return matrix\r
+   },\r
+   // add an element to another parent without changing the visual representation on the screen\r
+   toParent: function(parent) {\r
+     if(this == parent) return this\r
+     var ctm = this.screenCTM()\r
+     var pCtm = parent.screenCTM().inverse()\r
\r
+     this.addTo(parent).untransform().transform(pCtm.multiply(ctm))\r
\r
+     return this\r
+   },\r
+   // same as above with parent equals root-svg\r
+   toDoc: function() {\r
+     return this.toParent(this.doc())\r
+   }\r
\r
+ })\r
\r
+ SVG.Transformation = SVG.invent({\r
\r
+   create: function(source, inversed){\r
\r
+     if(arguments.length > 1 && typeof inversed != 'boolean'){\r
+       return this.constructor.call(this, [].slice.call(arguments))\r
+     }\r
\r
+     if(Array.isArray(source)){\r
+       for(var i = 0, len = this.arguments.length; i < len; ++i){\r
+         this[this.arguments[i]] = source[i]\r
+       }\r
+     } else if(typeof source == 'object'){\r
+       for(var i = 0, len = this.arguments.length; i < len; ++i){\r
+         this[this.arguments[i]] = source[this.arguments[i]]\r
+       }\r
+     }\r
\r
+     this.inversed = false\r
\r
+     if(inversed === true){\r
+       this.inversed = true\r
+     }\r
\r
+   }\r
\r
+ , extend: {\r
\r
+     arguments: []\r
+   , method: ''\r
\r
+   , at: function(pos){\r
\r
+       var params = []\r
\r
+       for(var i = 0, len = this.arguments.length; i < len; ++i){\r
+         params.push(this[this.arguments[i]])\r
+       }\r
\r
+       var m = this._undo || new SVG.Matrix()\r
\r
+       m = new SVG.Matrix().morph(SVG.Matrix.prototype[this.method].apply(m, params)).at(pos)\r
\r
+       return this.inversed ? m.inverse() : m\r
\r
+     }\r
\r
+   , undo: function(o){\r
+       for(var i = 0, len = this.arguments.length; i < len; ++i){\r
+         o[this.arguments[i]] = typeof this[this.arguments[i]] == 'undefined' ? 0 : o[this.arguments[i]]\r
+       }\r
\r
+       // The method SVG.Matrix.extract which was used before calling this\r
+       // method to obtain a value for the parameter o doesn't return a cx and\r
+       // a cy so we use the ones that were provided to this object at its creation\r
+       o.cx = this.cx\r
+       o.cy = this.cy\r
\r
+       this._undo = new SVG[capitalize(this.method)](o, true).at(1)\r
\r
+       return this\r
+     }\r
\r
+   }\r
\r
+ })\r
\r
+ SVG.Translate = SVG.invent({\r
\r
+   parent: SVG.Matrix\r
+ , inherit: SVG.Transformation\r
\r
+ , create: function(source, inversed){\r
+     this.constructor.apply(this, [].slice.call(arguments))\r
+   }\r
\r
+ , extend: {\r
+     arguments: ['transformedX', 'transformedY']\r
+   , method: 'translate'\r
+   }\r
\r
+ })\r
\r
+ SVG.Rotate = SVG.invent({\r
\r
+   parent: SVG.Matrix\r
+ , inherit: SVG.Transformation\r
\r
+ , create: function(source, inversed){\r
+     this.constructor.apply(this, [].slice.call(arguments))\r
+   }\r
\r
+ , extend: {\r
+     arguments: ['rotation', 'cx', 'cy']\r
+   , method: 'rotate'\r
+   , at: function(pos){\r
+       var m = new SVG.Matrix().rotate(new SVG.Number().morph(this.rotation - (this._undo ? this._undo.rotation : 0)).at(pos), this.cx, this.cy)\r
+       return this.inversed ? m.inverse() : m\r
+     }\r
+   , undo: function(o){\r
+       this._undo = o\r
+       return this\r
+     }\r
+   }\r
\r
+ })\r
\r
+ SVG.Scale = SVG.invent({\r
\r
+   parent: SVG.Matrix\r
+ , inherit: SVG.Transformation\r
\r
+ , create: function(source, inversed){\r
+     this.constructor.apply(this, [].slice.call(arguments))\r
+   }\r
\r
+ , extend: {\r
+     arguments: ['scaleX', 'scaleY', 'cx', 'cy']\r
+   , method: 'scale'\r
+   }\r
\r
+ })\r
\r
+ SVG.Skew = SVG.invent({\r
\r
+   parent: SVG.Matrix\r
+ , inherit: SVG.Transformation\r
\r
+ , create: function(source, inversed){\r
+     this.constructor.apply(this, [].slice.call(arguments))\r
+   }\r
\r
+ , extend: {\r
+     arguments: ['skewX', 'skewY', 'cx', 'cy']\r
+   , method: 'skew'\r
+   }\r
\r
+ })\r
+ SVG.extend(SVG.Element, {\r
+   // Dynamic style generator\r
+   style: function(s, v) {\r
+     if (arguments.length == 0) {\r
+       // get full style\r
+       return this.node.style.cssText || ''\r
\r
+     } else if (arguments.length < 2) {\r
+       // apply every style individually if an object is passed\r
+       if (typeof s == 'object') {\r
+         for (v in s) this.style(v, s[v])\r
\r
 -      } else if (SVG.regex.isCss.test(s)) {\r
 -        // parse css string\r
 -        s = s.split(/\s*;\s*/)\r
 -          // filter out suffix ; and stuff like ;;\r
 -          .filter(function(e) { return !!e })\r
 -          .map(function(e){ return e.split(/\s*:\s*/) })\r
 -\r
 -        // apply every definition individually\r
 -        while (v = s.pop()) {\r
 -          this.style(v[0], v[1])\r
 -        }\r
+       } else {\r
+         // act as a getter if the first and only argument is not an object\r
+         return this.node.style[camelCase(s)]\r
+       }\r
\r
+     } else {\r
+       this.node.style[camelCase(s)] = v === null || SVG.regex.isBlank.test(v) ? '' : v\r
+     }\r
\r
+     return this\r
+   }\r
 -})
++})\r
++
+ SVG.Parent = SVG.invent({\r
+   // Initialize node\r
+   create: function(element) {\r
+     this.constructor.call(this, element)\r
+   }\r
\r
+   // Inherit from\r
+ , inherit: SVG.Element\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Returns all child elements\r
+     children: function() {\r
+       return SVG.utils.map(SVG.utils.filterSVGElements(this.node.childNodes), function(node) {\r
+         return SVG.adopt(node)\r
+       })\r
+     }\r
+     // Add given element at a position\r
+   , add: function(element, i) {\r
+       if (i == null)\r
+         this.node.appendChild(element.node)\r
+       else if (element.node != this.node.childNodes[i])\r
+         this.node.insertBefore(element.node, this.node.childNodes[i])\r
\r
+       return this\r
+     }\r
+     // Basically does the same as `add()` but returns the added element instead\r
+   , put: function(element, i) {\r
+       this.add(element, i)\r
+       return element\r
+     }\r
+     // Checks if the given element is a child\r
+   , has: function(element) {\r
+       return this.index(element) >= 0\r
+     }\r
+     // Gets index of given element\r
+   , index: function(element) {\r
+       return [].slice.call(this.node.childNodes).indexOf(element.node)\r
+     }\r
+     // Get a element at the given index\r
+   , get: function(i) {\r
+       return SVG.adopt(this.node.childNodes[i])\r
+     }\r
+     // Get first child\r
+   , first: function() {\r
+       return this.get(0)\r
+     }\r
+     // Get the last child\r
+   , last: function() {\r
+       return this.get(this.node.childNodes.length - 1)\r
+     }\r
+     // Iterates over all children and invokes a given block\r
+   , each: function(block, deep) {\r
+       var i, il\r
+         , children = this.children()\r
\r
+       for (i = 0, il = children.length; i < il; i++) {\r
+         if (children[i] instanceof SVG.Element)\r
+           block.apply(children[i], [i, children])\r
\r
+         if (deep && (children[i] instanceof SVG.Container))\r
+           children[i].each(block, deep)\r
+       }\r
\r
+       return this\r
+     }\r
+     // Remove a given child\r
+   , removeElement: function(element) {\r
+       this.node.removeChild(element.node)\r
\r
+       return this\r
+     }\r
+     // Remove all elements in this container\r
+   , clear: function() {\r
+       // remove children\r
+       while(this.node.hasChildNodes())\r
+         this.node.removeChild(this.node.lastChild)\r
\r
+       // remove defs reference\r
+       delete this._defs\r
\r
+       return this\r
+     }\r
+   , // Get defs\r
+     defs: function() {\r
+       return this.doc().defs()\r
+     }\r
+   }\r
\r
+ })\r
+ SVG.extend(SVG.Parent, {\r
 -\r
 -  ungroup: function(parent, depth) {\r
 -    if(depth === 0 || this instanceof SVG.Defs || this.node == SVG.parser.draw) return this\r
++  flatten: function(parent) {\r
++    if(this instanceof SVG.Defs) return this\r
\r
+     parent = parent || (this instanceof SVG.Doc ? this : this.parent(SVG.Parent))\r
 -    depth = depth || Infinity\r
\r
+     this.each(function(){\r
+       if(this instanceof SVG.Defs) return this\r
 -      if(this instanceof SVG.Parent) return this.ungroup(parent, depth-1)\r
++      if(this instanceof SVG.Parent) return this.flatten(parent)\r
+       return this.toParent(parent)\r
+     })\r
\r
++    // we need this so that SVG.Doc does not get removed\r
+     this.node.firstChild || this.remove()\r
\r
+     return this\r
 -  },\r
 -\r
 -  flatten: function(parent, depth) {\r
 -    return this.ungroup(parent, depth)\r
+   }\r
 -\r
 -})
++})\r
++
+ SVG.Container = SVG.invent({\r
+   // Initialize node\r
+   create: function(element) {\r
+     this.constructor.call(this, element)\r
+   }\r
\r
+   // Inherit from\r
+ , inherit: SVG.Parent\r
\r
 -})
 -\r
 -SVG.ViewBox = SVG.invent({\r
 -\r
 -  create: function(source) {\r
 -    var i, base = [0, 0, 0, 0]\r
 -\r
 -    var x, y, width, height, box, view, we, he\r
 -      , wm   = 1 // width multiplier\r
 -      , hm   = 1 // height multiplier\r
 -      , reg  = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/gi\r
 -\r
 -    if(source instanceof SVG.Element){\r
 -\r
 -      we = source\r
 -      he = source\r
 -      view = (source.attr('viewBox') || '').match(reg)\r
 -      box = source.bbox\r
 -\r
 -      // get dimensions of current node\r
 -      width  = new SVG.Number(source.width())\r
 -      height = new SVG.Number(source.height())\r
 -\r
 -      // find nearest non-percentual dimensions\r
 -      while (width.unit == '%') {\r
 -        wm *= width.value\r
 -        width = new SVG.Number(we instanceof SVG.Doc ? we.parent().offsetWidth : we.parent().width())\r
 -        we = we.parent()\r
 -      }\r
 -      while (height.unit == '%') {\r
 -        hm *= height.value\r
 -        height = new SVG.Number(he instanceof SVG.Doc ? he.parent().offsetHeight : he.parent().height())\r
 -        he = he.parent()\r
 -      }\r
 -\r
 -      // ensure defaults\r
 -      this.x      = 0\r
 -      this.y      = 0\r
 -      this.width  = width  * wm\r
 -      this.height = height * hm\r
 -      this.zoom   = 1\r
 -\r
 -      if (view) {\r
 -        // get width and height from viewbox\r
 -        x      = parseFloat(view[0])\r
 -        y      = parseFloat(view[1])\r
 -        width  = parseFloat(view[2])\r
 -        height = parseFloat(view[3])\r
 -\r
 -        // calculate zoom accoring to viewbox\r
 -        this.zoom = ((this.width / this.height) > (width / height)) ?\r
 -          this.height / height :\r
 -          this.width  / width\r
 -\r
 -        // calculate real pixel dimensions on parent SVG.Doc element\r
 -        this.x      = x\r
 -        this.y      = y\r
 -        this.width  = width\r
 -        this.height = height\r
 -\r
 -      }\r
 -\r
 -    }else{\r
 -\r
 -      // ensure source as object\r
 -      source = typeof source === 'string' ?\r
 -        source.match(reg).map(function(el){ return parseFloat(el) }) :\r
 -      Array.isArray(source) ?\r
 -        source :\r
 -      typeof source == 'object' ?\r
 -        [source.x, source.y, source.width, source.height] :\r
 -      arguments.length == 4 ?\r
 -        [].slice.call(arguments) :\r
 -        base\r
 -\r
 -      this.x = source[0]\r
 -      this.y = source[1]\r
 -      this.width = source[2]\r
 -      this.height = source[3]\r
 -    }\r
 -\r
 -\r
 -  }\r
 -\r
 -, extend: {\r
 -\r
 -    toString: function() {\r
 -      return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height\r
 -    }\r
 -  , morph: function(x, y, width, height){\r
 -      this.destination = new SVG.ViewBox(x, y, width, height)\r
 -      return this\r
 -    }\r
 -\r
 -  , at: function(pos) {\r
 -\r
 -      if(!this.destination) return this\r
 -\r
 -      return new SVG.ViewBox([\r
 -          this.x + (this.destination.x - this.x) * pos\r
 -        , this.y + (this.destination.y - this.y) * pos\r
 -        , this.width + (this.destination.width - this.width) * pos\r
 -        , this.height + (this.destination.height - this.height) * pos\r
 -      ])\r
 -\r
 -    }\r
 -\r
 -  }\r
 -\r
 -  // Define parent\r
 -, parent: SVG.Container\r
 -\r
 -  // Add parent method\r
 -, construct: {\r
 -\r
 -    // get/set viewbox\r
 -    viewbox: function(x, y, width, height) {\r
 -      if (arguments.length == 0)\r
 -        // act as a getter if there are no arguments\r
 -        return new SVG.ViewBox(this)\r
 -\r
 -      // otherwise act as a setter\r
 -      return this.attr('viewBox', new SVG.ViewBox(x, y, width, height))\r
 -    }\r
 -\r
 -  }\r
 -\r
  })
- SVG.extend(SVG.Element, {
-   // Create a hyperlink element
-   linkTo: function(url) {
-     var link = new SVG.A
-     if (typeof url == 'function')
-       url.call(link, link)
-     else
-       link.to(url)
-     return this.parent().put(link).put(this)
-   }
+ // Add events to elements\r
+ ;[  'click'\r
+   , 'dblclick'\r
+   , 'mousedown'\r
+   , 'mouseup'\r
+   , 'mouseover'\r
+   , 'mouseout'\r
+   , 'mousemove'\r
+   // , 'mouseenter' -> not supported by IE\r
+   // , 'mouseleave' -> not supported by IE\r
+   , 'touchstart'\r
+   , 'touchmove'\r
+   , 'touchleave'\r
+   , 'touchend'\r
+   , 'touchcancel' ].forEach(function(event) {\r
\r
+   // add event to SVG.Element\r
+   SVG.Element.prototype[event] = function(f) {\r
+     // bind event to element rather than element node\r
+     SVG.on(this.node, event, f)\r
+     return this\r
+   }\r
+ })\r
\r
+ // Initialize listeners stack\r
+ SVG.listeners = []\r
+ SVG.handlerMap = []\r
+ SVG.listenerId = 0\r
\r
+ // Add event binder in the SVG namespace\r
+ SVG.on = function(node, event, listener, binding, options) {\r
+   // create listener, get object-index\r
+   var l     = listener.bind(binding || node.instance || node)\r
+     , index = (SVG.handlerMap.indexOf(node) + 1 || SVG.handlerMap.push(node)) - 1\r
+     , ev    = event.split('.')[0]\r
+     , ns    = event.split('.')[1] || '*'\r
\r
\r
+   // ensure valid object\r
+   SVG.listeners[index]         = SVG.listeners[index]         || {}\r
+   SVG.listeners[index][ev]     = SVG.listeners[index][ev]     || {}\r
+   SVG.listeners[index][ev][ns] = SVG.listeners[index][ev][ns] || {}\r
\r
+   if(!listener._svgjsListenerId)\r
+     listener._svgjsListenerId = ++SVG.listenerId\r
\r
+   // reference listener\r
+   SVG.listeners[index][ev][ns][listener._svgjsListenerId] = l\r
\r
+   // add listener\r
+   node.addEventListener(ev, l, options || false)\r
+ }\r
\r
+ // Add event unbinder in the SVG namespace\r
+ SVG.off = function(node, event, listener) {\r
+   var index = SVG.handlerMap.indexOf(node)\r
+     , ev    = event && event.split('.')[0]\r
+     , ns    = event && event.split('.')[1]\r
+     , namespace = ''\r
\r
+   if(index == -1) return\r
\r
+   if (listener) {\r
+     if(typeof listener == 'function') listener = listener._svgjsListenerId\r
+     if(!listener) return\r
\r
+     // remove listener reference\r
+     if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns || '*']) {\r
+       // remove listener\r
+       node.removeEventListener(ev, SVG.listeners[index][ev][ns || '*'][listener], false)\r
\r
+       delete SVG.listeners[index][ev][ns || '*'][listener]\r
+     }\r
\r
+   } else if (ns && ev) {\r
+     // remove all listeners for a namespaced event\r
+     if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns]) {\r
+       for (listener in SVG.listeners[index][ev][ns])\r
+         SVG.off(node, [ev, ns].join('.'), listener)\r
\r
+       delete SVG.listeners[index][ev][ns]\r
+     }\r
\r
+   } else if (ns){\r
+     // remove all listeners for a specific namespace\r
+     for(event in SVG.listeners[index]){\r
+         for(namespace in SVG.listeners[index][event]){\r
+             if(ns === namespace){\r
+                 SVG.off(node, [event, ns].join('.'))\r
+             }\r
+         }\r
+     }\r
\r
+   } else if (ev) {\r
+     // remove all listeners for the event\r
+     if (SVG.listeners[index][ev]) {\r
+       for (namespace in SVG.listeners[index][ev])\r
+         SVG.off(node, [ev, namespace].join('.'))\r
\r
+       delete SVG.listeners[index][ev]\r
+     }\r
\r
+   } else {\r
+     // remove all listeners on a given node\r
+     for (event in SVG.listeners[index])\r
+       SVG.off(node, event)\r
\r
+     delete SVG.listeners[index]\r
+     delete SVG.handlerMap[index]\r
\r
+   }\r
+ }\r
\r
+ //\r
+ SVG.extend(SVG.Element, {\r
+   // Bind given event to listener\r
+   on: function(event, listener, binding, options) {\r
+     SVG.on(this.node, event, listener, binding, options)\r
\r
+     return this\r
+   }\r
+   // Unbind event from listener\r
+ , off: function(event, listener) {\r
+     SVG.off(this.node, event, listener)\r
\r
+     return this\r
+   }\r
+   // Fire given event\r
+ , fire: function(event, data) {\r
\r
+     // Dispatch event\r
+     if(event instanceof window.Event){\r
+         this.node.dispatchEvent(event)\r
+     }else{\r
+         this.node.dispatchEvent(event = new window.CustomEvent(event, {detail:data, cancelable: true}))\r
+     }\r
\r
+     this._event = event\r
+     return this\r
+   }\r
+ , event: function() {\r
+     return this._event\r
+   }\r
+ })\r
\r
+ SVG.Defs = SVG.invent({\r
+   // Initialize node\r
+   create: 'defs'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Container\r
\r
  })
- SVG.Marker = SVG.invent({
-   // Initialize node
-   create: 'marker'
-   // Inherit from
- , inherit: SVG.Container
-   // Add class methods
- , extend: {
-     // Set width of element
-     width: function(width) {
-       return this.attr('markerWidth', width)
-     }
-     // Set height of element
-   , height: function(height) {
-       return this.attr('markerHeight', height)
-     }
-     // Set marker refX and refY
-   , ref: function(x, y) {
-       return this.attr('refX', x).attr('refY', y)
-     }
-     // Update marker
-   , update: function(block) {
-       // remove all content
-       this.clear()
-       // invoke passed block
-       if (typeof block == 'function')
-         block.call(this, this)
-       return this
-     }
-     // Return the fill id
-   , toString: function() {
-       return 'url(#' + this.id() + ')'
-     }
-   }
-   // Add parent method
- , construct: {
-     marker: function(width, height, block) {
-       // Create marker element in defs
-       return this.defs().marker(width, height, block)
-     }
-   }
+ SVG.G = SVG.invent({\r
+   // Initialize node\r
+   create: 'g'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Container\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Move over x-axis\r
+     x: function(x) {\r
+       return x == null ? this.transform('x') : this.transform({ x: x - this.x() }, true)\r
+     }\r
+     // Move over y-axis\r
+   , y: function(y) {\r
+       return y == null ? this.transform('y') : this.transform({ y: y - this.y() }, true)\r
+     }\r
+     // Move by center over x-axis\r
+   , cx: function(x) {\r
+       return x == null ? this.gbox().cx : this.x(x - this.gbox().width / 2)\r
+     }\r
+     // Move by center over y-axis\r
+   , cy: function(y) {\r
+       return y == null ? this.gbox().cy : this.y(y - this.gbox().height / 2)\r
+     }\r
+   , gbox: function() {\r
\r
+       var bbox  = this.bbox()\r
+         , trans = this.transform()\r
\r
+       bbox.x  += trans.x\r
+       bbox.x2 += trans.x\r
+       bbox.cx += trans.x\r
\r
+       bbox.y  += trans.y\r
+       bbox.y2 += trans.y\r
+       bbox.cy += trans.y\r
\r
+       return bbox\r
+     }\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create a group element\r
+     group: function() {\r
+       return this.put(new SVG.G)\r
+     }\r
+   }\r
+ })\r
+ // ### This module adds backward / forward functionality to elements.\r
\r
+ //\r
+ SVG.extend(SVG.Element, {\r
+   // Get all siblings, including myself\r
+   siblings: function() {\r
+     return this.parent().children()\r
+   }\r
+   // Get the curent position siblings\r
+ , position: function() {\r
+     return this.parent().index(this)\r
+   }\r
+   // Get the next element (will return null if there is none)\r
+ , next: function() {\r
+     return this.siblings()[this.position() + 1]\r
+   }\r
+   // Get the next element (will return null if there is none)\r
+ , previous: function() {\r
+     return this.siblings()[this.position() - 1]\r
+   }\r
+   // Send given element one step forward\r
+ , forward: function() {\r
+     var i = this.position() + 1\r
+       , p = this.parent()\r
\r
+     // move node one step forward\r
+     p.removeElement(this).add(this, i)\r
\r
+     // make sure defs node is always at the top\r
+     if (p instanceof SVG.Doc)\r
+       p.node.appendChild(p.defs().node)\r
\r
+     return this\r
+   }\r
+   // Send given element one step backward\r
+ , backward: function() {\r
+     var i = this.position()\r
\r
+     if (i > 0)\r
+       this.parent().removeElement(this).add(this, i - 1)\r
\r
+     return this\r
+   }\r
+   // Send given element all the way to the front\r
+ , front: function() {\r
+     var p = this.parent()\r
\r
+     // Move node forward\r
+     p.node.appendChild(this.node)\r
\r
+     // Make sure defs node is always at the top\r
+     if (p instanceof SVG.Doc)\r
+       p.node.appendChild(p.defs().node)\r
\r
+     return this\r
+   }\r
+   // Send given element all the way to the back\r
+ , back: function() {\r
+     if (this.position() > 0)\r
+       this.parent().removeElement(this).add(this, 0)\r
\r
+     return this\r
+   }\r
+   // Inserts a given element before the targeted element\r
+ , before: function(element) {\r
+     element.remove()\r
\r
+     var i = this.position()\r
\r
+     this.parent().add(element, i)\r
\r
+     return this\r
+   }\r
+   // Insters a given element after the targeted element\r
+ , after: function(element) {\r
+     element.remove()\r
\r
+     var i = this.position()\r
\r
+     this.parent().add(element, i + 1)\r
\r
+     return this\r
+   }\r
\r
  })
- SVG.extend(SVG.Defs, {
-   // Create marker
-   marker: function(width, height, block) {
-     // Set default viewbox to match the width and height, set ref to cx and cy and set orient to auto
-     return this.put(new SVG.Marker)
-       .size(width, height)
-       .ref(width / 2, height / 2)
-       .viewbox(0, 0, width, height)
-       .attr('orient', 'auto')
-       .update(block)
-   }
+ SVG.Mask = SVG.invent({\r
+   // Initialize node\r
 -  create: function() {\r
 -    this.constructor.call(this, SVG.create('mask'))\r
 -\r
 -    // keep references to masked elements\r
 -    this.targets = []\r
 -  }\r
++  create: 'mask'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Container\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Unmask all masked elements and remove itself\r
+     remove: function() {\r
+       // unmask all targets\r
 -      for (var i = this.targets.length - 1; i >= 0; i--)\r
 -        if (this.targets[i])\r
 -          this.targets[i].unmask()\r
 -      this.targets = []\r
++      this.targets().forEach(function(el) {\r
++        el.unmask()\r
++      })\r
\r
+       // remove mask from parent\r
 -      this.parent().removeElement(this)\r
++      return SVG.Element.prototype.remove.call(this)\r
++    }\r
\r
 -      return this\r
++  , targets: function() {\r
++      return SVG.select('svg [mask*="' +this.id() +'"]')\r
+     }\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create masking element\r
+     mask: function() {\r
+       return this.defs().put(new SVG.Mask)\r
+     }\r
+   }\r
+ })\r
\r
\r
+ SVG.extend(SVG.Element, {\r
+   // Distribute mask to svg element\r
+   maskWith: function(element) {\r
+     // use given mask or create a new one\r
 -    this.masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element)\r
 -\r
 -    // store reverence on self in mask\r
 -    this.masker.targets.push(this)\r
++    var masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element)\r
\r
+     // apply mask\r
 -    return this.attr('mask', 'url("#' + this.masker.attr('id') + '")')\r
++    return this.attr('mask', 'url("#' + masker.attr('id') + '")')\r
+   }\r
+   // Unmask element\r
+ , unmask: function() {\r
 -    delete this.masker\r
+     return this.attr('mask', null)\r
+   }\r
 -\r
++, masker: function() {\r
++    return this.reference('mask')\r
++  }\r
+ })\r
+ SVG.ClipPath = SVG.invent({\r
+   // Initialize node\r
 -  create: function() {\r
 -    this.constructor.call(this, SVG.create('clipPath'))\r
 -\r
 -    // keep references to clipped elements\r
 -    this.targets = []\r
 -  }\r
++  create: 'clipPath'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Container\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Unclip all clipped elements and remove itself\r
+     remove: function() {\r
+       // unclip all targets\r
 -      for (var i = this.targets.length - 1; i >= 0; i--)\r
 -        if (this.targets[i])\r
 -          this.targets[i].unclip()\r
 -      this.targets = []\r
++      this.targets().forEach(function(el) {\r
++        el.unclip()\r
++      })\r
\r
+       // remove clipPath from parent\r
 -      this.parent().removeElement(this)\r
++      return SVG.Element.prototype.remove.call(this)\r
++    }\r
\r
 -      return this\r
++  , targets: function() {\r
++      return SVG.select('svg [clip-path*="' +this.id() +'"]')\r
+     }\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create clipping element\r
+     clip: function() {\r
+       return this.defs().put(new SVG.ClipPath)\r
+     }\r
+   }\r
+ })\r
\r
+ //\r
+ SVG.extend(SVG.Element, {\r
+   // Distribute clipPath to svg element\r
+   clipWith: function(element) {\r
+     // use given clip or create a new one\r
 -    this.clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element)\r
 -\r
 -    // store reverence on self in mask\r
 -    this.clipper.targets.push(this)\r
++    var clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element)\r
\r
+     // apply mask\r
 -    return this.attr('clip-path', 'url("#' + this.clipper.attr('id') + '")')\r
++    return this.attr('clip-path', 'url("#' + clipper.attr('id') + '")')\r
+   }\r
+   // Unclip element\r
+ , unclip: function() {\r
 -    delete this.clipper\r
+     return this.attr('clip-path', null)\r
+   }\r
++, clipper: function() {\r
++    return this.reference('clip-path')\r
++  }\r
\r
  })
- SVG.extend(SVG.Line, SVG.Polyline, SVG.Polygon, SVG.Path, {
-   // Create and attach markers
-   marker: function(marker, width, height, block) {
-     var attr = ['marker']
-     // Build attribute name
-     if (marker != 'all') attr.push(marker)
-     attr = attr.join('-')
-     // Set marker attribute
-     marker = arguments[1] instanceof SVG.Marker ?
-       arguments[1] :
-       this.doc().marker(width, height, block)
-     return this.attr(attr, marker)
-   }
+ SVG.Gradient = SVG.invent({\r
+   // Initialize node\r
+   create: function(type) {\r
+     this.constructor.call(this, SVG.create(type + 'Gradient'))\r
 -\r
 -    // store type\r
 -    this.type = type\r
+   }\r
\r
+   // Inherit from\r
+ , inherit: SVG.Container\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Add a color stop\r
+     at: function(offset, color, opacity) {\r
+       return this.put(new SVG.Stop).update(offset, color, opacity)\r
+     }\r
+     // Update gradient\r
+   , update: function(block) {\r
+       // remove all stops\r
+       this.clear()\r
\r
+       // invoke passed block\r
+       if (typeof block == 'function')\r
+         block.call(this, this)\r
\r
+       return this\r
+     }\r
+     // Return the fill id\r
+   , fill: function() {\r
+       return 'url(#' + this.id() + ')'\r
+     }\r
+     // Alias string convertion to fill\r
+   , toString: function() {\r
+       return this.fill()\r
+     }\r
+     // custom attr to handle transform\r
+   , attr: function(a, b, c) {\r
+       if(a == 'transform') a = 'gradientTransform'\r
+       return SVG.Container.prototype.attr.call(this, a, b, c)\r
+     }\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create gradient element in defs\r
+     gradient: function(type, block) {\r
+       return this.defs().gradient(type, block)\r
+     }\r
+   }\r
+ })\r
\r
+ // Add animatable methods to both gradient and fx module\r
+ SVG.extend(SVG.Gradient, SVG.FX, {\r
+   // From position\r
+   from: function(x, y) {\r
 -    return (this._target || this).type == 'radial' ?\r
++    return (this._target || this).type == 'radialGradient' ?\r
+       this.attr({ fx: new SVG.Number(x), fy: new SVG.Number(y) }) :\r
+       this.attr({ x1: new SVG.Number(x), y1: new SVG.Number(y) })\r
+   }\r
+   // To position\r
+ , to: function(x, y) {\r
 -    return (this._target || this).type == 'radial' ?\r
++    return (this._target || this).type == 'radialGradient' ?\r
+       this.attr({ cx: new SVG.Number(x), cy: new SVG.Number(y) }) :\r
+       this.attr({ x2: new SVG.Number(x), y2: new SVG.Number(y) })\r
+   }\r
+ })\r
\r
+ // Base gradient generation\r
+ SVG.extend(SVG.Defs, {\r
+   // define gradient\r
+   gradient: function(type, block) {\r
+     return this.put(new SVG.Gradient(type)).update(block)\r
+   }\r
\r
+ })\r
\r
+ SVG.Stop = SVG.invent({\r
+   // Initialize node\r
+   create: 'stop'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Element\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // add color stops\r
+     update: function(o) {\r
+       if (typeof o == 'number' || o instanceof SVG.Number) {\r
+         o = {\r
+           offset:  arguments[0]\r
+         , color:   arguments[1]\r
+         , opacity: arguments[2]\r
+         }\r
+       }\r
\r
+       // set attributes\r
+       if (o.opacity != null) this.attr('stop-opacity', o.opacity)\r
+       if (o.color   != null) this.attr('stop-color', o.color)\r
+       if (o.offset  != null) this.attr('offset', new SVG.Number(o.offset))\r
\r
+       return this\r
+     }\r
+   }\r
\r
+ })\r
+ SVG.Pattern = SVG.invent({\r
+   // Initialize node\r
+   create: 'pattern'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Container\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Return the fill id\r
+     fill: function() {\r
+       return 'url(#' + this.id() + ')'\r
+     }\r
+     // Update pattern by rebuilding\r
+   , update: function(block) {\r
+       // remove content\r
+       this.clear()\r
\r
+       // invoke passed block\r
+       if (typeof block == 'function')\r
+         block.call(this, this)\r
\r
+       return this\r
+     }\r
+     // Alias string convertion to fill\r
+   , toString: function() {\r
+       return this.fill()\r
+     }\r
+     // custom attr to handle transform\r
+   , attr: function(a, b, c) {\r
+       if(a == 'transform') a = 'patternTransform'\r
+       return SVG.Container.prototype.attr.call(this, a, b, c)\r
+     }\r
\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create pattern element in defs\r
+     pattern: function(width, height, block) {\r
+       return this.defs().pattern(width, height, block)\r
+     }\r
+   }\r
+ })\r
\r
+ SVG.extend(SVG.Defs, {\r
+   // Define gradient\r
+   pattern: function(width, height, block) {\r
+     return this.put(new SVG.Pattern).update(block).attr({\r
+       x:            0\r
+     , y:            0\r
+     , width:        width\r
+     , height:       height\r
+     , patternUnits: 'userSpaceOnUse'\r
+     })\r
+   }\r
\r
  })
- // Define list of available attributes for stroke and fill
- var sugar = {
-   stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset']
- , fill:   ['color', 'opacity', 'rule']
- , prefix: function(t, a) {
-     return a == 'color' ? t : t + '-' + a
-   }
- }
- // Add sugar for fill and stroke
- ;['fill', 'stroke'].forEach(function(m) {
-   var i, extension = {}
-   extension[m] = function(o) {
-     if (typeof o == 'undefined')
-       return this
-     if (typeof o == 'string' || SVG.Color.isRgb(o) || (o && typeof o.fill === 'function'))
-       this.attr(m, o)
-     else
-       // set all attributes from sugar.fill and sugar.stroke list
-       for (i = sugar[m].length - 1; i >= 0; i--)
-         if (o[sugar[m][i]] != null)
-           this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]])
-     return this
-   }
-   SVG.extend(SVG.Element, SVG.FX, extension)
+ SVG.Doc = SVG.invent({\r
+   // Initialize node\r
+   create: function(element) {\r
+     if (element) {\r
+       // ensure the presence of a dom element\r
+       element = typeof element == 'string' ?\r
+         document.getElementById(element) :\r
+         element\r
\r
+       // If the target is an svg element, use that element as the main wrapper.\r
+       // This allows svg.js to work with svg documents as well.\r
+       if (element.nodeName == 'svg') {\r
+         this.constructor.call(this, element)\r
+       } else {\r
+         this.constructor.call(this, SVG.create('svg'))\r
+         element.appendChild(this.node)\r
+         this.size('100%', '100%')\r
+       }\r
\r
+       // set svg element attributes and ensure defs node\r
+       this.namespace().defs()\r
+     }\r
+   }\r
\r
+   // Inherit from\r
+ , inherit: SVG.Container\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Add namespaces\r
+     namespace: function() {\r
+       return this\r
+         .attr({ xmlns: SVG.ns, version: '1.1' })\r
+         .attr('xmlns:xlink', SVG.xlink, SVG.xmlns)\r
+         .attr('xmlns:svgjs', SVG.svgjs, SVG.xmlns)\r
+     }\r
+     // Creates and returns defs element\r
+   , defs: function() {\r
+       if (!this._defs) {\r
+         var defs\r
\r
+         // Find or create a defs element in this instance\r
+         if (defs = this.node.getElementsByTagName('defs')[0])\r
+           this._defs = SVG.adopt(defs)\r
+         else\r
+           this._defs = new SVG.Defs\r
\r
+         // Make sure the defs node is at the end of the stack\r
+         this.node.appendChild(this._defs.node)\r
+       }\r
\r
+       return this._defs\r
+     }\r
+     // custom parent method\r
+   , parent: function() {\r
+       return this.node.parentNode.nodeName == '#document' ? null : this.node.parentNode\r
+     }\r
+     // Fix for possible sub-pixel offset. See:\r
+     // https://bugzilla.mozilla.org/show_bug.cgi?id=608812\r
+   , spof: function(spof) {\r
+       var pos = this.node.getScreenCTM()\r
\r
+       if (pos)\r
+         this\r
+           .style('left', (-pos.e % 1) + 'px')\r
+           .style('top',  (-pos.f % 1) + 'px')\r
\r
+       return this\r
+     }\r
\r
+       // Removes the doc from the DOM\r
+   , remove: function() {\r
+       if(this.parent()) {\r
+         this.parent().removeChild(this.node)\r
+       }\r
\r
+       return this\r
+     }\r
+   , clear: function() {\r
+       // remove children\r
+       while(this.node.hasChildNodes())\r
+         this.node.removeChild(this.node.lastChild)\r
\r
+       // remove defs reference\r
+       delete this._defs\r
\r
+       // add back parser\r
+       if(!SVG.parser.draw.parentNode)\r
+         this.node.appendChild(SVG.parser.draw)\r
\r
+       return this\r
+     }\r
+   }\r
\r
+ })\r
+ SVG.Shape = SVG.invent({\r
+   // Initialize node\r
+   create: function(element) {\r
+     this.constructor.call(this, element)\r
+   }\r
\r
+   // Inherit from\r
+ , inherit: SVG.Element\r
\r
  })
- SVG.extend(SVG.Element, SVG.FX, {
-   // Map rotation to transform
-   rotate: function(d, cx, cy) {
-     return this.transform({ rotation: d, cx: cx, cy: cy })
-   }
-   // Map skew to transform
- , skew: function(x, y, cx, cy) {
-     return arguments.length == 1  || arguments.length == 3 ?
-       this.transform({ skew: x, cx: y, cy: cx }) :
-       this.transform({ skewX: x, skewY: y, cx: cx, cy: cy })
-   }
-   // Map scale to transform
- , scale: function(x, y, cx, cy) {
-     return arguments.length == 1  || arguments.length == 3 ?
-       this.transform({ scale: x, cx: y, cy: cx }) :
-       this.transform({ scaleX: x, scaleY: y, cx: cx, cy: cy })
-   }
-   // Map translate to transform
- , translate: function(x, y) {
-     return this.transform({ x: x, y: y })
-   }
-   // Map flip to transform
- , flip: function(a, o) {
-     o = typeof a == 'number' ? a : o
-     return this.transform({ flip: a || 'both', offset: o })
-   }
-   // Map matrix to transform
- , matrix: function(m) {
-     return this.attr('transform', new SVG.Matrix(arguments.length == 6 ? [].slice.call(arguments) : m))
-   }
-   // Opacity
- , opacity: function(value) {
-     return this.attr('opacity', value)
-   }
-   // Relative move over x axis
- , dx: function(x) {
-     return this.x(new SVG.Number(x).plus(this instanceof SVG.FX ? 0 : this.x()), true)
-   }
-   // Relative move over y axis
- , dy: function(y) {
-     return this.y(new SVG.Number(y).plus(this instanceof SVG.FX ? 0 : this.y()), true)
-   }
-   // Relative move over x and y axes
- , dmove: function(x, y) {
-     return this.dx(x).dy(y)
-   }
\r
+ SVG.Bare = SVG.invent({\r
+   // Initialize\r
+   create: function(element, inherit) {\r
+     // construct element\r
+     this.constructor.call(this, SVG.create(element))\r
\r
+     // inherit custom methods\r
+     if (inherit)\r
+       for (var method in inherit.prototype)\r
+         if (typeof inherit.prototype[method] === 'function')\r
+           this[method] = inherit.prototype[method]\r
+   }\r
\r
+   // Inherit from\r
+ , inherit: SVG.Element\r
\r
+   // Add methods\r
+ , extend: {\r
+     // Insert some plain text\r
+     words: function(text) {\r
+       // remove contents\r
+       while (this.node.hasChildNodes())\r
+         this.node.removeChild(this.node.lastChild)\r
\r
+       // create text node\r
+       this.node.appendChild(document.createTextNode(text))\r
\r
+       return this\r
+     }\r
+   }\r
+ })\r
\r
\r
+ SVG.extend(SVG.Parent, {\r
+   // Create an element that is not described by SVG.js\r
+   element: function(element, inherit) {\r
+     return this.put(new SVG.Bare(element, inherit))\r
+   }\r
+ })\r
+ SVG.Symbol = SVG.invent({\r
+   // Initialize node\r
+   create: 'symbol'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Container\r
\r
+ , construct: {\r
+     // create symbol\r
+     symbol: function() {\r
+       return this.put(new SVG.Symbol)\r
+     }\r
+   }\r
+ })\r
+ SVG.Use = SVG.invent({\r
+   // Initialize node\r
+   create: 'use'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Shape\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Use element as a reference\r
+     element: function(element, file) {\r
+       // Set lined element\r
+       return this.attr('href', (file || '') + '#' + element, SVG.xlink)\r
+     }\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create a use element\r
+     use: function(element, file) {\r
+       return this.put(new SVG.Use).element(element, file)\r
+     }\r
+   }\r
  })
- SVG.extend(SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.FX, {
-   // Add x and y radius
-   radius: function(x, y) {
-     var type = (this._target || this).type;
-     return type == 'radialGradient' || type == 'radialGradient' ?
-       this.attr('r', new SVG.Number(x)) :
-       this.rx(x).ry(y == null ? x : y)
-   }
+ SVG.Rect = SVG.invent({\r
+   // Initialize node\r
+   create: 'rect'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Shape\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create a rect element\r
+     rect: function(width, height) {\r
+       return this.put(new SVG.Rect()).size(width, height)\r
+     }\r
+   }\r
  })
- SVG.extend(SVG.Path, {
-   // Get path length
-   length: function() {
-     return this.node.getTotalLength()
-   }
-   // Get point at length
- , pointAt: function(length) {
-     return new SVG.Point(this.node.getPointAtLength(length))
-   }
+ SVG.Circle = SVG.invent({\r
+   // Initialize node\r
+   create: 'circle'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Shape\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create circle element, based on ellipse\r
+     circle: function(size) {\r
+       return this.put(new SVG.Circle).rx(new SVG.Number(size).divide(2)).move(0, 0)\r
+     }\r
+   }\r
+ })\r
\r
+ SVG.extend(SVG.Circle, SVG.FX, {\r
+   // Radius x value\r
+   rx: function(rx) {\r
+     return this.attr('r', rx)\r
+   }\r
+   // Alias radius x value\r
+ , ry: function(ry) {\r
+     return this.rx(ry)\r
+   }\r
+ })\r
\r
+ SVG.Ellipse = SVG.invent({\r
+   // Initialize node\r
+   create: 'ellipse'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Shape\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create an ellipse\r
+     ellipse: function(width, height) {\r
+       return this.put(new SVG.Ellipse).size(width, height).move(0, 0)\r
+     }\r
+   }\r
+ })\r
\r
+ SVG.extend(SVG.Ellipse, SVG.Rect, SVG.FX, {\r
+   // Radius x value\r
+   rx: function(rx) {\r
+     return this.attr('rx', rx)\r
+   }\r
+   // Radius y value\r
+ , ry: function(ry) {\r
+     return this.attr('ry', ry)\r
+   }\r
+ })\r
\r
+ // Add common method\r
+ SVG.extend(SVG.Circle, SVG.Ellipse, {\r
+     // Move over x-axis\r
+     x: function(x) {\r
+       return x == null ? this.cx() - this.rx() : this.cx(x + this.rx())\r
+     }\r
+     // Move over y-axis\r
+   , y: function(y) {\r
+       return y == null ? this.cy() - this.ry() : this.cy(y + this.ry())\r
+     }\r
+     // Move by center over x-axis\r
+   , cx: function(x) {\r
+       return x == null ? this.attr('cx') : this.attr('cx', x)\r
+     }\r
+     // Move by center over y-axis\r
+   , cy: function(y) {\r
+       return y == null ? this.attr('cy') : this.attr('cy', y)\r
+     }\r
+     // Set width of element\r
+   , width: function(width) {\r
+       return width == null ? this.rx() * 2 : this.rx(new SVG.Number(width).divide(2))\r
+     }\r
+     // Set height of element\r
+   , height: function(height) {\r
+       return height == null ? this.ry() * 2 : this.ry(new SVG.Number(height).divide(2))\r
+     }\r
+     // Custom size function\r
+   , size: function(width, height) {\r
+       var p = proportionalSize(this, width, height)\r
\r
+       return this\r
+         .rx(new SVG.Number(p.width).divide(2))\r
+         .ry(new SVG.Number(p.height).divide(2))\r
+     }\r
  })
- SVG.extend(SVG.Parent, SVG.Text, SVG.Tspan, SVG.FX, {
-   // Set font
-   font: function(a, v) {
-     if (typeof a == 'object') {
-       for (v in a) this.font(v, a[v])
-     }
-     return a == 'leading' ?
-         this.leading(v) :
-       a == 'anchor' ?
-         this.attr('text-anchor', v) :
-       a == 'size' || a == 'family' || a == 'weight' || a == 'stretch' || a == 'variant' || a == 'style' ?
-         this.attr('font-'+ a, v) :
-         this.attr(a, v)
-   }
+ SVG.Line = SVG.invent({\r
+   // Initialize node\r
+   create: 'line'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Shape\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Get array\r
+     array: function() {\r
+       return new SVG.PointArray([\r
+         [ this.attr('x1'), this.attr('y1') ]\r
+       , [ this.attr('x2'), this.attr('y2') ]\r
+       ])\r
+     }\r
+     // Overwrite native plot() method\r
+   , plot: function(x1, y1, x2, y2) {\r
+       if (x1 == null)\r
+         return this.array()\r
+       else if (typeof y1 !== 'undefined')\r
+         x1 = { x1: x1, y1: y1, x2: x2, y2: y2 }\r
+       else\r
+         x1 = new SVG.PointArray(x1).toLine()\r
\r
+       return this.attr(x1)\r
+     }\r
+     // Move by left top corner\r
+   , move: function(x, y) {\r
+       return this.attr(this.array().move(x, y).toLine())\r
+     }\r
+     // Set element size to given width and height\r
+   , size: function(width, height) {\r
+       var p = proportionalSize(this, width, height)\r
\r
+       return this.attr(this.array().size(p.width, p.height).toLine())\r
+     }\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create a line element\r
+     line: function(x1, y1, x2, y2) {\r
+       // make sure plot is called as a setter\r
+       // x1 is not necessarily a number, it can also be an array, a string and a SVG.PointArray\r
+       return SVG.Line.prototype.plot.apply(\r
+         this.put(new SVG.Line)\r
+       , x1 != null ? [x1, y1, x2, y2] : [0, 0, 0, 0]\r
+       )\r
+     }\r
+   }\r
+ })\r
+ SVG.Polyline = SVG.invent({\r
+   // Initialize node\r
+   create: 'polyline'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Shape\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create a wrapped polyline element\r
+     polyline: function(p) {\r
+       // make sure plot is called as a setter\r
+       return this.put(new SVG.Polyline).plot(p || new SVG.PointArray)\r
+     }\r
+   }\r
+ })\r
\r
+ SVG.Polygon = SVG.invent({\r
+   // Initialize node\r
+   create: 'polygon'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Shape\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create a wrapped polygon element\r
+     polygon: function(p) {\r
+       // make sure plot is called as a setter\r
+       return this.put(new SVG.Polygon).plot(p || new SVG.PointArray)\r
+     }\r
+   }\r
+ })\r
\r
+ // Add polygon-specific functions\r
+ SVG.extend(SVG.Polyline, SVG.Polygon, {\r
+   // Get array\r
+   array: function() {\r
+     return this._array || (this._array = new SVG.PointArray(this.attr('points')))\r
+   }\r
+   // Plot new path\r
+ , plot: function(p) {\r
+     return (p == null) ?\r
+       this.array() :\r
+       this.clear().attr('points', typeof p == 'string' ? p : (this._array = new SVG.PointArray(p)))\r
+   }\r
+   // Clear array cache\r
+ , clear: function() {\r
+     delete this._array\r
+     return this\r
+   }\r
+   // Move by left top corner\r
+ , move: function(x, y) {\r
+     return this.attr('points', this.array().move(x, y))\r
+   }\r
+   // Set element size to given width and height\r
+ , size: function(width, height) {\r
+     var p = proportionalSize(this, width, height)\r
\r
+     return this.attr('points', this.array().size(p.width, p.height))\r
+   }\r
\r
+ })\r
+ // unify all point to point elements\r
+ SVG.extend(SVG.Line, SVG.Polyline, SVG.Polygon, {\r
+   // Define morphable array\r
+   morphArray:  SVG.PointArray\r
+   // Move by left top corner over x-axis\r
+ , x: function(x) {\r
+     return x == null ? this.bbox().x : this.move(x, this.bbox().y)\r
+   }\r
+   // Move by left top corner over y-axis\r
+ , y: function(y) {\r
+     return y == null ? this.bbox().y : this.move(this.bbox().x, y)\r
+   }\r
+   // Set width of element\r
+ , width: function(width) {\r
+     var b = this.bbox()\r
\r
+     return width == null ? b.width : this.size(width, b.height)\r
+   }\r
+   // Set height of element\r
+ , height: function(height) {\r
+     var b = this.bbox()\r
\r
+     return height == null ? b.height : this.size(b.width, height)\r
+   }\r
  })
- SVG.extend(SVG.Element, {
-   // Store data values on svg nodes
-   data: function(a, v, r) {
-     if (typeof a == 'object') {
-       for (v in a)
-         this.data(v, a[v])
-     } else if (arguments.length < 2) {
-       try {
-         return JSON.parse(this.attr('data-' + a))
-       } catch(e) {
-         return this.attr('data-' + a)
-       }
-     } else {
-       this.attr(
-         'data-' + a
-       , v === null ?
-           null :
-         r === true || typeof v === 'string' || typeof v === 'number' ?
-           v :
-           JSON.stringify(v)
-       )
-     }
-     return this
-   }
+ SVG.Path = SVG.invent({\r
+   // Initialize node\r
+   create: 'path'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Shape\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Define morphable array\r
+     morphArray:  SVG.PathArray\r
+     // Get array\r
+   , array: function() {\r
+       return this._array || (this._array = new SVG.PathArray(this.attr('d')))\r
+     }\r
+     // Plot new path\r
+   , plot: function(d) {\r
+       return (d == null) ?\r
+         this.array() :\r
+         this.clear().attr('d', typeof d == 'string' ? d : (this._array = new SVG.PathArray(d)))\r
+     }\r
+     // Clear array cache\r
+   , clear: function() {\r
+       delete this._array\r
+       return this\r
+     }\r
+     // Move by left top corner\r
+   , move: function(x, y) {\r
+       return this.attr('d', this.array().move(x, y))\r
+     }\r
+     // Move by left top corner over x-axis\r
+   , x: function(x) {\r
+       return x == null ? this.bbox().x : this.move(x, this.bbox().y)\r
+     }\r
+     // Move by left top corner over y-axis\r
+   , y: function(y) {\r
+       return y == null ? this.bbox().y : this.move(this.bbox().x, y)\r
+     }\r
+     // Set element size to given width and height\r
+   , size: function(width, height) {\r
+       var p = proportionalSize(this, width, height)\r
\r
+       return this.attr('d', this.array().size(p.width, p.height))\r
+     }\r
+     // Set width of element\r
+   , width: function(width) {\r
+       return width == null ? this.bbox().width : this.size(width, this.bbox().height)\r
+     }\r
+     // Set height of element\r
+   , height: function(height) {\r
+       return height == null ? this.bbox().height : this.size(this.bbox().width, height)\r
+     }\r
\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create a wrapped path element\r
+     path: function(d) {\r
+       // make sure plot is called as a setter\r
+       return this.put(new SVG.Path).plot(d || new SVG.PathArray)\r
+     }\r
+   }\r
+ })\r
+ SVG.Image = SVG.invent({\r
+   // Initialize node\r
+   create: 'image'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Shape\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // (re)load image\r
 -    load: function(url) {\r
++    load: function(url, callback) {\r
+       if (!url) return this\r
\r
 -      var self = this\r
 -        , img  = new window.Image()\r
++      var img = new window.Image()\r
\r
 -      // preload image\r
 -      SVG.on(img, 'load', function() {\r
 -        var p = self.parent(SVG.Pattern)\r
++      SVG.on(img, 'load', function(e) {\r
\r
 -        if(p === null) return\r
++        var p = this.parent()\r
\r
+         // ensure image size\r
 -        if (self.width() == 0 && self.height() == 0)\r
 -          self.size(img.width, img.height)\r
++        if (this.width() == 0 && this.height() == 0)\r
++          this.size(img.width, img.height)\r
\r
 -        // ensure pattern size if not set\r
 -        if (p && p.width() == 0 && p.height() == 0)\r
 -          p.size(self.width(), self.height())\r
++        if(p instanceof SVG.Pattern) {\r
++          // ensure pattern size if not set\r
++          if (p.width() == 0 && p.height() == 0)\r
++            p.size(this.width(), this.height())\r
++        }\r
\r
 -        // callback\r
 -        if (typeof self._loaded === 'function')\r
 -          self._loaded.call(self, {\r
++        if(typeof callback == 'function') {\r
++          callback.call(this, {\r
+             width:  img.width\r
+           , height: img.height\r
+           , ratio:  img.width / img.height\r
+           , url:    url\r
+           })\r
 -      })\r
 -\r
 -      SVG.on(img, 'error', function(e){\r
 -        if (typeof self._error === 'function'){\r
 -            self._error.call(self, e)\r
+         }\r
 -      })\r
++      }, this)\r
\r
 -      return this.attr('href', (img.src = this.src = url), SVG.xlink)\r
 -    }\r
 -    // Add loaded callback\r
 -  , loaded: function(loaded) {\r
 -      this._loaded = loaded\r
 -      return this\r
 -    }\r
 -\r
 -  , error: function(error) {\r
 -      this._error = error\r
 -      return this\r
++      return this.attr('href', (img.src = url), SVG.xlink)\r
+     }\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // create image element, load image and set its size\r
 -    image: function(source, width, height) {\r
 -      return this.put(new SVG.Image).load(source).size(width || 0, height || width || 0)\r
++    image: function(source, callback) {\r
++      return this.put(new SVG.Image).size(0, 0).load(source, callback)\r
+     }\r
+   }\r
 -\r
 -})
++})\r
++
+ SVG.Text = SVG.invent({\r
+   // Initialize node\r
+   create: function() {\r
+     this.constructor.call(this, SVG.create('text'))\r
\r
+     this.dom.leading = new SVG.Number(1.3)    // store leading value for rebuilding\r
+     this._rebuild = true                      // enable automatic updating of dy values\r
+     this._build   = false                     // disable build mode for adding multiple lines\r
\r
+     // set default font\r
+     this.attr('font-family', SVG.defaults.attrs['font-family'])\r
+   }\r
\r
+   // Inherit from\r
 -, inherit: SVG.Shape\r
++, inherit: SVG.Parent\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Move over x-axis\r
+     x: function(x) {\r
+       // act as getter\r
+       if (x == null)\r
+         return this.attr('x')\r
\r
+       return this.attr('x', x)\r
+     }\r
+     // Move over y-axis\r
+   , y: function(y) {\r
+       var oy = this.attr('y')\r
+         , o  = typeof oy === 'number' ? oy - this.bbox().y : 0\r
\r
+       // act as getter\r
+       if (y == null)\r
+         return typeof oy === 'number' ? oy - o : oy\r
\r
+       return this.attr('y', typeof y === 'number' ? y + o : y)\r
+     }\r
+     // Move center over x-axis\r
+   , cx: function(x) {\r
+       return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2)\r
+     }\r
+     // Move center over y-axis\r
+   , cy: function(y) {\r
+       return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2)\r
+     }\r
+     // Set the text content\r
+   , text: function(text) {\r
+       // act as getter\r
+       if (typeof text === 'undefined'){\r
+         var text = ''\r
+         var children = this.node.childNodes\r
+         for(var i = 0, len = children.length; i < len; ++i){\r
\r
+           // add newline if its not the first child and newLined is set to true\r
+           if(i != 0 && children[i].nodeType != 3 && SVG.adopt(children[i]).dom.newLined == true){\r
+             text += '\n'\r
+           }\r
\r
+           // add content of this node\r
+           text += children[i].textContent\r
+         }\r
\r
+         return text\r
+       }\r
\r
+       // remove existing content\r
+       this.clear().build(true)\r
\r
+       if (typeof text === 'function') {\r
+         // call block\r
+         text.call(this, this)\r
\r
+       } else {\r
+         // store text and make sure text is not blank\r
+         text = text.split('\n')\r
\r
+         // build new lines\r
+         for (var i = 0, il = text.length; i < il; i++)\r
+           this.tspan(text[i]).newLine()\r
+       }\r
\r
+       // disable build mode and rebuild lines\r
+       return this.build(false).rebuild()\r
+     }\r
+     // Set font size\r
+   , size: function(size) {\r
+       return this.attr('font-size', size).rebuild()\r
+     }\r
+     // Set / get leading\r
+   , leading: function(value) {\r
+       // act as getter\r
+       if (value == null)\r
+         return this.dom.leading\r
\r
+       // act as setter\r
+       this.dom.leading = new SVG.Number(value)\r
\r
+       return this.rebuild()\r
+     }\r
 -    // Get all the first level lines\r
 -  , lines: function() {\r
 -      var node = (this.textPath && this.textPath() || this).node\r
 -\r
 -      // filter tspans and map them to SVG.js instances\r
 -      var lines = SVG.utils.map(SVG.utils.filterSVGElements(node.childNodes), function(el){\r
 -        return SVG.adopt(el)\r
 -      })\r
 -\r
 -      // return an instance of SVG.set\r
 -      return new SVG.Set(lines)\r
 -    }\r
+     // Rebuild appearance type\r
+   , rebuild: function(rebuild) {\r
+       // store new rebuild flag if given\r
+       if (typeof rebuild == 'boolean')\r
+         this._rebuild = rebuild\r
\r
+       // define position of all lines\r
+       if (this._rebuild) {\r
+         var self = this\r
+           , blankLineOffset = 0\r
+           , dy = this.dom.leading * new SVG.Number(this.attr('font-size'))\r
\r
 -        this.lines().each(function() {\r
++        this.each(function() {\r
+           if (this.dom.newLined) {\r
+             if (!self.textPath())\r
+               this.attr('x', self.attr('x'))\r
+             if(this.text() == '\n') {\r
+               blankLineOffset += dy\r
+             }else{\r
+               this.attr('dy', dy + blankLineOffset)\r
+               blankLineOffset = 0\r
+             }\r
+           }\r
+         })\r
\r
+         this.fire('rebuild')\r
+       }\r
\r
+       return this\r
+     }\r
+     // Enable / disable build mode\r
+   , build: function(build) {\r
+       this._build = !!build\r
+       return this\r
+     }\r
+     // overwrite method from parent to set data properly\r
+   , setData: function(o){\r
+       this.dom = o\r
+       this.dom.leading = new SVG.Number(o.leading || 1.3)\r
+       return this\r
+     }\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create text element\r
+     text: function(text) {\r
+       return this.put(new SVG.Text).text(text)\r
+     }\r
+     // Create plain text element\r
+   , plain: function(text) {\r
+       return this.put(new SVG.Text).plain(text)\r
+     }\r
+   }\r
\r
+ })\r
\r
+ SVG.Tspan = SVG.invent({\r
+   // Initialize node\r
+   create: 'tspan'\r
\r
+   // Inherit from\r
 -, inherit: SVG.Shape\r
++, inherit: SVG.Parent\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Set text content\r
+     text: function(text) {\r
+       if(text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '')\r
\r
+       typeof text === 'function' ? text.call(this, this) : this.plain(text)\r
\r
+       return this\r
+     }\r
+     // Shortcut dx\r
+   , dx: function(dx) {\r
+       return this.attr('dx', dx)\r
+     }\r
+     // Shortcut dy\r
+   , dy: function(dy) {\r
+       return this.attr('dy', dy)\r
+     }\r
+     // Create new line\r
+   , newLine: function() {\r
+       // fetch text parent\r
+       var t = this.parent(SVG.Text)\r
\r
+       // mark new line\r
+       this.dom.newLined = true\r
\r
+       // apply new hy¡n\r
+       return this.dy(t.dom.leading * t.attr('font-size')).attr('x', t.x())\r
+     }\r
+   }\r
\r
+ })\r
\r
+ SVG.extend(SVG.Text, SVG.Tspan, {\r
+   // Create plain text node\r
+   plain: function(text) {\r
+     // clear if build mode is disabled\r
+     if (this._build === false)\r
+       this.clear()\r
\r
+     // create text node\r
+     this.node.appendChild(document.createTextNode(text))\r
\r
+     return this\r
+   }\r
+   // Create a tspan\r
+ , tspan: function(text) {\r
+     var node  = (this.textPath && this.textPath() || this).node\r
+       , tspan = new SVG.Tspan\r
\r
+     // clear if build mode is disabled\r
+     if (this._build === false)\r
+       this.clear()\r
\r
+     // add new tspan\r
+     node.appendChild(tspan.node)\r
\r
+     return tspan.text(text)\r
+   }\r
 -  // Clear all lines\r
 -, clear: function() {\r
 -    var node = (this.textPath && this.textPath() || this).node\r
 -\r
 -    // remove existing child nodes\r
 -    while (node.hasChildNodes())\r
 -      node.removeChild(node.lastChild)\r
 -\r
 -    return this\r
 -  }\r
+   // Get length of text element\r
+ , length: function() {\r
+     return this.node.getComputedTextLength()\r
+   }\r
+ })\r
+ SVG.TextPath = SVG.invent({\r
+   // Initialize node\r
+   create: 'textPath'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Parent\r
\r
+   // Define parent class\r
+ , parent: SVG.Text\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create path for text to run on\r
+     path: function(d) {\r
+       // create textPath element\r
+       var path  = new SVG.TextPath\r
+         , track = this.doc().defs().path(d)\r
\r
+       // move lines to textpath\r
+       while (this.node.hasChildNodes())\r
+         path.node.appendChild(this.node.firstChild)\r
\r
+       // add textPath element as child node\r
+       this.node.appendChild(path.node)\r
\r
+       // link textPath to path and add content\r
+       path.attr('href', '#' + track, SVG.xlink)\r
\r
+       return this\r
+     }\r
+     // return the array of the path track element\r
+   , array: function() {\r
+       var track = this.track()\r
\r
+       return track ? track.array() : null\r
+     }\r
+     // Plot path if any\r
+   , plot: function(d) {\r
+       var track = this.track()\r
+         , pathArray = null\r
\r
+       if (track) {\r
+         pathArray = track.plot(d)\r
+       }\r
\r
+       return (d == null) ? pathArray : this\r
+     }\r
+     // Get the path track element\r
+   , track: function() {\r
+       var path = this.textPath()\r
\r
+       if (path)\r
+         return path.reference('href')\r
+     }\r
+     // Get the textPath child\r
+   , textPath: function() {\r
+       if (this.node.firstChild && this.node.firstChild.nodeName == 'textPath')\r
+         return SVG.adopt(this.node.firstChild)\r
+     }\r
+   }\r
+ })\r
+ SVG.Nested = SVG.invent({\r
+   // Initialize node\r
+   create: function() {\r
+     this.constructor.call(this, SVG.create('svg'))\r
\r
+     this.style('overflow', 'visible')\r
+   }\r
\r
+   // Inherit from\r
+ , inherit: SVG.Container\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create nested svg document\r
+     nested: function() {\r
+       return this.put(new SVG.Nested)\r
+     }\r
+   }\r
  })
- SVG.extend(SVG.Element, {
-   // Remember arbitrary data
-   remember: function(k, v) {
-     // remember every item in an object individually
-     if (typeof arguments[0] == 'object')
-       for (var v in k)
-         this.remember(v, k[v])
-     // retrieve memory
-     else if (arguments.length == 1)
-       return this.memory()[k]
-     // store memory
-     else
-       this.memory()[k] = v
-     return this
-   }
-   // Erase a given memory
- , forget: function() {
-     if (arguments.length == 0)
-       this._memory = {}
-     else
-       for (var i = arguments.length - 1; i >= 0; i--)
-         delete this.memory()[arguments[i]]
-     return this
-   }
-   // Initialize or return local memory object
- , memory: function() {
-     return this._memory || (this._memory = {})
-   }
+ SVG.A = SVG.invent({\r
+   // Initialize node\r
+   create: 'a'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Container\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Link url\r
+     to: function(url) {\r
+       return this.attr('href', url, SVG.xlink)\r
+     }\r
+     // Link show attribute\r
+   , show: function(target) {\r
+       return this.attr('show', target, SVG.xlink)\r
+     }\r
+     // Link target attribute\r
+   , target: function(target) {\r
+       return this.attr('target', target)\r
+     }\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     // Create a hyperlink element\r
+     link: function(url) {\r
+       return this.put(new SVG.A).to(url)\r
+     }\r
+   }\r
+ })\r
\r
+ SVG.extend(SVG.Element, {\r
+   // Create a hyperlink element\r
+   linkTo: function(url) {\r
+     var link = new SVG.A\r
\r
+     if (typeof url == 'function')\r
+       url.call(link, link)\r
+     else\r
+       link.to(url)\r
\r
+     return this.parent().put(link).put(this)\r
+   }\r
\r
  })
- // Method for getting an element by id
- SVG.get = function(id) {
-   var node = document.getElementById(idFromReference(id) || id)
-   return SVG.adopt(node)
- }
- // Select elements by query string
- SVG.select = function(query, parent) {
-   return SVG.utils.map((parent || document).querySelectorAll(query), function(node) {
-     return SVG.adopt(node)
-   })
- }
- SVG.$$ = function(query, parent) {
-   return SVG.utils.map((parent || document).querySelectorAll(query), function(node) {
-     return SVG.adopt(node)
-   })
- }
- SVG.$ = function(query, parent) {
-   return SVG.adopt((parent || document).querySelector(query))
- }
- SVG.extend(SVG.Parent, {
-   // Scoped select method
-   select: function(query) {
-     return SVG.select(query, this.node)
-   }
+ SVG.Marker = SVG.invent({\r
+   // Initialize node\r
+   create: 'marker'\r
\r
+   // Inherit from\r
+ , inherit: SVG.Container\r
\r
+   // Add class methods\r
+ , extend: {\r
+     // Set width of element\r
+     width: function(width) {\r
+       return this.attr('markerWidth', width)\r
+     }\r
+     // Set height of element\r
+   , height: function(height) {\r
+       return this.attr('markerHeight', height)\r
+     }\r
+     // Set marker refX and refY\r
+   , ref: function(x, y) {\r
+       return this.attr('refX', x).attr('refY', y)\r
+     }\r
+     // Update marker\r
+   , update: function(block) {\r
+       // remove all content\r
+       this.clear()\r
\r
+       // invoke passed block\r
+       if (typeof block == 'function')\r
+         block.call(this, this)\r
\r
+       return this\r
+     }\r
+     // Return the fill id\r
+   , toString: function() {\r
+       return 'url(#' + this.id() + ')'\r
+     }\r
+   }\r
\r
+   // Add parent method\r
+ , construct: {\r
+     marker: function(width, height, block) {\r
+       // Create marker element in defs\r
+       return this.defs().marker(width, height, block)\r
+     }\r
+   }\r
\r
+ })\r
\r
+ SVG.extend(SVG.Defs, {\r
+   // Create marker\r
+   marker: function(width, height, block) {\r
+     // Set default viewbox to match the width and height, set ref to cx and cy and set orient to auto\r
+     return this.put(new SVG.Marker)\r
+       .size(width, height)\r
+       .ref(width / 2, height / 2)\r
+       .viewbox(0, 0, width, height)\r
+       .attr('orient', 'auto')\r
+       .update(block)\r
+   }\r
\r
+ })\r
\r
+ SVG.extend(SVG.Line, SVG.Polyline, SVG.Polygon, SVG.Path, {\r
+   // Create and attach markers\r
+   marker: function(marker, width, height, block) {\r
+     var attr = ['marker']\r
\r
+     // Build attribute name\r
+     if (marker != 'all') attr.push(marker)\r
+     attr = attr.join('-')\r
\r
+     // Set marker attribute\r
+     marker = arguments[1] instanceof SVG.Marker ?\r
+       arguments[1] :\r
+       this.doc().marker(width, height, block)\r
\r
+     return this.attr(attr, marker)\r
+   }\r
\r
  })
- function isNulledBox(box) {
-   return !box.w && !box.h && !box.x && !box.y
- }
- function domContains(node) {
-   return (document.documentElement.contains || function(node) {
-     // This is IE - it does not support contains() for top-level SVGs
-     while (node.parentNode){
-       node = node.parentNode;
-     }
-     return node == document
-   }).call(document.documentElement, node)
- }
- function pathRegReplace(a, b, c, d) {
-   return c + d.replace(SVG.regex.dots, ' .')
- }
- // creates deep clone of array
- function array_clone(arr){
-   var clone = arr.slice(0)
-   for(var i = clone.length; i--;){
-     if(Array.isArray(clone[i])){
-       clone[i] = array_clone(clone[i])
-     }
-   }
-   return clone
- }
- // tests if a given element is instance of an object
- function is(el, obj){
-   return el instanceof obj
- }
- // tests if a given selector matches an element
- function matches(el, selector) {
-   return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);
- }
- // Convert dash-separated-string to camelCase
- function camelCase(s) {
-   return s.toLowerCase().replace(/-(.)/g, function(m, g) {
-     return g.toUpperCase()
-   })
- }
- // Capitalize first letter of a string
- function capitalize(s) {
-   return s.charAt(0).toUpperCase() + s.slice(1)
- }
- // Ensure to six-based hex
- function fullHex(hex) {
-   return hex.length == 4 ?
-     [ '#',
-       hex.substring(1, 2), hex.substring(1, 2)
-     , hex.substring(2, 3), hex.substring(2, 3)
-     , hex.substring(3, 4), hex.substring(3, 4)
-     ].join('') : hex
- }
- // Component to hex value
- function compToHex(comp) {
-   var hex = comp.toString(16)
-   return hex.length == 1 ? '0' + hex : hex
- }
- // Calculate proportional width and height values when necessary
- function proportionalSize(element, width, height) {
-   if (width == null || height == null) {
-     var box = element.bbox()
-     if (width == null)
-       width = box.width / box.height * height
-     else if (height == null)
-       height = box.height / box.width * width
-   }
-   return {
-     width:  width
-   , height: height
-   }
- }
- // Delta transform point
- function deltaTransformPoint(matrix, x, y) {
-   return {
-     x: x * matrix.a + y * matrix.c + 0
-   , y: x * matrix.b + y * matrix.d + 0
-   }
- }
- // Map matrix array to object
- function arrayToMatrix(a) {
-   return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] }
- }
- // Parse matrix if required
- function parseMatrix(matrix) {
-   if (!(matrix instanceof SVG.Matrix))
-     matrix = new SVG.Matrix(matrix)
-   return matrix
- }
- // Add centre point to transform object
- function ensureCentre(o, target) {
-   o.cx = o.cx == null ? target.bbox().cx : o.cx
-   o.cy = o.cy == null ? target.bbox().cy : o.cy
- }
- // PathArray Helpers
- function arrayToString(a) {
-   for (var i = 0, il = a.length, s = ''; i < il; i++) {
-     s += a[i][0]
-     if (a[i][1] != null) {
-       s += a[i][1]
-       if (a[i][2] != null) {
-         s += ' '
-         s += a[i][2]
-         if (a[i][3] != null) {
-           s += ' '
-           s += a[i][3]
-           s += ' '
-           s += a[i][4]
-           if (a[i][5] != null) {
-             s += ' '
-             s += a[i][5]
-             s += ' '
-             s += a[i][6]
-             if (a[i][7] != null) {
-               s += ' '
-               s += a[i][7]
-             }
-           }
-         }
-       }
-     }
-   }
-   return s + ' '
- }
- // Deep new id assignment
- function assignNewId(node) {
-   // do the same for SVG child nodes as well
-   for (var i = node.childNodes.length - 1; i >= 0; i--)
-     if (node.childNodes[i] instanceof window.SVGElement)
-       assignNewId(node.childNodes[i])
-   return SVG.adopt(node).id(SVG.eid(node.nodeName))
- }
- // Add more bounding box properties
- function fullBox(b) {
-   if (b.x == null) {
-     b.x      = 0
-     b.y      = 0
-     b.width  = 0
-     b.height = 0
-   }
-   b.w  = b.width
-   b.h  = b.height
-   b.x2 = b.x + b.width
-   b.y2 = b.y + b.height
-   b.cx = b.x + b.width / 2
-   b.cy = b.y + b.height / 2
-   return b
- }
- // Get id from reference string
- function idFromReference(url) {
-   var m = (url || '').toString().match(SVG.regex.reference)
-   if (m) return m[1]
- }
- // Create matrix array for looping
- var abcdef = 'abcdef'.split('')
- SVG.Box = SVG.invent({
-   create: function(source) {
-     var base = [0,0,0,0]
-     source = typeof source === 'string' ?
-         source.split(SVG.regex.delimiter).map(parseFloat) :
-       Array.isArray(source) ?
-         source :
-       typeof source == 'object' ?
-         [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] :
-       arguments.length == 4 ?
-         [].slice.call(arguments) :
-         base
-     this.x = source[0]
-     this.y = source[1]
-     this.width = source[2]
-     this.height = source[3]
-     // add center, right, bottom...
-     fullBox(this)
-   }
- , extend: {
-     // Merge rect box with another, return a new instance
-     merge: function(box) {
-       var x = Math.min(this.x, box.x)
-         , y = Math.min(this.y, box.y)
-       return new SVG.Box(
-         x, y,
-         Math.max(this.x + this.width,  box.x + box.width)  - x,
-         Math.max(this.y + this.height, box.y + box.height) - y
-       )
-     }
-   , transform: function(m) {
-       var xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, p
-       var pts = [
-         new SVG.Point(this.x, this.y),
-         new SVG.Point(this.x2, this.y),
-         new SVG.Point(this.x, this.y2),
-         new SVG.Point(this.x2, this.y2)
-       ]
-       pts.forEach(function(p) {
-         p = p.transform(m)
-         xMin = Math.min(xMin,p.x)
-         xMax = Math.max(xMax,p.x)
-         yMin = Math.min(yMin,p.y)
-         yMax = Math.max(yMax,p.y)
-       })
-       return new SVG.Box(
-         xMin, yMin,
-         xMax-xMin,
-         yMax-yMin
-       )
-     }
-   , addOffset: function() {
-       // offset by window scroll position, because getBoundingClientRect changes when window is scrolled
-       this.x += window.pageXOffset
-       this.y += window.pageYOffset
-       return this
-     }
-   , toString: function() {
-       return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height
-     }
-   , morph: function(x, y, width, height){
-       this.destination = new SVG.Box(x, y, width, height)
-       return this
-     }
-   , at: function(pos) {
-       if(!this.destination) return this
-       return new SVG.Box(
-           this.x + (this.destination.x - this.x) * pos
-         , this.y + (this.destination.y - this.y) * pos
-         , this.width + (this.destination.width - this.width) * pos
-         , this.height + (this.destination.height - this.height) * pos
-       )
-     }
-   }
-     // Define Parent
- , parent: SVG.Element
-   // Constructor
- , construct: {
-     // Get bounding box
-     bbox: function() {
-       var box
-       try {
-         // find native bbox
-         box = this.node.getBBox()
-         if(isNulledBox(box) && !domContains(this.node)) {
-           throw new Exception('Element not in the dom')
-         }
-       } catch(e) {
-         try {
-           var clone = this.clone(SVG.parser.draw).show()
-           box = clone.node.getBBox()
-           clone.remove()
-         } catch(e) {
-           console.warn('Getting a bounding box of this element is not possible')
-         }
-       }
-       return new SVG.Box(box)
-     }
-   , rbox: function(el) {
-       // IE11 throws an error when element not in dom
-       try{
-         var box = new SVG.Box(this.node.getBoundingClientRect())
-         if (el) return box.transform(el.screenCTM().inverse())
-         return box.addOffset()
-       } catch(e) {
-         return new SVG.Box()
-       }
-     }
-   }
+ // Define list of available attributes for stroke and fill\r
+ var sugar = {\r
+   stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset']\r
+ , fill:   ['color', 'opacity', 'rule']\r
+ , prefix: function(t, a) {\r
+     return a == 'color' ? t : t + '-' + a\r
+   }\r
+ }\r
\r
+ // Add sugar for fill and stroke\r
+ ;['fill', 'stroke'].forEach(function(m) {\r
+   var i, extension = {}\r
\r
+   extension[m] = function(o) {\r
+     if (typeof o == 'undefined')\r
+       return this\r
+     if (typeof o == 'string' || SVG.Color.isRgb(o) || (o && typeof o.fill === 'function'))\r
+       this.attr(m, o)\r
\r
+     else\r
+       // set all attributes from sugar.fill and sugar.stroke list\r
+       for (i = sugar[m].length - 1; i >= 0; i--)\r
+         if (o[sugar[m][i]] != null)\r
+           this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]])\r
\r
+     return this\r
+   }\r
\r
+   SVG.extend(SVG.Element, SVG.FX, extension)\r
\r
+ })\r
\r
+ SVG.extend(SVG.Element, SVG.FX, {\r
+   // Map rotation to transform\r
+   rotate: function(d, cx, cy) {\r
+     return this.transform({ rotation: d, cx: cx, cy: cy })\r
+   }\r
+   // Map skew to transform\r
+ , skew: function(x, y, cx, cy) {\r
+     return arguments.length == 1  || arguments.length == 3 ?\r
+       this.transform({ skew: x, cx: y, cy: cx }) :\r
+       this.transform({ skewX: x, skewY: y, cx: cx, cy: cy })\r
+   }\r
+   // Map scale to transform\r
+ , scale: function(x, y, cx, cy) {\r
+     return arguments.length == 1  || arguments.length == 3 ?\r
+       this.transform({ scale: x, cx: y, cy: cx }) :\r
+       this.transform({ scaleX: x, scaleY: y, cx: cx, cy: cy })\r
+   }\r
+   // Map translate to transform\r
+ , translate: function(x, y) {\r
+     return this.transform({ x: x, y: y })\r
+   }\r
+   // Map flip to transform\r
+ , flip: function(a, o) {\r
+     o = typeof a == 'number' ? a : o\r
+     return this.transform({ flip: a || 'both', offset: o })\r
+   }\r
+   // Map matrix to transform\r
+ , matrix: function(m) {\r
+     return this.attr('transform', new SVG.Matrix(arguments.length == 6 ? [].slice.call(arguments) : m))\r
+   }\r
+   // Opacity\r
+ , opacity: function(value) {\r
+     return this.attr('opacity', value)\r
+   }\r
+   // Relative move over x axis\r
+ , dx: function(x) {\r
+     return this.x(new SVG.Number(x).plus(this instanceof SVG.FX ? 0 : this.x()), true)\r
+   }\r
+   // Relative move over y axis\r
+ , dy: function(y) {\r
+     return this.y(new SVG.Number(y).plus(this instanceof SVG.FX ? 0 : this.y()), true)\r
+   }\r
+   // Relative move over x and y axes\r
+ , dmove: function(x, y) {\r
+     return this.dx(x).dy(y)\r
+   }\r
+ })\r
\r
+ SVG.extend(SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.FX, {\r
+   // Add x and y radius\r
+   radius: function(x, y) {\r
+     var type = (this._target || this).type;\r
 -    return type == 'radial' || type == 'circle' ?\r
++    return type == 'radialGradient' || type == 'radialGradient' ?\r
+       this.attr('r', new SVG.Number(x)) :\r
+       this.rx(x).ry(y == null ? x : y)\r
+   }\r
+ })\r
\r
+ SVG.extend(SVG.Path, {\r
+   // Get path length\r
+   length: function() {\r
+     return this.node.getTotalLength()\r
+   }\r
+   // Get point at length\r
+ , pointAt: function(length) {\r
 -    return this.node.getPointAtLength(length)\r
++    return new SVG.Point(this.node.getPointAtLength(length))\r
+   }\r
+ })\r
\r
+ SVG.extend(SVG.Parent, SVG.Text, SVG.Tspan, SVG.FX, {\r
+   // Set font\r
+   font: function(a, v) {\r
+     if (typeof a == 'object') {\r
+       for (v in a) this.font(v, a[v])\r
+     }\r
\r
+     return a == 'leading' ?\r
+         this.leading(v) :\r
+       a == 'anchor' ?\r
+         this.attr('text-anchor', v) :\r
+       a == 'size' || a == 'family' || a == 'weight' || a == 'stretch' || a == 'variant' || a == 'style' ?\r
+         this.attr('font-'+ a, v) :\r
+         this.attr(a, v)\r
+   }\r
+ })\r
 -SVG.Set = SVG.invent({\r
 -  // Initialize\r
 -  create: function(members) {\r
 -    // Set initial state\r
 -    Array.isArray(members) ? this.members = members : this.clear()\r
 -  }\r
 -\r
 -  // Add class methods\r
 -, extend: {\r
 -    // Add element to set\r
 -    add: function() {\r
 -      var i, il, elements = [].slice.call(arguments)\r
 -\r
 -      for (i = 0, il = elements.length; i < il; i++)\r
 -        this.members.push(elements[i])\r
 -\r
 -      return this\r
 -    }\r
 -    // Remove element from set\r
 -  , remove: function(element) {\r
 -      var i = this.index(element)\r
 -\r
 -      // remove given child\r
 -      if (i > -1)\r
 -        this.members.splice(i, 1)\r
 -\r
 -      return this\r
 -    }\r
 -    // Iterate over all members\r
 -  , each: function(block) {\r
 -      for (var i = 0, il = this.members.length; i < il; i++)\r
 -        block.apply(this.members[i], [i, this.members])\r
 -\r
 -      return this\r
 -    }\r
 -    // Restore to defaults\r
 -  , clear: function() {\r
 -      // initialize store\r
 -      this.members = []\r
 -\r
 -      return this\r
 -    }\r
 -    // Get the length of a set\r
 -  , length: function() {\r
 -      return this.members.length\r
 -    }\r
 -    // Checks if a given element is present in set\r
 -  , has: function(element) {\r
 -      return this.index(element) >= 0\r
 -    }\r
 -    // retuns index of given element in set\r
 -  , index: function(element) {\r
 -      return this.members.indexOf(element)\r
 -    }\r
 -    // Get member at given index\r
 -  , get: function(i) {\r
 -      return this.members[i]\r
 -    }\r
 -    // Get first member\r
 -  , first: function() {\r
 -      return this.get(0)\r
 -    }\r
 -    // Get last member\r
 -  , last: function() {\r
 -      return this.get(this.members.length - 1)\r
 -    }\r
 -    // Default value\r
 -  , valueOf: function() {\r
 -      return this.members\r
 -    }\r
 -    // Get the bounding box of all members included or empty box if set has no items\r
 -  , bbox: function(){\r
 -      // return an empty box of there are no members\r
 -      if (this.members.length == 0)\r
 -        return new SVG.RBox()\r
 -\r
 -      // get the first rbox and update the target bbox\r
 -      var rbox = this.members[0].rbox(this.members[0].doc())\r
 -\r
 -      this.each(function() {\r
 -        // user rbox for correct position and visual representation\r
 -        rbox = rbox.merge(this.rbox(this.doc()))\r
 -      })\r
 -\r
 -      return rbox\r
 -    }\r
 -  }\r
 -\r
 -  // Add parent method\r
 -, construct: {\r
 -    // Create a new set\r
 -    set: function(members) {\r
 -      return new SVG.Set(members)\r
 -    }\r
 -  }\r
 -})\r
 -\r
 -SVG.FX.Set = SVG.invent({\r
 -  // Initialize node\r
 -  create: function(set) {\r
 -    // store reference to set\r
 -    this.set = set\r
 -  }\r
 -\r
 -})\r
 -\r
 -// Alias methods\r
 -SVG.Set.inherit = function() {\r
 -  var m\r
 -    , methods = []\r
 -\r
 -  // gather shape methods\r
 -  for(var m in SVG.Shape.prototype)\r
 -    if (typeof SVG.Shape.prototype[m] == 'function' && typeof SVG.Set.prototype[m] != 'function')\r
 -      methods.push(m)\r
 -\r
 -  // apply shape aliasses\r
 -  methods.forEach(function(method) {\r
 -    SVG.Set.prototype[method] = function() {\r
 -      for (var i = 0, il = this.members.length; i < il; i++)\r
 -        if (this.members[i] && typeof this.members[i][method] == 'function')\r
 -          this.members[i][method].apply(this.members[i], arguments)\r
 -\r
 -      return method == 'animate' ? (this.fx || (this.fx = new SVG.FX.Set(this))) : this\r
 -    }\r
 -  })\r
 -\r
 -  // clear methods for the next round\r
 -  methods = []\r
 -\r
 -  // gather fx methods\r
 -  for(var m in SVG.FX.prototype)\r
 -    if (typeof SVG.FX.prototype[m] == 'function' && typeof SVG.FX.Set.prototype[m] != 'function')\r
 -      methods.push(m)\r
 -\r
 -  // apply fx aliasses\r
 -  methods.forEach(function(method) {\r
 -    SVG.FX.Set.prototype[method] = function() {\r
 -      for (var i = 0, il = this.set.members.length; i < il; i++)\r
 -        this.set.members[i].fx[method].apply(this.set.members[i].fx, arguments)\r
 -\r
 -      return this\r
 -    }\r
 -  })\r
 -}\r
 -\r
 -\r
 -
\r
+ SVG.extend(SVG.Element, {\r
+   // Store data values on svg nodes\r
+   data: function(a, v, r) {\r
+     if (typeof a == 'object') {\r
+       for (v in a)\r
+         this.data(v, a[v])\r
\r
+     } else if (arguments.length < 2) {\r
+       try {\r
+         return JSON.parse(this.attr('data-' + a))\r
+       } catch(e) {\r
+         return this.attr('data-' + a)\r
+       }\r
\r
+     } else {\r
+       this.attr(\r
+         'data-' + a\r
+       , v === null ?\r
+           null :\r
+         r === true || typeof v === 'string' || typeof v === 'number' ?\r
+           v :\r
+           JSON.stringify(v)\r
+       )\r
+     }\r
\r
+     return this\r
+   }\r
  })
- SVG.extend(SVG.Doc, SVG.Nested, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View, {
-   viewbox: function(x, y, width, height) {
-     // act as getter
-     if(x == null) return new SVG.Box(this.attr('viewBox'))
-     // act as setter
-     return this.attr('viewBox', new SVG.Box(x, y, width, height))
-   }
+ SVG.extend(SVG.Element, {\r
+   // Remember arbitrary data\r
+   remember: function(k, v) {\r
+     // remember every item in an object individually\r
+     if (typeof arguments[0] == 'object')\r
+       for (var v in k)\r
+         this.remember(v, k[v])\r
\r
+     // retrieve memory\r
+     else if (arguments.length == 1)\r
+       return this.memory()[k]\r
\r
+     // store memory\r
+     else\r
+       this.memory()[k] = v\r
\r
+     return this\r
+   }\r
\r
+   // Erase a given memory\r
+ , forget: function() {\r
+     if (arguments.length == 0)\r
+       this._memory = {}\r
+     else\r
+       for (var i = arguments.length - 1; i >= 0; i--)\r
+         delete this.memory()[arguments[i]]\r
\r
+     return this\r
+   }\r
\r
+   // Initialize or return local memory object\r
+ , memory: function() {\r
+     return this._memory || (this._memory = {})\r
+   }\r
\r
  })
- return SVG
- }));
+ // Method for getting an element by id\r
+ SVG.get = function(id) {\r
+   var node = document.getElementById(idFromReference(id) || id)\r
+   return SVG.adopt(node)\r
+ }\r
\r
+ // Select elements by query string\r
+ SVG.select = function(query, parent) {\r
 -  return new SVG.Set(\r
 -    SVG.utils.map((parent || document).querySelectorAll(query), function(node) {\r
 -      return SVG.adopt(node)\r
 -    })\r
 -  )\r
++  return SVG.utils.map((parent || document).querySelectorAll(query), function(node) {\r
++    return SVG.adopt(node)\r
++  })\r
++}\r
++\r
++SVG.$$ = function(query, parent) {\r
++  return SVG.utils.map((parent || document).querySelectorAll(query), function(node) {\r
++    return SVG.adopt(node)\r
++  })\r
++}\r
++\r
++SVG.$ = function(query, parent) {\r
++  return SVG.adopt((parent || document).querySelector(query))\r
+ }\r
\r
+ SVG.extend(SVG.Parent, {\r
+   // Scoped select method\r
+   select: function(query) {\r
+     return SVG.select(query, this.node)\r
+   }\r
++})\r
++
++function isNulledBox(box) {\r
++  return !box.w && !box.h && !box.x && !box.y\r
++}\r
++\r
++function domContains(node) {\r
++  return (document.documentElement.contains || function(node) {\r
++    // This is IE - it does not support contains() for top-level SVGs\r
++    while (node.parentNode){\r
++      node = node.parentNode;\r
++    }\r
++    return node == document\r
++  }).call(document.documentElement, node)\r
++}\r
\r
 -})
+ function pathRegReplace(a, b, c, d) {\r
+   return c + d.replace(SVG.regex.dots, ' .')\r
+ }\r
\r
+ // creates deep clone of array\r
+ function array_clone(arr){\r
+   var clone = arr.slice(0)\r
+   for(var i = clone.length; i--;){\r
+     if(Array.isArray(clone[i])){\r
+       clone[i] = array_clone(clone[i])\r
+     }\r
+   }\r
+   return clone\r
+ }\r
\r
+ // tests if a given element is instance of an object\r
+ function is(el, obj){\r
+   return el instanceof obj\r
+ }\r
\r
+ // tests if a given selector matches an element\r
+ function matches(el, selector) {\r
+   return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);\r
+ }\r
\r
+ // Convert dash-separated-string to camelCase\r
+ function camelCase(s) {\r
+   return s.toLowerCase().replace(/-(.)/g, function(m, g) {\r
+     return g.toUpperCase()\r
+   })\r
+ }\r
\r
+ // Capitalize first letter of a string\r
+ function capitalize(s) {\r
+   return s.charAt(0).toUpperCase() + s.slice(1)\r
+ }\r
\r
+ // Ensure to six-based hex\r
+ function fullHex(hex) {\r
+   return hex.length == 4 ?\r
+     [ '#',\r
+       hex.substring(1, 2), hex.substring(1, 2)\r
+     , hex.substring(2, 3), hex.substring(2, 3)\r
+     , hex.substring(3, 4), hex.substring(3, 4)\r
+     ].join('') : hex\r
+ }\r
\r
+ // Component to hex value\r
+ function compToHex(comp) {\r
+   var hex = comp.toString(16)\r
+   return hex.length == 1 ? '0' + hex : hex\r
+ }\r
\r
+ // Calculate proportional width and height values when necessary\r
+ function proportionalSize(element, width, height) {\r
+   if (width == null || height == null) {\r
+     var box = element.bbox()\r
\r
+     if (width == null)\r
+       width = box.width / box.height * height\r
+     else if (height == null)\r
+       height = box.height / box.width * width\r
+   }\r
\r
+   return {\r
+     width:  width\r
+   , height: height\r
+   }\r
+ }\r
\r
+ // Delta transform point\r
+ function deltaTransformPoint(matrix, x, y) {\r
+   return {\r
+     x: x * matrix.a + y * matrix.c + 0\r
+   , y: x * matrix.b + y * matrix.d + 0\r
+   }\r
+ }\r
\r
+ // Map matrix array to object\r
+ function arrayToMatrix(a) {\r
+   return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] }\r
+ }\r
\r
+ // Parse matrix if required\r
+ function parseMatrix(matrix) {\r
+   if (!(matrix instanceof SVG.Matrix))\r
+     matrix = new SVG.Matrix(matrix)\r
\r
+   return matrix\r
+ }\r
\r
+ // Add centre point to transform object\r
+ function ensureCentre(o, target) {\r
+   o.cx = o.cx == null ? target.bbox().cx : o.cx\r
+   o.cy = o.cy == null ? target.bbox().cy : o.cy\r
+ }\r
\r
+ // PathArray Helpers\r
+ function arrayToString(a) {\r
+   for (var i = 0, il = a.length, s = ''; i < il; i++) {\r
+     s += a[i][0]\r
\r
+     if (a[i][1] != null) {\r
+       s += a[i][1]\r
\r
+       if (a[i][2] != null) {\r
+         s += ' '\r
+         s += a[i][2]\r
\r
+         if (a[i][3] != null) {\r
+           s += ' '\r
+           s += a[i][3]\r
+           s += ' '\r
+           s += a[i][4]\r
\r
+           if (a[i][5] != null) {\r
+             s += ' '\r
+             s += a[i][5]\r
+             s += ' '\r
+             s += a[i][6]\r
\r
+             if (a[i][7] != null) {\r
+               s += ' '\r
+               s += a[i][7]\r
+             }\r
+           }\r
+         }\r
+       }\r
+     }\r
+   }\r
\r
+   return s + ' '\r
+ }\r
\r
+ // Deep new id assignment\r
+ function assignNewId(node) {\r
+   // do the same for SVG child nodes as well\r
+   for (var i = node.childNodes.length - 1; i >= 0; i--)\r
+     if (node.childNodes[i] instanceof window.SVGElement)\r
+       assignNewId(node.childNodes[i])\r
\r
+   return SVG.adopt(node).id(SVG.eid(node.nodeName))\r
+ }\r
\r
+ // Add more bounding box properties\r
+ function fullBox(b) {\r
+   if (b.x == null) {\r
+     b.x      = 0\r
+     b.y      = 0\r
+     b.width  = 0\r
+     b.height = 0\r
+   }\r
\r
+   b.w  = b.width\r
+   b.h  = b.height\r
+   b.x2 = b.x + b.width\r
+   b.y2 = b.y + b.height\r
+   b.cx = b.x + b.width / 2\r
+   b.cy = b.y + b.height / 2\r
\r
+   return b\r
+ }\r
\r
+ // Get id from reference string\r
+ function idFromReference(url) {\r
 -  var m = url.toString().match(SVG.regex.reference)\r
++  var m = (url || '').toString().match(SVG.regex.reference)\r
\r
+   if (m) return m[1]\r
+ }\r
\r
+ // Create matrix array for looping\r
 -var abcdef = 'abcdef'.split('')
 -// Add CustomEvent to IE9 and IE10\r
 -if (typeof window.CustomEvent !== 'function') {\r
 -  // Code from: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent\r
 -  var CustomEvent = function(event, options) {\r
 -    options = options || { bubbles: false, cancelable: false, detail: undefined }\r
 -    var e = document.createEvent('CustomEvent')\r
 -    e.initCustomEvent(event, options.bubbles, options.cancelable, options.detail)\r
 -    return e\r
++var abcdef = 'abcdef'.split('')\r
++
++SVG.Box = SVG.invent({\r
++  create: function(source) {\r
++    var base = [0,0,0,0]\r
++    source = typeof source === 'string' ?\r
++        source.split(SVG.regex.delimiter).map(parseFloat) :\r
++      Array.isArray(source) ?\r
++        source :\r
++      typeof source == 'object' ?\r
++        [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] :\r
++      arguments.length == 4 ?\r
++        [].slice.call(arguments) :\r
++        base\r
++\r
++    this.x = source[0]\r
++    this.y = source[1]\r
++    this.width = source[2]\r
++    this.height = source[3]\r
++\r
++    // add center, right, bottom...\r
++    fullBox(this)\r
+   }\r
++, extend: {\r
++    // Merge rect box with another, return a new instance\r
++    merge: function(box) {\r
++      var x = Math.min(this.x, box.x)\r
++        , y = Math.min(this.y, box.y)\r
\r
 -  CustomEvent.prototype = window.Event.prototype\r
++      return new SVG.Box(\r
++        x, y,\r
++        Math.max(this.x + this.width,  box.x + box.width)  - x,\r
++        Math.max(this.y + this.height, box.y + box.height) - y\r
++      )\r
++    }\r
\r
 -  window.CustomEvent = CustomEvent\r
 -}\r
++  , transform: function(m) {\r
++      var xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, p, bbox\r
\r
 -// requestAnimationFrame / cancelAnimationFrame Polyfill with fallback based on Paul Irish\r
 -(function(w) {\r
 -  var lastTime = 0\r
 -  var vendors = ['moz', 'webkit']\r
++      var pts = [\r
++        new SVG.Point(this.x, this.y),\r
++        new SVG.Point(this.x2, this.y),\r
++        new SVG.Point(this.x, this.y2),\r
++        new SVG.Point(this.x2, this.y2)\r
++      ]\r
++\r
++      pts.forEach(function(p) {\r
++        p = p.transform(m)\r
++        xMin = Math.min(xMin,p.x)\r
++        xMax = Math.max(xMax,p.x)\r
++        yMin = Math.min(yMin,p.y)\r
++        yMax = Math.max(yMax,p.y)\r
++      })\r
\r
 -  for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {\r
 -    w.requestAnimationFrame = w[vendors[x] + 'RequestAnimationFrame']\r
 -    w.cancelAnimationFrame  = w[vendors[x] + 'CancelAnimationFrame'] ||\r
 -                              w[vendors[x] + 'CancelRequestAnimationFrame']\r
++      return new SVG.Box(\r
++        xMin, yMin,\r
++        xMax-xMin,\r
++        yMax-yMin\r
++      )\r
++    }\r
++\r
++  , addOffset: function() {\r
++      // offset by window scroll position, because getBoundingClientRect changes when window is scrolled\r
++      this.x += window.pageXOffset\r
++      this.y += window.pageYOffset\r
++      return this\r
++    }\r
++  , toString: function() {\r
++      return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height\r
++    }\r
++  , morph: function(x, y, width, height){\r
++      this.destination = new SVG.Box(x, y, width, height)\r
++      return this\r
++    }\r
++\r
++  , at: function(pos) {\r
++      if(!this.destination) return this\r
++\r
++      return new SVG.Box(\r
++          this.x + (this.destination.x - this.x) * pos\r
++        , this.y + (this.destination.y - this.y) * pos\r
++        , this.width + (this.destination.width - this.width) * pos\r
++        , this.height + (this.destination.height - this.height) * pos\r
++      )\r
++\r
++    }\r
+   }\r
\r
 -  w.requestAnimationFrame = w.requestAnimationFrame ||\r
 -    function(callback) {\r
 -      var currTime = new Date().getTime()\r
 -      var timeToCall = Math.max(0, 16 - (currTime - lastTime))\r
++    // Define Parent\r
++, parent: SVG.Element\r
\r
 -      var id = w.setTimeout(function() {\r
 -        callback(currTime + timeToCall)\r
 -      }, timeToCall)\r
++  // Constructor\r
++, construct: {\r
++    // Get bounding box\r
++    bbox: function() {\r
++      var box\r
++\r
++      try {\r
++        // find native bbox\r
++        box = this.node.getBBox()\r
++\r
++        if(isNulledBox(box) && !domContains(this.node)) {\r
++          throw new Exception('Element not in the dom')\r
++        }\r
++      } catch(e) {\r
++        try {\r
++          var clone = this.clone(SVG.parser.draw.instance).show()\r
++          box = clone.node.getBBox()\r
++          clone.remove()\r
++        } catch(e) {\r
++          console.warn('Getting a bounding box of this element is not possible')\r
++        }\r
++      }\r
\r
 -      lastTime = currTime + timeToCall\r
 -      return id\r
++      return new SVG.Box(box)\r
++    }\r
++\r
++  , rbox: function(el) {\r
++      // IE11 throws an error when element not in dom\r
++      try{\r
++        var box = new SVG.Box(this.node.getBoundingClientRect())\r
++        if (el) return box.transform(el.screenCTM().inverse())\r
++        return box.addOffset()\r
++      } catch(e) {\r
++        return new SVG.Box()\r
++      }\r
+     }\r
++  }\r
++})\r
\r
 -  w.cancelAnimationFrame = w.cancelAnimationFrame || w.clearTimeout;\r
++SVG.extend(SVG.Doc, SVG.Nested, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View, {\r
++  viewbox: function(x, y, width, height) {\r
++    // act as getter\r
++    if(x == null) return new SVG.Box(this.attr('viewBox'))\r
++\r
++    // act as setter\r
++    return this.attr('viewBox', new SVG.Box(x, y, width, height))\r
++  }\r
++})\r
\r
 -}(window))\r
\r
+ return SVG\r
\r
+ }));\r
diff --cc dist/svg.min.js
index 4e9e07c111cd3ebe4fe8264f3e5b0e6349b3dae2,838575c31945597c64cc4951edc4b32bcca175aa..45932adcd29bafe40245662d919da1128b204b4c
@@@ -1,2 -1,3 +1,2 @@@
- /*! svg.js v2.5.0 MIT*/;!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t,t.document)}):"object"==typeof exports?module.exports=t.document?e(t,t.document):function(t){return e(t,t.document)}:t.SVG=e(t,t.document)}("undefined"!=typeof window?window:this,function(t,e){function i(t){return!(t.w||t.h||t.x||t.y)}function n(t){return(e.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t==e}).call(e.documentElement,t)}function r(t,e,i,n){return i+n.replace(b.regex.dots," .")}function s(t){for(var e=t.slice(0),i=e.length;i--;)Array.isArray(e[i])&&(e[i]=s(e[i]));return e}function a(t,e){return t instanceof e}function o(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}function h(t){return t.toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()})}function u(t){return t.charAt(0).toUpperCase()+t.slice(1)}function l(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}function c(t){var e=t.toString(16);return 1==e.length?"0"+e:e}function f(t,e,i){if(null==e||null==i){var n=t.bbox();null==e?e=n.width/n.height*i:null==i&&(i=n.height/n.width*e)}return{width:e,height:i}}function d(t,e,i){return{x:e*t.a+i*t.c+0,y:e*t.b+i*t.d+0}}function p(t){return{a:t[0],b:t[1],c:t[2],d:t[3],e:t[4],f:t[5]}}function m(t){return t instanceof b.Matrix||(t=new b.Matrix(t)),t}function x(t,e){t.cx=null==t.cx?e.bbox().cx:t.cx,t.cy=null==t.cy?e.bbox().cy:t.cy}function y(t){for(var e=0,i=t.length,n="";e<i;e++)n+=t[e][0],null!=t[e][1]&&(n+=t[e][1],null!=t[e][2]&&(n+=" ",n+=t[e][2],null!=t[e][3]&&(n+=" ",n+=t[e][3],n+=" ",n+=t[e][4],null!=t[e][5]&&(n+=" ",n+=t[e][5],n+=" ",n+=t[e][6],null!=t[e][7]&&(n+=" ",n+=t[e][7])))));return n+" "}function v(e){for(var i=e.childNodes.length-1;i>=0;i--)e.childNodes[i]instanceof t.SVGElement&&v(e.childNodes[i]);return b.adopt(e).id(b.eid(e.nodeName))}function g(t){return null==t.x&&(t.x=0,t.y=0,t.width=0,t.height=0),t.w=t.width,t.h=t.height,t.x2=t.x+t.width,t.y2=t.y+t.height,t.cx=t.x+t.width/2,t.cy=t.y+t.height/2,t}function w(t){var e=(t||"").toString().match(b.regex.reference);if(e)return e[1]}var b=this.SVG=function(t){if(b.supported)return t=new b.Doc(t),b.parser.draw||b.prepare(),t};if(b.ns="http://www.w3.org/2000/svg",b.xmlns="http://www.w3.org/2000/xmlns/",b.xlink="http://www.w3.org/1999/xlink",b.svgjs="http://svgjs.com/svgjs",b.supported=function(){return!!e.createElementNS&&!!e.createElementNS(b.ns,"svg").createSVGRect}(),!b.supported)return!1;b.did=1e3,b.eid=function(t){return"Svgjs"+u(t)+b.did++},b.create=function(t){var i=e.createElementNS(this.ns,t);return i.setAttribute("id",this.eid(t)),i},b.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]},b.invent=function(t){var e="function"==typeof t.create?t.create:function(){this.constructor.call(this,b.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&b.extend(e,t.extend),t.construct&&b.extend(t.parent||b.Container,t.construct),e},b.adopt=function(e){if(!e)return null;if(e.instance)return e.instance;var i;return i="svg"==e.nodeName?e.parentNode instanceof t.SVGElement?new b.Nested:new b.Doc:"linearGradient"==e.nodeName?new b.Gradient("linear"):"radialGradient"==e.nodeName?new b.Gradient("radial"):b[u(e.nodeName)]?new(b[u(e.nodeName)]):new b.Element(e),i.type=e.nodeName,i.node=e,e.instance=i,i instanceof b.Doc&&i.namespace().defs(),i.setData(JSON.parse(e.getAttribute("svgjs:data"))||{}),i},b.prepare=function(){var t=e.getElementsByTagName("body")[0],i=(t?new b.Doc(t):new b.Doc(e.documentElement).nested()).size(2,0);b.parser={body:t||e.documentElement,draw:i.style({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"}),poly:i.polyline().node,path:i.path().node,native:b.create("svg")}},b.parser={native:b.create("svg")},e.addEventListener("DOMContentLoaded",function(){b.parser.draw||b.prepare()},!1),b.regex={numberAndUnit:/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,reference:/#([a-z0-9\-_]+)/i,transforms:/\)\s*,?\s*/,whitespace:/\s/g,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isBlank:/^(\s+)?$/,isNumber:/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,isPercent:/^-?[\d\.]+%$/,isImage:/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,delimiter:/[\s,]+/,hyphen:/([^e])\-/gi,pathLetters:/[MLHVCSQTAZ]/gi,isPathLetter:/[MLHVCSQTAZ]/i,numbersWithDots:/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,dots:/\./g},b.utils={map:function(t,e){var i,n=t.length,r=[];for(i=0;i<n;i++)r.push(e(t[i]));return r},filter:function(t,e){var i,n=t.length,r=[];for(i=0;i<n;i++)e(t[i])&&r.push(t[i]);return r},radians:function(t){return t%360*Math.PI/180},degrees:function(t){return 180*t/Math.PI%360},filterSVGElements:function(e){return this.filter(e,function(e){return e instanceof t.SVGElement})}},b.defaults={attrs:{"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",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":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"}},b.Color=function(t){var e;this.r=0,this.g=0,this.b=0,t&&("string"==typeof t?b.regex.isRgb.test(t)?(e=b.regex.rgb.exec(t.replace(b.regex.whitespace,"")),this.r=parseInt(e[1]),this.g=parseInt(e[2]),this.b=parseInt(e[3])):b.regex.isHex.test(t)&&(e=b.regex.hex.exec(l(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))},b.extend(b.Color,{toString:function(){return this.toHex()},toHex:function(){return"#"+c(this.r)+c(this.g)+c(this.b)},toRgb:function(){return"rgb("+[this.r,this.g,this.b].join()+")"},brightness:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11},morph:function(t){return this.destination=new b.Color(t),this},at:function(t){return this.destination?(t=t<0?0:t>1?1:t,new b.Color({r:~~(this.r+(this.destination.r-this.r)*t),g:~~(this.g+(this.destination.g-this.g)*t),b:~~(this.b+(this.destination.b-this.b)*t)})):this}}),b.Color.test=function(t){return t+="",b.regex.isHex.test(t)||b.regex.isRgb.test(t)},b.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},b.Color.isColor=function(t){return b.Color.isRgb(t)||b.Color.test(t)},b.Array=function(t,e){t=(t||[]).valueOf(),0==t.length&&e&&(t=e.valueOf()),this.value=this.parse(t)},b.extend(b.Array,{morph:function(t){if(this.destination=this.parse(t),this.value.length!=this.destination.length){for(var e=this.value[this.value.length-1],i=this.destination[this.destination.length-1];this.value.length>this.destination.length;)this.destination.push(i);for(;this.value.length<this.destination.length;)this.value.push(e)}return this},settle:function(){for(var t=0,e=this.value.length,i=[];t<e;t++)i.indexOf(this.value[t])==-1&&i.push(this.value[t]);return this.value=i},at:function(t){if(!this.destination)return this;for(var e=0,i=this.value.length,n=[];e<i;e++)n.push(this.value[e]+(this.destination[e]-this.value[e])*t);return new b.Array(n)},toString:function(){return this.value.join(" ")},valueOf:function(){return this.value},parse:function(t){return t=t.valueOf(),Array.isArray(t)?t:t.trim().split(b.regex.delimiter).map(parseFloat)},reverse:function(){return this.value.reverse(),this},clone:function(){var t=new this.constructor;return t.value=s(this.value),t}}),b.PointArray=function(t,e){b.Array.call(this,t,e||[[0,0]])},b.PointArray.prototype=new b.Array,b.PointArray.prototype.constructor=b.PointArray,b.extend(b.PointArray,{toString:function(){for(var t=0,e=this.value.length,i=[];t<e;t++)i.push(this.value[t].join(","));return i.join(" ")},toLine:function(){return{x1:this.value[0][0],y1:this.value[0][1],x2:this.value[1][0],y2:this.value[1][1]}},at:function(t){if(!this.destination)return this;for(var e=0,i=this.value.length,n=[];e<i;e++)n.push([this.value[e][0]+(this.destination[e][0]-this.value[e][0])*t,this.value[e][1]+(this.destination[e][1]-this.value[e][1])*t]);return new b.PointArray(n)},parse:function(t){var e=[];if(t=t.valueOf(),Array.isArray(t)){if(Array.isArray(t[0]))return t}else t=t.trim().split(b.regex.delimiter).map(parseFloat);t.length%2!==0&&t.pop();for(var i=0,n=t.length;i<n;i+=2)e.push([t[i],t[i+1]]);return e},move:function(t,e){var i=this.bbox();if(t-=i.x,e-=i.y,!isNaN(t)&&!isNaN(e))for(var n=this.value.length-1;n>=0;n--)this.value[n]=[this.value[n][0]+t,this.value[n][1]+e];return this},size:function(t,e){var i,n=this.bbox();for(i=this.value.length-1;i>=0;i--)n.width&&(this.value[i][0]=(this.value[i][0]-n.x)*t/n.width+n.x),n.height&&(this.value[i][1]=(this.value[i][1]-n.y)*e/n.height+n.y);return this},bbox:function(){return b.parser.poly.setAttribute("points",this.toString()),b.parser.poly.getBBox()}}),b.PathArray=function(t,e){b.Array.call(this,t,e||[["M",0,0]])},b.PathArray.prototype=new b.Array,b.PathArray.prototype.constructor=b.PathArray,b.extend(b.PathArray,{toString:function(){return y(this.value)},move:function(t,e){var i=this.bbox();if(t-=i.x,e-=i.y,!isNaN(t)&&!isNaN(e))for(var n,r=this.value.length-1;r>=0;r--)n=this.value[r][0],"M"==n||"L"==n||"T"==n?(this.value[r][1]+=t,this.value[r][2]+=e):"H"==n?this.value[r][1]+=t:"V"==n?this.value[r][1]+=e:"C"==n||"S"==n||"Q"==n?(this.value[r][1]+=t,this.value[r][2]+=e,this.value[r][3]+=t,this.value[r][4]+=e,"C"==n&&(this.value[r][5]+=t,this.value[r][6]+=e)):"A"==n&&(this.value[r][6]+=t,this.value[r][7]+=e);return this},size:function(t,e){var i,n,r=this.bbox();for(i=this.value.length-1;i>=0;i--)n=this.value[i][0],"M"==n||"L"==n||"T"==n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y):"H"==n?this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x:"V"==n?this.value[i][1]=(this.value[i][1]-r.y)*e/r.height+r.y:"C"==n||"S"==n||"Q"==n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y,this.value[i][3]=(this.value[i][3]-r.x)*t/r.width+r.x,this.value[i][4]=(this.value[i][4]-r.y)*e/r.height+r.y,"C"==n&&(this.value[i][5]=(this.value[i][5]-r.x)*t/r.width+r.x,this.value[i][6]=(this.value[i][6]-r.y)*e/r.height+r.y)):"A"==n&&(this.value[i][1]=this.value[i][1]*t/r.width,this.value[i][2]=this.value[i][2]*e/r.height,this.value[i][6]=(this.value[i][6]-r.x)*t/r.width+r.x,this.value[i][7]=(this.value[i][7]-r.y)*e/r.height+r.y);return this},equalCommands:function(t){var e,i,n;for(t=new b.PathArray(t),n=this.value.length===t.value.length,e=0,i=this.value.length;n&&e<i;e++)n=this.value[e][0]===t.value[e][0];return n},morph:function(t){return t=new b.PathArray(t),this.equalCommands(t)?this.destination=t:this.destination=null,this},at:function(t){if(!this.destination)return this;var e,i,n,r,s=this.value,a=this.destination.value,o=[],h=new b.PathArray;for(e=0,i=s.length;e<i;e++){for(o[e]=[s[e][0]],n=1,r=s[e].length;n<r;n++)o[e][n]=s[e][n]+(a[e][n]-s[e][n])*t;"A"===o[e][0]&&(o[e][4]=+(0!=o[e][4]),o[e][5]=+(0!=o[e][5]))}return h.value=o,h},parse:function(t){if(t instanceof b.PathArray)return t.valueOf();var e,i,n,s,a,o,h=0,u=0,l={M:2,L:2,H:1,V:1,C:6,S:4,Q:4,T:2,A:7};t="string"==typeof t?t.replace(b.regex.numbersWithDots,r).replace(b.regex.pathLetters," $& ").replace(b.regex.hyphen,"$1 -").trim().split(b.regex.delimiter):t.reduce(function(t,e){return[].concat.apply(t,e)},[]);var o=[];do{for(b.regex.isPathLetter.test(t[0])?(s=t[0],t.shift()):"M"==s?s="L":"m"==s&&(s="l"),a=[s.toUpperCase()],e=0;e<l[a[0]];++e)a.push(parseFloat(t.shift()));s==a[0]?"M"==s||"L"==s||"C"==s||"Q"==s||"S"==s||"T"==s?(h=a[l[a[0]]-1],u=a[l[a[0]]]):"V"==s?u=a[1]:"H"==s?h=a[1]:"A"==s&&(h=a[6],u=a[7]):"m"==s||"l"==s||"c"==s||"s"==s||"q"==s||"t"==s?(a[1]+=h,a[2]+=u,null!=a[3]&&(a[3]+=h,a[4]+=u),null!=a[5]&&(a[5]+=h,a[6]+=u),h=a[l[a[0]]-1],u=a[l[a[0]]]):"v"==s?(a[1]+=u,u=a[1]):"h"==s?(a[1]+=h,h=a[1]):"a"==s&&(a[6]+=h,a[7]+=u,h=a[6],u=a[7]),"M"==a[0]&&(i=h,n=u),"Z"==a[0]&&(h=i,u=n),o.push(a)}while(t.length);return o},bbox:function(){return b.parser.path.setAttribute("d",this.toString()),b.parser.path.getBBox()}}),b.Number=b.invent({create:function(t,e){this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-3.4e38:3.4e38:"string"==typeof t?(e=t.match(b.regex.numberAndUnit),e&&(this.value=parseFloat(e[1]),"%"==e[5]?this.value/=100:"s"==e[5]&&(this.value*=1e3),this.unit=e[5])):t instanceof b.Number&&(this.value=t.valueOf(),this.unit=t.unit)},extend:{toString:function(){return("%"==this.unit?~~(1e8*this.value)/1e6:"s"==this.unit?this.value/1e3:this.value)+this.unit},toJSON:function(){return this.toString()},valueOf:function(){return this.value},plus:function(t){return t=new b.Number(t),new b.Number(this+t,this.unit||t.unit)},minus:function(t){return t=new b.Number(t),new b.Number(this-t,this.unit||t.unit)},times:function(t){return t=new b.Number(t),new b.Number(this*t,this.unit||t.unit)},divide:function(t){return t=new b.Number(t),new b.Number(this/t,this.unit||t.unit)},to:function(t){var e=new b.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new b.Number(t),t.relative&&(this.destination.value+=this.value),this},at:function(t){return this.destination?new b.Number(this.destination).minus(this).times(t).plus(this):this}}}),b.Element=b.invent({create:function(t){this._event=null,this.dom={},(this.node=t)&&(this.type=t.nodeName,this.node.instance=this)},extend:{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var i=f(this,t,e);return this.width(new b.Number(i.width)).height(new b.Number(i.height))},clone:function(t,e){this.writeDataToDom();var i=v(this.node.cloneNode(!0));return t?t.add(i):this.after(i),i},remove:function(){return this.parent()&&this.parent().removeElement(this),this},replace:function(t){return this.after(t).remove(),t},addTo:function(t){return t.put(this)},putIn:function(t){return t.add(this)},id:function(t){return this.attr("id",t)},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")},toString:function(){return this.attr("id")},classes:function(){var t=this.attr("class");return null==t?[]:t.trim().split(b.regex.delimiter)},hasClass:function(t){return this.classes().indexOf(t)!=-1},addClass:function(t){if(!this.hasClass(t)){var e=this.classes();e.push(t),this.attr("class",e.join(" "))}return this},removeClass:function(t){return this.hasClass(t)&&this.attr("class",this.classes().filter(function(e){return e!=t}).join(" ")),this},toggleClass:function(t){return this.hasClass(t)?this.removeClass(t):this.addClass(t)},reference:function(t){return b.get(this.attr(t))},parent:function(e){var i=this;if(!i.node.parentNode)return null;if(i=b.adopt(i.node.parentNode),!e)return i;for(;i&&i.node instanceof t.SVGElement;){if("string"==typeof e?i.matches(e):i instanceof e)return i;i=b.adopt(i.node.parentNode)}},doc:function(){return this instanceof b.Doc?this:this.parent(b.Doc)},parents:function(t){var e=[],i=this;do{if(i=i.parent(t),!i||!i.node)break;e.push(i)}while(i.parent);return e},matches:function(t){return o(this.node,t)},native:function(){return this.node},svg:function(t){var i,n;if(!(t&&this instanceof b.Parent))return this.node.outerHTML;for(i=e.createElementNS(b.ns,"svg"),i.innerHTML=t,n=i.childNodes.length;n--;)1!=i.firstChild.nodeType?i.removeChild(i.firstChild):this.node.appendChild(i.firstChild);return this},writeDataToDom:function(){return this.is(b.Parent)&&this.each(function(){this.writeDataToDom()}),this.node.removeAttribute("svgjs:data"),Object.keys(this.dom).length&&this.node.setAttribute("svgjs:data",JSON.stringify(this.dom)),this},setData:function(t){return this.dom=t,this},is:function(t){return a(this,t)}}}),b.easing={"-":function(t){return t},"<>":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return-Math.cos(t*Math.PI/2)+1}},b.morph=function(t){return function(e,i){return new b.MorphObj(e,i).at(t)}},b.Situation=b.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new b.Number(t.duration).valueOf(),this.delay=new b.Number(t.delay).valueOf(),this.start=+new Date+this.delay,this.finish=this.start+this.duration,this.ease=t.ease,this.loop=0,this.loops=!1,this.animations={},this.attrs={},this.styles={},this.transforms=[],this.once={}}}),b.FX=b.invent({create:function(t){this._target=t,this.situations=[],this.active=!1,this.situation=null,this.paused=!1,this.lastPos=0,this.pos=0,this.absPos=0,this._speed=1},extend:{animate:function(t,e,i){"object"==typeof t&&(e=t.ease,i=t.delay,t=t.duration);var n=new b.Situation({duration:t||1e3,delay:i||0,ease:b.easing[e||"-"]||e});return this.queue(n),this},delay:function(t){var e=new b.Situation({duration:t,delay:0,ease:b.easing["-"]});return this.queue(e)},target:function(t){return t&&t instanceof b.Element?(this._target=t,this):this._target},timeToAbsPos:function(t){return(t-this.situation.start)/(this.situation.duration/this._speed)},absPosToTime:function(t){return this.situation.duration/this._speed*t+this.situation.start},startAnimFrame:function(){this.stopAnimFrame(),this.animationFrame=requestAnimationFrame(function(){this.step()}.bind(this))},stopAnimFrame:function(){cancelAnimationFrame(this.animationFrame)},start:function(){return!this.active&&this.situation&&(this.active=!0,this.startCurrent()),this},startCurrent:function(){return this.situation.start=+new Date+this.situation.delay/this._speed,this.situation.finish=this.situation.start+this.situation.duration/this._speed,this.initAnimations().step()},queue:function(t){return("function"==typeof t||t instanceof b.Situation)&&this.situations.push(t),this.situation||(this.situation=this.situations.shift()),this},dequeue:function(){return this.stop(),this.situation=this.situations.shift(),this.situation&&(this.situation instanceof b.Situation?this.start():this.situation.call(this)),this},initAnimations:function(){var t,e,i=this.situation;if(i.init)return this;for(t in i.animations)e=this.target()[t](),i.animations[t]instanceof b.Number&&(e=new b.Number(e)),i.animations[t]=e.morph(i.animations[t]);for(t in i.attrs)i.attrs[t]=new b.MorphObj(this.target().attr(t),i.attrs[t]);for(t in i.styles)i.styles[t]=new b.MorphObj(this.target().style(t),i.styles[t]);return i.initialTransformation=this.target().matrixify(),i.init=!0,this},clearQueue:function(){return this.situations=[],this},clearCurrent:function(){return this.situation=null,this},stop:function(t,e){var i=this.active;return this.active=!1,e&&this.clearQueue(),t&&this.situation&&(!i&&this.startCurrent(),this.atEnd()),this.stopAnimFrame(),this.clearCurrent()},reset:function(){if(this.situation){var t=this.situation;this.stop(),this.situation=t,this.atStart()}return this},finish:function(){for(this.stop(!0,!1);this.dequeue().situation&&this.stop(!0,!1););return this.clearQueue().clearCurrent(),this},atStart:function(){return this.at(0,!0)},atEnd:function(){return this.situation.loops===!0&&(this.situation.loops=this.situation.loop+1),"number"==typeof this.situation.loops?this.at(this.situation.loops,!0):this.at(1,!0)},at:function(t,e){var i=this.situation.duration/this._speed;return this.absPos=t,e||(this.situation.reversed&&(this.absPos=1-this.absPos),this.absPos+=this.situation.loop),this.situation.start=+new Date-this.absPos*i,this.situation.finish=this.situation.start+i,this.step(!0)},speed:function(t){return 0===t?this.pause():t?(this._speed=t,this.at(this.absPos,!0)):this._speed},loop:function(t,e){var i=this.last();return i.loops=null==t||t,i.loop=0,e&&(i.reversing=!0),this},pause:function(){return this.paused=!0,this.stopAnimFrame(),this},play:function(){return this.paused?(this.paused=!1,this.at(this.absPos,!0)):this},reverse:function(t){var e=this.last();return"undefined"==typeof t?e.reversed=!e.reversed:e.reversed=t,this},progress:function(t){return t?this.situation.ease(this.pos):this.pos},after:function(t){var e=this.last(),i=function i(n){n.detail.situation==e&&(t.call(this,e),this.off("finished.fx",i))};return this.target().on("finished.fx",i),this._callStart()},during:function(t){var e=this.last(),i=function(i){i.detail.situation==e&&t.call(this,i.detail.pos,b.morph(i.detail.pos),i.detail.eased,e)};return this.target().off("during.fx",i).on("during.fx",i),this.after(function(){this.off("during.fx",i)}),this._callStart()},afterAll:function(t){var e=function e(i){t.call(this),this.off("allfinished.fx",e)};return this.target().off("allfinished.fx",e).on("allfinished.fx",e),this._callStart()},duringAll:function(t){var e=function(e){t.call(this,e.detail.pos,b.morph(e.detail.pos),e.detail.eased,e.detail.situation)};return this.target().off("during.fx",e).on("during.fx",e),this.afterAll(function(){this.off("during.fx",e)}),this._callStart()},last:function(){return this.situations.length?this.situations[this.situations.length-1]:this.situation},add:function(t,e,i){return this.last()[i||"animations"][t]=e,this._callStart()},step:function(t){if(t||(this.absPos=this.timeToAbsPos(+new Date)),this.situation.loops!==!1){var e,i,n;e=Math.max(this.absPos,0),i=Math.floor(e),this.situation.loops===!0||i<this.situation.loops?(this.pos=e-i,n=this.situation.loop,this.situation.loop=i):(this.absPos=this.situation.loops,this.pos=1,n=this.situation.loop-1,this.situation.loop=this.situation.loops),this.situation.reversing&&(this.situation.reversed=this.situation.reversed!=Boolean((this.situation.loop-n)%2))}else this.absPos=Math.min(this.absPos,1),this.pos=this.absPos;this.pos<0&&(this.pos=0),this.situation.reversed&&(this.pos=1-this.pos);var r=this.situation.ease(this.pos);for(var s in this.situation.once)s>this.lastPos&&s<=r&&(this.situation.once[s].call(this.target(),this.pos,r),delete this.situation.once[s]);return this.active&&this.target().fire("during",{pos:this.pos,eased:r,fx:this,situation:this.situation}),this.situation?(this.eachAt(),1==this.pos&&!this.situation.reversed||this.situation.reversed&&0==this.pos?(this.stopAnimFrame(),this.target().fire("finished",{fx:this,situation:this.situation}),this.situations.length||(this.target().fire("allfinished"),this.target().off(".fx"),this.active=!1),this.active?this.dequeue():this.clearCurrent()):!this.paused&&this.active&&this.startAnimFrame(),this.lastPos=r,this):this},eachAt:function(){var t,e,i=this,n=this.target(),r=this.situation;for(t in r.animations)e=[].concat(r.animations[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n[t].apply(n,e);for(t in r.attrs)e=[t].concat(r.attrs[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n.attr.apply(n,e);for(t in r.styles)e=[t].concat(r.styles[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n.style.apply(n,e);if(r.transforms.length){for(e=r.initialTransformation,t=0,len=r.transforms.length;t<len;t++){var s=r.transforms[t];s instanceof b.Matrix?e=s.relative?e.multiply((new b.Matrix).morph(s).at(r.ease(this.pos))):e.morph(s).at(r.ease(this.pos)):(s.relative||s.undo(e.extract()),e=e.multiply(s.at(r.ease(this.pos))))}n.matrix(e)}return this},once:function(t,e,i){return i||(t=this.situation.ease(t)),this.situation.once[t]=e,this},_callStart:function(){return setTimeout(function(){this.start()}.bind(this),0),this}},parent:b.Element,construct:{animate:function(t,e,i){return(this.fx||(this.fx=new b.FX(this))).animate(t,e,i)},delay:function(t){return(this.fx||(this.fx=new b.FX(this))).delay(t)},stop:function(t,e){return this.fx&&this.fx.stop(t,e),this},finish:function(){return this.fx&&this.fx.finish(),this},pause:function(){return this.fx&&this.fx.pause(),this},play:function(){return this.fx&&this.fx.play(),this},speed:function(t){if(this.fx){if(null==t)return this.fx.speed();this.fx.speed(t)}return this}}}),b.MorphObj=b.invent({create:function(t,e){return b.Color.isColor(e)?new b.Color(t).morph(e):b.regex.numberAndUnit.test(e)?new b.Number(t).morph(e):(this.value=t,void(this.destination=e))},extend:{at:function(t,e){return e<1?this.value:this.destination},valueOf:function(){return this.value}}}),b.extend(b.FX,{attr:function(t,e,i){if("object"==typeof t)for(var n in t)this.attr(n,t[n]);else this.add(t,e,"attrs");return this},style:function(t,e){if("object"==typeof t)for(var i in t)this.style(i,t[i]);else this.add(t,e,"styles");return this},x:function(t,e){if(this.target()instanceof b.G)return this.transform({x:t},e),this;var i=new b.Number(t);return i.relative=e,this.add("x",i)},y:function(t,e){if(this.target()instanceof b.G)return this.transform({y:t},e),this;var i=new b.Number(t);return i.relative=e,this.add("y",i)},cx:function(t){return this.add("cx",new b.Number(t))},cy:function(t){return this.add("cy",new b.Number(t))},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 b.Text)this.attr("font-size",t);else{var i;t&&e||(i=this.target().bbox()),t||(t=i.width/i.height*e),e||(e=i.height/i.width*t),this.add("width",new b.Number(t)).add("height",new b.Number(e))}return this},plot:function(){return this.add("plot",arguments.length>1?[].slice.call(arguments):arguments[0])},leading:function(t){return this.target().leading?this.add("leading",new b.Number(t)):this},viewbox:function(t,e,i,n){return this.target()instanceof b.Container&&this.add("viewbox",new b.Box(t,e,i,n)),this},update:function(t){if(this.target()instanceof b.Stop){if("number"==typeof t||t instanceof b.Number)return this.update({offset:arguments[0],color:arguments[1],opacity:arguments[2]});null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",t.offset)}return this}}),b.Matrix=b.invent({create:function(t){var e,i=p([1,0,0,1,0,0]);for(t=t instanceof b.Element?t.matrixify():"string"==typeof t?p(t.split(b.regex.delimiter).map(parseFloat)):6==arguments.length?p([].slice.call(arguments)):Array.isArray(t)?p(t):"object"==typeof t?t:i,e=P.length-1;e>=0;--e)this[P[e]]=t&&"number"==typeof t[P[e]]?t[P[e]]:i[P[e]]},extend:{extract:function(){var t=d(this,0,1),e=d(this,1,0),i=180/Math.PI*Math.atan2(t.y,t.x)-90;return{x:this.e,y:this.f,transformedX:(this.e*Math.cos(i*Math.PI/180)+this.f*Math.sin(i*Math.PI/180))/Math.sqrt(this.a*this.a+this.b*this.b),transformedY:(this.f*Math.cos(i*Math.PI/180)+this.e*Math.sin(-i*Math.PI/180))/Math.sqrt(this.c*this.c+this.d*this.d),skewX:-i,skewY:180/Math.PI*Math.atan2(e.y,e.x),scaleX:Math.sqrt(this.a*this.a+this.b*this.b),scaleY:Math.sqrt(this.c*this.c+this.d*this.d),rotation:i,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f,matrix:new b.Matrix(this)}},clone:function(){return new b.Matrix(this)},morph:function(t){return this.destination=new b.Matrix(t),this},at:function(t){if(!this.destination)return this;var e=new b.Matrix({a:this.a+(this.destination.a-this.a)*t,b:this.b+(this.destination.b-this.b)*t,c:this.c+(this.destination.c-this.c)*t,d:this.d+(this.destination.d-this.d)*t,e:this.e+(this.destination.e-this.e)*t,f:this.f+(this.destination.f-this.f)*t});return e},multiply:function(t){return new b.Matrix(this.native().multiply(m(t).native()))},inverse:function(){return new b.Matrix(this.native().inverse())},translate:function(t,e){return new b.Matrix(this.native().translate(t||0,e||0))},scale:function(t,e,i,n){return 1==arguments.length?e=t:3==arguments.length&&(n=i,i=e,e=t),this.around(i,n,new b.Matrix(t,0,0,e,0,0))},rotate:function(t,e,i){return t=b.utils.radians(t),this.around(e,i,new b.Matrix(Math.cos(t),Math.sin(t),-Math.sin(t),Math.cos(t),0,0))},flip:function(t,e){return e="number"==typeof t?t:e,"x"==t?this.scale(-1,1,e,0):"y"==t?this.scale(1,-1,0,e):this.scale(-1,-1,e,e)},skew:function(t,e,i,n){return 1==arguments.length?e=t:3==arguments.length&&(n=i,i=e,e=t),t=b.utils.radians(t),e=b.utils.radians(e),this.around(i,n,new b.Matrix(1,Math.tan(e),Math.tan(t),1,0,0))},skewX:function(t,e,i){return this.skew(t,0,e,i)},skewY:function(t,e,i){return this.skew(0,t,e,i)},around:function(t,e,i){return this.multiply(new b.Matrix(1,0,0,1,t||0,e||0)).multiply(i).multiply(new b.Matrix(1,0,0,1,-t||0,-e||0))},native:function(){for(var t=b.parser.native.createSVGMatrix(),e=P.length-1;e>=0;e--)t[P[e]]=this[P[e]];return t},toString:function(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}},parent:b.Element,construct:{ctm:function(){return new b.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof b.Nested){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new b.Matrix(e)}return new b.Matrix(this.node.getScreenCTM())}}}),b.Point=b.invent({create:function(t,e){var i,n={x:0,y:0};i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"==typeof t?{x:t.x,y:t.y}:null!=t?{x:t,y:null!=e?e:t}:n,this.x=i.x,this.y=i.y},extend:{clone:function(){return new b.Point(this)},morph:function(t,e){return this.destination=new b.Point(t,e),this},at:function(t){if(!this.destination)return this;var e=new b.Point({x:this.x+(this.destination.x-this.x)*t,y:this.y+(this.destination.y-this.y)*t});return e},native:function(){var t=b.parser.native.createSVGPoint();return t.x=this.x,t.y=this.y,t},transform:function(t){return new b.Point(this.native().matrixTransform(t.native()))}}}),b.extend(b.Element,{point:function(t,e){return new b.Point(t,e).transform(this.screenCTM().inverse())}}),b.extend(b.Element,{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]=b.regex.isNumber.test(e[i].nodeValue)?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 e=this.node.getAttribute(t),null==e?b.defaults.attrs[t]:b.regex.isNumber.test(e)?parseFloat(e):e;"fill"!=t&&"stroke"!=t||(b.regex.isImage.test(e)&&(e=this.doc().defs().image(e)),e instanceof b.Image&&(e=this.doc().defs().pattern(0,0,function(){this.add(e)}))),"number"==typeof e?e=new b.Number(e):b.Color.isColor(e)?e=new b.Color(e):Array.isArray(e)&&(e=new b.Array(e)),"leading"==t?this.leading&&this.leading(e):"string"==typeof i?this.node.setAttributeNS(i,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!=t&&"x"!=t||this.rebuild(t,e)}return this}}),b.extend(b.Element,{transform:function(t,e){var i,n=this;if("object"!=typeof t)return i=new b.Matrix(n).extract(),"string"==typeof t?i[t]:i;if(i=new b.Matrix(n),e=!!e||!!t.relative,null!=t.a)i=e?i.multiply(new b.Matrix(t)):new b.Matrix(t);else if(null!=t.rotation)x(t,n),i=e?i.rotate(t.rotation,t.cx,t.cy):i.rotate(t.rotation-i.extract().rotation,t.cx,t.cy);else if(null!=t.scale||null!=t.scaleX||null!=t.scaleY){if(x(t,n),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,!e){var r=i.extract();t.scaleX=1*t.scaleX/r.scaleX,t.scaleY=1*t.scaleY/r.scaleY}i=i.scale(t.scaleX,t.scaleY,t.cx,t.cy)}else if(null!=t.skew||null!=t.skewX||null!=t.skewY){if(x(t,n),t.skewX=null!=t.skew?t.skew:null!=t.skewX?t.skewX:0,t.skewY=null!=t.skew?t.skew:null!=t.skewY?t.skewY:0,!e){var r=i.extract();i=i.multiply((new b.Matrix).skew(r.skewX,r.skewY,t.cx,t.cy).inverse())}i=i.skew(t.skewX,t.skewY,t.cx,t.cy)}else t.flip?i=i.flip(t.flip,null==t.offset?n.bbox()["c"+t.flip]:t.offset):null==t.x&&null==t.y||(e?i=i.translate(t.x,t.y):(null!=t.x&&(i.e=t.x),
- null!=t.y&&(i.f=t.y)));return this.attr("transform",i)}}),b.extend(b.FX,{transform:function(t,e){var i,n=this.target();return"object"!=typeof t?(i=new b.Matrix(n).extract(),"string"==typeof t?i[t]:i):(e=!!e||!!t.relative,null!=t.a?i=new b.Matrix(t):null!=t.rotation?(x(t,n),i=new b.Rotate(t.rotation,t.cx,t.cy)):null!=t.scale||null!=t.scaleX||null!=t.scaleY?(x(t,n),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,i=new b.Scale(t.scaleX,t.scaleY,t.cx,t.cy)):null!=t.skewX||null!=t.skewY?(x(t,n),t.skewX=null!=t.skewX?t.skewX:0,t.skewY=null!=t.skewY?t.skewY:0,i=new b.Skew(t.skewX,t.skewY,t.cx,t.cy)):t.flip?i=(new b.Matrix).flip(t.flip,null==t.offset?n.bbox()["c"+t.flip]:t.offset):null==t.x&&null==t.y||(i=new b.Translate(t.x,t.y)),i?(i.relative=e,this.last().transforms.push(i),this._callStart()):this)}}),b.extend(b.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){var t=(this.attr("transform")||"").split(b.regex.transforms).slice(0,-1).map(function(t){var e=t.trim().split("(");return[e[0],e[1].split(b.regex.delimiter).map(function(t){return parseFloat(t)})]}).reduce(function(t,e){return"matrix"==e[0]?t.multiply(p(e[1])):t[e[0]].apply(t,e[1])},new b.Matrix);return t},toParent:function(t){if(this==t)return this;var e=this.screenCTM(),i=t.screenCTM().inverse();return this.addTo(t).untransform().transform(i.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),b.Transformation=b.invent({create:function(t,e){if(arguments.length>1&&"boolean"!=typeof e)return this.constructor.call(this,[].slice.call(arguments));if(Array.isArray(t))for(var i=0,n=this.arguments.length;i<n;++i)this[this.arguments[i]]=t[i];else if("object"==typeof t)for(var i=0,n=this.arguments.length;i<n;++i)this[this.arguments[i]]=t[this.arguments[i]];this.inversed=!1,e===!0&&(this.inversed=!0)},extend:{arguments:[],method:"",at:function(t){for(var e=[],i=0,n=this.arguments.length;i<n;++i)e.push(this[this.arguments[i]]);var r=this._undo||new b.Matrix;return r=(new b.Matrix).morph(b.Matrix.prototype[this.method].apply(r,e)).at(t),this.inversed?r.inverse():r},undo:function(t){for(var e=0,i=this.arguments.length;e<i;++e)t[this.arguments[e]]="undefined"==typeof this[this.arguments[e]]?0:t[this.arguments[e]];return t.cx=this.cx,t.cy=this.cy,this._undo=new(b[u(this.method)])(t,!0).at(1),this}}}),b.Translate=b.invent({parent:b.Matrix,inherit:b.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["transformedX","transformedY"],method:"translate"}}),b.Rotate=b.invent({parent:b.Matrix,inherit:b.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["rotation","cx","cy"],method:"rotate",at:function(t){var e=(new b.Matrix).rotate((new b.Number).morph(this.rotation-(this._undo?this._undo.rotation:0)).at(t),this.cx,this.cy);return this.inversed?e.inverse():e},undo:function(t){this._undo=t}}}),b.Scale=b.invent({parent:b.Matrix,inherit:b.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["scaleX","scaleY","cx","cy"],method:"scale"}}),b.Skew=b.invent({parent:b.Matrix,inherit:b.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["skewX","skewY","cx","cy"],method:"skew"}}),b.extend(b.Element,{style:function(t,e){if(0==arguments.length)return this.node.style.cssText||"";if(arguments.length<2){if("object"!=typeof t)return this.node.style[h(t)];for(e in t)this.style(e,t[e])}else this.node.style[h(t)]=null===e||b.regex.isBlank.test(e)?"":e;return this}}),b.Parent=b.invent({create:function(t){this.constructor.call(this,t)},inherit:b.Element,extend:{children:function(){return b.utils.map(b.utils.filterSVGElements(this.node.childNodes),function(t){return b.adopt(t)})},add:function(t,e){return null==e?this.node.appendChild(t.node):t.node!=this.node.childNodes[e]&&this.node.insertBefore(t.node,this.node.childNodes[e]),this},put:function(t,e){return this.add(t,e),t},has:function(t){return this.index(t)>=0},index:function(t){return[].slice.call(this.node.childNodes).indexOf(t.node)},get:function(t){return b.adopt(this.node.childNodes[t])},first:function(){return this.get(0)},last:function(){return this.get(this.node.childNodes.length-1)},each:function(t,e){var i,n,r=this.children();for(i=0,n=r.length;i<n;i++)r[i]instanceof b.Element&&t.apply(r[i],[i,r]),e&&r[i]instanceof b.Container&&r[i].each(t,e);return this},removeElement:function(t){return this.node.removeChild(t.node),this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return delete this._defs,this},defs:function(){return this.doc().defs()}}}),b.extend(b.Parent,{flatten:function(t){return this instanceof b.Defs?this:(t=t||(this instanceof b.Doc?this:this.parent(b.Parent)),this.each(function(){return this instanceof b.Defs?this:this instanceof b.Parent?this.flatten(t):this.toParent(t)}),this.node.firstChild||this.remove(),this)}}),b.Container=b.invent({create:function(t){this.constructor.call(this,t)},inherit:b.Parent}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","touchstart","touchmove","touchleave","touchend","touchcancel"].forEach(function(t){b.Element.prototype[t]=function(e){var i=this;return this.node["on"+t]="function"==typeof e?function(){return e.apply(i,arguments)}:null,this}}),b.listeners=[],b.handlerMap=[],b.listenerId=0,b.on=function(t,e,i,n){var r=i.bind(n||t.instance||t),s=(b.handlerMap.indexOf(t)+1||b.handlerMap.push(t))-1,a=e.split(".")[0],o=e.split(".")[1]||"*";b.listeners[s]=b.listeners[s]||{},b.listeners[s][a]=b.listeners[s][a]||{},b.listeners[s][a][o]=b.listeners[s][a][o]||{},i._svgjsListenerId||(i._svgjsListenerId=++b.listenerId),b.listeners[s][a][o][i._svgjsListenerId]=r,t.addEventListener(a,r,!1)},b.off=function(t,e,i){var n=b.handlerMap.indexOf(t),r=e&&e.split(".")[0],s=e&&e.split(".")[1];if(n!=-1)if(i){if("function"==typeof i&&(i=i._svgjsListenerId),!i)return;b.listeners[n][r]&&b.listeners[n][r][s||"*"]&&(t.removeEventListener(r,b.listeners[n][r][s||"*"][i],!1),delete b.listeners[n][r][s||"*"][i])}else if(s&&r){if(b.listeners[n][r]&&b.listeners[n][r][s]){for(i in b.listeners[n][r][s])b.off(t,[r,s].join("."),i);delete b.listeners[n][r][s]}}else if(s)for(e in b.listeners[n])for(namespace in b.listeners[n][e])s===namespace&&b.off(t,[e,s].join("."));else if(r){if(b.listeners[n][r]){for(namespace in b.listeners[n][r])b.off(t,[r,namespace].join("."));delete b.listeners[n][r]}}else{for(e in b.listeners[n])b.off(t,e);delete b.listeners[n],delete b.handlerMap[n]}},b.extend(b.Element,{on:function(t,e,i){return b.on(this.node,t,e,i),this},off:function(t,e){return b.off(this.node,t,e),this},fire:function(e,i){return e instanceof t.Event?this.node.dispatchEvent(e):this.node.dispatchEvent(e=new t.CustomEvent(e,{detail:i,cancelable:!0})),this._event=e,this},event:function(){return this._event}}),b.Defs=b.invent({create:"defs",inherit:b.Container}),b.G=b.invent({create:"g",inherit:b.Container,extend:{x:function(t){return null==t?this.transform("x"):this.transform({x:t-this.x()},!0)},y:function(t){return null==t?this.transform("y"):this.transform({y:t-this.y()},!0)},cx:function(t){return null==t?this.gbox().cx:this.x(t-this.gbox().width/2)},cy:function(t){return null==t?this.gbox().cy:this.y(t-this.gbox().height/2)},gbox:function(){var t=this.bbox(),e=this.transform();return t.x+=e.x,t.x2+=e.x,t.cx+=e.x,t.y+=e.y,t.y2+=e.y,t.cy+=e.y,t}},construct:{group:function(){return this.put(new b.G)}}}),b.extend(b.Element,{siblings:function(){return this.parent().children()},position:function(){return this.parent().index(this)},next:function(){return this.siblings()[this.position()+1]},previous:function(){return this.siblings()[this.position()-1]},forward:function(){var t=this.position()+1,e=this.parent();return e.removeElement(this).add(this,t),e instanceof b.Doc&&e.node.appendChild(e.defs().node),this},backward:function(){var t=this.position();return t>0&&this.parent().removeElement(this).add(this,t-1),this},front:function(){var t=this.parent();return t.node.appendChild(this.node),t instanceof b.Doc&&t.node.appendChild(t.defs().node),this},back:function(){return this.position()>0&&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}}),b.Mask=b.invent({create:"mask",inherit:b.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unmask()}),b.Element.prototype.remove.call(this)},targets:function(){return b.select('svg [mask*="'+this.id()+'"]')}},construct:{mask:function(){return this.defs().put(new b.Mask)}}}),b.extend(b.Element,{maskWith:function(t){var e=t instanceof b.Mask?t:this.parent().mask().add(t);return this.attr("mask",'url("#'+e.attr("id")+'")')},unmask:function(){return this.attr("mask",null)},masker:function(){return this.reference("mask")}}),b.ClipPath=b.invent({create:"clipPath",inherit:b.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unclip()}),b.Element.prototype.remove.call(this)},targets:function(){return b.select('svg [clip-path*="'+this.id()+'"]')}},construct:{clip:function(){return this.defs().put(new b.ClipPath)}}}),b.extend(b.Element,{clipWith:function(t){var e=t instanceof b.ClipPath?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.attr("id")+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}),b.Gradient=b.invent({create:function(t){this.constructor.call(this,b.create(t+"Gradient"))},inherit:b.Container,extend:{at:function(t,e,i){return this.put(new b.Stop).update(t,e,i)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},fill:function(){return"url(#"+this.id()+")"},toString:function(){return this.fill()},attr:function(t,e,i){return"transform"==t&&(t="gradientTransform"),b.Container.prototype.attr.call(this,t,e,i)}},construct:{gradient:function(t,e){return this.defs().gradient(t,e)}}}),b.extend(b.Gradient,b.FX,{from:function(t,e){return"radialGradient"==(this._target||this).type?this.attr({fx:new b.Number(t),fy:new b.Number(e)}):this.attr({x1:new b.Number(t),y1:new b.Number(e)})},to:function(t,e){return"radialGradient"==(this._target||this).type?this.attr({cx:new b.Number(t),cy:new b.Number(e)}):this.attr({x2:new b.Number(t),y2:new b.Number(e)})}}),b.extend(b.Defs,{gradient:function(t,e){return this.put(new b.Gradient(t)).update(e)}}),b.Stop=b.invent({create:"stop",inherit:b.Element,extend:{update:function(t){return("number"==typeof t||t instanceof b.Number)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),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 b.Number(t.offset)),this}}}),b.Pattern=b.invent({create:"pattern",inherit:b.Container,extend:{fill:function(){return"url(#"+this.id()+")"},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return this.fill()},attr:function(t,e,i){return"transform"==t&&(t="patternTransform"),b.Container.prototype.attr.call(this,t,e,i)}},construct:{pattern:function(t,e,i){return this.defs().pattern(t,e,i)}}}),b.extend(b.Defs,{pattern:function(t,e,i){return this.put(new b.Pattern).update(i).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),b.Doc=b.invent({create:function(t){t&&(t="string"==typeof t?e.getElementById(t):t,"svg"==t.nodeName?this.constructor.call(this,t):(this.constructor.call(this,b.create("svg")),t.appendChild(this.node),this.size("100%","100%")),this.namespace().defs())},inherit:b.Container,extend:{namespace:function(){return this.attr({xmlns:b.ns,version:"1.1"}).attr("xmlns:xlink",b.xlink,b.xmlns).attr("xmlns:svgjs",b.svgjs,b.xmlns)},defs:function(){if(!this._defs){var t;(t=this.node.getElementsByTagName("defs")[0])?this._defs=b.adopt(t):this._defs=new b.Defs,this.node.appendChild(this._defs.node)}return this._defs},parent:function(){return"#document"==this.node.parentNode.nodeName?null:this.node.parentNode},spof:function(t){var e=this.node.getScreenCTM();return e&&this.style("left",-e.e%1+"px").style("top",-e.f%1+"px"),this},remove:function(){return this.parent()&&this.parent().removeChild(this.node),this}}}),b.Shape=b.invent({create:function(t){this.constructor.call(this,t)},inherit:b.Element}),b.Bare=b.invent({create:function(t,e){if(this.constructor.call(this,b.create(t)),e)for(var i in e.prototype)"function"==typeof e.prototype[i]&&(this[i]=e.prototype[i])},inherit:b.Element,extend:{words:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(e.createTextNode(t)),this}}}),b.extend(b.Parent,{element:function(t,e){return this.put(new b.Bare(t,e))}}),b.Symbol=b.invent({create:"symbol",inherit:b.Container,construct:{symbol:function(){return this.put(new b.Symbol)}}}),b.Use=b.invent({create:"use",inherit:b.Shape,extend:{element:function(t,e){return this.attr("href",(e||"")+"#"+t,b.xlink)}},construct:{use:function(t,e){return this.put(new b.Use).element(t,e)}}}),b.Rect=b.invent({create:"rect",inherit:b.Shape,construct:{rect:function(t,e){return this.put(new b.Rect).size(t,e)}}}),b.Circle=b.invent({create:"circle",inherit:b.Shape,construct:{circle:function(t){return this.put(new b.Circle).rx(new b.Number(t).divide(2)).move(0,0)}}}),b.extend(b.Circle,b.FX,{rx:function(t){return this.attr("r",t)},ry:function(t){return this.rx(t)}}),b.Ellipse=b.invent({create:"ellipse",inherit:b.Shape,construct:{ellipse:function(t,e){return this.put(new b.Ellipse).size(t,e).move(0,0)}}}),b.extend(b.Ellipse,b.Rect,b.FX,{rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)}}),b.extend(b.Circle,b.Ellipse,{x:function(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())},y:function(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())},cx:function(t){return null==t?this.attr("cx"):this.attr("cx",t)},cy:function(t){return null==t?this.attr("cy"):this.attr("cy",t)},width:function(t){return null==t?2*this.rx():this.rx(new b.Number(t).divide(2))},height:function(t){return null==t?2*this.ry():this.ry(new b.Number(t).divide(2))},size:function(t,e){var i=f(this,t,e);return this.rx(new b.Number(i.width).divide(2)).ry(new b.Number(i.height).divide(2))}}),b.Line=b.invent({create:"line",inherit:b.Shape,extend:{array:function(){return new b.PointArray([[this.attr("x1"),this.attr("y1")],[this.attr("x2"),this.attr("y2")]])},plot:function(t,e,i,n){return null==t?this.array():(t="undefined"!=typeof e?{x1:t,y1:e,x2:i,y2:n}:new b.PointArray(t).toLine(),this.attr(t))},move:function(t,e){return this.attr(this.array().move(t,e).toLine())},size:function(t,e){var i=f(this,t,e);return this.attr(this.array().size(i.width,i.height).toLine())}},construct:{line:function(t,e,i,n){return b.Line.prototype.plot.apply(this.put(new b.Line),null!=t?[t,e,i,n]:[0,0,0,0])}}}),b.Polyline=b.invent({create:"polyline",inherit:b.Shape,construct:{polyline:function(t){return this.put(new b.Polyline).plot(t||new b.PointArray)}}}),b.Polygon=b.invent({create:"polygon",inherit:b.Shape,construct:{polygon:function(t){return this.put(new b.Polygon).plot(t||new b.PointArray)}}}),b.extend(b.Polyline,b.Polygon,{array:function(){return this._array||(this._array=new b.PointArray(this.attr("points")))},plot:function(t){return null==t?this.array():this.attr("points",this._array=new b.PointArray(t))},move:function(t,e){return this.attr("points",this.array().move(t,e))},size:function(t,e){var i=f(this,t,e);return this.attr("points",this.array().size(i.width,i.height))}}),b.extend(b.Line,b.Polyline,b.Polygon,{morphArray:b.PointArray,x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},width:function(t){var e=this.bbox();return null==t?e.width:this.size(t,e.height)},height:function(t){var e=this.bbox();return null==t?e.height:this.size(e.width,t)}}),b.Path=b.invent({create:"path",inherit:b.Shape,extend:{morphArray:b.PathArray,array:function(){return this._array||(this._array=new b.PathArray(this.attr("d")))},plot:function(t){return null==t?this.array():this.attr("d",this._array=new b.PathArray(t))},move:function(t,e){return this.attr("d",this.array().move(t,e))},x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},size:function(t,e){var i=f(this,t,e);return this.attr("d",this.array().size(i.width,i.height))},width:function(t){return null==t?this.bbox().width:this.size(t,this.bbox().height)},height:function(t){return null==t?this.bbox().height:this.size(this.bbox().width,t)}},construct:{path:function(t){return this.put(new b.Path).plot(t||new b.PathArray)}}}),b.Image=b.invent({create:"image",inherit:b.Shape,extend:{load:function(e,i){if(!e)return this;var n=new t.Image;return b.on(n,"load",function(t){var r=this.parent();0==this.width()&&0==this.height()&&this.size(n.width,n.height),r instanceof b.Pattern&&0==r.width()&&0==r.height()&&r.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:n.width,height:n.height,ratio:n.width/n.height,url:e})},this),this.attr("href",n.src=e,b.xlink)}},construct:{image:function(t,e){return this.put(new b.Image).size(0,0).load(t,e)}}}),b.Text=b.invent({create:function(){this.constructor.call(this,b.create("text")),this.dom.leading=new b.Number(1.3),this._rebuild=!0,this._build=!1,this.attr("font-family",b.defaults.attrs["font-family"])},inherit:b.Parent,extend:{x:function(t){return null==t?this.attr("x"):this.attr("x",t)},y:function(t){var e=this.attr("y"),i="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-i:e:this.attr("y","number"==typeof t?t+i: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)},text:function(t){if("undefined"==typeof t){for(var t="",e=this.node.childNodes,i=0,n=e.length;i<n;++i)0!=i&&3!=e[i].nodeType&&1==b.adopt(e[i]).dom.newLined&&(t+="\n"),t+=e[i].textContent;return t}if(this.clear().build(!0),"function"==typeof t)t.call(this,this);else{t=t.split("\n");for(var i=0,r=t.length;i<r;i++)this.tspan(t[i]).newLine()}return this.build(!1).rebuild()},size:function(t){return this.attr("font-size",t).rebuild()},leading:function(t){return null==t?this.dom.leading:(this.dom.leading=new b.Number(t),this.rebuild())},rebuild:function(t){if("boolean"==typeof t&&(this._rebuild=t),this._rebuild){var e=this,i=0,n=this.dom.leading*new b.Number(this.attr("font-size"));this.each(function(){this.dom.newLined&&(e.textPath()||this.attr("x",e.attr("x")),"\n"==this.text()?i+=n:(this.attr("dy",n+i),i=0))}),this.fire("rebuild")}return this},build:function(t){return this._build=!!t,this},setData:function(t){return this.dom=t,this.dom.leading=new b.Number(t.leading||1.3),this}},construct:{text:function(t){return this.put(new b.Text).text(t)},plain:function(t){return this.put(new b.Text).plain(t)}}}),b.Tspan=b.invent({create:"tspan",inherit:b.Parent,extend:{text:function(t){return null==t?this.node.textContent+(this.dom.newLined?"\n":""):("function"==typeof t?t.call(this,this):this.plain(t),this)},dx:function(t){return this.attr("dx",t)},dy:function(t){return this.attr("dy",t)},newLine:function(){var t=this.parent(b.Text);return this.dom.newLined=!0,this.dy(t.dom.leading*t.attr("font-size")).attr("x",t.x())}}}),b.extend(b.Text,b.Tspan,{plain:function(t){return this._build===!1&&this.clear(),this.node.appendChild(e.createTextNode(t)),this},tspan:function(t){var e=(this.textPath&&this.textPath()||this).node,i=new b.Tspan;return this._build===!1&&this.clear(),e.appendChild(i.node),i.text(t)},length:function(){return this.node.getComputedTextLength()}}),b.TextPath=b.invent({create:"textPath",inherit:b.Parent,parent:b.Text,construct:{path:function(t){for(var e=new b.TextPath,i=this.doc().defs().path(t);this.node.hasChildNodes();)e.node.appendChild(this.node.firstChild);return this.node.appendChild(e.node),e.attr("href","#"+i,b.xlink),this},array:function(){var t=this.track();return t?t.array():null},plot:function(t){var e=this.track(),i=null;return e&&(i=e.plot(t)),null==t?i:this},track:function(){var t=this.textPath();if(t)return t.reference("href")},textPath:function(){if(this.node.firstChild&&"textPath"==this.node.firstChild.nodeName)return b.adopt(this.node.firstChild)}}}),b.Nested=b.invent({create:function(){this.constructor.call(this,b.create("svg")),this.style("overflow","visible")},inherit:b.Container,construct:{nested:function(){return this.put(new b.Nested)}}}),b.A=b.invent({create:"a",inherit:b.Container,extend:{to:function(t){return this.attr("href",t,b.xlink)},show:function(t){return this.attr("show",t,b.xlink)},target:function(t){return this.attr("target",t)}},construct:{link:function(t){return this.put(new b.A).to(t)}}}),b.extend(b.Element,{linkTo:function(t){var e=new b.A;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}),b.Marker=b.invent({create:"marker",inherit:b.Container,extend:{width:function(t){return this.attr("markerWidth",t)},height:function(t){return this.attr("markerHeight",t)},ref:function(t,e){return this.attr("refX",t).attr("refY",e)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return"url(#"+this.id()+")"}},construct:{marker:function(t,e,i){return this.defs().marker(t,e,i)}}}),b.extend(b.Defs,{marker:function(t,e,i){return this.put(new b.Marker).size(t,e).ref(t/2,e/2).viewbox(0,0,t,e).attr("orient","auto").update(i)}}),b.extend(b.Line,b.Polyline,b.Polygon,b.Path,{marker:function(t,e,i,n){var r=["marker"];return"all"!=t&&r.push(t),r=r.join("-"),t=arguments[1]instanceof b.Marker?arguments[1]:this.doc().marker(e,i,n),this.attr(r,t)}});var M={stroke:["color","width","opacity","linecap","linejoin","miterlimit","dasharray","dashoffset"],fill:["color","opacity","rule"],prefix:function(t,e){return"color"==e?t:t+"-"+e}};["fill","stroke"].forEach(function(t){var e,i={};i[t]=function(i){if("undefined"==typeof i)return this;if("string"==typeof i||b.Color.isRgb(i)||i&&"function"==typeof i.fill)this.attr(t,i);else for(e=M[t].length-1;e>=0;e--)null!=i[M[t][e]]&&this.attr(M.prefix(t,M[t][e]),i[M[t][e]]);return this},b.extend(b.Element,b.FX,i)}),b.extend(b.Element,b.FX,{rotate:function(t,e,i){return this.transform({rotation:t,cx:e,cy:i})},skew:function(t,e,i,n){return 1==arguments.length||3==arguments.length?this.transform({skew:t,cx:e,cy:i}):this.transform({skewX:t,skewY:e,cx:i,cy:n})},scale:function(t,e,i,n){return 1==arguments.length||3==arguments.length?this.transform({scale:t,cx:e,cy:i}):this.transform({scaleX:t,scaleY:e,cx:i,cy:n})},translate:function(t,e){return this.transform({x:t,y:e})},flip:function(t,e){return e="number"==typeof t?t:e,this.transform({flip:t||"both",offset:e})},matrix:function(t){return this.attr("transform",new b.Matrix(6==arguments.length?[].slice.call(arguments):t))},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new b.Number(t).plus(this instanceof b.FX?0:this.x()),!0)},dy:function(t){return this.y(new b.Number(t).plus(this instanceof b.FX?0:this.y()),!0)},dmove:function(t,e){return this.dx(t).dy(e)}}),b.extend(b.Rect,b.Ellipse,b.Circle,b.Gradient,b.FX,{radius:function(t,e){var i=(this._target||this).type;return"radialGradient"==i||"radialGradient"==i?this.attr("r",new b.Number(t)):this.rx(t).ry(null==e?t:e)}}),b.extend(b.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return new b.Point(this.node.getPointAtLength(t))}}),b.extend(b.Parent,b.Text,b.Tspan,b.FX,{font:function(t,e){if("object"==typeof t)for(e in t)this.font(e,t[e]);return"leading"==t?this.leading(e):"anchor"==t?this.attr("text-anchor",e):"size"==t||"family"==t||"weight"==t||"stretch"==t||"variant"==t||"style"==t?this.attr("font-"+t,e):this.attr(t,e)}}),b.extend(b.Element,{data:function(t,e,i){if("object"==typeof t)for(e in t)this.data(e,t[e]);else if(arguments.length<2)try{return JSON.parse(this.attr("data-"+t))}catch(e){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}}),b.extend(b.Element,{remember:function(t,e){if("object"==typeof arguments[0])for(var e in t)this.remember(e,t[e]);else{if(1==arguments.length)return this.memory()[t];this.memory()[t]=e}return this},forget:function(){if(0==arguments.length)this._memory={};else for(var t=arguments.length-1;t>=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory||(this._memory={})}}),b.get=function(t){var i=e.getElementById(w(t)||t);return b.adopt(i)},b.select=function(t,i){return b.utils.map((i||e).querySelectorAll(t),function(t){return b.adopt(t)})},b.$$=function(t,i){return b.utils.map((i||e).querySelectorAll(t),function(t){return b.adopt(t)})},b.$=function(t,i){return b.adopt((i||e).querySelector(t))},b.extend(b.Parent,{select:function(t){return b.select(t,this.node)}});var P="abcdef".split("");return b.Box=b.invent({create:function(t){var e=[0,0,0,0];t="string"==typeof t?t.split(b.regex.delimiter).map(parseFloat):Array.isArray(t)?t:"object"==typeof t?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4==arguments.length?[].slice.call(arguments):e,this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],g(this)},extend:{merge:function(t){var e=Math.min(this.x,t.x),i=Math.min(this.y,t.y);return new b.Box(e,i,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-i)},transform:function(t){var e=1/0,i=-(1/0),n=1/0,r=-(1/0),s=[new b.Point(this.x,this.y),new b.Point(this.x2,this.y),new b.Point(this.x,this.y2),new b.Point(this.x2,this.y2)];return s.forEach(function(s){s=s.transform(t),e=Math.min(e,s.x),i=Math.max(i,s.x),n=Math.min(n,s.y),r=Math.max(r,s.y)}),new b.Box(e,n,i-e,r-n)},addOffset:function(){return this.x+=t.pageXOffset,this.y+=t.pageYOffset,this},toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height},morph:function(t,e,i,n){return this.destination=new b.Box(t,e,i,n),this},at:function(t){return this.destination?new b.Box(this.x+(this.destination.x-this.x)*t,this.y+(this.destination.y-this.y)*t,this.width+(this.destination.width-this.width)*t,this.height+(this.destination.height-this.height)*t):this}},parent:b.Element,construct:{bbox:function(){var t;try{if(t=this.node.getBBox(),i(t)&&!n(this.node))throw new Exception("Element not in the dom")}catch(i){try{var e=this.clone(b.parser.draw).show();t=e.node.getBBox(),e.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return new b.Box(t)},rbox:function(t){try{var e=new b.Box(this.node.getBoundingClientRect());return t?e.transform(t.screenCTM().inverse()):e.addOffset()}catch(t){return new b.Box}}}}),b.extend(b.Doc,b.Nested,b.Symbol,b.Image,b.Pattern,b.Marker,b.ForeignObject,b.View,{viewbox:function(t,e,i,n){return null==t?new b.Box(this.attr("viewBox")):this.attr("viewBox",new b.Box(t,e,i,n))}}),b});
 -/*! svg.js v2.6.0 MIT*/;!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t,t.document)}):"object"==typeof exports?module.exports=t.document?e(t,t.document):function(t){return e(t,t.document)}:t.SVG=e(t,t.document)}("undefined"!=typeof window?window:this,function(t,e){function i(t,e,i,n){return i+n.replace(g.regex.dots," .")}function n(t){for(var e=t.slice(0),i=e.length;i--;)Array.isArray(e[i])&&(e[i]=n(e[i]));return e}function r(t,e){return t instanceof e}function s(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}function o(t){return t.toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()})}function a(t){return t.charAt(0).toUpperCase()+t.slice(1)}function h(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}function u(t){var e=t.toString(16);return 1==e.length?"0"+e:e}function l(t,e,i){if(null==e||null==i){var n=t.bbox();null==e?e=n.width/n.height*i:null==i&&(i=n.height/n.width*e)}return{width:e,height:i}}function c(t,e,i){return{x:e*t.a+i*t.c+0,y:e*t.b+i*t.d+0}}function f(t){return{a:t[0],b:t[1],c:t[2],d:t[3],e:t[4],f:t[5]}}function d(t){return t instanceof g.Matrix||(t=new g.Matrix(t)),t}function p(t,e){t.cx=null==t.cx?e.bbox().cx:t.cx,t.cy=null==t.cy?e.bbox().cy:t.cy}function m(t){for(var e=0,i=t.length,n="";e<i;e++)n+=t[e][0],null!=t[e][1]&&(n+=t[e][1],null!=t[e][2]&&(n+=" ",n+=t[e][2],null!=t[e][3]&&(n+=" ",n+=t[e][3],n+=" ",n+=t[e][4],null!=t[e][5]&&(n+=" ",n+=t[e][5],n+=" ",n+=t[e][6],null!=t[e][7]&&(n+=" ",n+=t[e][7])))));return n+" "}function x(e){for(var i=e.childNodes.length-1;i>=0;i--)e.childNodes[i]instanceof t.SVGElement&&x(e.childNodes[i]);return g.adopt(e).id(g.eid(e.nodeName))}function y(t){return null==t.x&&(t.x=0,t.y=0,t.width=0,t.height=0),t.w=t.width,t.h=t.height,t.x2=t.x+t.width,t.y2=t.y+t.height,t.cx=t.x+t.width/2,t.cy=t.y+t.height/2,t}function v(t){var e=t.toString().match(g.regex.reference);if(e)return e[1]}var g=this.SVG=function(t){if(g.supported)return t=new g.Doc(t),g.parser.draw||g.prepare(),t};if(g.ns="http://www.w3.org/2000/svg",g.xmlns="http://www.w3.org/2000/xmlns/",g.xlink="http://www.w3.org/1999/xlink",g.svgjs="http://svgjs.com/svgjs",g.supported=function(){return!!e.createElementNS&&!!e.createElementNS(g.ns,"svg").createSVGRect}(),!g.supported)return!1;g.did=1e3,g.eid=function(t){return"Svgjs"+a(t)+g.did++},g.create=function(t){var i=e.createElementNS(this.ns,t);return i.setAttribute("id",this.eid(t)),i},g.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];g.Set&&g.Set.inherit&&g.Set.inherit()},g.invent=function(t){var e="function"==typeof t.create?t.create:function(){this.constructor.call(this,g.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&g.extend(e,t.extend),t.construct&&g.extend(t.parent||g.Container,t.construct),e},g.adopt=function(e){if(!e)return null;if(e.instance)return e.instance;var i;return i="svg"==e.nodeName?e.parentNode instanceof t.SVGElement?new g.Nested:new g.Doc:"linearGradient"==e.nodeName?new g.Gradient("linear"):"radialGradient"==e.nodeName?new g.Gradient("radial"):g[a(e.nodeName)]?new(g[a(e.nodeName)]):new g.Element(e),i.type=e.nodeName,i.node=e,e.instance=i,i instanceof g.Doc&&i.namespace().defs(),i.setData(JSON.parse(e.getAttribute("svgjs:data"))||{}),i},g.prepare=function(){var t=e.getElementsByTagName("body")[0],i=(t?new g.Doc(t):g.adopt(e.documentElement).nested()).size(2,0);g.parser={body:t||e.documentElement,draw:i.style("opacity:0;position:absolute;left:-100%;top:-100%;overflow:hidden").node,poly:i.polyline().node,path:i.path().node,native:g.create("svg")}},g.parser={native:g.create("svg")},e.addEventListener("DOMContentLoaded",function(){g.parser.draw||g.prepare()},!1),g.regex={numberAndUnit:/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,reference:/#([a-z0-9\-_]+)/i,transforms:/\)\s*,?\s*/,whitespace:/\s/g,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isBlank:/^(\s+)?$/,isNumber:/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,isPercent:/^-?[\d\.]+%$/,isImage:/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,delimiter:/[\s,]+/,hyphen:/([^e])\-/gi,pathLetters:/[MLHVCSQTAZ]/gi,isPathLetter:/[MLHVCSQTAZ]/i,numbersWithDots:/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,dots:/\./g},g.utils={map:function(t,e){var i,n=t.length,r=[];for(i=0;i<n;i++)r.push(e(t[i]));return r},filter:function(t,e){var i,n=t.length,r=[];for(i=0;i<n;i++)e(t[i])&&r.push(t[i]);return r},radians:function(t){return t%360*Math.PI/180},degrees:function(t){return 180*t/Math.PI%360},filterSVGElements:function(e){return this.filter(e,function(e){return e instanceof t.SVGElement})}},g.defaults={attrs:{"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",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":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"}},g.Color=function(t){var e;this.r=0,this.g=0,this.b=0,t&&("string"==typeof t?g.regex.isRgb.test(t)?(e=g.regex.rgb.exec(t.replace(g.regex.whitespace,"")),this.r=parseInt(e[1]),this.g=parseInt(e[2]),this.b=parseInt(e[3])):g.regex.isHex.test(t)&&(e=g.regex.hex.exec(h(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))},g.extend(g.Color,{toString:function(){return this.toHex()},toHex:function(){return"#"+u(this.r)+u(this.g)+u(this.b)},toRgb:function(){return"rgb("+[this.r,this.g,this.b].join()+")"},brightness:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11},morph:function(t){return this.destination=new g.Color(t),this},at:function(t){return this.destination?(t=t<0?0:t>1?1:t,new g.Color({r:~~(this.r+(this.destination.r-this.r)*t),g:~~(this.g+(this.destination.g-this.g)*t),b:~~(this.b+(this.destination.b-this.b)*t)})):this}}),g.Color.test=function(t){return t+="",g.regex.isHex.test(t)||g.regex.isRgb.test(t)},g.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},g.Color.isColor=function(t){return g.Color.isRgb(t)||g.Color.test(t)},g.Array=function(t,e){t=(t||[]).valueOf(),0==t.length&&e&&(t=e.valueOf()),this.value=this.parse(t)},g.extend(g.Array,{morph:function(t){if(this.destination=this.parse(t),this.value.length!=this.destination.length){for(var e=this.value[this.value.length-1],i=this.destination[this.destination.length-1];this.value.length>this.destination.length;)this.destination.push(i);for(;this.value.length<this.destination.length;)this.value.push(e)}return this},settle:function(){for(var t=0,e=this.value.length,i=[];t<e;t++)i.indexOf(this.value[t])==-1&&i.push(this.value[t]);return this.value=i},at:function(t){if(!this.destination)return this;for(var e=0,i=this.value.length,n=[];e<i;e++)n.push(this.value[e]+(this.destination[e]-this.value[e])*t);return new g.Array(n)},toString:function(){return this.value.join(" ")},valueOf:function(){return this.value},parse:function(t){return t=t.valueOf(),Array.isArray(t)?t:this.split(t)},split:function(t){return t.trim().split(g.regex.delimiter).map(parseFloat)},reverse:function(){return this.value.reverse(),this},clone:function(){var t=new this.constructor;return t.value=n(this.value),t}}),g.PointArray=function(t,e){g.Array.call(this,t,e||[[0,0]])},g.PointArray.prototype=new g.Array,g.PointArray.prototype.constructor=g.PointArray,g.extend(g.PointArray,{toString:function(){for(var t=0,e=this.value.length,i=[];t<e;t++)i.push(this.value[t].join(","));return i.join(" ")},toLine:function(){return{x1:this.value[0][0],y1:this.value[0][1],x2:this.value[1][0],y2:this.value[1][1]}},at:function(t){if(!this.destination)return this;for(var e=0,i=this.value.length,n=[];e<i;e++)n.push([this.value[e][0]+(this.destination[e][0]-this.value[e][0])*t,this.value[e][1]+(this.destination[e][1]-this.value[e][1])*t]);return new g.PointArray(n)},parse:function(t){var e=[];if(t=t.valueOf(),Array.isArray(t)){if(Array.isArray(t[0]))return t}else t=t.trim().split(g.regex.delimiter).map(parseFloat);t.length%2!==0&&t.pop();for(var i=0,n=t.length;i<n;i+=2)e.push([t[i],t[i+1]]);return e},move:function(t,e){var i=this.bbox();if(t-=i.x,e-=i.y,!isNaN(t)&&!isNaN(e))for(var n=this.value.length-1;n>=0;n--)this.value[n]=[this.value[n][0]+t,this.value[n][1]+e];return this},size:function(t,e){var i,n=this.bbox();for(i=this.value.length-1;i>=0;i--)n.width&&(this.value[i][0]=(this.value[i][0]-n.x)*t/n.width+n.x),n.height&&(this.value[i][1]=(this.value[i][1]-n.y)*e/n.height+n.y);return this},bbox:function(){return g.parser.poly.setAttribute("points",this.toString()),g.parser.poly.getBBox()}});for(var w={M:function(t,e,i){return e.x=i.x=t[0],e.y=i.y=t[1],["M",e.x,e.y]},L:function(t,e){return e.x=t[0],e.y=t[1],["L",t[0],t[1]]},H:function(t,e){return e.x=t[0],["H",t[0]]},V:function(t,e){return e.y=t[0],["V",t[0]]},C:function(t,e){return e.x=t[4],e.y=t[5],["C",t[0],t[1],t[2],t[3],t[4],t[5]]},S:function(t,e){return e.x=t[2],e.y=t[3],["S",t[0],t[1],t[2],t[3]]},Q:function(t,e){return e.x=t[2],e.y=t[3],["Q",t[0],t[1],t[2],t[3]]},T:function(t,e){return e.x=t[0],e.y=t[1],["T",t[0],t[1]]},Z:function(t,e,i){return e.x=i.x,e.y=i.y,["Z"]},A:function(t,e){return e.x=t[5],e.y=t[6],["A",t[0],t[1],t[2],t[3],t[4],t[5],t[6]]}},b="mlhvqtcsaz".split(""),C=0,N=b.length;C<N;++C)w[b[C]]=function(t){return function(e,i,n){if("H"==t)e[0]=e[0]+i.x;else if("V"==t)e[0]=e[0]+i.y;else if("A"==t)e[5]=e[5]+i.x,e[6]=e[6]+i.y;else for(var r=0,s=e.length;r<s;++r)e[r]=e[r]+(r%2?i.y:i.x);return w[t](e,i,n)}}(b[C].toUpperCase());g.PathArray=function(t,e){g.Array.call(this,t,e||[["M",0,0]])},g.PathArray.prototype=new g.Array,g.PathArray.prototype.constructor=g.PathArray,g.extend(g.PathArray,{toString:function(){return m(this.value)},move:function(t,e){var i=this.bbox();if(t-=i.x,e-=i.y,!isNaN(t)&&!isNaN(e))for(var n,r=this.value.length-1;r>=0;r--)n=this.value[r][0],"M"==n||"L"==n||"T"==n?(this.value[r][1]+=t,this.value[r][2]+=e):"H"==n?this.value[r][1]+=t:"V"==n?this.value[r][1]+=e:"C"==n||"S"==n||"Q"==n?(this.value[r][1]+=t,this.value[r][2]+=e,this.value[r][3]+=t,this.value[r][4]+=e,"C"==n&&(this.value[r][5]+=t,this.value[r][6]+=e)):"A"==n&&(this.value[r][6]+=t,this.value[r][7]+=e);return this},size:function(t,e){var i,n,r=this.bbox();for(i=this.value.length-1;i>=0;i--)n=this.value[i][0],"M"==n||"L"==n||"T"==n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y):"H"==n?this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x:"V"==n?this.value[i][1]=(this.value[i][1]-r.y)*e/r.height+r.y:"C"==n||"S"==n||"Q"==n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y,this.value[i][3]=(this.value[i][3]-r.x)*t/r.width+r.x,this.value[i][4]=(this.value[i][4]-r.y)*e/r.height+r.y,"C"==n&&(this.value[i][5]=(this.value[i][5]-r.x)*t/r.width+r.x,this.value[i][6]=(this.value[i][6]-r.y)*e/r.height+r.y)):"A"==n&&(this.value[i][1]=this.value[i][1]*t/r.width,this.value[i][2]=this.value[i][2]*e/r.height,this.value[i][6]=(this.value[i][6]-r.x)*t/r.width+r.x,this.value[i][7]=(this.value[i][7]-r.y)*e/r.height+r.y);return this},equalCommands:function(t){var e,i,n;for(t=new g.PathArray(t),n=this.value.length===t.value.length,e=0,i=this.value.length;n&&e<i;e++)n=this.value[e][0]===t.value[e][0];return n},morph:function(t){return t=new g.PathArray(t),this.equalCommands(t)?this.destination=t:this.destination=null,this},at:function(t){if(!this.destination)return this;var e,i,n,r,s=this.value,o=this.destination.value,a=[],h=new g.PathArray;for(e=0,i=s.length;e<i;e++){for(a[e]=[s[e][0]],n=1,r=s[e].length;n<r;n++)a[e][n]=s[e][n]+(o[e][n]-s[e][n])*t;"A"===a[e][0]&&(a[e][4]=+(0!=a[e][4]),a[e][5]=+(0!=a[e][5]))}return h.value=a,h},parse:function(t){if(t instanceof g.PathArray)return t.valueOf();var e,n,r={M:2,L:2,H:1,V:1,C:6,S:4,Q:4,T:2,A:7};t="string"==typeof t?t.replace(g.regex.numbersWithDots,i).replace(g.regex.pathLetters," $& ").replace(g.regex.hyphen,"$1 -").trim().split(g.regex.delimiter):t.reduce(function(t,e){return[].concat.call(t,e)},[]);var n=[],s=new g.Point,o=new g.Point,a=0,h=t.length;do g.regex.isPathLetter.test(t[a])?(e=t[a],++a):"M"==e?e="L":"m"==e&&(e="l"),n.push(w[e].call(null,t.slice(a,a+=r[e.toUpperCase()]).map(parseFloat),s,o));while(h>a);return n},bbox:function(){return g.parser.path.setAttribute("d",this.toString()),g.parser.path.getBBox()}}),g.Number=g.invent({create:function(t,e){this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-3.4e38:3.4e38:"string"==typeof t?(e=t.match(g.regex.numberAndUnit),e&&(this.value=parseFloat(e[1]),"%"==e[5]?this.value/=100:"s"==e[5]&&(this.value*=1e3),this.unit=e[5])):t instanceof g.Number&&(this.value=t.valueOf(),this.unit=t.unit)},extend:{toString:function(){return("%"==this.unit?~~(1e8*this.value)/1e6:"s"==this.unit?this.value/1e3:this.value)+this.unit},toJSON:function(){return this.toString()},valueOf:function(){return this.value},plus:function(t){return t=new g.Number(t),new g.Number(this+t,this.unit||t.unit)},minus:function(t){return t=new g.Number(t),new g.Number(this-t,this.unit||t.unit)},times:function(t){return t=new g.Number(t),new g.Number(this*t,this.unit||t.unit)},divide:function(t){return t=new g.Number(t),new g.Number(this/t,this.unit||t.unit)},to:function(t){var e=new g.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new g.Number(t),t.relative&&(this.destination.value+=this.value),this},at:function(t){return this.destination?new g.Number(this.destination).minus(this).times(t).plus(this):this}}}),g.Element=g.invent({create:function(t){this._stroke=g.defaults.attrs.stroke,this._event=null,this.dom={},(this.node=t)&&(this.type=t.nodeName,this.node.instance=this,this._stroke=t.getAttribute("stroke")||this._stroke)},extend:{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var i=l(this,t,e);return this.width(new g.Number(i.width)).height(new g.Number(i.height))},clone:function(t,e){this.writeDataToDom();var i=x(this.node.cloneNode(!0));return t?t.add(i):this.after(i),i},remove:function(){return this.parent()&&this.parent().removeElement(this),this},replace:function(t){return this.after(t).remove(),t},addTo:function(t){return t.put(this)},putIn:function(t){return t.add(this)},id:function(t){return this.attr("id",t)},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")},toString:function(){return this.attr("id")},classes:function(){var t=this.attr("class");return null==t?[]:t.trim().split(g.regex.delimiter)},hasClass:function(t){return this.classes().indexOf(t)!=-1},addClass:function(t){if(!this.hasClass(t)){var e=this.classes();e.push(t),this.attr("class",e.join(" "))}return this},removeClass:function(t){return this.hasClass(t)&&this.attr("class",this.classes().filter(function(e){return e!=t}).join(" ")),this},toggleClass:function(t){return this.hasClass(t)?this.removeClass(t):this.addClass(t)},reference:function(t){return g.get(this.attr(t))},parent:function(e){var i=this;if(!i.node.parentNode)return null;if(i=g.adopt(i.node.parentNode),!e)return i;for(;i&&i.node instanceof t.SVGElement;){if("string"==typeof e?i.matches(e):i instanceof e)return i;i=g.adopt(i.node.parentNode)}},doc:function(){return this instanceof g.Doc?this:this.parent(g.Doc)},parents:function(t){var e=[],i=this;do{if(i=i.parent(t),!i||!i.node)break;e.push(i)}while(i.parent);return e},matches:function(t){return s(this.node,t)},native:function(){return this.node},svg:function(t){var i=e.createElement("svg");if(!(t&&this instanceof g.Parent))return i.appendChild(t=e.createElement("svg")),this.writeDataToDom(),t.appendChild(this.node.cloneNode(!0)),i.innerHTML.replace(/^<svg>/,"").replace(/<\/svg>$/,"");i.innerHTML="<svg>"+t.replace(/\n/,"").replace(/<(\w+)([^<]+?)\/>/g,"<$1$2></$1>")+"</svg>";for(var n=0,r=i.firstChild.childNodes.length;n<r;n++)this.node.appendChild(i.firstChild.firstChild);return this},writeDataToDom:function(){if(this.each||this.lines){var t=this.each?this:this.lines();t.each(function(){this.writeDataToDom()})}return this.node.removeAttribute("svgjs:data"),Object.keys(this.dom).length&&this.node.setAttribute("svgjs:data",JSON.stringify(this.dom)),this},setData:function(t){return this.dom=t,this},is:function(t){return r(this,t)}}}),g.easing={"-":function(t){return t},"<>":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return-Math.cos(t*Math.PI/2)+1}},g.morph=function(t){return function(e,i){return new g.MorphObj(e,i).at(t)}},g.Situation=g.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new g.Number(t.duration).valueOf(),this.delay=new g.Number(t.delay).valueOf(),this.start=+new Date+this.delay,this.finish=this.start+this.duration,this.ease=t.ease,this.loop=0,this.loops=!1,this.animations={},this.attrs={},this.styles={},this.transforms=[],this.once={}}}),g.FX=g.invent({create:function(t){this._target=t,this.situations=[],this.active=!1,this.situation=null,this.paused=!1,this.lastPos=0,this.pos=0,this.absPos=0,this._speed=1},extend:{animate:function(t,e,i){"object"==typeof t&&(e=t.ease,i=t.delay,t=t.duration);var n=new g.Situation({duration:t||1e3,delay:i||0,ease:g.easing[e||"-"]||e});return this.queue(n),this},delay:function(t){var e=new g.Situation({duration:t,delay:0,ease:g.easing["-"]});return this.queue(e)},target:function(t){return t&&t instanceof g.Element?(this._target=t,this):this._target},timeToAbsPos:function(t){return(t-this.situation.start)/(this.situation.duration/this._speed)},absPosToTime:function(t){return this.situation.duration/this._speed*t+this.situation.start},startAnimFrame:function(){this.stopAnimFrame(),this.animationFrame=t.requestAnimationFrame(function(){this.step()}.bind(this))},stopAnimFrame:function(){t.cancelAnimationFrame(this.animationFrame)},start:function(){return!this.active&&this.situation&&(this.active=!0,this.startCurrent()),this},startCurrent:function(){return this.situation.start=+new Date+this.situation.delay/this._speed,this.situation.finish=this.situation.start+this.situation.duration/this._speed,this.initAnimations().step()},queue:function(t){return("function"==typeof t||t instanceof g.Situation)&&this.situations.push(t),this.situation||(this.situation=this.situations.shift()),this},dequeue:function(){return this.stop(),this.situation=this.situations.shift(),this.situation&&(this.situation instanceof g.Situation?this.start():this.situation.call(this)),this},initAnimations:function(){var t,e,i=this.situation;if(i.init)return this;for(t in i.animations)e=this.target()[t](),i.animations[t]instanceof g.Number&&(e=new g.Number(e)),i.animations[t]=e.morph(i.animations[t]);for(t in i.attrs)i.attrs[t]=new g.MorphObj(this.target().attr(t),i.attrs[t]);for(t in i.styles)i.styles[t]=new g.MorphObj(this.target().style(t),i.styles[t]);return i.initialTransformation=this.target().matrixify(),i.init=!0,this},clearQueue:function(){return this.situations=[],this},clearCurrent:function(){return this.situation=null,this},stop:function(t,e){var i=this.active;return this.active=!1,e&&this.clearQueue(),t&&this.situation&&(!i&&this.startCurrent(),this.atEnd()),this.stopAnimFrame(),this.clearCurrent()},reset:function(){if(this.situation){var t=this.situation;this.stop(),this.situation=t,this.atStart()}return this},finish:function(){for(this.stop(!0,!1);this.dequeue().situation&&this.stop(!0,!1););return this.clearQueue().clearCurrent(),this},atStart:function(){return this.at(0,!0)},atEnd:function(){return this.situation.loops===!0&&(this.situation.loops=this.situation.loop+1),"number"==typeof this.situation.loops?this.at(this.situation.loops,!0):this.at(1,!0)},at:function(t,e){var i=this.situation.duration/this._speed;return this.absPos=t,e||(this.situation.reversed&&(this.absPos=1-this.absPos),this.absPos+=this.situation.loop),this.situation.start=+new Date-this.absPos*i,this.situation.finish=this.situation.start+i,this.step(!0)},speed:function(t){return 0===t?this.pause():t?(this._speed=t,this.at(this.absPos,!0)):this._speed},loop:function(t,e){var i=this.last();return i.loops=null==t||t,i.loop=0,e&&(i.reversing=!0),this},pause:function(){return this.paused=!0,this.stopAnimFrame(),this},play:function(){return this.paused?(this.paused=!1,this.at(this.absPos,!0)):this},reverse:function(t){var e=this.last();return"undefined"==typeof t?e.reversed=!e.reversed:e.reversed=t,this},progress:function(t){return t?this.situation.ease(this.pos):this.pos},after:function(t){var e=this.last(),i=function i(n){n.detail.situation==e&&(t.call(this,e),this.off("finished.fx",i))};return this.target().on("finished.fx",i),this._callStart()},during:function(t){var e=this.last(),i=function(i){i.detail.situation==e&&t.call(this,i.detail.pos,g.morph(i.detail.pos),i.detail.eased,e)};return this.target().off("during.fx",i).on("during.fx",i),this.after(function(){this.off("during.fx",i)}),this._callStart()},afterAll:function(t){var e=function e(i){t.call(this),this.off("allfinished.fx",e)};return this.target().off("allfinished.fx",e).on("allfinished.fx",e),this._callStart()},duringAll:function(t){var e=function(e){t.call(this,e.detail.pos,g.morph(e.detail.pos),e.detail.eased,e.detail.situation)};return this.target().off("during.fx",e).on("during.fx",e),this.afterAll(function(){this.off("during.fx",e)}),this._callStart()},last:function(){return this.situations.length?this.situations[this.situations.length-1]:this.situation},add:function(t,e,i){return this.last()[i||"animations"][t]=e,this._callStart()},step:function(t){if(t||(this.absPos=this.timeToAbsPos(+new Date)),this.situation.loops!==!1){var e,i,n;e=Math.max(this.absPos,0),i=Math.floor(e),this.situation.loops===!0||i<this.situation.loops?(this.pos=e-i,n=this.situation.loop,this.situation.loop=i):(this.absPos=this.situation.loops,this.pos=1,n=this.situation.loop-1,this.situation.loop=this.situation.loops),this.situation.reversing&&(this.situation.reversed=this.situation.reversed!=Boolean((this.situation.loop-n)%2))}else this.absPos=Math.min(this.absPos,1),this.pos=this.absPos;this.pos<0&&(this.pos=0),this.situation.reversed&&(this.pos=1-this.pos);var r=this.situation.ease(this.pos);for(var s in this.situation.once)s>this.lastPos&&s<=r&&(this.situation.once[s].call(this.target(),this.pos,r),delete this.situation.once[s]);return this.active&&this.target().fire("during",{pos:this.pos,eased:r,fx:this,situation:this.situation}),this.situation?(this.eachAt(),1==this.pos&&!this.situation.reversed||this.situation.reversed&&0==this.pos?(this.stopAnimFrame(),this.target().fire("finished",{fx:this,situation:this.situation}),this.situations.length||(this.target().fire("allfinished"),this.target().off(".fx"),this.active=!1),this.active?this.dequeue():this.clearCurrent()):!this.paused&&this.active&&this.startAnimFrame(),this.lastPos=r,this):this},eachAt:function(){var t,e,i,n=this,r=this.target(),s=this.situation;for(t in s.animations)i=[].concat(s.animations[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(s.ease(n.pos),n.pos):t}),r[t].apply(r,i);for(t in s.attrs)i=[t].concat(s.attrs[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(s.ease(n.pos),n.pos):t}),r.attr.apply(r,i);for(t in s.styles)i=[t].concat(s.styles[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(s.ease(n.pos),n.pos):t}),r.style.apply(r,i);if(s.transforms.length){for(i=s.initialTransformation,t=0,e=s.transforms.length;t<e;t++){var o=s.transforms[t];o instanceof g.Matrix?i=o.relative?i.multiply((new g.Matrix).morph(o).at(s.ease(this.pos))):i.morph(o).at(s.ease(this.pos)):(o.relative||o.undo(i.extract()),i=i.multiply(o.at(s.ease(this.pos))))}r.matrix(i)}return this},once:function(t,e,i){return i||(t=this.situation.ease(t)),this.situation.once[t]=e,this},_callStart:function(){return setTimeout(function(){this.start()}.bind(this),0),this}},parent:g.Element,construct:{animate:function(t,e,i){return(this.fx||(this.fx=new g.FX(this))).animate(t,e,i)},delay:function(t){return(this.fx||(this.fx=new g.FX(this))).delay(t)},stop:function(t,e){return this.fx&&this.fx.stop(t,e),this},finish:function(){return this.fx&&this.fx.finish(),this},pause:function(){return this.fx&&this.fx.pause(),this},play:function(){return this.fx&&this.fx.play(),this},speed:function(t){if(this.fx){if(null==t)return this.fx.speed();this.fx.speed(t)}return this}}}),g.MorphObj=g.invent({create:function(t,e){return g.Color.isColor(e)?new g.Color(t).morph(e):g.regex.numberAndUnit.test(e)?new g.Number(t).morph(e):(this.value=t,void(this.destination=e))},extend:{at:function(t,e){return e<1?this.value:this.destination},valueOf:function(){return this.value}}}),g.extend(g.FX,{attr:function(t,e,i){if("object"==typeof t)for(var n in t)this.attr(n,t[n]);else this.add(t,e,"attrs");return this},style:function(t,e){if("object"==typeof t)for(var i in t)this.style(i,t[i]);else this.add(t,e,"styles");return this},x:function(t,e){if(this.target()instanceof g.G)return this.transform({x:t},e),this;var i=new g.Number(t);return i.relative=e,this.add("x",i)},y:function(t,e){if(this.target()instanceof g.G)return this.transform({y:t},e),this;var i=new g.Number(t);return i.relative=e,this.add("y",i)},cx:function(t){return this.add("cx",new g.Number(t))},cy:function(t){return this.add("cy",new g.Number(t))},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 g.Text)this.attr("font-size",t);else{var i;t&&e||(i=this.target().bbox()),t||(t=i.width/i.height*e),e||(e=i.height/i.width*t),this.add("width",new g.Number(t)).add("height",new g.Number(e))}return this},plot:function(){return this.add("plot",arguments.length>1?[].slice.call(arguments):arguments[0])},leading:function(t){return this.target().leading?this.add("leading",new g.Number(t)):this},viewbox:function(t,e,i,n){return this.target()instanceof g.Container&&this.add("viewbox",new g.ViewBox(t,e,i,n)),this},update:function(t){if(this.target()instanceof g.Stop){if("number"==typeof t||t instanceof g.Number)return this.update({offset:arguments[0],color:arguments[1],opacity:arguments[2]});null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",t.offset)}return this}}),g.Box=g.invent({create:function(t,e,i,n){return"object"!=typeof t||t instanceof g.Element?(4==arguments.length&&(this.x=t,this.y=e,this.width=i,this.height=n),void y(this)):g.Box.call(this,null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height)},extend:{merge:function(t){var e=new this.constructor;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,y(e)},transform:function(t){var e,i=1/0,n=-(1/0),r=1/0,s=-(1/0),o=[new g.Point(this.x,this.y),new g.Point(this.x2,this.y),new g.Point(this.x,this.y2),new g.Point(this.x2,this.y2)];return o.forEach(function(e){e=e.transform(t),i=Math.min(i,e.x),n=Math.max(n,e.x),r=Math.min(r,e.y),s=Math.max(s,e.y)}),e=new this.constructor,e.x=i,e.width=n-i,e.y=r,e.height=s-r,y(e),e}}}),g.BBox=g.invent({create:function(t){if(g.Box.apply(this,[].slice.call(arguments)),t instanceof g.Element){var i;try{if(e.documentElement.contains){if(!e.documentElement.contains(t.node))throw new Exception("Element not in the dom")}else{for(var n=t.node;n.parentNode;)n=n.parentNode;if(n!=e)throw new Exception("Element not in the dom")}i=t.node.getBBox()}catch(e){if(t instanceof g.Shape){var r=t.clone(g.parser.draw.instance).show();i=r.node.getBBox(),r.remove()}else i={x:t.node.clientLeft,y:t.node.clientTop,width:t.node.clientWidth,height:t.node.clientHeight}}g.Box.call(this,i)}},inherit:g.Box,parent:g.Element,construct:{bbox:function(){return new g.BBox(this)}}}),g.BBox.prototype.constructor=g.BBox,g.extend(g.Element,{tbox:function(){return console.warn("Use of TBox is deprecated and mapped to RBox. Use .rbox() instead."),this.rbox(this.doc())}}),g.RBox=g.invent({create:function(t){g.Box.apply(this,[].slice.call(arguments)),t instanceof g.Element&&g.Box.call(this,t.node.getBoundingClientRect())},inherit:g.Box,parent:g.Element,extend:{addOffset:function(){return this.x+=t.pageXOffset,this.y+=t.pageYOffset,this}},construct:{rbox:function(t){return t?new g.RBox(this).transform(t.screenCTM().inverse()):new g.RBox(this).addOffset()}}}),g.RBox.prototype.constructor=g.RBox,g.Matrix=g.invent({create:function(t){var e,i=f([1,0,0,1,0,0]);for(t=t instanceof g.Element?t.matrixify():"string"==typeof t?f(t.split(g.regex.delimiter).map(parseFloat)):6==arguments.length?f([].slice.call(arguments)):Array.isArray(t)?f(t):"object"==typeof t?t:i,e=P.length-1;e>=0;--e)this[P[e]]=t&&"number"==typeof t[P[e]]?t[P[e]]:i[P[e]]},extend:{extract:function(){var t=c(this,0,1),e=c(this,1,0),i=180/Math.PI*Math.atan2(t.y,t.x)-90;return{x:this.e,y:this.f,transformedX:(this.e*Math.cos(i*Math.PI/180)+this.f*Math.sin(i*Math.PI/180))/Math.sqrt(this.a*this.a+this.b*this.b),transformedY:(this.f*Math.cos(i*Math.PI/180)+this.e*Math.sin(-i*Math.PI/180))/Math.sqrt(this.c*this.c+this.d*this.d),skewX:-i,skewY:180/Math.PI*Math.atan2(e.y,e.x),scaleX:Math.sqrt(this.a*this.a+this.b*this.b),scaleY:Math.sqrt(this.c*this.c+this.d*this.d),rotation:i,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f,matrix:new g.Matrix(this)}},clone:function(){return new g.Matrix(this)},morph:function(t){return this.destination=new g.Matrix(t),this},at:function(t){if(!this.destination)return this;var e=new g.Matrix({a:this.a+(this.destination.a-this.a)*t,b:this.b+(this.destination.b-this.b)*t,c:this.c+(this.destination.c-this.c)*t,d:this.d+(this.destination.d-this.d)*t,e:this.e+(this.destination.e-this.e)*t,f:this.f+(this.destination.f-this.f)*t});return e},multiply:function(t){return new g.Matrix(this.native().multiply(d(t).native()))},inverse:function(){return new g.Matrix(this.native().inverse())},translate:function(t,e){return new g.Matrix(this.native().translate(t||0,e||0))},scale:function(t,e,i,n){return 1==arguments.length?e=t:3==arguments.length&&(n=i,i=e,e=t),this.around(i,n,new g.Matrix(t,0,0,e,0,0))},rotate:function(t,e,i){return t=g.utils.radians(t),this.around(e,i,new g.Matrix(Math.cos(t),Math.sin(t),-Math.sin(t),Math.cos(t),0,0))},flip:function(t,e){return"x"==t?this.scale(-1,1,e,0):"y"==t?this.scale(1,-1,0,e):this.scale(-1,-1,t,null!=e?e:t)},skew:function(t,e,i,n){return 1==arguments.length?e=t:3==arguments.length&&(n=i,i=e,e=t),t=g.utils.radians(t),e=g.utils.radians(e),this.around(i,n,new g.Matrix(1,Math.tan(e),Math.tan(t),1,0,0))},skewX:function(t,e,i){return this.skew(t,0,e,i)},skewY:function(t,e,i){return this.skew(0,t,e,i)},around:function(t,e,i){return this.multiply(new g.Matrix(1,0,0,1,t||0,e||0)).multiply(i).multiply(new g.Matrix(1,0,0,1,-t||0,-e||0))},native:function(){for(var t=g.parser.native.createSVGMatrix(),e=P.length-1;e>=0;e--)t[P[e]]=this[P[e]];return t},toString:function(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}},parent:g.Element,construct:{ctm:function(){return new g.Matrix(this.node.getCTM());
 -},screenCTM:function(){if(this instanceof g.Nested){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new g.Matrix(e)}return new g.Matrix(this.node.getScreenCTM())}}}),g.Point=g.invent({create:function(t,e){var i,n={x:0,y:0};i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"==typeof t?{x:t.x,y:t.y}:null!=t?{x:t,y:null!=e?e:t}:n,this.x=i.x,this.y=i.y},extend:{clone:function(){return new g.Point(this)},morph:function(t,e){return this.destination=new g.Point(t,e),this},at:function(t){if(!this.destination)return this;var e=new g.Point({x:this.x+(this.destination.x-this.x)*t,y:this.y+(this.destination.y-this.y)*t});return e},native:function(){var t=g.parser.native.createSVGPoint();return t.x=this.x,t.y=this.y,t},transform:function(t){return new g.Point(this.native().matrixTransform(t.native()))}}}),g.extend(g.Element,{point:function(t,e){return new g.Point(t,e).transform(this.screenCTM().inverse())}}),g.extend(g.Element,{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]=g.regex.isNumber.test(e[i].nodeValue)?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 e=this.node.getAttribute(t),null==e?g.defaults.attrs[t]:g.regex.isNumber.test(e)?parseFloat(e):e;"stroke-width"==t?this.attr("stroke",parseFloat(e)>0?this._stroke:null):"stroke"==t&&(this._stroke=e),"fill"!=t&&"stroke"!=t||(g.regex.isImage.test(e)&&(e=this.doc().defs().image(e,0,0)),e instanceof g.Image&&(e=this.doc().defs().pattern(0,0,function(){this.add(e)}))),"number"==typeof e?e=new g.Number(e):g.Color.isColor(e)?e=new g.Color(e):Array.isArray(e)&&(e=new g.Array(e)),"leading"==t?this.leading&&this.leading(e):"string"==typeof i?this.node.setAttributeNS(i,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!=t&&"x"!=t||this.rebuild(t,e)}return this}}),g.extend(g.Element,{transform:function(t,e){var i,n,r=this;if("object"!=typeof t)return i=new g.Matrix(r).extract(),"string"==typeof t?i[t]:i;if(i=new g.Matrix(r),e=!!e||!!t.relative,null!=t.a)i=e?i.multiply(new g.Matrix(t)):new g.Matrix(t);else if(null!=t.rotation)p(t,r),i=e?i.rotate(t.rotation,t.cx,t.cy):i.rotate(t.rotation-i.extract().rotation,t.cx,t.cy);else if(null!=t.scale||null!=t.scaleX||null!=t.scaleY){if(p(t,r),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,!e){var s=i.extract();t.scaleX=1*t.scaleX/s.scaleX,t.scaleY=1*t.scaleY/s.scaleY}i=i.scale(t.scaleX,t.scaleY,t.cx,t.cy)}else if(null!=t.skew||null!=t.skewX||null!=t.skewY){if(p(t,r),t.skewX=null!=t.skew?t.skew:null!=t.skewX?t.skewX:0,t.skewY=null!=t.skew?t.skew:null!=t.skewY?t.skewY:0,!e){var s=i.extract();i=i.multiply((new g.Matrix).skew(s.skewX,s.skewY,t.cx,t.cy).inverse())}i=i.skew(t.skewX,t.skewY,t.cx,t.cy)}else t.flip?("x"==t.flip||"y"==t.flip?t.offset=null==t.offset?r.bbox()["c"+t.flip]:t.offset:null==t.offset?(n=r.bbox(),t.flip=n.cx,t.offset=n.cy):t.flip=t.offset,i=(new g.Matrix).flip(t.flip,t.offset)):null==t.x&&null==t.y||(e?i=i.translate(t.x,t.y):(null!=t.x&&(i.e=t.x),null!=t.y&&(i.f=t.y)));return this.attr("transform",i)}}),g.extend(g.FX,{transform:function(t,e){var i,n,r=this.target();return"object"!=typeof t?(i=new g.Matrix(r).extract(),"string"==typeof t?i[t]:i):(e=!!e||!!t.relative,null!=t.a?i=new g.Matrix(t):null!=t.rotation?(p(t,r),i=new g.Rotate(t.rotation,t.cx,t.cy)):null!=t.scale||null!=t.scaleX||null!=t.scaleY?(p(t,r),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,i=new g.Scale(t.scaleX,t.scaleY,t.cx,t.cy)):null!=t.skewX||null!=t.skewY?(p(t,r),t.skewX=null!=t.skewX?t.skewX:0,t.skewY=null!=t.skewY?t.skewY:0,i=new g.Skew(t.skewX,t.skewY,t.cx,t.cy)):t.flip?("x"==t.flip||"y"==t.flip?t.offset=null==t.offset?r.bbox()["c"+t.flip]:t.offset:null==t.offset?(n=r.bbox(),t.flip=n.cx,t.offset=n.cy):t.flip=t.offset,i=(new g.Matrix).flip(t.flip,t.offset)):null==t.x&&null==t.y||(i=new g.Translate(t.x,t.y)),i?(i.relative=e,this.last().transforms.push(i),this._callStart()):this)}}),g.extend(g.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){var t=(this.attr("transform")||"").split(g.regex.transforms).slice(0,-1).map(function(t){var e=t.trim().split("(");return[e[0],e[1].split(g.regex.delimiter).map(function(t){return parseFloat(t)})]}).reduce(function(t,e){return"matrix"==e[0]?t.multiply(f(e[1])):t[e[0]].apply(t,e[1])},new g.Matrix);return t},toParent:function(t){if(this==t)return this;var e=this.screenCTM(),i=t.screenCTM().inverse();return this.addTo(t).untransform().transform(i.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),g.Transformation=g.invent({create:function(t,e){if(arguments.length>1&&"boolean"!=typeof e)return this.constructor.call(this,[].slice.call(arguments));if(Array.isArray(t))for(var i=0,n=this.arguments.length;i<n;++i)this[this.arguments[i]]=t[i];else if("object"==typeof t)for(var i=0,n=this.arguments.length;i<n;++i)this[this.arguments[i]]=t[this.arguments[i]];this.inversed=!1,e===!0&&(this.inversed=!0)},extend:{arguments:[],method:"",at:function(t){for(var e=[],i=0,n=this.arguments.length;i<n;++i)e.push(this[this.arguments[i]]);var r=this._undo||new g.Matrix;return r=(new g.Matrix).morph(g.Matrix.prototype[this.method].apply(r,e)).at(t),this.inversed?r.inverse():r},undo:function(t){for(var e=0,i=this.arguments.length;e<i;++e)t[this.arguments[e]]="undefined"==typeof this[this.arguments[e]]?0:t[this.arguments[e]];return t.cx=this.cx,t.cy=this.cy,this._undo=new(g[a(this.method)])(t,!0).at(1),this}}}),g.Translate=g.invent({parent:g.Matrix,inherit:g.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["transformedX","transformedY"],method:"translate"}}),g.Rotate=g.invent({parent:g.Matrix,inherit:g.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["rotation","cx","cy"],method:"rotate",at:function(t){var e=(new g.Matrix).rotate((new g.Number).morph(this.rotation-(this._undo?this._undo.rotation:0)).at(t),this.cx,this.cy);return this.inversed?e.inverse():e},undo:function(t){return this._undo=t,this}}}),g.Scale=g.invent({parent:g.Matrix,inherit:g.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["scaleX","scaleY","cx","cy"],method:"scale"}}),g.Skew=g.invent({parent:g.Matrix,inherit:g.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["skewX","skewY","cx","cy"],method:"skew"}}),g.extend(g.Element,{style:function(t,e){if(0==arguments.length)return this.node.style.cssText||"";if(arguments.length<2)if("object"==typeof t)for(e in t)this.style(e,t[e]);else{if(!g.regex.isCss.test(t))return this.node.style[o(t)];for(t=t.split(/\s*;\s*/).filter(function(t){return!!t}).map(function(t){return t.split(/\s*:\s*/)});e=t.pop();)this.style(e[0],e[1])}else this.node.style[o(t)]=null===e||g.regex.isBlank.test(e)?"":e;return this}}),g.Parent=g.invent({create:function(t){this.constructor.call(this,t)},inherit:g.Element,extend:{children:function(){return g.utils.map(g.utils.filterSVGElements(this.node.childNodes),function(t){return g.adopt(t)})},add:function(t,e){return null==e?this.node.appendChild(t.node):t.node!=this.node.childNodes[e]&&this.node.insertBefore(t.node,this.node.childNodes[e]),this},put:function(t,e){return this.add(t,e),t},has:function(t){return this.index(t)>=0},index:function(t){return[].slice.call(this.node.childNodes).indexOf(t.node)},get:function(t){return g.adopt(this.node.childNodes[t])},first:function(){return this.get(0)},last:function(){return this.get(this.node.childNodes.length-1)},each:function(t,e){var i,n,r=this.children();for(i=0,n=r.length;i<n;i++)r[i]instanceof g.Element&&t.apply(r[i],[i,r]),e&&r[i]instanceof g.Container&&r[i].each(t,e);return this},removeElement:function(t){return this.node.removeChild(t.node),this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return delete this._defs,this},defs:function(){return this.doc().defs()}}}),g.extend(g.Parent,{ungroup:function(t,e){return 0===e||this instanceof g.Defs||this.node==g.parser.draw?this:(t=t||(this instanceof g.Doc?this:this.parent(g.Parent)),e=e||1/0,this.each(function(){return this instanceof g.Defs?this:this instanceof g.Parent?this.ungroup(t,e-1):this.toParent(t)}),this.node.firstChild||this.remove(),this)},flatten:function(t,e){return this.ungroup(t,e)}}),g.Container=g.invent({create:function(t){this.constructor.call(this,t)},inherit:g.Parent}),g.ViewBox=g.invent({create:function(t){var e,i,n,r,s,o,a,h,u=[0,0,0,0],l=1,c=1,f=/[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/gi;if(t instanceof g.Element){for(a=t,h=t,o=(t.attr("viewBox")||"").match(f),s=t.bbox,n=new g.Number(t.width()),r=new g.Number(t.height());"%"==n.unit;)l*=n.value,n=new g.Number(a instanceof g.Doc?a.parent().offsetWidth:a.parent().width()),a=a.parent();for(;"%"==r.unit;)c*=r.value,r=new g.Number(h instanceof g.Doc?h.parent().offsetHeight:h.parent().height()),h=h.parent();this.x=0,this.y=0,this.width=n*l,this.height=r*c,this.zoom=1,o&&(e=parseFloat(o[0]),i=parseFloat(o[1]),n=parseFloat(o[2]),r=parseFloat(o[3]),this.zoom=this.width/this.height>n/r?this.height/r:this.width/n,this.x=e,this.y=i,this.width=n,this.height=r)}else t="string"==typeof t?t.match(f).map(function(t){return parseFloat(t)}):Array.isArray(t)?t:"object"==typeof t?[t.x,t.y,t.width,t.height]:4==arguments.length?[].slice.call(arguments):u,this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3]},extend:{toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height},morph:function(t,e,i,n){return this.destination=new g.ViewBox(t,e,i,n),this},at:function(t){return this.destination?new g.ViewBox([this.x+(this.destination.x-this.x)*t,this.y+(this.destination.y-this.y)*t,this.width+(this.destination.width-this.width)*t,this.height+(this.destination.height-this.height)*t]):this}},parent:g.Container,construct:{viewbox:function(t,e,i,n){return 0==arguments.length?new g.ViewBox(this):this.attr("viewBox",new g.ViewBox(t,e,i,n))}}}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","touchstart","touchmove","touchleave","touchend","touchcancel"].forEach(function(t){g.Element.prototype[t]=function(e){return g.on(this.node,t,e),this}}),g.listeners=[],g.handlerMap=[],g.listenerId=0,g.on=function(t,e,i,n,r){var s=i.bind(n||t.instance||t),o=(g.handlerMap.indexOf(t)+1||g.handlerMap.push(t))-1,a=e.split(".")[0],h=e.split(".")[1]||"*";g.listeners[o]=g.listeners[o]||{},g.listeners[o][a]=g.listeners[o][a]||{},g.listeners[o][a][h]=g.listeners[o][a][h]||{},i._svgjsListenerId||(i._svgjsListenerId=++g.listenerId),g.listeners[o][a][h][i._svgjsListenerId]=s,t.addEventListener(a,s,r||!1)},g.off=function(t,e,i){var n=g.handlerMap.indexOf(t),r=e&&e.split(".")[0],s=e&&e.split(".")[1],o="";if(n!=-1)if(i){if("function"==typeof i&&(i=i._svgjsListenerId),!i)return;g.listeners[n][r]&&g.listeners[n][r][s||"*"]&&(t.removeEventListener(r,g.listeners[n][r][s||"*"][i],!1),delete g.listeners[n][r][s||"*"][i])}else if(s&&r){if(g.listeners[n][r]&&g.listeners[n][r][s]){for(i in g.listeners[n][r][s])g.off(t,[r,s].join("."),i);delete g.listeners[n][r][s]}}else if(s)for(e in g.listeners[n])for(o in g.listeners[n][e])s===o&&g.off(t,[e,s].join("."));else if(r){if(g.listeners[n][r]){for(o in g.listeners[n][r])g.off(t,[r,o].join("."));delete g.listeners[n][r]}}else{for(e in g.listeners[n])g.off(t,e);delete g.listeners[n],delete g.handlerMap[n]}},g.extend(g.Element,{on:function(t,e,i,n){return g.on(this.node,t,e,i,n),this},off:function(t,e){return g.off(this.node,t,e),this},fire:function(e,i){return e instanceof t.Event?this.node.dispatchEvent(e):this.node.dispatchEvent(e=new t.CustomEvent(e,{detail:i,cancelable:!0})),this._event=e,this},event:function(){return this._event}}),g.Defs=g.invent({create:"defs",inherit:g.Container}),g.G=g.invent({create:"g",inherit:g.Container,extend:{x:function(t){return null==t?this.transform("x"):this.transform({x:t-this.x()},!0)},y:function(t){return null==t?this.transform("y"):this.transform({y:t-this.y()},!0)},cx:function(t){return null==t?this.gbox().cx:this.x(t-this.gbox().width/2)},cy:function(t){return null==t?this.gbox().cy:this.y(t-this.gbox().height/2)},gbox:function(){var t=this.bbox(),e=this.transform();return t.x+=e.x,t.x2+=e.x,t.cx+=e.x,t.y+=e.y,t.y2+=e.y,t.cy+=e.y,t}},construct:{group:function(){return this.put(new g.G)}}}),g.extend(g.Element,{siblings:function(){return this.parent().children()},position:function(){return this.parent().index(this)},next:function(){return this.siblings()[this.position()+1]},previous:function(){return this.siblings()[this.position()-1]},forward:function(){var t=this.position()+1,e=this.parent();return e.removeElement(this).add(this,t),e instanceof g.Doc&&e.node.appendChild(e.defs().node),this},backward:function(){var t=this.position();return t>0&&this.parent().removeElement(this).add(this,t-1),this},front:function(){var t=this.parent();return t.node.appendChild(this.node),t instanceof g.Doc&&t.node.appendChild(t.defs().node),this},back:function(){return this.position()>0&&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}}),g.Mask=g.invent({create:function(){this.constructor.call(this,g.create("mask")),this.targets=[]},inherit:g.Container,extend:{remove:function(){for(var t=this.targets.length-1;t>=0;t--)this.targets[t]&&this.targets[t].unmask();return this.targets=[],this.parent().removeElement(this),this}},construct:{mask:function(){return this.defs().put(new g.Mask)}}}),g.extend(g.Element,{maskWith:function(t){return this.masker=t instanceof g.Mask?t:this.parent().mask().add(t),this.masker.targets.push(this),this.attr("mask",'url("#'+this.masker.attr("id")+'")')},unmask:function(){return delete this.masker,this.attr("mask",null)}}),g.ClipPath=g.invent({create:function(){this.constructor.call(this,g.create("clipPath")),this.targets=[]},inherit:g.Container,extend:{remove:function(){for(var t=this.targets.length-1;t>=0;t--)this.targets[t]&&this.targets[t].unclip();return this.targets=[],this.parent().removeElement(this),this}},construct:{clip:function(){return this.defs().put(new g.ClipPath)}}}),g.extend(g.Element,{clipWith:function(t){return this.clipper=t instanceof g.ClipPath?t:this.parent().clip().add(t),this.clipper.targets.push(this),this.attr("clip-path",'url("#'+this.clipper.attr("id")+'")')},unclip:function(){return delete this.clipper,this.attr("clip-path",null)}}),g.Gradient=g.invent({create:function(t){this.constructor.call(this,g.create(t+"Gradient")),this.type=t},inherit:g.Container,extend:{at:function(t,e,i){return this.put(new g.Stop).update(t,e,i)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},fill:function(){return"url(#"+this.id()+")"},toString:function(){return this.fill()},attr:function(t,e,i){return"transform"==t&&(t="gradientTransform"),g.Container.prototype.attr.call(this,t,e,i)}},construct:{gradient:function(t,e){return this.defs().gradient(t,e)}}}),g.extend(g.Gradient,g.FX,{from:function(t,e){return"radial"==(this._target||this).type?this.attr({fx:new g.Number(t),fy:new g.Number(e)}):this.attr({x1:new g.Number(t),y1:new g.Number(e)})},to:function(t,e){return"radial"==(this._target||this).type?this.attr({cx:new g.Number(t),cy:new g.Number(e)}):this.attr({x2:new g.Number(t),y2:new g.Number(e)})}}),g.extend(g.Defs,{gradient:function(t,e){return this.put(new g.Gradient(t)).update(e)}}),g.Stop=g.invent({create:"stop",inherit:g.Element,extend:{update:function(t){return("number"==typeof t||t instanceof g.Number)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),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 g.Number(t.offset)),this}}}),g.Pattern=g.invent({create:"pattern",inherit:g.Container,extend:{fill:function(){return"url(#"+this.id()+")"},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return this.fill()},attr:function(t,e,i){return"transform"==t&&(t="patternTransform"),g.Container.prototype.attr.call(this,t,e,i)}},construct:{pattern:function(t,e,i){return this.defs().pattern(t,e,i)}}}),g.extend(g.Defs,{pattern:function(t,e,i){return this.put(new g.Pattern).update(i).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),g.Doc=g.invent({create:function(t){t&&(t="string"==typeof t?e.getElementById(t):t,"svg"==t.nodeName?this.constructor.call(this,t):(this.constructor.call(this,g.create("svg")),t.appendChild(this.node),this.size("100%","100%")),this.namespace().defs())},inherit:g.Container,extend:{namespace:function(){return this.attr({xmlns:g.ns,version:"1.1"}).attr("xmlns:xlink",g.xlink,g.xmlns).attr("xmlns:svgjs",g.svgjs,g.xmlns)},defs:function(){if(!this._defs){var t;(t=this.node.getElementsByTagName("defs")[0])?this._defs=g.adopt(t):this._defs=new g.Defs,this.node.appendChild(this._defs.node)}return this._defs},parent:function(){return"#document"==this.node.parentNode.nodeName?null:this.node.parentNode},spof:function(t){var e=this.node.getScreenCTM();return e&&this.style("left",-e.e%1+"px").style("top",-e.f%1+"px"),this},remove:function(){return this.parent()&&this.parent().removeChild(this.node),this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return delete this._defs,g.parser.draw.parentNode||this.node.appendChild(g.parser.draw),this}}}),g.Shape=g.invent({create:function(t){this.constructor.call(this,t)},inherit:g.Element}),g.Bare=g.invent({create:function(t,e){if(this.constructor.call(this,g.create(t)),e)for(var i in e.prototype)"function"==typeof e.prototype[i]&&(this[i]=e.prototype[i])},inherit:g.Element,extend:{words:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(e.createTextNode(t)),this}}}),g.extend(g.Parent,{element:function(t,e){return this.put(new g.Bare(t,e))}}),g.Symbol=g.invent({create:"symbol",inherit:g.Container,construct:{symbol:function(){return this.put(new g.Symbol)}}}),g.Use=g.invent({create:"use",inherit:g.Shape,extend:{element:function(t,e){return this.attr("href",(e||"")+"#"+t,g.xlink)}},construct:{use:function(t,e){return this.put(new g.Use).element(t,e)}}}),g.Rect=g.invent({create:"rect",inherit:g.Shape,construct:{rect:function(t,e){return this.put(new g.Rect).size(t,e)}}}),g.Circle=g.invent({create:"circle",inherit:g.Shape,construct:{circle:function(t){return this.put(new g.Circle).rx(new g.Number(t).divide(2)).move(0,0)}}}),g.extend(g.Circle,g.FX,{rx:function(t){return this.attr("r",t)},ry:function(t){return this.rx(t)}}),g.Ellipse=g.invent({create:"ellipse",inherit:g.Shape,construct:{ellipse:function(t,e){return this.put(new g.Ellipse).size(t,e).move(0,0)}}}),g.extend(g.Ellipse,g.Rect,g.FX,{rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)}}),g.extend(g.Circle,g.Ellipse,{x:function(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())},y:function(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())},cx:function(t){return null==t?this.attr("cx"):this.attr("cx",t)},cy:function(t){return null==t?this.attr("cy"):this.attr("cy",t)},width:function(t){return null==t?2*this.rx():this.rx(new g.Number(t).divide(2))},height:function(t){return null==t?2*this.ry():this.ry(new g.Number(t).divide(2))},size:function(t,e){var i=l(this,t,e);return this.rx(new g.Number(i.width).divide(2)).ry(new g.Number(i.height).divide(2))}}),g.Line=g.invent({create:"line",inherit:g.Shape,extend:{array:function(){return new g.PointArray([[this.attr("x1"),this.attr("y1")],[this.attr("x2"),this.attr("y2")]])},plot:function(t,e,i,n){return null==t?this.array():(t="undefined"!=typeof e?{x1:t,y1:e,x2:i,y2:n}:new g.PointArray(t).toLine(),this.attr(t))},move:function(t,e){return this.attr(this.array().move(t,e).toLine())},size:function(t,e){var i=l(this,t,e);return this.attr(this.array().size(i.width,i.height).toLine())}},construct:{line:function(t,e,i,n){return g.Line.prototype.plot.apply(this.put(new g.Line),null!=t?[t,e,i,n]:[0,0,0,0])}}}),g.Polyline=g.invent({create:"polyline",inherit:g.Shape,construct:{polyline:function(t){return this.put(new g.Polyline).plot(t||new g.PointArray)}}}),g.Polygon=g.invent({create:"polygon",inherit:g.Shape,construct:{polygon:function(t){return this.put(new g.Polygon).plot(t||new g.PointArray)}}}),g.extend(g.Polyline,g.Polygon,{array:function(){return this._array||(this._array=new g.PointArray(this.attr("points")))},plot:function(t){return null==t?this.array():this.clear().attr("points","string"==typeof t?t:this._array=new g.PointArray(t))},clear:function(){return delete this._array,this},move:function(t,e){return this.attr("points",this.array().move(t,e))},size:function(t,e){var i=l(this,t,e);return this.attr("points",this.array().size(i.width,i.height))}}),g.extend(g.Line,g.Polyline,g.Polygon,{morphArray:g.PointArray,x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},width:function(t){var e=this.bbox();return null==t?e.width:this.size(t,e.height)},height:function(t){var e=this.bbox();return null==t?e.height:this.size(e.width,t)}}),g.Path=g.invent({create:"path",inherit:g.Shape,extend:{morphArray:g.PathArray,array:function(){return this._array||(this._array=new g.PathArray(this.attr("d")))},plot:function(t){return null==t?this.array():this.clear().attr("d","string"==typeof t?t:this._array=new g.PathArray(t))},clear:function(){return delete this._array,this},move:function(t,e){return this.attr("d",this.array().move(t,e))},x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},size:function(t,e){var i=l(this,t,e);return this.attr("d",this.array().size(i.width,i.height))},width:function(t){return null==t?this.bbox().width:this.size(t,this.bbox().height)},height:function(t){return null==t?this.bbox().height:this.size(this.bbox().width,t)}},construct:{path:function(t){return this.put(new g.Path).plot(t||new g.PathArray)}}}),g.Image=g.invent({create:"image",inherit:g.Shape,extend:{load:function(e){if(!e)return this;var i=this,n=new t.Image;return g.on(n,"load",function(){var t=i.parent(g.Pattern);null!==t&&(0==i.width()&&0==i.height()&&i.size(n.width,n.height),t&&0==t.width()&&0==t.height()&&t.size(i.width(),i.height()),"function"==typeof i._loaded&&i._loaded.call(i,{width:n.width,height:n.height,ratio:n.width/n.height,url:e}))}),g.on(n,"error",function(t){"function"==typeof i._error&&i._error.call(i,t)}),this.attr("href",n.src=this.src=e,g.xlink)},loaded:function(t){return this._loaded=t,this},error:function(t){return this._error=t,this}},construct:{image:function(t,e,i){return this.put(new g.Image).load(t).size(e||0,i||e||0)}}}),g.Text=g.invent({create:function(){this.constructor.call(this,g.create("text")),this.dom.leading=new g.Number(1.3),this._rebuild=!0,this._build=!1,this.attr("font-family",g.defaults.attrs["font-family"])},inherit:g.Shape,extend:{x:function(t){return null==t?this.attr("x"):this.attr("x",t)},y:function(t){var e=this.attr("y"),i="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-i:e:this.attr("y","number"==typeof t?t+i: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)},text:function(t){if("undefined"==typeof t){for(var t="",e=this.node.childNodes,i=0,n=e.length;i<n;++i)0!=i&&3!=e[i].nodeType&&1==g.adopt(e[i]).dom.newLined&&(t+="\n"),t+=e[i].textContent;return t}if(this.clear().build(!0),"function"==typeof t)t.call(this,this);else{t=t.split("\n");for(var i=0,r=t.length;i<r;i++)this.tspan(t[i]).newLine()}return this.build(!1).rebuild()},size:function(t){return this.attr("font-size",t).rebuild()},leading:function(t){return null==t?this.dom.leading:(this.dom.leading=new g.Number(t),this.rebuild())},lines:function(){var t=(this.textPath&&this.textPath()||this).node,e=g.utils.map(g.utils.filterSVGElements(t.childNodes),function(t){return g.adopt(t)});return new g.Set(e)},rebuild:function(t){if("boolean"==typeof t&&(this._rebuild=t),this._rebuild){var e=this,i=0,n=this.dom.leading*new g.Number(this.attr("font-size"));this.lines().each(function(){this.dom.newLined&&(e.textPath()||this.attr("x",e.attr("x")),"\n"==this.text()?i+=n:(this.attr("dy",n+i),i=0))}),this.fire("rebuild")}return this},build:function(t){return this._build=!!t,this},setData:function(t){return this.dom=t,this.dom.leading=new g.Number(t.leading||1.3),this}},construct:{text:function(t){return this.put(new g.Text).text(t)},plain:function(t){return this.put(new g.Text).plain(t)}}}),g.Tspan=g.invent({create:"tspan",inherit:g.Shape,extend:{text:function(t){return null==t?this.node.textContent+(this.dom.newLined?"\n":""):("function"==typeof t?t.call(this,this):this.plain(t),this)},dx:function(t){return this.attr("dx",t)},dy:function(t){return this.attr("dy",t)},newLine:function(){var t=this.parent(g.Text);return this.dom.newLined=!0,this.dy(t.dom.leading*t.attr("font-size")).attr("x",t.x())}}}),g.extend(g.Text,g.Tspan,{plain:function(t){return this._build===!1&&this.clear(),this.node.appendChild(e.createTextNode(t)),this},tspan:function(t){var e=(this.textPath&&this.textPath()||this).node,i=new g.Tspan;return this._build===!1&&this.clear(),e.appendChild(i.node),i.text(t)},clear:function(){for(var t=(this.textPath&&this.textPath()||this).node;t.hasChildNodes();)t.removeChild(t.lastChild);return this},length:function(){return this.node.getComputedTextLength()}}),g.TextPath=g.invent({create:"textPath",inherit:g.Parent,parent:g.Text,construct:{path:function(t){for(var e=new g.TextPath,i=this.doc().defs().path(t);this.node.hasChildNodes();)e.node.appendChild(this.node.firstChild);return this.node.appendChild(e.node),e.attr("href","#"+i,g.xlink),this},array:function(){var t=this.track();return t?t.array():null},plot:function(t){var e=this.track(),i=null;return e&&(i=e.plot(t)),null==t?i:this},track:function(){var t=this.textPath();if(t)return t.reference("href")},textPath:function(){if(this.node.firstChild&&"textPath"==this.node.firstChild.nodeName)return g.adopt(this.node.firstChild)}}}),g.Nested=g.invent({create:function(){this.constructor.call(this,g.create("svg")),this.style("overflow","visible")},inherit:g.Container,construct:{nested:function(){return this.put(new g.Nested)}}}),g.A=g.invent({create:"a",inherit:g.Container,extend:{to:function(t){return this.attr("href",t,g.xlink)},show:function(t){return this.attr("show",t,g.xlink)},target:function(t){return this.attr("target",t)}},construct:{link:function(t){return this.put(new g.A).to(t)}}}),g.extend(g.Element,{linkTo:function(t){var e=new g.A;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}),g.Marker=g.invent({create:"marker",inherit:g.Container,extend:{width:function(t){return this.attr("markerWidth",t)},height:function(t){return this.attr("markerHeight",t)},ref:function(t,e){return this.attr("refX",t).attr("refY",e)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return"url(#"+this.id()+")"}},construct:{marker:function(t,e,i){return this.defs().marker(t,e,i)}}}),g.extend(g.Defs,{marker:function(t,e,i){return this.put(new g.Marker).size(t,e).ref(t/2,e/2).viewbox(0,0,t,e).attr("orient","auto").update(i)}}),g.extend(g.Line,g.Polyline,g.Polygon,g.Path,{marker:function(t,e,i,n){var r=["marker"];return"all"!=t&&r.push(t),r=r.join("-"),t=arguments[1]instanceof g.Marker?arguments[1]:this.doc().marker(e,i,n),this.attr(r,t)}});var M={stroke:["color","width","opacity","linecap","linejoin","miterlimit","dasharray","dashoffset"],fill:["color","opacity","rule"],prefix:function(t,e){return"color"==e?t:t+"-"+e}};["fill","stroke"].forEach(function(t){var e,i={};i[t]=function(i){if("undefined"==typeof i)return this;if("string"==typeof i||g.Color.isRgb(i)||i&&"function"==typeof i.fill)this.attr(t,i);else for(e=M[t].length-1;e>=0;e--)null!=i[M[t][e]]&&this.attr(M.prefix(t,M[t][e]),i[M[t][e]]);return this},g.extend(g.Element,g.FX,i)}),g.extend(g.Element,g.FX,{rotate:function(t,e,i){return this.transform({rotation:t,cx:e,cy:i})},skew:function(t,e,i,n){return 1==arguments.length||3==arguments.length?this.transform({skew:t,cx:e,cy:i}):this.transform({skewX:t,skewY:e,cx:i,cy:n})},scale:function(t,e,i,n){return 1==arguments.length||3==arguments.length?this.transform({scale:t,cx:e,cy:i}):this.transform({scaleX:t,scaleY:e,cx:i,cy:n})},translate:function(t,e){return this.transform({x:t,y:e})},flip:function(t,e){return e="number"==typeof t?t:e,this.transform({flip:t||"both",offset:e})},matrix:function(t){return this.attr("transform",new g.Matrix(6==arguments.length?[].slice.call(arguments):t))},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new g.Number(t).plus(this instanceof g.FX?0:this.x()),!0)},dy:function(t){return this.y(new g.Number(t).plus(this instanceof g.FX?0:this.y()),!0)},dmove:function(t,e){return this.dx(t).dy(e)}}),g.extend(g.Rect,g.Ellipse,g.Circle,g.Gradient,g.FX,{radius:function(t,e){var i=(this._target||this).type;return"radial"==i||"circle"==i?this.attr("r",new g.Number(t)):this.rx(t).ry(null==e?t:e)}}),g.extend(g.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return this.node.getPointAtLength(t)}}),g.extend(g.Parent,g.Text,g.Tspan,g.FX,{font:function(t,e){if("object"==typeof t)for(e in t)this.font(e,t[e]);return"leading"==t?this.leading(e):"anchor"==t?this.attr("text-anchor",e):"size"==t||"family"==t||"weight"==t||"stretch"==t||"variant"==t||"style"==t?this.attr("font-"+t,e):this.attr(t,e)}}),g.Set=g.invent({create:function(t){Array.isArray(t)?this.members=t:this.clear()},extend:{add:function(){var t,e,i=[].slice.call(arguments);for(t=0,e=i.length;t<e;t++)this.members.push(i[t]);return this},remove:function(t){var e=this.index(t);return e>-1&&this.members.splice(e,1),this},each:function(t){for(var e=0,i=this.members.length;e<i;e++)t.apply(this.members[e],[e,this.members]);return this},clear:function(){return this.members=[],this},length:function(){return this.members.length},has:function(t){return this.index(t)>=0},index:function(t){return this.members.indexOf(t)},get:function(t){return this.members[t]},first:function(){return this.get(0)},last:function(){return this.get(this.members.length-1)},valueOf:function(){return this.members},bbox:function(){if(0==this.members.length)return new g.RBox;var t=this.members[0].rbox(this.members[0].doc());return this.each(function(){t=t.merge(this.rbox(this.doc()))}),t}},construct:{set:function(t){return new g.Set(t)}}}),g.FX.Set=g.invent({create:function(t){this.set=t}}),g.Set.inherit=function(){var t,e=[];for(var t in g.Shape.prototype)"function"==typeof g.Shape.prototype[t]&&"function"!=typeof g.Set.prototype[t]&&e.push(t);e.forEach(function(t){g.Set.prototype[t]=function(){for(var e=0,i=this.members.length;e<i;e++)this.members[e]&&"function"==typeof this.members[e][t]&&this.members[e][t].apply(this.members[e],arguments);return"animate"==t?this.fx||(this.fx=new g.FX.Set(this)):this}}),e=[];for(var t in g.FX.prototype)"function"==typeof g.FX.prototype[t]&&"function"!=typeof g.FX.Set.prototype[t]&&e.push(t);e.forEach(function(t){g.FX.Set.prototype[t]=function(){for(var e=0,i=this.set.members.length;e<i;e++)this.set.members[e].fx[t].apply(this.set.members[e].fx,arguments);return this}})},g.extend(g.Element,{data:function(t,e,i){if("object"==typeof t)for(e in t)this.data(e,t[e]);else if(arguments.length<2)try{
 -return JSON.parse(this.attr("data-"+t))}catch(e){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}}),g.extend(g.Element,{remember:function(t,e){if("object"==typeof arguments[0])for(var e in t)this.remember(e,t[e]);else{if(1==arguments.length)return this.memory()[t];this.memory()[t]=e}return this},forget:function(){if(0==arguments.length)this._memory={};else for(var t=arguments.length-1;t>=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory||(this._memory={})}}),g.get=function(t){var i=e.getElementById(v(t)||t);return g.adopt(i)},g.select=function(t,i){return new g.Set(g.utils.map((i||e).querySelectorAll(t),function(t){return g.adopt(t)}))},g.extend(g.Parent,{select:function(t){return g.select(t,this.node)}});var P="abcdef".split("");if("function"!=typeof t.CustomEvent){var A=function(t,i){i=i||{bubbles:!1,cancelable:!1,detail:void 0};var n=e.createEvent("CustomEvent");return n.initCustomEvent(t,i.bubbles,i.cancelable,i.detail),n};A.prototype=t.Event.prototype,t.CustomEvent=A}return function(e){for(var i=0,n=["moz","webkit"],r=0;r<n.length&&!t.requestAnimationFrame;++r)e.requestAnimationFrame=e[n[r]+"RequestAnimationFrame"],e.cancelAnimationFrame=e[n[r]+"CancelAnimationFrame"]||e[n[r]+"CancelRequestAnimationFrame"];e.requestAnimationFrame=e.requestAnimationFrame||function(t){var n=(new Date).getTime(),r=Math.max(0,16-(n-i)),s=e.setTimeout(function(){t(n+r)},r);return i=n+r,s},e.cancelAnimationFrame=e.cancelAnimationFrame||e.clearTimeout}(t),g});
++/*! svg.js v3.0.0 MIT*/;!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t,t.document)}):"object"==typeof exports?module.exports=t.document?e(t,t.document):function(t){return e(t,t.document)}:t.SVG=e(t,t.document)}("undefined"!=typeof window?window:this,function(t,e){function i(t){return!(t.w||t.h||t.x||t.y)}function n(t){return(e.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t==e}).call(e.documentElement,t)}function r(t,e,i,n){return i+n.replace(b.regex.dots," .")}function s(t){for(var e=t.slice(0),i=e.length;i--;)Array.isArray(e[i])&&(e[i]=s(e[i]));return e}function a(t,e){return t instanceof e}function o(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}function h(t){return t.toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()})}function u(t){return t.charAt(0).toUpperCase()+t.slice(1)}function l(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}function c(t){var e=t.toString(16);return 1==e.length?"0"+e:e}function f(t,e,i){if(null==e||null==i){var n=t.bbox();null==e?e=n.width/n.height*i:null==i&&(i=n.height/n.width*e)}return{width:e,height:i}}function d(t,e,i){return{x:e*t.a+i*t.c+0,y:e*t.b+i*t.d+0}}function p(t){return{a:t[0],b:t[1],c:t[2],d:t[3],e:t[4],f:t[5]}}function x(t){return t instanceof b.Matrix||(t=new b.Matrix(t)),t}function m(t,e){t.cx=null==t.cx?e.bbox().cx:t.cx,t.cy=null==t.cy?e.bbox().cy:t.cy}function y(t){for(var e=0,i=t.length,n="";e<i;e++)n+=t[e][0],null!=t[e][1]&&(n+=t[e][1],null!=t[e][2]&&(n+=" ",n+=t[e][2],null!=t[e][3]&&(n+=" ",n+=t[e][3],n+=" ",n+=t[e][4],null!=t[e][5]&&(n+=" ",n+=t[e][5],n+=" ",n+=t[e][6],null!=t[e][7]&&(n+=" ",n+=t[e][7])))));return n+" "}function v(e){for(var i=e.childNodes.length-1;i>=0;i--)e.childNodes[i]instanceof t.SVGElement&&v(e.childNodes[i]);return b.adopt(e).id(b.eid(e.nodeName))}function g(t){return null==t.x&&(t.x=0,t.y=0,t.width=0,t.height=0),t.w=t.width,t.h=t.height,t.x2=t.x+t.width,t.y2=t.y+t.height,t.cx=t.x+t.width/2,t.cy=t.y+t.height/2,t}function w(t){var e=(t||"").toString().match(b.regex.reference);if(e)return e[1]}var b=this.SVG=function(t){if(b.supported)return t=new b.Doc(t),b.parser.draw||b.prepare(),t};if(b.ns="http://www.w3.org/2000/svg",b.xmlns="http://www.w3.org/2000/xmlns/",b.xlink="http://www.w3.org/1999/xlink",b.svgjs="http://svgjs.com/svgjs",b.supported=function(){return!!e.createElementNS&&!!e.createElementNS(b.ns,"svg").createSVGRect}(),!b.supported)return!1;b.did=1e3,b.eid=function(t){return"Svgjs"+u(t)+b.did++},b.create=function(t){var i=e.createElementNS(this.ns,t);return i.setAttribute("id",this.eid(t)),i},b.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]},b.invent=function(t){var e="function"==typeof t.create?t.create:function(){this.constructor.call(this,b.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&b.extend(e,t.extend),t.construct&&b.extend(t.parent||b.Container,t.construct),e},b.adopt=function(e){if(!e)return null;if(e.instance)return e.instance;var i;return i="svg"==e.nodeName?e.parentNode instanceof t.SVGElement?new b.Nested:new b.Doc:"linearGradient"==e.nodeName?new b.Gradient("linear"):"radialGradient"==e.nodeName?new b.Gradient("radial"):b[u(e.nodeName)]?new(b[u(e.nodeName)]):new b.Element(e),i.type=e.nodeName,i.node=e,e.instance=i,i instanceof b.Doc&&i.namespace().defs(),i.setData(JSON.parse(e.getAttribute("svgjs:data"))||{}),i},b.prepare=function(){var t=e.getElementsByTagName("body")[0],i=(t?new b.Doc(t):b.adopt(e.documentElement).nested()).size(2,0);b.parser={body:t||e.documentElement,draw:i.style({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"}).node,poly:i.polyline().node,path:i.path().node,native:b.create("svg")}},b.parser={native:b.create("svg")},e.addEventListener("DOMContentLoaded",function(){b.parser.draw||b.prepare()},!1),b.regex={numberAndUnit:/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,reference:/#([a-z0-9\-_]+)/i,transforms:/\)\s*,?\s*/,whitespace:/\s/g,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isBlank:/^(\s+)?$/,isNumber:/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,isPercent:/^-?[\d\.]+%$/,isImage:/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,delimiter:/[\s,]+/,hyphen:/([^e])\-/gi,pathLetters:/[MLHVCSQTAZ]/gi,isPathLetter:/[MLHVCSQTAZ]/i,numbersWithDots:/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,dots:/\./g},b.utils={map:function(t,e){var i,n=t.length,r=[];for(i=0;i<n;i++)r.push(e(t[i]));return r},filter:function(t,e){var i,n=t.length,r=[];for(i=0;i<n;i++)e(t[i])&&r.push(t[i]);return r},radians:function(t){return t%360*Math.PI/180},degrees:function(t){return 180*t/Math.PI%360},filterSVGElements:function(e){return this.filter(e,function(e){return e instanceof t.SVGElement})}},b.defaults={attrs:{"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",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":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"}},b.Color=function(t){var e;this.r=0,this.g=0,this.b=0,t&&("string"==typeof t?b.regex.isRgb.test(t)?(e=b.regex.rgb.exec(t.replace(b.regex.whitespace,"")),this.r=parseInt(e[1]),this.g=parseInt(e[2]),this.b=parseInt(e[3])):b.regex.isHex.test(t)&&(e=b.regex.hex.exec(l(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))},b.extend(b.Color,{toString:function(){return this.toHex()},toHex:function(){return"#"+c(this.r)+c(this.g)+c(this.b)},toRgb:function(){return"rgb("+[this.r,this.g,this.b].join()+")"},brightness:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11},morph:function(t){return this.destination=new b.Color(t),this},at:function(t){return this.destination?(t=t<0?0:t>1?1:t,new b.Color({r:~~(this.r+(this.destination.r-this.r)*t),g:~~(this.g+(this.destination.g-this.g)*t),b:~~(this.b+(this.destination.b-this.b)*t)})):this}}),b.Color.test=function(t){return t+="",b.regex.isHex.test(t)||b.regex.isRgb.test(t)},b.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},b.Color.isColor=function(t){return b.Color.isRgb(t)||b.Color.test(t)},b.Array=function(t,e){t=(t||[]).valueOf(),0==t.length&&e&&(t=e.valueOf()),this.value=this.parse(t)},b.extend(b.Array,{morph:function(t){if(this.destination=this.parse(t),this.value.length!=this.destination.length){for(var e=this.value[this.value.length-1],i=this.destination[this.destination.length-1];this.value.length>this.destination.length;)this.destination.push(i);for(;this.value.length<this.destination.length;)this.value.push(e)}return this},settle:function(){for(var t=0,e=this.value.length,i=[];t<e;t++)i.indexOf(this.value[t])==-1&&i.push(this.value[t]);return this.value=i},at:function(t){if(!this.destination)return this;for(var e=0,i=this.value.length,n=[];e<i;e++)n.push(this.value[e]+(this.destination[e]-this.value[e])*t);return new b.Array(n)},toString:function(){return this.value.join(" ")},valueOf:function(){return this.value},parse:function(t){return t=t.valueOf(),Array.isArray(t)?t:t.trim().split(b.regex.delimiter).map(parseFloat)},reverse:function(){return this.value.reverse(),this},clone:function(){var t=new this.constructor;return t.value=s(this.value),t}}),b.PointArray=function(t,e){b.Array.call(this,t,e||[[0,0]])},b.PointArray.prototype=new b.Array,b.PointArray.prototype.constructor=b.PointArray,b.extend(b.PointArray,{toString:function(){for(var t=0,e=this.value.length,i=[];t<e;t++)i.push(this.value[t].join(","));return i.join(" ")},toLine:function(){return{x1:this.value[0][0],y1:this.value[0][1],x2:this.value[1][0],y2:this.value[1][1]}},at:function(t){if(!this.destination)return this;for(var e=0,i=this.value.length,n=[];e<i;e++)n.push([this.value[e][0]+(this.destination[e][0]-this.value[e][0])*t,this.value[e][1]+(this.destination[e][1]-this.value[e][1])*t]);return new b.PointArray(n)},parse:function(t){var e=[];if(t=t.valueOf(),Array.isArray(t)){if(Array.isArray(t[0]))return t}else t=t.trim().split(b.regex.delimiter).map(parseFloat);t.length%2!==0&&t.pop();for(var i=0,n=t.length;i<n;i+=2)e.push([t[i],t[i+1]]);return e},move:function(t,e){var i=this.bbox();if(t-=i.x,e-=i.y,!isNaN(t)&&!isNaN(e))for(var n=this.value.length-1;n>=0;n--)this.value[n]=[this.value[n][0]+t,this.value[n][1]+e];return this},size:function(t,e){var i,n=this.bbox();for(i=this.value.length-1;i>=0;i--)n.width&&(this.value[i][0]=(this.value[i][0]-n.x)*t/n.width+n.x),n.height&&(this.value[i][1]=(this.value[i][1]-n.y)*e/n.height+n.y);return this},bbox:function(){return b.parser.poly.setAttribute("points",this.toString()),b.parser.poly.getBBox()}});for(var C={M:function(t,e,i){return e.x=i.x=t[0],e.y=i.y=t[1],["M",e.x,e.y]},L:function(t,e){return e.x=t[0],e.y=t[1],["L",t[0],t[1]]},H:function(t,e){return e.x=t[0],["H",t[0]]},V:function(t,e){return e.y=t[0],["V",t[0]]},C:function(t,e){return e.x=t[4],e.y=t[5],["C",t[0],t[1],t[2],t[3],t[4],t[5]]},S:function(t,e){return e.x=t[2],e.y=t[3],["S",t[0],t[1],t[2],t[3]]},Q:function(t,e){return e.x=t[2],e.y=t[3],["Q",t[0],t[1],t[2],t[3]]},T:function(t,e){return e.x=t[0],e.y=t[1],["T",t[0],t[1]]},Z:function(t,e,i){return e.x=i.x,e.y=i.y,["Z"]},A:function(t,e){return e.x=t[5],e.y=t[6],["A",t[0],t[1],t[2],t[3],t[4],t[5],t[6]]}},M="mlhvqtcsaz".split(""),P=0,N=M.length;P<N;++P)C[M[P]]=function(t){return function(e,i,n){if("H"==t)e[0]=e[0]+i.x;else if("V"==t)e[0]=e[0]+i.y;else if("A"==t)e[5]=e[5]+i.x,e[6]=e[6]+i.y;else for(var r=0,s=e.length;r<s;++r)e[r]=e[r]+(r%2?i.y:i.x);return C[t](e,i,n)}}(M[P].toUpperCase());b.PathArray=function(t,e){b.Array.call(this,t,e||[["M",0,0]])},b.PathArray.prototype=new b.Array,b.PathArray.prototype.constructor=b.PathArray,b.extend(b.PathArray,{toString:function(){return y(this.value)},move:function(t,e){var i=this.bbox();if(t-=i.x,e-=i.y,!isNaN(t)&&!isNaN(e))for(var n,r=this.value.length-1;r>=0;r--)n=this.value[r][0],"M"==n||"L"==n||"T"==n?(this.value[r][1]+=t,this.value[r][2]+=e):"H"==n?this.value[r][1]+=t:"V"==n?this.value[r][1]+=e:"C"==n||"S"==n||"Q"==n?(this.value[r][1]+=t,this.value[r][2]+=e,this.value[r][3]+=t,this.value[r][4]+=e,"C"==n&&(this.value[r][5]+=t,this.value[r][6]+=e)):"A"==n&&(this.value[r][6]+=t,this.value[r][7]+=e);return this},size:function(t,e){var i,n,r=this.bbox();for(i=this.value.length-1;i>=0;i--)n=this.value[i][0],"M"==n||"L"==n||"T"==n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y):"H"==n?this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x:"V"==n?this.value[i][1]=(this.value[i][1]-r.y)*e/r.height+r.y:"C"==n||"S"==n||"Q"==n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y,this.value[i][3]=(this.value[i][3]-r.x)*t/r.width+r.x,this.value[i][4]=(this.value[i][4]-r.y)*e/r.height+r.y,"C"==n&&(this.value[i][5]=(this.value[i][5]-r.x)*t/r.width+r.x,this.value[i][6]=(this.value[i][6]-r.y)*e/r.height+r.y)):"A"==n&&(this.value[i][1]=this.value[i][1]*t/r.width,this.value[i][2]=this.value[i][2]*e/r.height,this.value[i][6]=(this.value[i][6]-r.x)*t/r.width+r.x,this.value[i][7]=(this.value[i][7]-r.y)*e/r.height+r.y);return this},equalCommands:function(t){var e,i,n;for(t=new b.PathArray(t),n=this.value.length===t.value.length,e=0,i=this.value.length;n&&e<i;e++)n=this.value[e][0]===t.value[e][0];return n},morph:function(t){return t=new b.PathArray(t),this.equalCommands(t)?this.destination=t:this.destination=null,this},at:function(t){if(!this.destination)return this;var e,i,n,r,s=this.value,a=this.destination.value,o=[],h=new b.PathArray;for(e=0,i=s.length;e<i;e++){for(o[e]=[s[e][0]],n=1,r=s[e].length;n<r;n++)o[e][n]=s[e][n]+(a[e][n]-s[e][n])*t;"A"===o[e][0]&&(o[e][4]=+(0!=o[e][4]),o[e][5]=+(0!=o[e][5]))}return h.value=o,h},parse:function(t){if(t instanceof b.PathArray)return t.valueOf();var e,i,n={M:2,L:2,H:1,V:1,C:6,S:4,Q:4,T:2,A:7};t="string"==typeof t?t.replace(b.regex.numbersWithDots,r).replace(b.regex.pathLetters," $& ").replace(b.regex.hyphen,"$1 -").trim().split(b.regex.delimiter):t.reduce(function(t,e){return[].concat.call(t,e)},[]);var i=[],s=new b.Point,a=new b.Point,o=0,h=t.length;do b.regex.isPathLetter.test(t[o])?(e=t[o],++o):"M"==e?e="L":"m"==e&&(e="l"),i.push(C[e].call(null,t.slice(o,o+=n[e.toUpperCase()]).map(parseFloat),s,a));while(h>o);return i},bbox:function(){return b.parser.path.setAttribute("d",this.toString()),b.parser.path.getBBox()}}),b.Number=b.invent({create:function(t,e){this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-3.4e38:3.4e38:"string"==typeof t?(e=t.match(b.regex.numberAndUnit),e&&(this.value=parseFloat(e[1]),"%"==e[5]?this.value/=100:"s"==e[5]&&(this.value*=1e3),this.unit=e[5])):t instanceof b.Number&&(this.value=t.valueOf(),this.unit=t.unit)},extend:{toString:function(){return("%"==this.unit?~~(1e8*this.value)/1e6:"s"==this.unit?this.value/1e3:this.value)+this.unit},toJSON:function(){return this.toString()},valueOf:function(){return this.value},plus:function(t){return t=new b.Number(t),new b.Number(this+t,this.unit||t.unit)},minus:function(t){return t=new b.Number(t),new b.Number(this-t,this.unit||t.unit)},times:function(t){return t=new b.Number(t),new b.Number(this*t,this.unit||t.unit)},divide:function(t){return t=new b.Number(t),new b.Number(this/t,this.unit||t.unit)},to:function(t){var e=new b.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new b.Number(t),t.relative&&(this.destination.value+=this.value),this},at:function(t){return this.destination?new b.Number(this.destination).minus(this).times(t).plus(this):this}}}),b.Element=b.invent({create:function(t){this._event=null,this.dom={},(this.node=t)&&(this.type=t.nodeName,this.node.instance=this)},extend:{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var i=f(this,t,e);return this.width(new b.Number(i.width)).height(new b.Number(i.height))},clone:function(t,e){this.writeDataToDom();var i=v(this.node.cloneNode(!0));return t?t.add(i):this.after(i),i},remove:function(){return this.parent()&&this.parent().removeElement(this),this},replace:function(t){return this.after(t).remove(),t},addTo:function(t){return t.put(this)},putIn:function(t){return t.add(this)},id:function(t){return this.attr("id",t)},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")},toString:function(){return this.attr("id")},classes:function(){var t=this.attr("class");return null==t?[]:t.trim().split(b.regex.delimiter)},hasClass:function(t){return this.classes().indexOf(t)!=-1},addClass:function(t){if(!this.hasClass(t)){var e=this.classes();e.push(t),this.attr("class",e.join(" "))}return this},removeClass:function(t){return this.hasClass(t)&&this.attr("class",this.classes().filter(function(e){return e!=t}).join(" ")),this},toggleClass:function(t){return this.hasClass(t)?this.removeClass(t):this.addClass(t)},reference:function(t){return b.get(this.attr(t))},parent:function(e){var i=this;if(!i.node.parentNode)return null;if(i=b.adopt(i.node.parentNode),!e)return i;for(;i&&i.node instanceof t.SVGElement;){if("string"==typeof e?i.matches(e):i instanceof e)return i;i=b.adopt(i.node.parentNode)}},doc:function(){return this instanceof b.Doc?this:this.parent(b.Doc)},parents:function(t){var e=[],i=this;do{if(i=i.parent(t),!i||!i.node)break;e.push(i)}while(i.parent);return e},matches:function(t){return o(this.node,t)},native:function(){return this.node},svg:function(t){var i,n;if(!(t&&this instanceof b.Parent))return this.node.outerHTML;for(i=e.createElementNS(b.ns,"svg"),i.innerHTML=t,n=i.childNodes.length;n--;)1!=i.firstChild.nodeType?i.removeChild(i.firstChild):this.node.appendChild(i.firstChild);return this},writeDataToDom:function(){return this.is(b.Parent)&&this.each(function(){this.writeDataToDom()}),this.node.removeAttribute("svgjs:data"),Object.keys(this.dom).length&&this.node.setAttribute("svgjs:data",JSON.stringify(this.dom)),this},setData:function(t){return this.dom=t,this},is:function(t){return a(this,t)}}}),b.easing={"-":function(t){return t},"<>":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return-Math.cos(t*Math.PI/2)+1}},b.morph=function(t){return function(e,i){return new b.MorphObj(e,i).at(t)}},b.Situation=b.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new b.Number(t.duration).valueOf(),this.delay=new b.Number(t.delay).valueOf(),this.start=+new Date+this.delay,this.finish=this.start+this.duration,this.ease=t.ease,this.loop=0,this.loops=!1,this.animations={},this.attrs={},this.styles={},this.transforms=[],this.once={}}}),b.FX=b.invent({create:function(t){this._target=t,this.situations=[],this.active=!1,this.situation=null,this.paused=!1,this.lastPos=0,this.pos=0,this.absPos=0,this._speed=1},extend:{animate:function(t,e,i){"object"==typeof t&&(e=t.ease,i=t.delay,t=t.duration);var n=new b.Situation({duration:t||1e3,delay:i||0,ease:b.easing[e||"-"]||e});return this.queue(n),this},delay:function(t){var e=new b.Situation({duration:t,delay:0,ease:b.easing["-"]});return this.queue(e)},target:function(t){return t&&t instanceof b.Element?(this._target=t,this):this._target},timeToAbsPos:function(t){return(t-this.situation.start)/(this.situation.duration/this._speed)},absPosToTime:function(t){return this.situation.duration/this._speed*t+this.situation.start},startAnimFrame:function(){this.stopAnimFrame(),this.animationFrame=t.requestAnimationFrame(function(){this.step()}.bind(this))},stopAnimFrame:function(){t.cancelAnimationFrame(this.animationFrame)},start:function(){return!this.active&&this.situation&&(this.active=!0,this.startCurrent()),this},startCurrent:function(){return this.situation.start=+new Date+this.situation.delay/this._speed,this.situation.finish=this.situation.start+this.situation.duration/this._speed,this.initAnimations().step()},queue:function(t){return("function"==typeof t||t instanceof b.Situation)&&this.situations.push(t),this.situation||(this.situation=this.situations.shift()),this},dequeue:function(){return this.stop(),this.situation=this.situations.shift(),this.situation&&(this.situation instanceof b.Situation?this.start():this.situation.call(this)),this},initAnimations:function(){var t,e,i=this.situation;if(i.init)return this;for(t in i.animations)e=this.target()[t](),i.animations[t]instanceof b.Number&&(e=new b.Number(e)),i.animations[t]=e.morph(i.animations[t]);for(t in i.attrs)i.attrs[t]=new b.MorphObj(this.target().attr(t),i.attrs[t]);for(t in i.styles)i.styles[t]=new b.MorphObj(this.target().style(t),i.styles[t]);return i.initialTransformation=this.target().matrixify(),i.init=!0,this},clearQueue:function(){return this.situations=[],this},clearCurrent:function(){return this.situation=null,this},stop:function(t,e){var i=this.active;return this.active=!1,e&&this.clearQueue(),t&&this.situation&&(!i&&this.startCurrent(),this.atEnd()),this.stopAnimFrame(),this.clearCurrent()},reset:function(){if(this.situation){var t=this.situation;this.stop(),this.situation=t,this.atStart()}return this},finish:function(){for(this.stop(!0,!1);this.dequeue().situation&&this.stop(!0,!1););return this.clearQueue().clearCurrent(),this},atStart:function(){return this.at(0,!0)},atEnd:function(){return this.situation.loops===!0&&(this.situation.loops=this.situation.loop+1),"number"==typeof this.situation.loops?this.at(this.situation.loops,!0):this.at(1,!0)},at:function(t,e){var i=this.situation.duration/this._speed;return this.absPos=t,e||(this.situation.reversed&&(this.absPos=1-this.absPos),this.absPos+=this.situation.loop),this.situation.start=+new Date-this.absPos*i,this.situation.finish=this.situation.start+i,this.step(!0)},speed:function(t){return 0===t?this.pause():t?(this._speed=t,this.at(this.absPos,!0)):this._speed},loop:function(t,e){var i=this.last();return i.loops=null==t||t,i.loop=0,e&&(i.reversing=!0),this},pause:function(){return this.paused=!0,this.stopAnimFrame(),this},play:function(){return this.paused?(this.paused=!1,this.at(this.absPos,!0)):this},reverse:function(t){var e=this.last();return"undefined"==typeof t?e.reversed=!e.reversed:e.reversed=t,this},progress:function(t){return t?this.situation.ease(this.pos):this.pos},after:function(t){var e=this.last(),i=function i(n){n.detail.situation==e&&(t.call(this,e),this.off("finished.fx",i))};return this.target().on("finished.fx",i),this._callStart()},during:function(t){var e=this.last(),i=function(i){i.detail.situation==e&&t.call(this,i.detail.pos,b.morph(i.detail.pos),i.detail.eased,e)};return this.target().off("during.fx",i).on("during.fx",i),this.after(function(){this.off("during.fx",i)}),this._callStart()},afterAll:function(t){var e=function e(i){t.call(this),this.off("allfinished.fx",e)};return this.target().off("allfinished.fx",e).on("allfinished.fx",e),this._callStart()},duringAll:function(t){var e=function(e){t.call(this,e.detail.pos,b.morph(e.detail.pos),e.detail.eased,e.detail.situation)};return this.target().off("during.fx",e).on("during.fx",e),this.afterAll(function(){this.off("during.fx",e)}),this._callStart()},last:function(){return this.situations.length?this.situations[this.situations.length-1]:this.situation},add:function(t,e,i){return this.last()[i||"animations"][t]=e,this._callStart()},step:function(t){if(t||(this.absPos=this.timeToAbsPos(+new Date)),this.situation.loops!==!1){var e,i,n;e=Math.max(this.absPos,0),i=Math.floor(e),this.situation.loops===!0||i<this.situation.loops?(this.pos=e-i,n=this.situation.loop,this.situation.loop=i):(this.absPos=this.situation.loops,this.pos=1,n=this.situation.loop-1,this.situation.loop=this.situation.loops),this.situation.reversing&&(this.situation.reversed=this.situation.reversed!=Boolean((this.situation.loop-n)%2))}else this.absPos=Math.min(this.absPos,1),this.pos=this.absPos;this.pos<0&&(this.pos=0),this.situation.reversed&&(this.pos=1-this.pos);var r=this.situation.ease(this.pos);for(var s in this.situation.once)s>this.lastPos&&s<=r&&(this.situation.once[s].call(this.target(),this.pos,r),delete this.situation.once[s]);return this.active&&this.target().fire("during",{pos:this.pos,eased:r,fx:this,situation:this.situation}),this.situation?(this.eachAt(),1==this.pos&&!this.situation.reversed||this.situation.reversed&&0==this.pos?(this.stopAnimFrame(),this.target().fire("finished",{fx:this,situation:this.situation}),this.situations.length||(this.target().fire("allfinished"),this.target().off(".fx"),this.active=!1),this.active?this.dequeue():this.clearCurrent()):!this.paused&&this.active&&this.startAnimFrame(),this.lastPos=r,this):this},eachAt:function(){var t,e,i,n=this,r=this.target(),s=this.situation;for(t in s.animations)i=[].concat(s.animations[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(s.ease(n.pos),n.pos):t}),r[t].apply(r,i);for(t in s.attrs)i=[t].concat(s.attrs[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(s.ease(n.pos),n.pos):t}),r.attr.apply(r,i);for(t in s.styles)i=[t].concat(s.styles[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(s.ease(n.pos),n.pos):t}),r.style.apply(r,i);if(s.transforms.length){for(i=s.initialTransformation,t=0,e=s.transforms.length;t<e;t++){var a=s.transforms[t];a instanceof b.Matrix?i=a.relative?i.multiply((new b.Matrix).morph(a).at(s.ease(this.pos))):i.morph(a).at(s.ease(this.pos)):(a.relative||a.undo(i.extract()),i=i.multiply(a.at(s.ease(this.pos))))}r.matrix(i)}return this},once:function(t,e,i){return i||(t=this.situation.ease(t)),this.situation.once[t]=e,this},_callStart:function(){return setTimeout(function(){this.start()}.bind(this),0),this}},parent:b.Element,construct:{animate:function(t,e,i){return(this.fx||(this.fx=new b.FX(this))).animate(t,e,i)},delay:function(t){return(this.fx||(this.fx=new b.FX(this))).delay(t)},stop:function(t,e){return this.fx&&this.fx.stop(t,e),this},finish:function(){return this.fx&&this.fx.finish(),this},pause:function(){return this.fx&&this.fx.pause(),this},play:function(){return this.fx&&this.fx.play(),this},speed:function(t){if(this.fx){if(null==t)return this.fx.speed();this.fx.speed(t)}return this}}}),b.MorphObj=b.invent({create:function(t,e){return b.Color.isColor(e)?new b.Color(t).morph(e):b.regex.numberAndUnit.test(e)?new b.Number(t).morph(e):(this.value=t,void(this.destination=e))},extend:{at:function(t,e){return e<1?this.value:this.destination},valueOf:function(){return this.value}}}),b.extend(b.FX,{attr:function(t,e,i){if("object"==typeof t)for(var n in t)this.attr(n,t[n]);else this.add(t,e,"attrs");return this},style:function(t,e){if("object"==typeof t)for(var i in t)this.style(i,t[i]);else this.add(t,e,"styles");return this},x:function(t,e){if(this.target()instanceof b.G)return this.transform({x:t},e),this;var i=new b.Number(t);return i.relative=e,this.add("x",i)},y:function(t,e){if(this.target()instanceof b.G)return this.transform({y:t},e),this;var i=new b.Number(t);return i.relative=e,this.add("y",i)},cx:function(t){return this.add("cx",new b.Number(t))},cy:function(t){return this.add("cy",new b.Number(t))},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 b.Text)this.attr("font-size",t);else{var i;t&&e||(i=this.target().bbox()),t||(t=i.width/i.height*e),e||(e=i.height/i.width*t),this.add("width",new b.Number(t)).add("height",new b.Number(e))}return this},plot:function(){return this.add("plot",arguments.length>1?[].slice.call(arguments):arguments[0])},leading:function(t){return this.target().leading?this.add("leading",new b.Number(t)):this},viewbox:function(t,e,i,n){return this.target()instanceof b.Container&&this.add("viewbox",new b.Box(t,e,i,n)),this},update:function(t){if(this.target()instanceof b.Stop){if("number"==typeof t||t instanceof b.Number)return this.update({offset:arguments[0],color:arguments[1],opacity:arguments[2]});null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",t.offset)}return this}}),b.Matrix=b.invent({create:function(t){var e,i=p([1,0,0,1,0,0]);for(t=t instanceof b.Element?t.matrixify():"string"==typeof t?p(t.split(b.regex.delimiter).map(parseFloat)):6==arguments.length?p([].slice.call(arguments)):Array.isArray(t)?p(t):"object"==typeof t?t:i,e=A.length-1;e>=0;--e)this[A[e]]=t&&"number"==typeof t[A[e]]?t[A[e]]:i[A[e]]},extend:{extract:function(){var t=d(this,0,1),e=d(this,1,0),i=180/Math.PI*Math.atan2(t.y,t.x)-90;return{x:this.e,y:this.f,transformedX:(this.e*Math.cos(i*Math.PI/180)+this.f*Math.sin(i*Math.PI/180))/Math.sqrt(this.a*this.a+this.b*this.b),transformedY:(this.f*Math.cos(i*Math.PI/180)+this.e*Math.sin(-i*Math.PI/180))/Math.sqrt(this.c*this.c+this.d*this.d),skewX:-i,skewY:180/Math.PI*Math.atan2(e.y,e.x),scaleX:Math.sqrt(this.a*this.a+this.b*this.b),scaleY:Math.sqrt(this.c*this.c+this.d*this.d),rotation:i,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f,matrix:new b.Matrix(this)}},clone:function(){return new b.Matrix(this)},morph:function(t){return this.destination=new b.Matrix(t),this},at:function(t){if(!this.destination)return this;var e=new b.Matrix({a:this.a+(this.destination.a-this.a)*t,b:this.b+(this.destination.b-this.b)*t,c:this.c+(this.destination.c-this.c)*t,d:this.d+(this.destination.d-this.d)*t,e:this.e+(this.destination.e-this.e)*t,f:this.f+(this.destination.f-this.f)*t});return e},multiply:function(t){return new b.Matrix(this.native().multiply(x(t).native()))},inverse:function(){return new b.Matrix(this.native().inverse())},translate:function(t,e){return new b.Matrix(this.native().translate(t||0,e||0))},scale:function(t,e,i,n){return 1==arguments.length?e=t:3==arguments.length&&(n=i,i=e,e=t),this.around(i,n,new b.Matrix(t,0,0,e,0,0))},rotate:function(t,e,i){return t=b.utils.radians(t),this.around(e,i,new b.Matrix(Math.cos(t),Math.sin(t),-Math.sin(t),Math.cos(t),0,0))},flip:function(t,e){return"x"==t?this.scale(-1,1,e,0):"y"==t?this.scale(1,-1,0,e):this.scale(-1,-1,t,null!=e?e:t)},skew:function(t,e,i,n){return 1==arguments.length?e=t:3==arguments.length&&(n=i,i=e,e=t),t=b.utils.radians(t),e=b.utils.radians(e),this.around(i,n,new b.Matrix(1,Math.tan(e),Math.tan(t),1,0,0))},skewX:function(t,e,i){return this.skew(t,0,e,i)},skewY:function(t,e,i){return this.skew(0,t,e,i)},around:function(t,e,i){return this.multiply(new b.Matrix(1,0,0,1,t||0,e||0)).multiply(i).multiply(new b.Matrix(1,0,0,1,-t||0,-e||0))},native:function(){for(var t=b.parser.native.createSVGMatrix(),e=A.length-1;e>=0;e--)t[A[e]]=this[A[e]];return t},toString:function(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}},parent:b.Element,construct:{ctm:function(){return new b.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof b.Nested){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new b.Matrix(e)}return new b.Matrix(this.node.getScreenCTM())}}}),b.Point=b.invent({create:function(t,e){var i,n={x:0,y:0};i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"==typeof t?{x:t.x,y:t.y}:null!=t?{x:t,y:null!=e?e:t}:n,this.x=i.x,this.y=i.y},extend:{clone:function(){return new b.Point(this)},morph:function(t,e){return this.destination=new b.Point(t,e),this},at:function(t){if(!this.destination)return this;var e=new b.Point({x:this.x+(this.destination.x-this.x)*t,y:this.y+(this.destination.y-this.y)*t});return e},native:function(){var t=b.parser.native.createSVGPoint();return t.x=this.x,t.y=this.y,t},transform:function(t){return new b.Point(this.native().matrixTransform(t.native()))}}}),b.extend(b.Element,{point:function(t,e){return new b.Point(t,e).transform(this.screenCTM().inverse())}}),b.extend(b.Element,{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]=b.regex.isNumber.test(e[i].nodeValue)?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 e=this.node.getAttribute(t),null==e?b.defaults.attrs[t]:b.regex.isNumber.test(e)?parseFloat(e):e;"fill"!=t&&"stroke"!=t||(b.regex.isImage.test(e)&&(e=this.doc().defs().image(e)),e instanceof b.Image&&(e=this.doc().defs().pattern(0,0,function(){this.add(e)}))),"number"==typeof e?e=new b.Number(e):b.Color.isColor(e)?e=new b.Color(e):Array.isArray(e)&&(e=new b.Array(e)),"leading"==t?this.leading&&this.leading(e):"string"==typeof i?this.node.setAttributeNS(i,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!=t&&"x"!=t||this.rebuild(t,e)}return this}}),b.extend(b.Element,{transform:function(t,e){var i,n,r=this;if("object"!=typeof t)return i=new b.Matrix(r).extract(),"string"==typeof t?i[t]:i;if(i=new b.Matrix(r),e=!!e||!!t.relative,null!=t.a)i=e?i.multiply(new b.Matrix(t)):new b.Matrix(t);else if(null!=t.rotation)m(t,r),i=e?i.rotate(t.rotation,t.cx,t.cy):i.rotate(t.rotation-i.extract().rotation,t.cx,t.cy);else if(null!=t.scale||null!=t.scaleX||null!=t.scaleY){if(m(t,r),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,
++!e){var s=i.extract();t.scaleX=1*t.scaleX/s.scaleX,t.scaleY=1*t.scaleY/s.scaleY}i=i.scale(t.scaleX,t.scaleY,t.cx,t.cy)}else if(null!=t.skew||null!=t.skewX||null!=t.skewY){if(m(t,r),t.skewX=null!=t.skew?t.skew:null!=t.skewX?t.skewX:0,t.skewY=null!=t.skew?t.skew:null!=t.skewY?t.skewY:0,!e){var s=i.extract();i=i.multiply((new b.Matrix).skew(s.skewX,s.skewY,t.cx,t.cy).inverse())}i=i.skew(t.skewX,t.skewY,t.cx,t.cy)}else t.flip?("x"==t.flip||"y"==t.flip?t.offset=null==t.offset?r.bbox()["c"+t.flip]:t.offset:null==t.offset?(n=r.bbox(),t.flip=n.cx,t.offset=n.cy):t.flip=t.offset,i=(new b.Matrix).flip(t.flip,t.offset)):null==t.x&&null==t.y||(e?i=i.translate(t.x,t.y):(null!=t.x&&(i.e=t.x),null!=t.y&&(i.f=t.y)));return this.attr("transform",i)}}),b.extend(b.FX,{transform:function(t,e){var i,n,r=this.target();return"object"!=typeof t?(i=new b.Matrix(r).extract(),"string"==typeof t?i[t]:i):(e=!!e||!!t.relative,null!=t.a?i=new b.Matrix(t):null!=t.rotation?(m(t,r),i=new b.Rotate(t.rotation,t.cx,t.cy)):null!=t.scale||null!=t.scaleX||null!=t.scaleY?(m(t,r),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,i=new b.Scale(t.scaleX,t.scaleY,t.cx,t.cy)):null!=t.skewX||null!=t.skewY?(m(t,r),t.skewX=null!=t.skewX?t.skewX:0,t.skewY=null!=t.skewY?t.skewY:0,i=new b.Skew(t.skewX,t.skewY,t.cx,t.cy)):t.flip?("x"==t.flip||"y"==t.flip?t.offset=null==t.offset?r.bbox()["c"+t.flip]:t.offset:null==t.offset?(n=r.bbox(),t.flip=n.cx,t.offset=n.cy):t.flip=t.offset,i=(new b.Matrix).flip(t.flip,t.offset)):null==t.x&&null==t.y||(i=new b.Translate(t.x,t.y)),i?(i.relative=e,this.last().transforms.push(i),this._callStart()):this)}}),b.extend(b.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){var t=(this.attr("transform")||"").split(b.regex.transforms).slice(0,-1).map(function(t){var e=t.trim().split("(");return[e[0],e[1].split(b.regex.delimiter).map(function(t){return parseFloat(t)})]}).reduce(function(t,e){return"matrix"==e[0]?t.multiply(p(e[1])):t[e[0]].apply(t,e[1])},new b.Matrix);return t},toParent:function(t){if(this==t)return this;var e=this.screenCTM(),i=t.screenCTM().inverse();return this.addTo(t).untransform().transform(i.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),b.Transformation=b.invent({create:function(t,e){if(arguments.length>1&&"boolean"!=typeof e)return this.constructor.call(this,[].slice.call(arguments));if(Array.isArray(t))for(var i=0,n=this.arguments.length;i<n;++i)this[this.arguments[i]]=t[i];else if("object"==typeof t)for(var i=0,n=this.arguments.length;i<n;++i)this[this.arguments[i]]=t[this.arguments[i]];this.inversed=!1,e===!0&&(this.inversed=!0)},extend:{arguments:[],method:"",at:function(t){for(var e=[],i=0,n=this.arguments.length;i<n;++i)e.push(this[this.arguments[i]]);var r=this._undo||new b.Matrix;return r=(new b.Matrix).morph(b.Matrix.prototype[this.method].apply(r,e)).at(t),this.inversed?r.inverse():r},undo:function(t){for(var e=0,i=this.arguments.length;e<i;++e)t[this.arguments[e]]="undefined"==typeof this[this.arguments[e]]?0:t[this.arguments[e]];return t.cx=this.cx,t.cy=this.cy,this._undo=new(b[u(this.method)])(t,!0).at(1),this}}}),b.Translate=b.invent({parent:b.Matrix,inherit:b.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["transformedX","transformedY"],method:"translate"}}),b.Rotate=b.invent({parent:b.Matrix,inherit:b.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["rotation","cx","cy"],method:"rotate",at:function(t){var e=(new b.Matrix).rotate((new b.Number).morph(this.rotation-(this._undo?this._undo.rotation:0)).at(t),this.cx,this.cy);return this.inversed?e.inverse():e},undo:function(t){return this._undo=t,this}}}),b.Scale=b.invent({parent:b.Matrix,inherit:b.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["scaleX","scaleY","cx","cy"],method:"scale"}}),b.Skew=b.invent({parent:b.Matrix,inherit:b.Transformation,create:function(t,e){this.constructor.apply(this,[].slice.call(arguments))},extend:{arguments:["skewX","skewY","cx","cy"],method:"skew"}}),b.extend(b.Element,{style:function(t,e){if(0==arguments.length)return this.node.style.cssText||"";if(arguments.length<2){if("object"!=typeof t)return this.node.style[h(t)];for(e in t)this.style(e,t[e])}else this.node.style[h(t)]=null===e||b.regex.isBlank.test(e)?"":e;return this}}),b.Parent=b.invent({create:function(t){this.constructor.call(this,t)},inherit:b.Element,extend:{children:function(){return b.utils.map(b.utils.filterSVGElements(this.node.childNodes),function(t){return b.adopt(t)})},add:function(t,e){return null==e?this.node.appendChild(t.node):t.node!=this.node.childNodes[e]&&this.node.insertBefore(t.node,this.node.childNodes[e]),this},put:function(t,e){return this.add(t,e),t},has:function(t){return this.index(t)>=0},index:function(t){return[].slice.call(this.node.childNodes).indexOf(t.node)},get:function(t){return b.adopt(this.node.childNodes[t])},first:function(){return this.get(0)},last:function(){return this.get(this.node.childNodes.length-1)},each:function(t,e){var i,n,r=this.children();for(i=0,n=r.length;i<n;i++)r[i]instanceof b.Element&&t.apply(r[i],[i,r]),e&&r[i]instanceof b.Container&&r[i].each(t,e);return this},removeElement:function(t){return this.node.removeChild(t.node),this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return delete this._defs,this},defs:function(){return this.doc().defs()}}}),b.extend(b.Parent,{flatten:function(t){return this instanceof b.Defs?this:(t=t||(this instanceof b.Doc?this:this.parent(b.Parent)),this.each(function(){return this instanceof b.Defs?this:this instanceof b.Parent?this.flatten(t):this.toParent(t)}),this.node.firstChild||this.remove(),this)}}),b.Container=b.invent({create:function(t){this.constructor.call(this,t)},inherit:b.Parent}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","touchstart","touchmove","touchleave","touchend","touchcancel"].forEach(function(t){b.Element.prototype[t]=function(e){return b.on(this.node,t,e),this}}),b.listeners=[],b.handlerMap=[],b.listenerId=0,b.on=function(t,e,i,n,r){var s=i.bind(n||t.instance||t),a=(b.handlerMap.indexOf(t)+1||b.handlerMap.push(t))-1,o=e.split(".")[0],h=e.split(".")[1]||"*";b.listeners[a]=b.listeners[a]||{},b.listeners[a][o]=b.listeners[a][o]||{},b.listeners[a][o][h]=b.listeners[a][o][h]||{},i._svgjsListenerId||(i._svgjsListenerId=++b.listenerId),b.listeners[a][o][h][i._svgjsListenerId]=s,t.addEventListener(o,s,r||!1)},b.off=function(t,e,i){var n=b.handlerMap.indexOf(t),r=e&&e.split(".")[0],s=e&&e.split(".")[1],a="";if(n!=-1)if(i){if("function"==typeof i&&(i=i._svgjsListenerId),!i)return;b.listeners[n][r]&&b.listeners[n][r][s||"*"]&&(t.removeEventListener(r,b.listeners[n][r][s||"*"][i],!1),delete b.listeners[n][r][s||"*"][i])}else if(s&&r){if(b.listeners[n][r]&&b.listeners[n][r][s]){for(i in b.listeners[n][r][s])b.off(t,[r,s].join("."),i);delete b.listeners[n][r][s]}}else if(s)for(e in b.listeners[n])for(a in b.listeners[n][e])s===a&&b.off(t,[e,s].join("."));else if(r){if(b.listeners[n][r]){for(a in b.listeners[n][r])b.off(t,[r,a].join("."));delete b.listeners[n][r]}}else{for(e in b.listeners[n])b.off(t,e);delete b.listeners[n],delete b.handlerMap[n]}},b.extend(b.Element,{on:function(t,e,i,n){return b.on(this.node,t,e,i,n),this},off:function(t,e){return b.off(this.node,t,e),this},fire:function(e,i){return e instanceof t.Event?this.node.dispatchEvent(e):this.node.dispatchEvent(e=new t.CustomEvent(e,{detail:i,cancelable:!0})),this._event=e,this},event:function(){return this._event}}),b.Defs=b.invent({create:"defs",inherit:b.Container}),b.G=b.invent({create:"g",inherit:b.Container,extend:{x:function(t){return null==t?this.transform("x"):this.transform({x:t-this.x()},!0)},y:function(t){return null==t?this.transform("y"):this.transform({y:t-this.y()},!0)},cx:function(t){return null==t?this.gbox().cx:this.x(t-this.gbox().width/2)},cy:function(t){return null==t?this.gbox().cy:this.y(t-this.gbox().height/2)},gbox:function(){var t=this.bbox(),e=this.transform();return t.x+=e.x,t.x2+=e.x,t.cx+=e.x,t.y+=e.y,t.y2+=e.y,t.cy+=e.y,t}},construct:{group:function(){return this.put(new b.G)}}}),b.extend(b.Element,{siblings:function(){return this.parent().children()},position:function(){return this.parent().index(this)},next:function(){return this.siblings()[this.position()+1]},previous:function(){return this.siblings()[this.position()-1]},forward:function(){var t=this.position()+1,e=this.parent();return e.removeElement(this).add(this,t),e instanceof b.Doc&&e.node.appendChild(e.defs().node),this},backward:function(){var t=this.position();return t>0&&this.parent().removeElement(this).add(this,t-1),this},front:function(){var t=this.parent();return t.node.appendChild(this.node),t instanceof b.Doc&&t.node.appendChild(t.defs().node),this},back:function(){return this.position()>0&&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}}),b.Mask=b.invent({create:"mask",inherit:b.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unmask()}),b.Element.prototype.remove.call(this)},targets:function(){return b.select('svg [mask*="'+this.id()+'"]')}},construct:{mask:function(){return this.defs().put(new b.Mask)}}}),b.extend(b.Element,{maskWith:function(t){var e=t instanceof b.Mask?t:this.parent().mask().add(t);return this.attr("mask",'url("#'+e.attr("id")+'")')},unmask:function(){return this.attr("mask",null)},masker:function(){return this.reference("mask")}}),b.ClipPath=b.invent({create:"clipPath",inherit:b.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unclip()}),b.Element.prototype.remove.call(this)},targets:function(){return b.select('svg [clip-path*="'+this.id()+'"]')}},construct:{clip:function(){return this.defs().put(new b.ClipPath)}}}),b.extend(b.Element,{clipWith:function(t){var e=t instanceof b.ClipPath?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.attr("id")+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}),b.Gradient=b.invent({create:function(t){this.constructor.call(this,b.create(t+"Gradient"))},inherit:b.Container,extend:{at:function(t,e,i){return this.put(new b.Stop).update(t,e,i)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},fill:function(){return"url(#"+this.id()+")"},toString:function(){return this.fill()},attr:function(t,e,i){return"transform"==t&&(t="gradientTransform"),b.Container.prototype.attr.call(this,t,e,i)}},construct:{gradient:function(t,e){return this.defs().gradient(t,e)}}}),b.extend(b.Gradient,b.FX,{from:function(t,e){return"radialGradient"==(this._target||this).type?this.attr({fx:new b.Number(t),fy:new b.Number(e)}):this.attr({x1:new b.Number(t),y1:new b.Number(e)})},to:function(t,e){return"radialGradient"==(this._target||this).type?this.attr({cx:new b.Number(t),cy:new b.Number(e)}):this.attr({x2:new b.Number(t),y2:new b.Number(e)})}}),b.extend(b.Defs,{gradient:function(t,e){return this.put(new b.Gradient(t)).update(e)}}),b.Stop=b.invent({create:"stop",inherit:b.Element,extend:{update:function(t){return("number"==typeof t||t instanceof b.Number)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),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 b.Number(t.offset)),this}}}),b.Pattern=b.invent({create:"pattern",inherit:b.Container,extend:{fill:function(){return"url(#"+this.id()+")"},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return this.fill()},attr:function(t,e,i){return"transform"==t&&(t="patternTransform"),b.Container.prototype.attr.call(this,t,e,i)}},construct:{pattern:function(t,e,i){return this.defs().pattern(t,e,i)}}}),b.extend(b.Defs,{pattern:function(t,e,i){return this.put(new b.Pattern).update(i).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),b.Doc=b.invent({create:function(t){t&&(t="string"==typeof t?e.getElementById(t):t,"svg"==t.nodeName?this.constructor.call(this,t):(this.constructor.call(this,b.create("svg")),t.appendChild(this.node),this.size("100%","100%")),this.namespace().defs())},inherit:b.Container,extend:{namespace:function(){return this.attr({xmlns:b.ns,version:"1.1"}).attr("xmlns:xlink",b.xlink,b.xmlns).attr("xmlns:svgjs",b.svgjs,b.xmlns)},defs:function(){if(!this._defs){var t;(t=this.node.getElementsByTagName("defs")[0])?this._defs=b.adopt(t):this._defs=new b.Defs,this.node.appendChild(this._defs.node)}return this._defs},parent:function(){return"#document"==this.node.parentNode.nodeName?null:this.node.parentNode},spof:function(t){var e=this.node.getScreenCTM();return e&&this.style("left",-e.e%1+"px").style("top",-e.f%1+"px"),this},remove:function(){return this.parent()&&this.parent().removeChild(this.node),this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return delete this._defs,b.parser.draw.parentNode||this.node.appendChild(b.parser.draw),this}}}),b.Shape=b.invent({create:function(t){this.constructor.call(this,t)},inherit:b.Element}),b.Bare=b.invent({create:function(t,e){if(this.constructor.call(this,b.create(t)),e)for(var i in e.prototype)"function"==typeof e.prototype[i]&&(this[i]=e.prototype[i])},inherit:b.Element,extend:{words:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(e.createTextNode(t)),this}}}),b.extend(b.Parent,{element:function(t,e){return this.put(new b.Bare(t,e))}}),b.Symbol=b.invent({create:"symbol",inherit:b.Container,construct:{symbol:function(){return this.put(new b.Symbol)}}}),b.Use=b.invent({create:"use",inherit:b.Shape,extend:{element:function(t,e){return this.attr("href",(e||"")+"#"+t,b.xlink)}},construct:{use:function(t,e){return this.put(new b.Use).element(t,e)}}}),b.Rect=b.invent({create:"rect",inherit:b.Shape,construct:{rect:function(t,e){return this.put(new b.Rect).size(t,e)}}}),b.Circle=b.invent({create:"circle",inherit:b.Shape,construct:{circle:function(t){return this.put(new b.Circle).rx(new b.Number(t).divide(2)).move(0,0)}}}),b.extend(b.Circle,b.FX,{rx:function(t){return this.attr("r",t)},ry:function(t){return this.rx(t)}}),b.Ellipse=b.invent({create:"ellipse",inherit:b.Shape,construct:{ellipse:function(t,e){return this.put(new b.Ellipse).size(t,e).move(0,0)}}}),b.extend(b.Ellipse,b.Rect,b.FX,{rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)}}),b.extend(b.Circle,b.Ellipse,{x:function(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())},y:function(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())},cx:function(t){return null==t?this.attr("cx"):this.attr("cx",t)},cy:function(t){return null==t?this.attr("cy"):this.attr("cy",t)},width:function(t){return null==t?2*this.rx():this.rx(new b.Number(t).divide(2))},height:function(t){return null==t?2*this.ry():this.ry(new b.Number(t).divide(2))},size:function(t,e){var i=f(this,t,e);return this.rx(new b.Number(i.width).divide(2)).ry(new b.Number(i.height).divide(2))}}),b.Line=b.invent({create:"line",inherit:b.Shape,extend:{array:function(){return new b.PointArray([[this.attr("x1"),this.attr("y1")],[this.attr("x2"),this.attr("y2")]])},plot:function(t,e,i,n){return null==t?this.array():(t="undefined"!=typeof e?{x1:t,y1:e,x2:i,y2:n}:new b.PointArray(t).toLine(),this.attr(t))},move:function(t,e){return this.attr(this.array().move(t,e).toLine())},size:function(t,e){var i=f(this,t,e);return this.attr(this.array().size(i.width,i.height).toLine())}},construct:{line:function(t,e,i,n){return b.Line.prototype.plot.apply(this.put(new b.Line),null!=t?[t,e,i,n]:[0,0,0,0])}}}),b.Polyline=b.invent({create:"polyline",inherit:b.Shape,construct:{polyline:function(t){return this.put(new b.Polyline).plot(t||new b.PointArray)}}}),b.Polygon=b.invent({create:"polygon",inherit:b.Shape,construct:{polygon:function(t){return this.put(new b.Polygon).plot(t||new b.PointArray)}}}),b.extend(b.Polyline,b.Polygon,{array:function(){return this._array||(this._array=new b.PointArray(this.attr("points")))},plot:function(t){return null==t?this.array():this.clear().attr("points","string"==typeof t?t:this._array=new b.PointArray(t))},clear:function(){return delete this._array,this},move:function(t,e){return this.attr("points",this.array().move(t,e))},size:function(t,e){var i=f(this,t,e);return this.attr("points",this.array().size(i.width,i.height))}}),b.extend(b.Line,b.Polyline,b.Polygon,{morphArray:b.PointArray,x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},width:function(t){var e=this.bbox();return null==t?e.width:this.size(t,e.height)},height:function(t){var e=this.bbox();return null==t?e.height:this.size(e.width,t)}}),b.Path=b.invent({create:"path",inherit:b.Shape,extend:{morphArray:b.PathArray,array:function(){return this._array||(this._array=new b.PathArray(this.attr("d")))},plot:function(t){return null==t?this.array():this.clear().attr("d","string"==typeof t?t:this._array=new b.PathArray(t))},clear:function(){return delete this._array,this},move:function(t,e){return this.attr("d",this.array().move(t,e))},x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},size:function(t,e){var i=f(this,t,e);return this.attr("d",this.array().size(i.width,i.height))},width:function(t){return null==t?this.bbox().width:this.size(t,this.bbox().height)},height:function(t){return null==t?this.bbox().height:this.size(this.bbox().width,t)}},construct:{path:function(t){return this.put(new b.Path).plot(t||new b.PathArray)}}}),b.Image=b.invent({create:"image",inherit:b.Shape,extend:{load:function(e,i){if(!e)return this;var n=new t.Image;return b.on(n,"load",function(t){var r=this.parent();0==this.width()&&0==this.height()&&this.size(n.width,n.height),r instanceof b.Pattern&&0==r.width()&&0==r.height()&&r.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:n.width,height:n.height,ratio:n.width/n.height,url:e})},this),this.attr("href",n.src=e,b.xlink)}},construct:{image:function(t,e){return this.put(new b.Image).size(0,0).load(t,e)}}}),b.Text=b.invent({create:function(){this.constructor.call(this,b.create("text")),this.dom.leading=new b.Number(1.3),this._rebuild=!0,this._build=!1,this.attr("font-family",b.defaults.attrs["font-family"])},inherit:b.Parent,extend:{x:function(t){return null==t?this.attr("x"):this.attr("x",t)},y:function(t){var e=this.attr("y"),i="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-i:e:this.attr("y","number"==typeof t?t+i: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)},text:function(t){if("undefined"==typeof t){for(var t="",e=this.node.childNodes,i=0,n=e.length;i<n;++i)0!=i&&3!=e[i].nodeType&&1==b.adopt(e[i]).dom.newLined&&(t+="\n"),t+=e[i].textContent;return t}if(this.clear().build(!0),"function"==typeof t)t.call(this,this);else{t=t.split("\n");for(var i=0,r=t.length;i<r;i++)this.tspan(t[i]).newLine()}return this.build(!1).rebuild()},size:function(t){return this.attr("font-size",t).rebuild()},leading:function(t){return null==t?this.dom.leading:(this.dom.leading=new b.Number(t),this.rebuild())},rebuild:function(t){if("boolean"==typeof t&&(this._rebuild=t),this._rebuild){var e=this,i=0,n=this.dom.leading*new b.Number(this.attr("font-size"));this.each(function(){this.dom.newLined&&(e.textPath()||this.attr("x",e.attr("x")),"\n"==this.text()?i+=n:(this.attr("dy",n+i),i=0))}),this.fire("rebuild")}return this},build:function(t){return this._build=!!t,this},setData:function(t){return this.dom=t,this.dom.leading=new b.Number(t.leading||1.3),this}},construct:{text:function(t){return this.put(new b.Text).text(t)},plain:function(t){return this.put(new b.Text).plain(t)}}}),b.Tspan=b.invent({create:"tspan",inherit:b.Parent,extend:{text:function(t){return null==t?this.node.textContent+(this.dom.newLined?"\n":""):("function"==typeof t?t.call(this,this):this.plain(t),this)},dx:function(t){return this.attr("dx",t)},dy:function(t){return this.attr("dy",t)},newLine:function(){var t=this.parent(b.Text);return this.dom.newLined=!0,this.dy(t.dom.leading*t.attr("font-size")).attr("x",t.x())}}}),b.extend(b.Text,b.Tspan,{plain:function(t){return this._build===!1&&this.clear(),this.node.appendChild(e.createTextNode(t)),this},tspan:function(t){var e=(this.textPath&&this.textPath()||this).node,i=new b.Tspan;return this._build===!1&&this.clear(),e.appendChild(i.node),i.text(t)},length:function(){return this.node.getComputedTextLength()}}),b.TextPath=b.invent({create:"textPath",inherit:b.Parent,parent:b.Text,construct:{path:function(t){for(var e=new b.TextPath,i=this.doc().defs().path(t);this.node.hasChildNodes();)e.node.appendChild(this.node.firstChild);return this.node.appendChild(e.node),e.attr("href","#"+i,b.xlink),this},array:function(){var t=this.track();return t?t.array():null},plot:function(t){var e=this.track(),i=null;return e&&(i=e.plot(t)),null==t?i:this},track:function(){var t=this.textPath();if(t)return t.reference("href")},textPath:function(){if(this.node.firstChild&&"textPath"==this.node.firstChild.nodeName)return b.adopt(this.node.firstChild)}}}),b.Nested=b.invent({create:function(){this.constructor.call(this,b.create("svg")),this.style("overflow","visible")},inherit:b.Container,construct:{nested:function(){return this.put(new b.Nested)}}}),b.A=b.invent({create:"a",inherit:b.Container,extend:{to:function(t){return this.attr("href",t,b.xlink)},show:function(t){return this.attr("show",t,b.xlink)},target:function(t){return this.attr("target",t)}},construct:{link:function(t){return this.put(new b.A).to(t)}}}),b.extend(b.Element,{linkTo:function(t){var e=new b.A;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}),b.Marker=b.invent({create:"marker",inherit:b.Container,extend:{width:function(t){return this.attr("markerWidth",t)},height:function(t){return this.attr("markerHeight",t)},ref:function(t,e){return this.attr("refX",t).attr("refY",e)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return"url(#"+this.id()+")"}},construct:{marker:function(t,e,i){return this.defs().marker(t,e,i)}}}),b.extend(b.Defs,{marker:function(t,e,i){return this.put(new b.Marker).size(t,e).ref(t/2,e/2).viewbox(0,0,t,e).attr("orient","auto").update(i)}}),b.extend(b.Line,b.Polyline,b.Polygon,b.Path,{marker:function(t,e,i,n){var r=["marker"];return"all"!=t&&r.push(t),r=r.join("-"),t=arguments[1]instanceof b.Marker?arguments[1]:this.doc().marker(e,i,n),this.attr(r,t)}});var k={stroke:["color","width","opacity","linecap","linejoin","miterlimit","dasharray","dashoffset"],fill:["color","opacity","rule"],prefix:function(t,e){return"color"==e?t:t+"-"+e}};["fill","stroke"].forEach(function(t){var e,i={};i[t]=function(i){if("undefined"==typeof i)return this;if("string"==typeof i||b.Color.isRgb(i)||i&&"function"==typeof i.fill)this.attr(t,i);else for(e=k[t].length-1;e>=0;e--)null!=i[k[t][e]]&&this.attr(k.prefix(t,k[t][e]),i[k[t][e]]);return this},b.extend(b.Element,b.FX,i)}),b.extend(b.Element,b.FX,{rotate:function(t,e,i){return this.transform({rotation:t,cx:e,cy:i})},skew:function(t,e,i,n){return 1==arguments.length||3==arguments.length?this.transform({skew:t,cx:e,cy:i}):this.transform({skewX:t,skewY:e,cx:i,cy:n})},scale:function(t,e,i,n){return 1==arguments.length||3==arguments.length?this.transform({scale:t,cx:e,cy:i}):this.transform({scaleX:t,scaleY:e,cx:i,cy:n})},translate:function(t,e){return this.transform({x:t,y:e})},flip:function(t,e){return e="number"==typeof t?t:e,this.transform({flip:t||"both",offset:e})},matrix:function(t){return this.attr("transform",new b.Matrix(6==arguments.length?[].slice.call(arguments):t))},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new b.Number(t).plus(this instanceof b.FX?0:this.x()),!0)},dy:function(t){return this.y(new b.Number(t).plus(this instanceof b.FX?0:this.y()),!0)},dmove:function(t,e){return this.dx(t).dy(e)}}),b.extend(b.Rect,b.Ellipse,b.Circle,b.Gradient,b.FX,{radius:function(t,e){var i=(this._target||this).type;return"radialGradient"==i||"radialGradient"==i?this.attr("r",new b.Number(t)):this.rx(t).ry(null==e?t:e)}}),b.extend(b.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return new b.Point(this.node.getPointAtLength(t))}}),b.extend(b.Parent,b.Text,b.Tspan,b.FX,{font:function(t,e){if("object"==typeof t)for(e in t)this.font(e,t[e]);return"leading"==t?this.leading(e):"anchor"==t?this.attr("text-anchor",e):"size"==t||"family"==t||"weight"==t||"stretch"==t||"variant"==t||"style"==t?this.attr("font-"+t,e):this.attr(t,e)}}),b.extend(b.Element,{data:function(t,e,i){if("object"==typeof t)for(e in t)this.data(e,t[e]);else if(arguments.length<2)try{return JSON.parse(this.attr("data-"+t))}catch(e){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}}),b.extend(b.Element,{remember:function(t,e){if("object"==typeof arguments[0])for(var e in t)this.remember(e,t[e]);else{if(1==arguments.length)return this.memory()[t];this.memory()[t]=e}return this},forget:function(){if(0==arguments.length)this._memory={};else for(var t=arguments.length-1;t>=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory||(this._memory={})}}),b.get=function(t){var i=e.getElementById(w(t)||t);return b.adopt(i)},b.select=function(t,i){return b.utils.map((i||e).querySelectorAll(t),function(t){return b.adopt(t)})},b.$$=function(t,i){return b.utils.map((i||e).querySelectorAll(t),function(t){return b.adopt(t)})},b.$=function(t,i){return b.adopt((i||e).querySelector(t))},b.extend(b.Parent,{select:function(t){return b.select(t,this.node)}});var A="abcdef".split("");return b.Box=b.invent({create:function(t){var e=[0,0,0,0];t="string"==typeof t?t.split(b.regex.delimiter).map(parseFloat):Array.isArray(t)?t:"object"==typeof t?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4==arguments.length?[].slice.call(arguments):e,this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],g(this)},extend:{merge:function(t){var e=Math.min(this.x,t.x),i=Math.min(this.y,t.y);return new b.Box(e,i,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-i)},transform:function(t){var e=1/0,i=-(1/0),n=1/0,r=-(1/0),s=[new b.Point(this.x,this.y),new b.Point(this.x2,this.y),new b.Point(this.x,this.y2),new b.Point(this.x2,this.y2)];return s.forEach(function(s){s=s.transform(t),e=Math.min(e,s.x),i=Math.max(i,s.x),n=Math.min(n,s.y),r=Math.max(r,s.y)}),new b.Box(e,n,i-e,r-n)},addOffset:function(){return this.x+=t.pageXOffset,this.y+=t.pageYOffset,this},toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height},morph:function(t,e,i,n){return this.destination=new b.Box(t,e,i,n),this},at:function(t){return this.destination?new b.Box(this.x+(this.destination.x-this.x)*t,this.y+(this.destination.y-this.y)*t,this.width+(this.destination.width-this.width)*t,this.height+(this.destination.height-this.height)*t):this}},parent:b.Element,construct:{bbox:function(){var t;try{if(t=this.node.getBBox(),i(t)&&!n(this.node))throw new Exception("Element not in the dom")}catch(i){try{var e=this.clone(b.parser.draw.instance).show();t=e.node.getBBox(),e.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return new b.Box(t)},rbox:function(t){try{var e=new b.Box(this.node.getBoundingClientRect());return t?e.transform(t.screenCTM().inverse()):e.addOffset()}catch(t){return new b.Box}}}}),b.extend(b.Doc,b.Nested,b.Symbol,b.Image,b.Pattern,b.Marker,b.ForeignObject,b.View,{viewbox:function(t,e,i,n){return null==t?new b.Box(this.attr("viewBox")):this.attr("viewBox",new b.Box(t,e,i,n))}}),b});
diff --cc package.json
index 2296853b3a2f9940a813747bbcc13b38ee7067e3,68b937de97a897bc06ff282b701c2fbdfad3c870..78534094c1bce35116a3cd67102e0c2db36d7071
@@@ -1,6 -1,6 +1,6 @@@
  {
    "name": "svg.js",
-   "version": "2.5.0",
 -  "version": "2.6.0",
++  "version": "3.0.0",
    "description": "A lightweight library for manipulating and animating SVG.",
    "url": "https://svgdotjs.github.io/",
    "homepage": "https://svgdotjs.github.io/",
      "karma-jasmine": "^1.0.2",
      "karma-phantomjs-launcher": "^1.0.2",
      "request": "^2.78.0",
-     "standard": "^9.0.1"
 +    "snazzy": "^6.0.0",
++    "standard": "^9.0.1",
+     "svgdom": "latest"
 +  },
 +  "standard": {
 +    "ignore": [
 +      "/dist",
 +      "/src/umd.js"
 +    ],
 +    "globals": [
 +      "SVG"
 +    ]
    }
  }
index 6d0cc725590508ca4c2184f655614d3aefb8d29b,3093ad1448216c4bd5ef12a51426548afcb40532..0da16b059ad27c7811bca58fb70945cf62eb697b
    </svg>
  
    <!-- include spec files here... -->
-   <script src="spec/svg.js"></script>
-   <script src="spec/selector.js"></script>
    <script src="spec/adopter.js"></script>
-   <script src="spec/regex.js"></script>
-   <script src="spec/container.js"></script>
-   <script src="spec/element.js"></script>
-   <script src="spec/memory.js"></script>
    <script src="spec/arrange.js"></script>
-   <script src="spec/event.js"></script>
+   <script src="spec/array.js"></script>
+   <script src="spec/bare.js"></script>
    <script src="spec/boxes.js"></script>
-   <script src="spec/matrix.js"></script>
-   <script src="spec/transformations.js"></script>
-   <script src="spec/point.js"></script>
-   <script src="spec/rect.js"></script>
    <script src="spec/circle.js"></script>
+   <script src="spec/clip.js"></script>
+   <script src="spec/color.js"></script>
+   <script src="spec/container.js"></script>
+   <script src="spec/defs.js"></script>
+   <script src="spec/doc.js"></script>
+   <script src="spec/easing.js"></script>
+   <script src="spec/element.js"></script>
    <script src="spec/ellipse.js"></script>
+   <script src="spec/event.js"></script>
+   <script src="spec/fx.js"></script>
+   <script src="spec/gradient.js"></script>
+   <script src="spec/group.js"></script>
+   <script src="spec/helper.js"></script>
+   <script src="spec/hyperlink.js"></script>
+   <script src="spec/image.js"></script>
    <script src="spec/line.js"></script>
-   <script src="spec/polyline.js"></script>
-   <script src="spec/polygon.js"></script>
-   <script src="spec/path.js"></script>
    <script src="spec/marker.js"></script>
-   <script src="spec/image.js"></script>
-   <script src="spec/text.js"></script>
-   <script src="spec/span.js"></script>
-   <script src="spec/textpath.js"></script>
-   <script src="spec/doc.js"></script>
-   <script src="spec/defs.js"></script>
-   <script src="spec/nested.js"></script>
-   <script src="spec/group.js"></script>
-   <script src="spec/gradient.js"></script>
-   <script src="spec/pattern.js"></script>
-   <script src="spec/use.js"></script>
-   <script src="spec/bare.js"></script>
-   <script src="spec/symbol.js"></script>
    <script src="spec/mask.js"></script>
-   <script src="spec/clip.js"></script>
-   <script src="spec/color.js"></script>
+   <script src="spec/matrix.js"></script>
+   <script src="spec/memory.js"></script>
+   <script src="spec/nested.js"></script>
    <script src="spec/number.js"></script>
-   <script src="spec/array.js"></script>
-   <script src="spec/hyperlink.js"></script>
+   <script src="spec/path.js"></script>
+   <script src="spec/pattern.js"></script>
+   <script src="spec/point.js"></script>
+   <script src="spec/polygon.js"></script>
+   <script src="spec/polyline.js"></script>
+   <script src="spec/rect.js"></script>
+   <script src="spec/regex.js"></script>
+   <script src="spec/selector.js"></script>
 -  <script src="spec/set.js"></script>
    <script src="spec/sugar.js"></script>
-   <script src="spec/fx.js"></script>
+   <script src="spec/svg.js"></script>
+   <script src="spec/symbol.js"></script>
+   <script src="spec/text.js"></script>
+   <script src="spec/textpath.js"></script>
+   <script src="spec/transformations.js"></script>
+   <script src="spec/tspan.js"></script>
+   <script src="spec/use.js"></script>
    <script src="spec/utils.js"></script>
+   <script src="spec/viewbox.js"></script>
  
-   <script type="text/javascript" src="spec/helper.js"></script>
  </body>
  </html>
Simple merge
Simple merge
index a1fe91c8eb867bdc6e87171b5a6eb49bc22ed961,28f30dd98cec3b7874261a1615b65adf312d041a..70642f5f4b737f9f24b067549748f593c0afc21c
@@@ -147,10 -141,16 +142,10 @@@ describe('Element', function() 
      })
      it('sets multiple styles with an object as the first argument', function() {
        var rect = draw.rect(100,100).style({ cursor: 'help', display: 'block' })
-       expect(stripped(rect.node.style.cssText)).toMatch(/cursor:help;/)
-       expect(stripped(rect.node.style.cssText)).toMatch(/display:block;/)
-       expect(stripped(rect.node.style.cssText).length).toBe(('display:block;cursor:help;').length)
+       expect(window.stripped(rect.node.style.cssText)).toMatch(/cursor:help/)
+       expect(window.stripped(rect.node.style.cssText)).toMatch(/display:block/)
+       expect(window.stripped(rect.node.style.cssText).length).toBe(('display:block;cursor:help').length)
      })
 -    it('sets multiple styles with a css string as the first argument', function() {
 -      var rect = draw.rect(100,100).style('cursor: help; display: block;')
 -      expect(window.stripped(rect.node.style.cssText)).toMatch(/cursor:help/)
 -      expect(window.stripped(rect.node.style.cssText)).toMatch(/display:block/)
 -      expect(window.stripped(rect.node.style.cssText).length).toBe(('display:block;cursor:help').length)
 -    })
      it('gets a style with a string key as the fists argument', function() {
        var rect = draw.rect(100,100).style({ cursor: 'progress', display: 'block' })
        expect(rect.style('cursor')).toBe('progress')
        }))
      })
  
-     it('ungroups everything to the doc root when called on SVG.Doc / does not flatten defs', function() {
+     it('ungroups everything to the doc root when called on SVG.Doc / does not ungroup defs/parser', function() {
 -      draw.ungroup()
 +      draw.flatten()
        expect(rect1.parent()).toBe(draw)
        expect(rect2.parent()).toBe(draw)
  
index bc30845b855158edd0431d03943808c8e7066901,4b51a9b967d77b5be55a5ca71bbd4c9749794efd..f5de8939262a473f8b1cc1e15bef0c2c2909a096
@@@ -39,5 -50,177 +39,5 @@@ describe('Image', function() 
          url: jasmine.any(String)
        })
      })
 -    it('does not execute the error callback', function() {
 -      expect(errorCb).not.toHaveBeenCalled()
 -    })
 -  })
 -
 -  describe('error()', function() {
 -    beforeEach(function(done) {
 -      loadCb = jasmine.createSpy('loadCb')
 -      errorCb = {cb: function(){ done() }}
 -      spyOn(errorCb, 'cb').and.callThrough()
 -      image = draw.image('not_existant.jpg', 100, 100).loaded(loadCb).error(errorCb.cb)
 -    })
 -
 -    it('should set the error callback', function() {
 -      expect(image._error).toBe(errorCb.cb)
 -    })
 -    it('executes the error callback', function() {
 -      expect(errorCb.cb).toHaveBeenCalledWith(jasmine.any(window.Event))
 -    })
 -    it('does not execute the load callback', function() {
 -      expect(loadCb).not.toHaveBeenCalled()
 -    })
    })
- })
 -
 -
 -  describe('x()', function() {
 -    it('should return the value of x without an argument', function() {
 -      expect(image.x()).toBe(0)
 -    })
 -    it('should set the value of x with the first argument', function() {
 -      image.x(123)
 -      var box = image.bbox()
 -      expect(box.x).toBe(123)
 -    })
 -  })
 -
 -  describe('y()', function() {
 -    it('should return the value of y without an argument', function() {
 -      expect(image.y()).toBe(0)
 -    })
 -    it('should set the value of y with the first argument', function() {
 -      image.y(345)
 -      var box = image.bbox()
 -      expect(box.y).toBe(345)
 -    })
 -  })
 -
 -  describe('cx()', function() {
 -    it('should return the value of cx without an argument', function() {
 -      expect(image.cx()).toBe(50)
 -    })
 -    it('should set the value of cx with the first argument', function() {
 -      image.cx(123)
 -      var box = image.bbox()
 -      expect(box.cx).toBe(123)
 -    })
 -  })
 -
 -  describe('cy()', function() {
 -    it('should return the value of cy without an argument', function() {
 -      expect(image.cy()).toBe(50)
 -    })
 -    it('should set the value of cy with the first argument', function() {
 -      image.cy(345)
 -      var box = image.bbox()
 -      expect(box.cy).toBe(345)
 -    })
 -  })
 -
 -  describe('move()', function() {
 -    it('should set the x and y position', function() {
 -      image.move(123,456)
 -      expect(image.node.getAttribute('x')).toBe('123')
 -      expect(image.node.getAttribute('y')).toBe('456')
 -    })
 -  })
 -
 -  describe('dx()', function() {
 -    it('moves the x positon of the element relative to the current position', function() {
 -      image.move(50,60)
 -      image.dx(100)
 -      expect(image.node.getAttribute('x')).toBe('150')
 -    })
 -  })
 -
 -  describe('dy()', function() {
 -    it('moves the y positon of the element relative to the current position', function() {
 -      image.move(50,60)
 -      image.dy(120)
 -      expect(image.node.getAttribute('y')).toBe('180')
 -    })
 -  })
 -
 -  describe('dmove()', function() {
 -    it('moves the x and y positon of the element relative to the current position', function() {
 -      image.move(50,60)
 -      image.dmove(80, 25)
 -      expect(image.node.getAttribute('x')).toBe('130')
 -      expect(image.node.getAttribute('y')).toBe('85')
 -    })
 -  })
 -
 -  describe('center()', function() {
 -    it('should set the cx and cy position', function() {
 -      image.center(321,567)
 -      var box = image.bbox()
 -      expect(box.cx).toBe(321)
 -      expect(box.cy).toBe(567)
 -    })
 -  })
 -
 -  describe('width()', function() {
 -    it('sets the width of the element', function() {
 -      image.width(789)
 -      expect(image.node.getAttribute('width')).toBe('789')
 -    })
 -    it('gets the width of the element if the argument is null', function() {
 -      expect(image.width().toString()).toBe(image.node.getAttribute('width'))
 -    })
 -  })
 -
 -  describe('height()', function() {
 -    it('sets the height of the element', function() {
 -      image.height(1236)
 -      expect(image.node.getAttribute('height')).toBe('1236')
 -    })
 -    it('gets the height of the element if the argument is null', function() {
 -      expect(image.height().toString()).toBe(image.node.getAttribute('height'))
 -    })
 -  })
 -
 -  describe('size()', function() {
 -    it('should define the width and height of the element', function() {
 -      image.size(987,654)
 -      expect(image.node.getAttribute('width')).toBe('987')
 -      expect(image.node.getAttribute('height')).toBe('654')
 -    })
 -    it('defines the width and height proportionally with only the width value given', function() {
 -      var box = image.bbox()
 -      image.size(500)
 -      expect(image.width()).toBe(500)
 -      expect(image.width() / image.height()).toBe(box.width / box.height)
 -    })
 -    it('defines the width and height proportionally with only the height value given', function() {
 -      var box = image.bbox()
 -      image.size(null, 525)
 -      expect(image.height()).toBe(525)
 -      expect(image.width() / image.height()).toBe(box.width / box.height)
 -    })
 -  })
 -
 -  describe('scale()', function() {
 -    it('should scale the element universally with one argument', function() {
 -      var box = image.scale(2).rbox()
 -
 -      expect(box.width).toBe(image.attr('width') * 2)
 -      expect(box.height).toBe(image.attr('height') * 2)
 -    })
 -    it('should scale the element over individual x and y axes with two arguments', function() {
 -      var box = image.scale(2, 3.5).rbox()
 -
 -      expect(box.width).toBe(image.attr('width') * 2)
 -      expect(box.height).toBe(image.attr('height') * 3.5)
 -    })
 -  })
 -
 -  describe('translate()', function() {
 -    it('should set the translation of an element', function() {
 -      image.transform({ x: 12, y: 12 })
 -      expect(image.node.getAttribute('transform')).toBe('matrix(1,0,0,1,12,12)')
 -    })
 -  })
 -
+ })
Simple merge
index 0fa699a3c1fb515acc9893829404726c2413ec73,7738b0e58a73525e0d02ff7dcfb307ee7fa88944..35f42e82b050eb55e7e6f16905ccf1ae0148929d
@@@ -82,28 -90,26 +90,25 @@@ describe('SVG', function() 
        expect(typeof SVG.Bogus).toBe('undefined')
      })
    })
-   
    describe('prepare()', function() {
      var drawing, wrapper, parser
-   
      beforeEach(function() {
-       wrapper = document.createElement('div')
-       document.getElementsByTagName('body')[0].appendChild(wrapper)
+       wrapper = document.createElement('svg')
+       document.documentElement.appendChild(wrapper)
        drawing = SVG(wrapper)
-       
-       parser = document.getElementsByTagName('body')[0].lastChild
      })
-   
      it('creates a parser element when calling SVG()', function() {
-       expect(SVG.parser.draw.node.nodeName).toBe('svg')
+       expect(SVG.parser.draw.nodeName).toBe('svg')
      })
      it('hides the parser', function() {
-       expect(SVG.parser.draw.node.getAttribute('style')).toBe('opacity: 0; position: absolute; left: -100%; top: -100%; overflow: hidden;')
 -      expect(window.stripped(SVG.parser.draw.getAttribute('style'))).toBe('overflow:hidden;top:-100%;left:-100%;position:absolute;opacity:0')
++      expect(window.stripped(SVG.parser.draw.getAttribute('style'))).toBe('opacity:0;position:absolute;left:-100%;top:-100%;overflow:hidden')
      })
      it('holds polyline and path', function() {
 -      expect(SVG.select('polyline', SVG.parser.draw).first().type).toBe('polyline')
 -      expect(SVG.select('path', SVG.parser.draw).first().type).toBe('path')
 +      expect(SVG.select('polyline', SVG.parser.draw.node)[0].type).toBe('polyline')
 +      expect(SVG.select('path', SVG.parser.draw.node)[0].type).toBe('path')
      })
    })
-   
 -
--})
++})
Simple merge
diff --cc src/boxes.js
index 5ab261a9307604b5a8649f976e641be4dc31896d,4a3af8e9d4049d4b070e4885037441edabf180b2..ce9dc486725628932bd386f98c224f6419af7c38
@@@ -50,64 -45,57 +50,63 @@@ SVG.Box = SVG.invent(
          yMax = Math.max(yMax,p.y)
        })
  
 -      bbox = new this.constructor()
 -      bbox.x = xMin
 -      bbox.width = xMax-xMin
 -      bbox.y = yMin
 -      bbox.height = yMax-yMin
 +      return new SVG.Box(
 +        xMin, yMin,
 +        xMax-xMin,
 +        yMax-yMin
 +      )
 +    }
  
 -      fullBox(bbox)
 +  , addOffset: function() {
 +      // offset by window scroll position, because getBoundingClientRect changes when window is scrolled
 +      this.x += window.pageXOffset
 +      this.y += window.pageYOffset
 +      return this
 +    }
 +  , toString: function() {
 +      return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height
 +    }
 +  , morph: function(x, y, width, height){
 +      this.destination = new SVG.Box(x, y, width, height)
 +      return this
 +    }
 +
 +  , at: function(pos) {
 +      if(!this.destination) return this
 +
 +      return new SVG.Box(
 +          this.x + (this.destination.x - this.x) * pos
 +        , this.y + (this.destination.y - this.y) * pos
 +        , this.width + (this.destination.width - this.width) * pos
 +        , this.height + (this.destination.height - this.height) * pos
 +      )
  
 -      return bbox
      }
    }
 -})
  
 -SVG.BBox = SVG.invent({
 -  // Initialize
 -  create: function(element) {
 -    SVG.Box.apply(this, [].slice.call(arguments))
 +    // Define Parent
 +, parent: SVG.Element
  
 -    // get values if element is given
 -    if (element instanceof SVG.Element) {
 +  // Constructor
 +, construct: {
 +    // Get bounding box
 +    bbox: function() {
        var box
  
 -      // yes this is ugly, but Firefox can be a bitch when it comes to elements that are not yet rendered
        try {
 +        // find native bbox
 +        box = this.node.getBBox()
  
 -        if (!document.documentElement.contains){
 -          // This is IE - it does not support contains() for top-level SVGs
 -          var topParent = element.node
 -          while (topParent.parentNode){
 -            topParent = topParent.parentNode
 -          }
 -          if (topParent != document) throw new Exception('Element not in the dom')
 -        } else {
 -          // the element is NOT in the dom, throw error
 -          if(!document.documentElement.contains(element.node)) throw new Exception('Element not in the dom')
 +        if(isNulledBox(box) && !domContains(this.node)) {
 +          throw new Exception('Element not in the dom')
          }
 -
 -        // find native bbox
 -        box = element.node.getBBox()
        } catch(e) {
 -        if(element instanceof SVG.Shape){
 -          var clone = element.clone(SVG.parser.draw.instance).show()
 +        try {
-           var clone = this.clone(SVG.parser.draw).show()
++          var clone = this.clone(SVG.parser.draw.instance).show()
            box = clone.node.getBBox()
            clone.remove()
 -        }else{
 -          box = {
 -            x:      element.node.clientLeft
 -          , y:      element.node.clientTop
 -          , width:  element.node.clientWidth
 -          , height: element.node.clientHeight
 -          }
 +        } catch(e) {
 +          console.warn('Getting a bounding box of this element is not possible')
          }
        }
  
diff --cc src/fx.js
Simple merge
diff --cc src/svg.js
index c5bc069bf741d0f14790688f8d94381cb392693c,ee8832e1825e2f90f7453c5f413a689616ea5955..775b6fa2b589efbc58c2ac600b4d6ae32dfc0562
@@@ -131,13 -135,7 +131,13 @@@ SVG.prepare = function() 
    // Create parser object
    SVG.parser = {
      body: body || document.documentElement
 -  , draw: draw.style('opacity:0;position:absolute;left:-100%;top:-100%;overflow:hidden').node
 +  , draw: draw.style({
 +      opacity:0,
 +      position:'absolute',
 +      left:'-100%',
 +      top:'-100%',
 +      overflow:'hidden'
-     })
++    }).node
    , poly: draw.polyline().node
    , path: draw.path().node
    , native: SVG.create('svg')