]> source.dussan.org Git - svg.js.git/commitdiff
Bumped to v0.9, added better style management, text support and extended animation... 0.10
authorwout <wout@impinc.co.uk>
Sat, 9 Mar 2013 21:28:47 +0000 (22:28 +0100)
committerwout <wout@impinc.co.uk>
Sat, 9 Mar 2013 21:28:47 +0000 (22:28 +0100)
26 files changed:
README.md
Rakefile
dist/svg.js
dist/svg.min.js
package.json [new file with mode: 0644]
src/arrange.js
src/bbox.js
src/color.js
src/doc.js
src/element.js
src/ellipse.js
src/event.js
src/fx.js
src/gradient.js
src/line.js
src/nested.js
src/path.js
src/pattern.js
src/poly.js
src/rect.js
src/regex.js
src/shape.js
src/sugar.js
src/svg.js
src/text.js
src/wrap.js

index 228aedd88551cd20d1d09cf3d6458c93fc7a4e34..5092b1bcdfd5fdf5b79b6101e3e7f8c9eed8a6d2 100644 (file)
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 A lightweight library for manipulating and animating SVG.
 
-Svg.js has no dependencies and aims to be as small as possible. The base library is 3k gzipped, with all bells and whistles about 5k.
+Svg.js has no dependencies and aims to be as small as possible. The base library is 3k gzipped, with all bells and whistles about 6.5k.
 
 Svg.js is licensed under the terms of the MIT License.
 
@@ -12,27 +12,27 @@ See [svgjs.com](http://svgjs.com) for an introduction, [documentation](http://sv
 
 ### Create a SVG document
 
-Use the `svg()` function to create a SVG document within a given html element:
+Use the `SVG()` function to create a SVG document within a given html element:
 
 ```javascript
-var draw = svg('paper').size(300, 300)
+var draw = SVG('canvas').size(300, 300)
 var rect = draw.rect(100, 100).attr({ fill: '#f06' })
 ```
 The first argument can either be an id of the element or the selected element itself.
 This will generate the following output:
 
 ```html
-<div id="paper">
+<div id="canvas">
        <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xlink="http://www.w3.org/1999/xlink" width="300" height="300">
                <rect width="100" height="100" fill="#f06"></rect>
        </svg>
 </div>
 ```
 
-By default the svg canvas follows the dimensions of its parent, in this case `#paper`:
+By default the svg canvas follows the dimensions of its parent, in this case `#canvas`:
 
 ```javascript
-var draw = svg('paper').size('100%', '100%')
+var draw = SVG('canvas').size('100%', '100%')
 ```
 
 ### Checking for SVG support
@@ -41,7 +41,7 @@ By default this library assumes the client's browser supports SVG. You can test
 
 ```javascript
 if (SVG.supported) {
-  var draw = svg('paper')
+  var draw = SVG('canvas')
   var rect = draw.rect(100, 100)
 } else {
   alert('SVG not supported')
@@ -71,6 +71,19 @@ var zoom = box.zoom
 
 If the size of the viewbox equals the size of the svg canvas, the zoom value will be 1.
 
+### Nested svg
+With this feature you can nest svg documents within each other. Nested svg documents have exactly the same features as the main, top-level svg document:
+
+```javascript
+var nested = draw.nested()
+
+var rect = nested.rect(200, 200)
+```
+
+
+_This functionality requires the nested.js module which is included in the default distribution._
+
+
 ## Elements
 
 ### Rect
@@ -240,11 +253,45 @@ rect.transform({
 Important: matrix transformations are not yet supported.
 
 
+### Style
+With the `style()` method the `style` attribute can be managed like attributes with `attr`:
+
+```javascript
+rect.style('cursor', 'pointer')
+```
+
+Multiple styles can be set at once using an object:
+
+```javascript
+rect.style({ cursor: 'pointer', fill: '#f03' })
+```
+
+Or a css string:
+
+```javascript
+rect.style('cursor:pointer;fill:#f03;')
+```
+
+Similarly to `attr()` the `style()` method can also act as a getter:
+
+```javascript
+rect.style('cursor')
+// => pointer
+```
+
+Or even a full getter:
+
+```javascript
+rect.style()
+// => 'cursor:pointer;fill:#f03;'
+```
+
+
 ### Move 
 Move the element to a given `x` and `y` position by its upper left corner:
 
 ```javascript
-rect.move(200, 350);
+rect.move(200, 350)
 ```
 
 Note that you can also use the following code to move elements around:
@@ -647,20 +694,6 @@ group.add(rect)
 _This functionality requires the group.js module which is included in the default distribution._
 
 
-
-## Nested svg
-With this feature you can nest svg documents within each other. Nested svg documents have exactly the same features as the main, top-level svg document:
-
-```javascript
-var nested = draw.nested()
-
-var rect = nested.rect(200, 200)
-```
-
-
-_This functionality requires the nested.js module which is included in the default distribution._
-
-
 ## Gradients
 
 There are linear and radial gradients. The linear gradient can be created like this:
@@ -932,8 +965,6 @@ _The Rakefile has been borrowed from [madrobby's](https://github.com/madrobby) [
 ## To-do
 - Instance module
 - Text on path module (write text along paths)
-- Dynamic css styles
-- Animatable unit values (e.g. '100%' or '30mm')
 
 
 ## Compatibility
index acda198c953001610a422f0a129206691f293c9b..5e32183f8d350ca53d036d0801bae33b41d2d773 100644 (file)
--- a/Rakefile
+++ b/Rakefile
@@ -1,4 +1,4 @@
-SVGJS_VERSION = '0.8'
+SVGJS_VERSION = '0.9'
 
 # all available modules in the correct loading order
 MODULES = %w[ svg regex color viewbox bbox element container fx event group arrange defs mask pattern gradient doc shape wrap rect ellipse line poly path image text nested sugar ]
@@ -53,12 +53,13 @@ BuildTask.define_task 'dist/svg.js' => MODULES.map {|m| "src/#{ m }.js" } do |ta
   
   File.open(task.name, 'w') do |file|
     file.puts "/* svg.js %s - %s - svgjs.com/license */" % [version_string, task.modules.join(' ')]
-
-    file.puts '(function() {'
+  
+    file.puts ';(function() {'
     file.puts "\n"
     file.puts svgjs
     file.puts '}).call(this);'
   end
+  
 end
 
 file 'dist/svg.min.js' => 'dist/svg.js' do |task|
index 7cec3bd66bf2f6982017dbbf3236eac0ea67e6d1..f3a0b84201b0028223986057843bf6229f26f332 100644 (file)
@@ -1,50 +1,54 @@
-/* svg.js v0.8-5-g5e3ff07 - svg regex color viewbox bbox element container fx event group arrange defs mask pattern gradient doc shape wrap rect ellipse line poly path image text nested sugar - svgjs.com/license */
-(function() {
+/* svg.js v0.9 - svg regex color viewbox bbox element container fx event group arrange defs mask pattern gradient doc shape wrap rect ellipse line poly path image text nested sugar - svgjs.com/license */
+;(function() {
 
-  this.svg = function(element) {
+  this.SVG = function(element) {
     if (SVG.supported)
       return new SVG.Doc(element)
   }
   
-  // The main wrapping element
-  this.SVG = {
-    /* default namespaces */
-    ns:    'http://www.w3.org/2000/svg'
-  , xlink: 'http://www.w3.org/1999/xlink'
+  // DEPRECATED!!! Use SVG() instead
+  this.svg = function(element) {
+    console.warn('WARNING: svg() is deprecated, please use SVG() instead.')
+    return SVG(element)
+  }
+  
+  // Default namespaces
+  SVG.ns = 'http://www.w3.org/2000/svg'
+  SVG.xlink = 'http://www.w3.org/1999/xlink'
+  
+  // Element id sequence
+  SVG.did  = 1000
+  
+  // Get next named element id
+  SVG.eid = function(name) {
+    return 'Svgjs' + name.charAt(0).toUpperCase() + name.slice(1) + 'Element' + (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))
     
-    /* element id sequence */
-  , did: 1000
+    return element
+  }
   
-    // Get next named element id
-  , eid: function(name) {
-      return 'Svgjs' + name.charAt(0).toUpperCase() + name.slice(1) + 'Element' + (SVG.did++)
-    }
-    // Method for element creation
-  , 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
-  , extend: function() {
-      var modules, methods, key, i
-      
-      /* get list of modules */
-      modules = Array.prototype.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]
-    }
+  SVG.extend = function() {
+    var modules, methods, key, i
+    
+    /* get list of modules */
+    modules = Array.prototype.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]
   }
   
   // svg support test
            !! document.createElementNS(SVG.ns,'svg').createSVGRect
   })()
   
-  if (!SVG.supported) return false;
+  if (!SVG.supported) return false
 
   SVG.regex = {
+    /* parse unit value */
+    unit:     /^([\d\.]+)([a-z%]{0,2})$/
     
-    unit:   /^([\d\.]+)([a-z%]{0,2})$/
+    /* parse hex value */
+  , hex:      /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i
     
-  , hex:    /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i
-  
-  , rgb:    /rgb\((\d+),(\d+),(\d+),([\d\.]+)\)/
-  
-  , hsb:    /hsb\((\d+),(\d+),(\d+),([\d\.]+)\)/
-  
-  , isHex:  /^#/i
-  
-  , isRgb:  /^rgb\(/
+    /* parse rgb value */
+  , rgb:      /rgb\((\d+),(\d+),(\d+),([\d\.]+)\)/
+    
+    /* parse hsb value */
+  , hsb:      /hsb\((\d+),(\d+),(\d+),([\d\.]+)\)/
+    
+    /* test hex value */
+  , isHex:    /^#[a-f0-9]{3,6}$/i
+    
+    /* test rgb value */
+  , isRgb:    /^rgb\(/
     
-  , isHsb:  /^hsb\(/
+    /* test hsb value */
+  , isHsb:    /^hsb\(/
     
+    /* test css declaration */
+  , isCss:    /[^:]+:[^;]+;?/
+    
+    /* test css property */
+  , isStyle:  /^font|text|leading|cursor/
+    
+    /* test for blank string */
+  , isBlank:  /^(\s+)?$/
+  
   }
 
   SVG.Color = function(color) {
       this.r = color.r
       this.g = color.g
       this.b = color.b
-      
     }
       
   }
     this.y = box.y + element.trans.y
     
     /* add the center */
-    this.cx = box.x + element.trans.x + box.width  / 2
+    this.cx = box.x + element.trans.x + box.width / 2
     this.cy = box.y + element.trans.y + box.height / 2
     
     /* plain width and height */
     }
     
     /* initialize style store */
-    this.style = {}
+    this.styles = {}
     
     /* initialize transformation store with defaults */
     this.trans = {
   , remove: function() {
       if (this.parent)
         this.parent.remove(this)
+      
       return this
     }
     // Get parent document
       if (arguments.length < 2) {
         /* apply every attribute individually if an object is passed */
         if (typeof a == 'object')
-          for (v in a) this.attr(v, a[v])
+          for (v in a)
+            this.attr(v, a[v])
         
         /* act as a getter for style attributes */
         else if (this._isStyle(a))
           return a == 'text' ?
                    this.content :
                  a == 'leading' ?
-                   this[a] :
-                   this.style[a]
+                   this.leading() :
+                   this.style(a)
         
         /* act as a getter if the first and only argument is not an object */
         else
-          return this.attrs[a]
+          return this.attrs[a] || this.node.getAttribute(a)
       
       } else if (v === null) {
         /* remove value */
         this.node.removeAttribute(a)
         
+      } else if (a == 'style') {
+        /* redirect to the style method */
+        return this.style(v)
+        
       } else {
         /* store value */
         this.attrs[a] = v
           a == 'text' ?
             this.text(v) :
           a == 'leading' ?
-            this[a] = v :
-            this.style[a] = v
-        
-          this.text(this.content)
+            this.leading(v) :
+            this.style(a, v)
+          
+          /* rebuild if required */
+          if (this.rebuild)
+            this.rebuild()
         }
       }
       
       return this
     }
     // Manage transformations
-  , transform: function(o) {
-      /* act as a getter if the first argument is a string */
-      if (typeof o === 'string')
-        return this.trans[o]
+  , transform: function(o, v) {
+      if (typeof o === 'string') {
+        /* act as a getter if only one string argument is given */
+        if (arguments.length < 2)
+          return this.trans[o]
         
+        /* apply transformations as object if key value arguments are given*/
+        var transform = {}
+        transform[o] = v
+        
+        return this.transform(transform)
+      }
+      
       /* ... otherwise continue as a setter */
-      var key, transform = []
+      var transform = []
       
       /* merge values */
-      for (key in o)
-        if (o[key] != null)
-          this.trans[key] = o[key]
+      for (v in o)
+        if (o[v] != null)
+          this.trans[v] = o[v]
       
       /* alias current transformations */
       o = this.trans
       /* add only te required transformations */
       return this.attr('transform', transform.join(' '))
     }
+    // Dynamic style generator
+  , style: function(s, v) {
+      if (arguments.length == 0) {
+        /* get full style */
+        return this.attr('style')
+      
+      } 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 if (SVG.regex.isCss.test(s)) {
+          /* parse css string */
+          s = s.split(';')
+  
+          /* apply every definition individually */
+          for (var i = 0; i < s.length; i++) {
+            v = s[i].split(':')
+  
+            if (v.length == 2)
+              this.style(v[0].replace(/\s+/g, ''), v[1].replace(/^\s+/,'').replace(/\s+$/,''))
+          }
+        } else {
+          /* act as a getter if the first and only argument is not an object */
+          return this.styles[s]
+        }
+      
+      } else if (v === null) {
+        /* remove value */
+        delete this.styles[s]
+        
+      } else {
+        /* store value */
+        this.styles[s] = v
+      }
+      
+      /* rebuild style string */
+      s = ''
+      for (v in this.styles)
+        s += v + ':' + this.styles[v] + ';'
+      
+      /* apply style */
+      this.node.setAttribute('style', s)
+      
+      return this
+    }
     // Store data values on svg nodes
   , data: function(a, v, r) {
       if (arguments.length < 2) {
     }
     // Show element
   , show: function() {
-      this.node.style.display = ''
-      
-      return this
+      return this.style('display', '')
     }
     // Hide element
   , hide: function() {
-      this.node.style.display = 'none'
-      
-      return this
+      return this.style('display', 'none')
     }
     // Is element visible?
   , visible: function() {
-      return this.node.style.display != 'none'
+      return this.style('display') != 'none'
     }
     // Private: find svg parent by instance
   , _parent: function(parent) {
     }
     // Private: tester method for style detection
   , _isStyle: function(attr) {
-      return typeof attr == 'string' && this._isText() ? (/^font|text|leading/).test(attr) : false
+      return typeof attr == 'string' ? SVG.regex.isStyle.test(attr) : false
     }
     // Private: element type tester
   , _isText: function() {
       duration = duration == null ? 1000 : duration
       ease = ease || '<>'
       
-      var akeys, tkeys, tvalues
+      var akeys, tkeys, skeys
         , element   = this.target
         , fx        = this
         , start     = new Date().getTime()
       /* start animation */
       this.interval = setInterval(function(){
         // This code was borrowed from the emile.js micro framework by Thomas Fuchs, aka MadRobby.
-        var index
+        var i, key
           , time = new Date().getTime()
           , pos = time > finish ? 1 : (time - start) / duration
         
         /* collect attribute keys */
         if (akeys == null) {
           akeys = []
-          for (var key in fx.attrs)
+          for (key in fx.attrs)
             akeys.push(key)
         }
         
         /* collect transformation keys */
         if (tkeys == null) {
           tkeys = []
-          for (var key in fx.trans)
+          for (key in fx.trans)
             tkeys.push(key)
-          
-          tvalues = {}
+        }
+        
+        /* collect style keys */
+        if (skeys == null) {
+          skeys = []
+          for (key in fx.styles)
+            skeys.push(key)
         }
         
         /* apply easing */
         if (fx._move)
           element.move(fx._at(fx._move.x, pos), fx._at(fx._move.y, pos))
         else if (fx._center)
-          element.move(fx._at(fx._center.x, pos), fx._at(fx._center.y, pos))
+          element.center(fx._at(fx._center.x, pos), fx._at(fx._center.y, pos))
         
         /* run all size properties */
         if (fx._size)
           element.size(fx._at(fx._size.width, pos), fx._at(fx._size.height, pos))
         
         /* animate attributes */
-        for (index = akeys.length - 1; index >= 0; index--)
-          element.attr(akeys[index], fx._at(fx.attrs[akeys[index]], pos))
+        for (i = akeys.length - 1; i >= 0; i--)
+          element.attr(akeys[i], fx._at(fx.attrs[akeys[i]], pos))
         
         /* animate transformations */
-        if (tkeys.length > 0) {
-          for (index = tkeys.length - 1; index >= 0; index--)
-            tvalues[tkeys[index]] = fx._at(fx.trans[tkeys[index]], pos)
-          
-          element.transform(tvalues)
-        }
+        for (i = tkeys.length - 1; i >= 0; i--)
+          element.transform(tkeys[i], fx._at(fx.trans[tkeys[i]], pos))
+        
+        /* animate styles */
+        for (i = skeys.length - 1; i >= 0; i--)
+          element.style(skeys[i], fx._at(fx.styles[skeys[i]], pos))
         
         /* callback for each keyframe */
         if (fx._during)
       else
         this.attrs[a] = { from: this.target.attr(a), to: v }
       
-      return this;  
+      return this
     }
     // Add animatable transformations
-  , transform: function(o) {
-      for (var key in o)
-        this.trans[key] = { from: this.target.trans[key], to: o[key] }
+  , transform: function(t, v) {
+      for (var key in t)
+        this.trans[key] = { from: this.target.trans[key], to: t[key] }
+      
+      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.styles[s] = { from: this.target.style(s), to: v }
       
       return this
     }
     }
     // Add animatable size
   , size: function(width, height) {
-      var box = this.target.bbox()
-      
-      this._size = {
-        width:  { from: box.width,  to: width  }
-      , height: { from: box.height, to: 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 = this.target.bbox()
+  
+        this._size = {
+          width:  { from: box.width,  to: width  }
+        , height: { from: box.height, to: height }
+        }
       }
       
       return this
       /* reset storage for properties that need animation */
       this.attrs    = {}
       this.trans    = {}
+      this.styles   = {}
       this._move    = null
       this._size    = null
       this._after   = null
   //     })
 
 
-  ;[ 'click',
-    'dblclick',
-    'mousedown',
-    'mouseup',
-    'mouseover',
-    'mouseout',
-    'mousemove',
-    'mouseenter',
-    'mouseleave',
-    'touchstart',
-    'touchend',
-    'touchmove',
-    'touchcancel' ].forEach(function(event) {
+  ;[ 'click'
+  , 'dblclick'
+  , 'mousedown'
+  , 'mouseup'
+  , 'mouseover'
+  , 'mouseout'
+  , 'mousemove'
+  , 'mouseenter'
+  , 'mouseleave'
+  , 'touchstart'
+  , 'touchend'
+  , 'touchmove'
+  , '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
+      this.node['on' + event] = typeof f == 'function' ?
+        function() { return f.apply(self, arguments) } : null
       
       return this
     }
       SVG.on(this.node, event, listener)
       
       return this
-    },
+    }
     // Unbind event from listener
-    off: function(event, listener) {
+  , off: function(event, listener) {
       SVG.off(this.node, event, listener)
       
       return this
     }
-  });
+  })
 
   SVG.G = function() {
     this.constructor.call(this, SVG.create('g'))
     }
     // Send given element one step backward
   , backward: function() {
-      var i
-      
       this.parent.level()
       
-      i = this.position()
+      var i = this.position()
       
       if (i > 1)
         this.parent.remove(this).add(this, i - 1)
       block(element)
       
       return element.attr({
-        x:            0,
-        y:            0,
-        width:        width,
-        height:       height,
-        patternUnits: 'userSpaceOnUse'
+        x:            0
+      , y:            0
+      , width:        width
+      , height:       height
+      , patternUnits: 'userSpaceOnUse'
       })
     }
     
       return this.type == 'radial' ?
         this.attr({ fx: x + '%', fy: y + '%' }) :
         this.attr({ x1: x + '%', y1: y + '%' })
-    },
+    }
     // To position
-    to: function(x, y) {
+  , to: function(x, y) {
       return this.type == 'radial' ?
         this.attr({ cx: x + '%', cy: y + '%' }) :
         this.attr({ x2: x + '%', y2: y + '%' })
-    },
+    }
     // Radius for radial gradient
-    radius: function(radius) {
+  , radius: function(radius) {
       return this.type == 'radial' ?
         this.attr({ r: radius + '%' }) :
         this
-    },
+    }
     // Add a color stop
-    at: function(stop) {
+  , at: function(stop) {
       return this.put(new SVG.Stop(stop))
-    },
+    }
     // Update gradient
-    update: function(block) {
+  , update: function(block) {
       /* remove all stops */
       while (this.node.hasChildNodes())
         this.node.removeChild(this.node.lastChild)
       block(this)
       
       return this
-    },
+    }
     // Return the fill id
-    fill: function() {
+  , fill: function() {
       return 'url(#' + this.attr('id') + ')'
     }
     
     
     /* add color stops */
     update: function(o) {
-      var index,
-          style = '',
-          attr  = ['opacity', 'color']
+      var index
+        , attr = ['opacity', 'color']
       
       /* build style attribute */
       for (index = attr.length - 1; index >= 0; index--)
         if (o[attr[index]] != null)
-          style += 'stop-' + attr[index] + ':' + o[attr[index]] + ';'
+          this.style('stop-' + attr[index], o[attr[index]])
       
       /* set attributes */
-      return this.attr({
-        offset: (o.offset != null ? o.offset : this.attrs.offset || 0) + '%',
-        style:  style
-      })
+      return this.attr('offset', (o.offset != null ? o.offset : this.attrs.offset || 0) + '%')
     }
     
   })
   // Basically it sets the position of the svg node to absolute
   // when the dom is loaded, and resets it to relative a few milliseconds later.
   SVG.Doc.prototype.stage = function() {
-    var check,
-        element = this,
-        wrapper = document.createElement('div')
+    var check
+      , element = this
+      , wrapper = document.createElement('div')
     
     /* set temp wrapper to position relative */
     wrapper.style.cssText = 'position:relative;height:100%;'
     /* check for dom:ready */
     check = function() {
       if (document.readyState === 'complete') {
-        element.attr('style', 'position:absolute;')
+        element.style('position:absolute;')
         setTimeout(function() {
           /* set position back to relative */
-          element.attr('style', 'position:relative;')
+          element.style('position:relative;')
           
           /* remove temp wrapper */
           element.parent.removeChild(element.node.parentNode)
   }
   
   // Inherit from SVG.Element
-  SVG.Shape.prototype = new SVG.Element()
+  SVG.Shape.prototype = new SVG.Element
 
   SVG.Wrap = function(element) {
     this.constructor.call(this, SVG.create('g'))
     // Move wrapper around
     move: function(x, y) {
       return this.transform({
-        x: x,
-        y: y
+        x: x
+      , y: y
       })
-    },
+    }
     // Set the actual size in pixels
-    size: function(width, height) {
+  , size: function(width, height) {
       var scale = width / this._b.width
       
       this.child.transform({
-        scaleX: scale,
-        scaleY: height != null ? height / this._b.height : scale
+        scaleX: scale
+      , scaleY: height != null ? height / this._b.height : scale
       })
   
       return this
-    },
+    }
     // Move by center
-    center: function(x, y) {
+  , center: function(x, y) {
       return this.move(
-        x + (this._b.width  * this.child.trans.scaleX) / -2,
-        y + (this._b.height * this.child.trans.scaleY) / -2
+        x + (this._b.width  * this.child.trans.scaleX) / -2
+      , y + (this._b.height * this.child.trans.scaleY) / -2
       )
-    },
+    }
     // Create distributed attr
-    attr: function(a, v, n) {
+  , attr: function(a, v, n) {
       /* call individual attributes if an object is given */
       if (typeof a == 'object') {
         for (v in a) this.attr(v, a[v])
       }
       
       return this
-    },
+    }
     // Distribute plot method to child
-    plot: function(data) {
+  , plot: function(data) {
       /* plot new shape */
       this.child.plot(data)
       
       
       /* reposition element withing wrapper */
       this.child.transform({
-        x: -this._b.x,
-        y: -this._b.y
+        x: -this._b.x
+      , y: -this._b.y
       })
       
       return this
   }
   
   // Inherit from SVG.Shape
-  SVG.Rect.prototype = new SVG.Shape()
+  SVG.Rect.prototype = new SVG.Shape
 
   SVG.Ellipse = function() {
     this.constructor.call(this, SVG.create('ellipse'))
     },
     // Custom size function
     size: function(width, height) {
-      return this.
-        attr({ rx: width / 2, ry: (height != null ? height : width) / 2 }).
-        center()
+      return this
+       .attr({ rx: width / 2, ry: (height != null ? height : width) / 2 })
+       .center()
     },
     // Custom center function
     center: function(x, y) {
       return this.attr({
-        cx: x || (this.attrs.x || 0) + (this.attrs.rx || 0),
-        cy: y || (this.attrs.y || 0) + (this.attrs.ry || 0)
+        cx: x != null ? x : (this.attrs.x || 0) + (this.attrs.rx || 0)
+      , cy: y != null ? y : (this.attrs.y || 0) + (this.attrs.ry || 0)
       })
     }
     
       var bbox = this.bbox()
       
       return this.attr({
-        x1: this.attr('x1') - bbox.x + x,
-        y1: this.attr('y1') - bbox.y + y,
-        x2: this.attr('x2') - bbox.x + x,
-        y2: this.attr('y2') - bbox.y + y
+        x1: this.attr('x1') - bbox.x + x
+      , y1: this.attr('y1') - bbox.y + y
+      , x2: this.attr('x2') - bbox.x + x
+      , y2: this.attr('y2') - bbox.y + y
       })
-    },
+    }
     // Move element by its center
-    center: function(x, y) {
+  , center: function(x, y) {
       var bbox = this.bbox()
       
       return this.move(x - bbox.width / 2, y - bbox.height / 2)
-    },
+    }
     // Set line size by width and height
-    size: function(width, height) {
+  , size: function(width, height) {
       var bbox = this.bbox()
       
-      this.attr(this.attr('x1') < this.attr('x2') ? 'x2' : 'x1', bbox.x + width)
-      return this.attr(this.attr('y1') < this.attr('y2') ? 'y2' : 'y1', bbox.y + height)
+      return this
+        .attr(this.attr('x1') < this.attr('x2') ? 'x2' : 'x1', bbox.x + width)
+        .attr(this.attr('y1') < this.attr('y2') ? 'y2' : 'y1', bbox.y + height)
     }
   })
   
   SVG.extend(SVG.Container, {
     line: function(x1, y1, x2, y2) {
       return this.put(new SVG.Line().attr({
-        x1: x1,
-        y1: y1,
-        x2: x2,
-        y2: y2
+        x1: x1
+      , y1: y1
+      , x2: x2
+      , y2: y2
       }))
     }
   })
   }
   
   // Inherit from SVG.Shape
-  SVG.Polyline.prototype = new SVG.Shape()
+  SVG.Polyline.prototype = new SVG.Shape
   
   // Add polygon-specific functions
   SVG.extend(SVG.Polyline, SVG.Poly)
   }
   
   // Inherit from SVG.Shape
-  SVG.Polygon.prototype = new SVG.Shape()
+  SVG.Polygon.prototype = new SVG.Shape
   
   // Add polygon-specific functions
   SVG.extend(SVG.Polygon, SVG.Poly)
   SVG.Path.prototype = new SVG.Shape()
   
   SVG.extend(SVG.Path, {
-    
-    /* move using transform */
+    // Move using transform
     move: function(x, y) {
       this.transform({
         x: x,
         y: y
       })
-    },
+    }
     
-    /* set path data */
-    plot: function(data) {
+    // Set path data
+  , plot: function(data) {
       return this.attr('d', data || 'M0,0')
     }
     
-  });
+  })
 
   SVG.Image = function() {
     this.constructor.call(this, SVG.create('image'))
     
   })
 
-  var _styleAttr = ['size', 'family', 'weight', 'stretch', 'variant', 'style']
+  var _styleAttr = ('size family weight stretch variant style').split(' ')
   
   SVG.Text = function() {
     this.constructor.call(this, SVG.create('text'))
     
     /* define default style */
-    this.style = { 'font-size':  16, 'font-family': 'Helvetica', 'text-anchor': 'start' }
-    this.leading = 1.2
+    this.styles = {
+      'font-size':    16
+    , 'font-family':  'Helvetica'
+    , 'text-anchor':  'start'
+    }
+    
+    this._leading = 1.2
   }
   
   // Inherit from SVG.Element
-  SVG.Text.prototype = new SVG.Shape()
+  SVG.Text.prototype = new SVG.Shape
   
   SVG.extend(SVG.Text, {
     // Set the text content
     text: function(text) {
-      /* update the content */
-      this.content = text = text || 'text'
-      this.lines = []
+      /* act as getter */
+      if (text == null)
+        return this.content
       
-      var index, length, tspan,
-          style   = this._style(),
-          parent  = this.doc(),
-          lines   = text.split("\n"),
-          size    = this.style['font-size']
+      /* remove existing lines */
+      this.clear()
       
-      /* remove existing child nodes */
-      while (this.node.hasChildNodes())
-        this.node.removeChild(this.node.lastChild)
+      /* update the content */
+      this.content = SVG.regex.isBlank.test(text) ? 'text' : text
+      
+      var i, il
+        , lines = text.split('\n')
       
       /* build new lines */
-      for (index = 0, length = lines.length; index < length; index++) {
-        /* create new tspan and set attributes */
-        tspan = new SVG.TSpan().
-          text(lines[index]).
-          attr({
-            dy:     size * this.leading - (index == 0 ? size * 0.3 : 0),
-            x:      (this.attrs.x || 0),
-            style:  style
-          })
+      for (i = 0, il = lines.length; i < il; i++)
+        this.tspan(lines[i])
         
-        /* add new tspan */
-        this.node.appendChild(tspan.node)
-        this.lines.push(tspan)
-      }
-      
       /* set style */
-      return this.attr('style', style)
-    },
-    
-    // Build style based on _styleAttr
-    _style: function() {
-      var index, style = ''
+      return this.attr('style', this.style())
+    }
+    // Create a tspan
+  , tspan: function(text) {
+      var tspan = new SVG.TSpan().text(text)
       
-      for (index = _styleAttr.length - 1; index >= 0; index--)
-        if (this.style['font-' + _styleAttr[index]] != null)
-          style += 'font-' + _styleAttr[index] + ':' + this.style['font-' + _styleAttr[index]] + ';'
+      /* add new tspan */
+      this.node.appendChild(tspan.node)
+      this.lines.push(tspan)
       
-      style += 'text-anchor:' + this.style['text-anchor'] + ';'
-        
-      return style
+      return tspan.attr('style', this.style())
+    }
+    // Move element by its center
+  , center: function(x, y) {
+      var anchor = this.style('text-anchor')
+        , box = this.bbox()
+        , x = anchor == 'start' ?
+            x - box.width / 2 :
+          anchor == 'end' ?
+            x + box.width / 2 : x
+      
+      return this.move(x, y - box.height / 2)
+    }
+    // Set font size
+  , size: function(size) {
+      return this.attr('font-size', size)
+    }
+    // Set / get leading
+  , leading: function(value) {
+      /* act as getter */
+      if (value == null)
+        return this._leading
+      
+      /* act as setter */
+      this._leading = value
+      
+      return this.rebuild()
+    }
+    // rebuild appearance type
+  , rebuild: function() {
+      var i, il
+        , size = this.styles['font-size']
+      
+      /* define position of all lines */
+      for (i = 0, il = this.lines.length; i < il; i++)
+        this.lines[i].attr({
+          dy: size * this._leading - (i == 0 ? size * 0.3 : 0)
+        , x: (this.attrs.x || 0)
+        , style: this.style()
+        })
+      
+      return this
+    }
+    // Clear all lines
+  , clear: function() {
+      /* remove existing child nodes */
+      while (this.node.hasChildNodes())
+        this.node.removeChild(this.node.lastChild)
+      
+      this.lines = []
+      
+      return this
     }
     
   })
   
-  
+  // tspan class
   SVG.TSpan = function() {
     this.constructor.call(this, SVG.create('tspan'))
   }
   
   // Inherit from SVG.Shape
-  SVG.TSpan.prototype = new SVG.Shape()
+  SVG.TSpan.prototype = new SVG.Shape
   
   // Include the container object
   SVG.extend(SVG.TSpan, {
       return this
     }
     
-  });
+  })
 
   SVG.Nested = function() {
     this.constructor.call(this, SVG.create('svg'))
     
-    this.attr('style', 'overflow:visible')
+    this.style('overflow', 'visible')
   }
   
   // Inherit from SVG.Container
   
   
   if (SVG.Text) {
-    SVG.extend(SVG.Text, {
+    SVG.extend(SVG.Text, SVG.FX, {
       // Set font 
       font: function(o) {
-        var key, attr = {}
-  
-        for (key in o)
-          key == 'leading' ?
-            attr[key] = o[key] :
+        for (var key in o)
           key == 'anchor' ?
-            attr['text-anchor'] = o[key] :
+            this.attr('text-anchor', o[key]) :
           _styleAttr.indexOf(key) > -1 ?
-            attr['font-'+ key] = o[key] :
-            void 0
-  
-        return this.attr(attr).text(this.content)
+            this.attr('font-'+ key, o[key]) :
+            this.attr(key, o[key])
+        
+        return this
       }
-  
+      
     })
   }
   
index 37d363f62923e335264ff3fcbf5bf0e307cee047..b406dedd4532f1d0743b2eddd503efc2e758724c 100644 (file)
@@ -1,2 +1,2 @@
-/* svg.js v0.8-5-g5e3ff07 - svg regex color viewbox bbox element container fx event group arrange defs mask pattern gradient doc shape wrap rect ellipse line poly path image text nested sugar - svgjs.com/license */
-(function(){this.svg=function(e){if(SVG.supported)return new SVG.Doc(e)},this.SVG={ns:"http://www.w3.org/2000/svg",xlink:"http://www.w3.org/1999/xlink",did:1e3,eid:function(e){return"Svgjs"+e.charAt(0).toUpperCase()+e.slice(1)+"Element"+SVG.did++},create:function(e){var t=document.createElementNS(this.ns,e);return t.setAttribute("id",this.eid(e)),t},extend:function(){var e,t,n,r;e=Array.prototype.slice.call(arguments),t=e.pop();for(r=e.length-1;r>=0;r--)if(e[r])for(n in t)e[r].prototype[n]=t[n]}},SVG.supported=function(){return!!document.createElementNS&&!!document.createElementNS(SVG.ns,"svg").createSVGRect}();if(!SVG.supported)return!1;SVG.regex={unit:/^([\d\.]+)([a-z%]{0,2})$/,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+),([\d\.]+)\)/,hsb:/hsb\((\d+),(\d+),(\d+),([\d\.]+)\)/,isHex:/^#/i,isRgb:/^rgb\(/,isHsb:/^hsb\(/},SVG.Color=function(e){var t;this.r=0,this.g=0,this.b=0,typeof e=="string"?SVG.regex.isRgb.test(e)?(t=SVG.regex.rgb.exec(e.replace(/\s/g,"")),this.r=parseInt(m[1]),this.g=parseInt(m[2]),this.b=parseInt(m[3])):SVG.regex.isHex.test(e)?(t=SVG.regex.hex.exec(this._fullHex(e)),this.r=parseInt(t[1],16),this.g=parseInt(t[2],16),this.b=parseInt(t[3],16)):SVG.regex.isHsb.test(e)&&(t=SVG.regex.hsb.exec(e.replace(/\s/g,"")),e=this._hsbToRgb(t[1],t[2],t[3])):typeof e=="object"&&(SVG.Color.isHsb(e)&&(e=this._hsbToRgb(e.h,e.s,e.b)),this.r=e.r,this.g=e.g,this.b=e.b)},SVG.extend(SVG.Color,{toString:function(){return this.toHex()},toHex:function(){return"#"+this._compToHex(this.r)+this._compToHex(this.g)+this._compToHex(this.b)},toRgb:function(){return"rgb("+[this.r,this.g,this.b].join()+")"},brightness:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11},_hsbToRgb:function(e,t,n){var i,s;e=parseInt(e)%360,e<0&&(e+=360),t=parseInt(t),t=t>100?100:t,n=parseInt(n),n=(n<0?0:n>100?100:n)*255/100,i=n*t/100,s=i*(e*256/60%256)/256;switch(Math.floor(e/60)){case 0:r=n,g=n-i+s,b=n-i;break;case 1:r=n-s,g=n,b=n-i;break;case 2:r=n-i,g=n,b=n-i+s;break;case 3:r=n-i,g=n-s,b=n;break;case 4:r=n-i+s,g=n-i,b=n;break;case 5:r=n,g=n-i,b=n-s}return{r:Math.floor(r+.5),g:Math.floor(g+.5),b:Math.floor(b+.5)}},_fullHex:function(e){return e.length==4?["#",e.substring(1,2),e.substring(1,2),e.substring(2,3),e.substring(2,3),e.substring(3,4),e.substring(3,4)].join(""):e},_compToHex:function(e){var t=e.toString(16);return t.length==1?"0"+t:t}}),SVG.Color.test=function(e){return e+="",SVG.regex.isHex.test(e)||SVG.regex.isRgb.test(e)||SVG.regex.isHsb.test(e)},SVG.Color.isRgb=function(e){return typeof e.r=="number"},SVG.Color.isHsb=function(e){return typeof e.h=="number"},SVG.ViewBox=function(e){var t,n,r,i,s=e.bbox(),o=(e.attr("viewBox")||"").match(/[\d\.]+/g);this.x=s.x,this.y=s.y,this.width=e.node.offsetWidth||e.attr("width"),this.height=e.node.offsetHeight||e.attr("height"),o&&(t=parseFloat(o[0]),n=parseFloat(o[1]),r=parseFloat(o[2])-t,i=parseFloat(o[3])-n,this.zoom=this.width/this.height>r/i?this.height/i:this.width/r,this.x=t,this.y=n,this.width=r,this.height=i),this.zoom=this.zoom||1},SVG.extend(SVG.ViewBox,{toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}}),SVG.BBox=function(e){var t=e.node.getBBox();this.x=t.x+e.trans.x,this.y=t.y+e.trans.y,this.cx=t.x+e.trans.x+t.width/2,this.cy=t.y+e.trans.y+t.height/2,this.width=t.width,this.height=t.height},SVG.Element=function(e){this.attrs={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,fill:"#000",stroke:"#000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0},this.style={},this.trans={x:0,y:0,scaleX:1,scaleY:1,rotation:0,skewX:0,skewY:0};if(this.node=e)this.type=e.nodeName,this.attrs.id=e.getAttribute("id")},SVG.extend(SVG.Element,{move:function(e,t){return this.attr({x:e,y:t})},center:function(e,t){var n=this.bbox();return this.move(e-n.width/2,t-n.height/2)},size:function(e,t){return this.attr({width:e,height:t})},clone:function(){var e;if(this instanceof SVG.Wrap)e=this.parent[this.child.node.nodeName](),e.attrs=this.attrs,e.child.trans=this.child.trans,e.child.attr(this.child.attrs).transform({}),e.plot&&e.plot(this.child.attrs[this.child instanceof SVG.Path?"d":"points"]);else{var t=this.node.nodeName;e=t=="rect"?this.parent[t](this.attrs.width,this.attrs.height):t=="ellipse"?this.parent[t](this.attrs.rx*2,this.attrs.ry*2):t=="image"?this.parent[t](this.src):t=="text"?this.parent[t](this.content):t=="g"?this.parent.group():this.parent[t](),e.attr(this.attrs)}return e.trans=this.trans,e.transform({})},remove:function(){return this.parent&&this.parent.remove(this),this},doc:function(){return this._parent(SVG.Doc)},nested:function(){return this._parent(SVG.Nested)},attr:function(e,t,n){if(arguments.length<2){if(typeof e!="object")return this._isStyle(e)?e=="text"?this.content:e=="leading"?this[e]:this.style[e]:this.attrs[e];for(t in e)this.attr(t,e[t])}else if(t===null)this.node.removeAttribute(e);else{this.attrs[e]=t;if(e=="x"&&this._isText())for(var r=this.lines.length-1;r>=0;r--)this.lines[r].attr(e,t);else{e=="stroke-width"&&this.attr("stroke",parseFloat(t)>0?this.attrs.stroke:null);if(SVG.Color.test(t)||SVG.Color.isRgb(t)||SVG.Color.isHsb(t))t=(new SVG.Color(t)).toHex();n!=null?this.node.setAttributeNS(n,e,t):this.node.setAttribute(e,t)}this._isStyle(e)&&(e=="text"?this.text(t):e=="leading"?this[e]=t:this.style[e]=t,this.text(this.content))}return this},transform:function(e){if(typeof e=="string")return this.trans[e];var t,n=[];for(t in e)e[t]!=null&&(this.trans[t]=e[t]);return e=this.trans,e.rotation!=0&&n.push("rotate("+e.rotation+","+(e.cx!=null?e.cx:this.bbox().cx)+","+(e.cy!=null?e.cy:this.bbox().cy)+")"),n.push("scale("+e.scaleX+","+e.scaleY+")"),e.skewX!=0&&n.push("skewX("+e.skewX+")"),e.skewY!=0&&n.push("skewY("+e.skewY+")"),n.push("translate("+e.x+","+e.y+")"),this.attr("transform",n.join(" "))},data:function(e,t,n){if(arguments.length<2)try{return JSON.parse(this.attr("data-"+e))}catch(r){return this.attr("data-"+e)}else this.attr("data-"+e,t===null?null:n===!0?t:JSON.stringify(t));return this},bbox:function(){return new SVG.BBox(this)},inside:function(e,t){var n=this.bbox();return e>n.x&&t>n.y&&e<n.x+n.width&&t<n.y+n.height},show:function(){return this.node.style.display="",this},hide:function(){return this.node.style.display="none",this},visible:function(){return this.node.style.display!="none"},_parent:function(e){var t=this;while(t!=null&&!(t instanceof e))t=t.parent;return t},_isStyle:function(e){return typeof e=="string"&&this._isText()?/^font|text|leading/.test(e):!1},_isText:function(){return this instanceof SVG.Text}}),SVG.Container=function(e){this.constructor.call(this,e)},SVG.Container.prototype=new SVG.Element,SVG.extend(SVG.Container,{add:function(e,t){if(!this.has(e)){t=t==null?this.children().length:t;if(e.parent){var n=e.parent.children().indexOf(e);e.parent.children().splice(n,1)}this.children().splice(t,0,e),this.node.insertBefore(e.node,this.node.childNodes[t]||null),e.parent=this}return this},put:function(e,t){return this.add(e,t),e},has:function(e){return this.children().indexOf(e)>=0},children:function(){return this._children||(this._children=[])},each:function(e){var t,n=this.children();for(t=0,length=n.length;t<length;t++)n[t]instanceof SVG.Shape&&e.apply(n[t],[t,n]);return this},remove:function(e){var t=this.children().indexOf(e);return this.children().splice(t,1),this.node.removeChild(e.node),e.parent=null,this},defs:function(){return this._defs||(this._defs=this.put(new SVG.Defs,0))},level:function(){return this.remove(this.defs()).put(this.defs(),0)},group:function(){return this.put(new SVG.G)},rect:function(e,t){return this.put((new SVG.Rect).size(e,t))},circle:function(e){return this.ellipse(e)},ellipse:function(e,t){return this.put((new SVG.Ellipse).size(e,t))},polyline:function(e){return this.put(new SVG.Wrap(new SVG.Polyline)).plot(e)},polygon:function(e){return this.put(new SVG.Wrap(new SVG.Polygon)).plot(e)},path:function(e){return this.put(new SVG.Wrap(new SVG.Path)).plot(e)},image:function(e,t,n){return t=t!=null?t:100,this.put((new SVG.Image).load(e).size(t,n!=null?n:t))},text:function(e){return this.put((new SVG.Text).text(e))},nested:function(){return this.put(new SVG.Nested)},gradient:function(e,t){return this.defs().gradient(e,t)},pattern:function(e,t,n){return this.defs().pattern(e,t,n)},mask:function(){return this.defs().put(new SVG.Mask)},first:function(){return this.children()[0]instanceof SVG.Defs?this.children()[1]:this.children()[0]},last:function(){return this.children()[this.children().length-1]},viewbox:function(){return arguments.length==0?new SVG.ViewBox(this):this.attr("viewBox",Array.prototype.slice.call(arguments).join(" "))},clear:function(){this._children=[];while(this.node.hasChildNodes())this.node.removeChild(this.node.lastChild);return this}}),SVG.FX=function(e){this.target=e},SVG.extend(SVG.FX,{animate:function(e,t){e=e==null?1e3:e,t=t||"<>";var n,r,i,s=this.target,o=this,u=(new Date).getTime(),a=u+e;return this.interval=setInterval(function(){var f,l=(new Date).getTime(),c=l>a?1:(l-u)/e;if(n==null){n=[];for(var h in o.attrs)n.push(h)}if(r==null){r=[];for(var h in o.trans)r.push(h);i={}}c=t=="<>"?-Math.cos(c*Math.PI)/2+.5:t==">"?Math.sin(c*Math.PI/2):t=="<"?-Math.cos(c*Math.PI/2)+1:t=="-"?c:typeof t=="function"?t(c):c,o._move?s.move(o._at(o._move.x,c),o._at(o._move.y,c)):o._center&&s.move(o._at(o._center.x,c),o._at(o._center.y,c)),o._size&&s.size(o._at(o._size.width,c),o._at(o._size.height,c));for(f=n.length-1;f>=0;f--)s.attr(n[f],o._at(o.attrs[n[f]],c));if(r.length>0){for(f=r.length-1;f>=0;f--)i[r[f]]=o._at(o.trans[r[f]],c);s.transform(i)}o._during&&o._during.call(s,c,function(e,t){return o._at({from:e,to:t},c)}),l>a&&(clearInterval(o.interval),o._after?o._after.apply(s,[o]):o.stop())},e>10?10:e),this},attr:function(e,t,n){if(typeof e=="object")for(var r in e)this.attr(r,e[r]);else this.attrs[e]={from:this.target.attr(e),to:t};return this},transform:function(e){for(var t in e)this.trans[t]={from:this.target.trans[t],to:e[t]};return this},move:function(e,t){var n=this.target.bbox();return this._move={x:{from:n.x,to:e},y:{from:n.y,to:t}},this},size:function(e,t){var n=this.target.bbox();return this._size={width:{from:n.width,to:e},height:{from:n.height,to:t}},this},center:function(e,t){var n=this.target.bbox();return this._move={x:{from:n.cx,to:e-n.width/2},y:{from:n.cy,to:t-n.height/2}},this},during:function(e){return this._during=e,this},after:function(e){return this._after=e,this},stop:function(){return clearInterval(this.interval),this.attrs={},this.trans={},this._move=null,this._size=null,this._after=null,this._during=null,this},_at:function(e,t){return typeof e.from=="number"?e.from+(e.to-e.from)*t:SVG.regex.unit.test(e.to)?this._unit(e,t):e.to&&(e.to.r||SVG.Color.test(e.to))?this._color(e,t):t<1?e.from:e.to},_unit:function(e,t){var n,r;return n=SVG.regex.unit.exec(e.from.toString()),r=parseFloat(n[1]),n=SVG.regex.unit.exec(e.to),r+(parseFloat(n[1])-r)*t+n[2]},_color:function(e,t){var n,r;return t=t<0?0:t>1?1:t,n=new SVG.Color(e.from),r=new SVG.Color(e.to),(new SVG.Color({r:~~(n.r+(r.r-n.r)*t),g:~~(n.g+(r.g-n.g)*t),b:~~(n.b+(r.b-n.b)*t)})).toHex()}}),SVG.extend(SVG.Element,{animate:function(e,t){return(this.fx||(this.fx=new SVG.FX(this))).stop().animate(e,t)},stop:function(){return this.fx.stop(),this}}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","mouseenter","mouseleave","touchstart","touchend","touchmove","touchcancel"].forEach(function(e){SVG.Element.prototype[e]=function(t){var n=this;return this.node["on"+e]=typeof t=="function"?function(){return t.apply(n,arguments)}:null,this}}),SVG.on=function(e,t,n){e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},SVG.off=function(e,t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent("on"+t,n)},SVG.extend(SVG.Element,{on:function(e,t){return SVG.on(this.node,e,t),this},off:function(e,t){return SVG.off(this.node,e,t),this}}),SVG.G=function(){this.constructor.call(this,SVG.create("g"))},SVG.G.prototype=new SVG.Container,SVG.extend(SVG.G,{move:function(e,t){return this.transform({x:e,y:t})},defs:function(){return this.doc().defs()}}),SVG.extend(SVG.Element,{siblings:function(){return this.parent.children()},position:function(){return this.siblings().indexOf(this)},next:function(){return this.siblings()[this.position()+1]},previous:function(){return this.siblings()[this.position()-1]},forward:function(){return this.parent.remove(this).put(this,this.position()+1)},backward:function(){var e;return this.parent.level(),e=this.position(),e>1&&this.parent.remove(this).add(this,e-1),this},front:function(){return this.parent.remove(this).put(this)},back:function(){return this.parent.level(),this.position()>1&&this.parent.remove(this).add(this,0),this}}),SVG.Defs=function(){this.constructor.call(this,SVG.create("defs"))},SVG.Defs.prototype=new SVG.Container,SVG.Mask=function(){this.constructor.call(this,SVG.create("mask"))},SVG.Mask.prototype=new SVG.Container,SVG.extend(SVG.Element,{maskWith:function(e){return this.mask=e instanceof SVG.Mask?e:this.parent.mask().add(e),this.attr("mask","url(#"+this.mask.attr("id")+")")}}),SVG.Pattern=function(e){this.constructor.call(this,SVG.create("pattern"))},SVG.Pattern.prototype=new SVG.Container,SVG.extend(SVG.Pattern,{fill:function(){return"url(#"+this.attr("id")+")"}}),SVG.extend(SVG.Defs,{pattern:function(e,t,n){var r=this.put(new SVG.Pattern);return n(r),r.attr({x:0,y:0,width:e,height:t,patternUnits:"userSpaceOnUse"})}}),SVG.Gradient=function(e){this.constructor.call(this,SVG.create(e+"Gradient")),this.type=e},SVG.Gradient.prototype=new SVG.Container,SVG.extend(SVG.Gradient,{from:function(e,t){return this.type=="radial"?this.attr({fx:e+"%",fy:t+"%"}):this.attr({x1:e+"%",y1:t+"%"})},to:function(e,t){return this.type=="radial"?this.attr({cx:e+"%",cy:t+"%"}):this.attr({x2:e+"%",y2:t+"%"})},radius:function(e){return this.type=="radial"?this.attr({r:e+"%"}):this},at:function(e){return this.put(new SVG.Stop(e))},update:function(e){while(this.node.hasChildNodes())this.node.removeChild(this.node.lastChild);return e(this),this},fill:function(){return"url(#"+this.attr("id")+")"}}),SVG.extend(SVG.Defs,{gradient:function(e,t){var n=this.put(new SVG.Gradient(e));return t(n),n}}),SVG.Stop=function(e){this.constructor.call(this,SVG.create("stop")),this.update(e)},SVG.Stop.prototype=new SVG.Element,SVG.extend(SVG.Stop,{update:function(e){var t,n="",r=["opacity","color"];for(t=r.length-1;t>=0;t--)e[r[t]]!=null&&(n+="stop-"+r[t]+":"+e[r[t]]+";");return this.attr({offset:(e.offset!=null?e.offset:this.attrs.offset||0)+"%",style:n})}}),SVG.Doc=function(e){this.constructor.call(this,SVG.create("svg")),this.parent=typeof e=="string"?document.getElementById(e):e,this.attr({xmlns:SVG.ns,version:"1.1",width:"100%",height:"100%"}).attr("xlink",SVG.xlink,SVG.ns).defs(),this.stage()},SVG.Doc.prototype=new SVG.Container,SVG.Doc.prototype.stage=function(){var e,t=this,n=document.createElement("div");return n.style.cssText="position:relative;height:100%;",t.parent.appendChild(n),n.appendChild(t.node),e=function(){document.readyState==="complete"?(t.attr("style","position:absolute;"),setTimeout(function(){t.attr("style","position:relative;"),t.parent.removeChild(t.node.parentNode),t.node.parentNode.removeChild(t.node),t.parent.appendChild(t.node)},5)):setTimeout(e,10)},e(),this},SVG.Shape=function(e){this.constructor.call(this,e)},SVG.Shape.prototype=new SVG.Element,SVG.Wrap=function(e){this.constructor.call(this,SVG.create("g")),this.node.insertBefore(e.node,null),this.child=e,this.type=e.node.nodeName},SVG.Wrap.prototype=new SVG.Shape,SVG.extend(SVG.Wrap,{move:function(e,t){return this.transform({x:e,y:t})},size:function(e,t){var n=e/this._b.width;return this.child.transform({scaleX:n,scaleY:t!=null?t/this._b.height:n}),this},center:function(e,t){return this.move(e+this._b.width*this.child.trans.scaleX/-2,t+this._b.height*this.child.trans.scaleY/-2)},attr:function(e,t,n){if(typeof e=="object")for(t in e)this.attr(t,e[t]);else{if(arguments.length<2)return e=="transform"?this.attrs[e]:this.child.attrs[e];e=="transform"?(this.attrs[e]=t,n!=null?this.node.setAttributeNS(n,e,t):this.node.setAttribute(e,t)):this.child.attr(e,t,n)}return this},plot:function(e){return this.child.plot(e),this._b=this.child.bbox(),this.child.transform({x:-this._b.x,y:-this._b.y}),this}}),SVG.Rect=function(){this.constructor.call(this,SVG.create("rect"))},SVG.Rect.prototype=new SVG.Shape,SVG.Ellipse=function(){this.constructor.call(this,SVG.create("ellipse"))},SVG.Ellipse.prototype=new SVG.Shape,SVG.extend(SVG.Ellipse,{move:function(e,t){return this.attrs.x=e,this.attrs.y=t,this.center()},size:function(e,t){return this.attr({rx:e/2,ry:(t!=null?t:e)/2}).center()},center:function(e,t){return this.attr({cx:e||(this.attrs.x||0)+(this.attrs.rx||0),cy:t||(this.attrs.y||0)+(this.attrs.ry||0)})}}),SVG.Line=function(){this.constructor.call(this,SVG.create("line"))},SVG.Line.prototype=new SVG.Shape,SVG.extend(SVG.Line,{move:function(e,t){var n=this.bbox();return this.attr({x1:this.attr("x1")-n.x+e,y1:this.attr("y1")-n.y+t,x2:this.attr("x2")-n.x+e,y2:this.attr("y2")-n.y+t})},center:function(e,t){var n=this.bbox();return this.move(e-n.width/2,t-n.height/2)},size:function(e,t){var n=this.bbox();return this.attr(this.attr("x1")<this.attr("x2")?"x2":"x1",n.x+e),this.attr(this.attr("y1")<this.attr("y2")?"y2":"y1",n.y+t)}}),SVG.extend(SVG.Container,{line:function(e,t,n,r){return this.put((new SVG.Line).attr({x1:e,y1:t,x2:n,y2:r}))}}),SVG.Poly={plot:function(e){return this.attr("points",e||"0,0"),this}},SVG.Polyline=function(){this.constructor.call(this,SVG.create("polyline"))},SVG.Polyline.prototype=new SVG.Shape,SVG.extend(SVG.Polyline,SVG.Poly),SVG.Polygon=function(){this.constructor.call(this,SVG.create("polygon"))},SVG.Polygon.prototype=new SVG.Shape,SVG.extend(SVG.Polygon,SVG.Poly),SVG.Path=function(){this.constructor.call(this,SVG.create("path"))},SVG.Path.prototype=new SVG.Shape,SVG.extend(SVG.Path,{move:function(e,t){this.transform({x:e,y:t})},plot:function(e){return this.attr("d",e||"M0,0")}}),SVG.Image=function(){this.constructor.call(this,SVG.create("image"))},SVG.Image.prototype=new SVG.Shape,SVG.extend(SVG.Image,{load:function(e){return this.src=e,e?this.attr("xlink:href",e,SVG.xlink):this}});var e=["size","family","weight","stretch","variant","style"];SVG.Text=function(){this.constructor.call(this,SVG.create("text")),this.style={"font-size":16,"font-family":"Helvetica","text-anchor":"start"},this.leading=1.2},SVG.Text.prototype=new SVG.Shape,SVG.extend(SVG.Text,{text:function(e){this.content=e=e||"text",this.lines=[];var t,n,r,i=this._style(),s=this.doc(),o=e.split("\n"),u=this.style["font-size"];while(this.node.hasChildNodes())this.node.removeChild(this.node.lastChild);for(t=0,n=o.length;t<n;t++)r=(new SVG.TSpan).text(o[t]).attr({dy:u*this.leading-(t==0?u*.3:0),x:this.attrs.x||0,style:i}),this.node.appendChild(r.node),this.lines.push(r);return this.attr("style",i)},_style:function(){var t,n="";for(t=e.length-1;t>=0;t--)this.style["font-"+e[t]]!=null&&(n+="font-"+e[t]+":"+this.style["font-"+e[t]]+";");return n+="text-anchor:"+this.style["text-anchor"]+";",n}}),SVG.TSpan=function(){this.constructor.call(this,SVG.create("tspan"))},SVG.TSpan.prototype=new SVG.Shape,SVG.extend(SVG.TSpan,{text:function(e){return this.node.appendChild(document.createTextNode(e)),this}}),SVG.Nested=function(){this.constructor.call(this,SVG.create("svg")),this.attr("style","overflow:visible")},SVG.Nested.prototype=new SVG.Container,SVG._stroke=["color","width","opacity","linecap","linejoin","miterlimit","dasharray","dashoffset"],SVG._fill=["color","opacity","rule"];var t=function(e,t){return t=="color"?e:e+"-"+t};["fill","stroke"].forEach(function(e){var n={};n[e]=function(n){var r;if(typeof n=="string"||SVG.Color.isRgb(n)||SVG.Color.isHsb(n))this.attr(e,n);else for(index=SVG["_"+e].length-1;index>=0;index--)n[SVG["_"+e][index]]!=null&&this.attr(t(e,SVG["_"+e][index]),n[SVG["_"+e][index]]);return this},SVG.extend(SVG.Shape,SVG.FX,n)}),SVG.extend(SVG.Element,SVG.FX,{rotate:function(e,t,n){return this.transform({rotation:e||0,cx:t,cy:n})},skew:function(e,t){return this.transform({skewX:e||0,skewY:t||0})},scale:function(e,t){return this.transform({scaleX:e,scaleY:t==null?e:t})},opacity:function(e){return this.attr("opacity",e)}}),SVG.Text&&SVG.extend(SVG.Text,{font:function(t){var n,r={};for(n in t)n=="leading"?r[n]=t[n]:n=="anchor"?r["text-anchor"]=t[n]:e.indexOf(n)>-1?r["font-"+n]=t[n]:void 0;return this.attr(r).text(this.content)}})}).call(this);
\ No newline at end of file
+/* svg.js v0.9 - svg regex color viewbox bbox element container fx event group arrange defs mask pattern gradient doc shape wrap rect ellipse line poly path image text nested sugar - svgjs.com/license */
+(function(){this.SVG=function(e){if(SVG.supported)return new SVG.Doc(e)},this.svg=function(e){return console.warn("WARNING: svg() is deprecated, please use SVG() instead."),SVG(e)},SVG.ns="http://www.w3.org/2000/svg",SVG.xlink="http://www.w3.org/1999/xlink",SVG.did=1e3,SVG.eid=function(e){return"Svgjs"+e.charAt(0).toUpperCase()+e.slice(1)+"Element"+SVG.did++},SVG.create=function(e){var t=document.createElementNS(this.ns,e);return t.setAttribute("id",this.eid(e)),t},SVG.extend=function(){var e,t,n,r;e=Array.prototype.slice.call(arguments),t=e.pop();for(r=e.length-1;r>=0;r--)if(e[r])for(n in t)e[r].prototype[n]=t[n]},SVG.supported=function(){return!!document.createElementNS&&!!document.createElementNS(SVG.ns,"svg").createSVGRect}();if(!SVG.supported)return!1;SVG.regex={unit:/^([\d\.]+)([a-z%]{0,2})$/,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+),([\d\.]+)\)/,hsb:/hsb\((\d+),(\d+),(\d+),([\d\.]+)\)/,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isHsb:/^hsb\(/,isCss:/[^:]+:[^;]+;?/,isStyle:/^font|text|leading|cursor/,isBlank:/^(\s+)?$/},SVG.Color=function(e){var t;this.r=0,this.g=0,this.b=0,typeof e=="string"?SVG.regex.isRgb.test(e)?(t=SVG.regex.rgb.exec(e.replace(/\s/g,"")),this.r=parseInt(m[1]),this.g=parseInt(m[2]),this.b=parseInt(m[3])):SVG.regex.isHex.test(e)?(t=SVG.regex.hex.exec(this._fullHex(e)),this.r=parseInt(t[1],16),this.g=parseInt(t[2],16),this.b=parseInt(t[3],16)):SVG.regex.isHsb.test(e)&&(t=SVG.regex.hsb.exec(e.replace(/\s/g,"")),e=this._hsbToRgb(t[1],t[2],t[3])):typeof e=="object"&&(SVG.Color.isHsb(e)&&(e=this._hsbToRgb(e.h,e.s,e.b)),this.r=e.r,this.g=e.g,this.b=e.b)},SVG.extend(SVG.Color,{toString:function(){return this.toHex()},toHex:function(){return"#"+this._compToHex(this.r)+this._compToHex(this.g)+this._compToHex(this.b)},toRgb:function(){return"rgb("+[this.r,this.g,this.b].join()+")"},brightness:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11},_hsbToRgb:function(e,t,n){var i,s;e=parseInt(e)%360,e<0&&(e+=360),t=parseInt(t),t=t>100?100:t,n=parseInt(n),n=(n<0?0:n>100?100:n)*255/100,i=n*t/100,s=i*(e*256/60%256)/256;switch(Math.floor(e/60)){case 0:r=n,g=n-i+s,b=n-i;break;case 1:r=n-s,g=n,b=n-i;break;case 2:r=n-i,g=n,b=n-i+s;break;case 3:r=n-i,g=n-s,b=n;break;case 4:r=n-i+s,g=n-i,b=n;break;case 5:r=n,g=n-i,b=n-s}return{r:Math.floor(r+.5),g:Math.floor(g+.5),b:Math.floor(b+.5)}},_fullHex:function(e){return e.length==4?["#",e.substring(1,2),e.substring(1,2),e.substring(2,3),e.substring(2,3),e.substring(3,4),e.substring(3,4)].join(""):e},_compToHex:function(e){var t=e.toString(16);return t.length==1?"0"+t:t}}),SVG.Color.test=function(e){return e+="",SVG.regex.isHex.test(e)||SVG.regex.isRgb.test(e)||SVG.regex.isHsb.test(e)},SVG.Color.isRgb=function(e){return typeof e.r=="number"},SVG.Color.isHsb=function(e){return typeof e.h=="number"},SVG.ViewBox=function(e){var t,n,r,i,s=e.bbox(),o=(e.attr("viewBox")||"").match(/[\d\.]+/g);this.x=s.x,this.y=s.y,this.width=e.node.offsetWidth||e.attr("width"),this.height=e.node.offsetHeight||e.attr("height"),o&&(t=parseFloat(o[0]),n=parseFloat(o[1]),r=parseFloat(o[2])-t,i=parseFloat(o[3])-n,this.zoom=this.width/this.height>r/i?this.height/i:this.width/r,this.x=t,this.y=n,this.width=r,this.height=i),this.zoom=this.zoom||1},SVG.extend(SVG.ViewBox,{toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}}),SVG.BBox=function(e){var t=e.node.getBBox();this.x=t.x+e.trans.x,this.y=t.y+e.trans.y,this.cx=t.x+e.trans.x+t.width/2,this.cy=t.y+e.trans.y+t.height/2,this.width=t.width,this.height=t.height},SVG.Element=function(e){this.attrs={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,fill:"#000",stroke:"#000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0},this.styles={},this.trans={x:0,y:0,scaleX:1,scaleY:1,rotation:0,skewX:0,skewY:0};if(this.node=e)this.type=e.nodeName,this.attrs.id=e.getAttribute("id")},SVG.extend(SVG.Element,{move:function(e,t){return this.attr({x:e,y:t})},center:function(e,t){var n=this.bbox();return this.move(e-n.width/2,t-n.height/2)},size:function(e,t){return this.attr({width:e,height:t})},clone:function(){var e;if(this instanceof SVG.Wrap)e=this.parent[this.child.node.nodeName](),e.attrs=this.attrs,e.child.trans=this.child.trans,e.child.attr(this.child.attrs).transform({}),e.plot&&e.plot(this.child.attrs[this.child instanceof SVG.Path?"d":"points"]);else{var t=this.node.nodeName;e=t=="rect"?this.parent[t](this.attrs.width,this.attrs.height):t=="ellipse"?this.parent[t](this.attrs.rx*2,this.attrs.ry*2):t=="image"?this.parent[t](this.src):t=="text"?this.parent[t](this.content):t=="g"?this.parent.group():this.parent[t](),e.attr(this.attrs)}return e.trans=this.trans,e.transform({})},remove:function(){return this.parent&&this.parent.remove(this),this},doc:function(){return this._parent(SVG.Doc)},nested:function(){return this._parent(SVG.Nested)},attr:function(e,t,n){if(arguments.length<2){if(typeof e!="object")return this._isStyle(e)?e=="text"?this.content:e=="leading"?this.leading():this.style(e):this.attrs[e]||this.node.getAttribute(e);for(t in e)this.attr(t,e[t])}else if(t===null)this.node.removeAttribute(e);else{if(e=="style")return this.style(t);this.attrs[e]=t;if(e=="x"&&this._isText())for(var r=this.lines.length-1;r>=0;r--)this.lines[r].attr(e,t);else{e=="stroke-width"&&this.attr("stroke",parseFloat(t)>0?this.attrs.stroke:null);if(SVG.Color.test(t)||SVG.Color.isRgb(t)||SVG.Color.isHsb(t))t=(new SVG.Color(t)).toHex();n!=null?this.node.setAttributeNS(n,e,t):this.node.setAttribute(e,t)}this._isStyle(e)&&(e=="text"?this.text(t):e=="leading"?this.leading(t):this.style(e,t),this.rebuild&&this.rebuild())}return this},transform:function(e,t){if(typeof e=="string"){if(arguments.length<2)return this.trans[e];var n={};return n[e]=t,this.transform(n)}var n=[];for(t in e)e[t]!=null&&(this.trans[t]=e[t]);return e=this.trans,e.rotation!=0&&n.push("rotate("+e.rotation+","+(e.cx!=null?e.cx:this.bbox().cx)+","+(e.cy!=null?e.cy:this.bbox().cy)+")"),n.push("scale("+e.scaleX+","+e.scaleY+")"),e.skewX!=0&&n.push("skewX("+e.skewX+")"),e.skewY!=0&&n.push("skewY("+e.skewY+")"),n.push("translate("+e.x+","+e.y+")"),this.attr("transform",n.join(" "))},style:function(e,t){if(arguments.length==0)return this.attr("style");if(arguments.length<2)if(typeof e=="object")for(t in e)this.style(t,e[t]);else{if(!SVG.regex.isCss.test(e))return this.styles[e];e=e.split(";");for(var n=0;n<e.length;n++)t=e[n].split(":"),t.length==2&&this.style(t[0].replace(/\s+/g,""),t[1].replace(/^\s+/,"").replace(/\s+$/,""))}else t===null?delete this.styles[e]:this.styles[e]=t;e="";for(t in this.styles)e+=t+":"+this.styles[t]+";";return this.node.setAttribute("style",e),this},data:function(e,t,n){if(arguments.length<2)try{return JSON.parse(this.attr("data-"+e))}catch(r){return this.attr("data-"+e)}else this.attr("data-"+e,t===null?null:n===!0?t:JSON.stringify(t));return this},bbox:function(){return new SVG.BBox(this)},inside:function(e,t){var n=this.bbox();return e>n.x&&t>n.y&&e<n.x+n.width&&t<n.y+n.height},show:function(){return this.style("display","")},hide:function(){return this.style("display","none")},visible:function(){return this.style("display")!="none"},_parent:function(e){var t=this;while(t!=null&&!(t instanceof e))t=t.parent;return t},_isStyle:function(e){return typeof e=="string"?SVG.regex.isStyle.test(e):!1},_isText:function(){return this instanceof SVG.Text}}),SVG.Container=function(e){this.constructor.call(this,e)},SVG.Container.prototype=new SVG.Element,SVG.extend(SVG.Container,{add:function(e,t){if(!this.has(e)){t=t==null?this.children().length:t;if(e.parent){var n=e.parent.children().indexOf(e);e.parent.children().splice(n,1)}this.children().splice(t,0,e),this.node.insertBefore(e.node,this.node.childNodes[t]||null),e.parent=this}return this},put:function(e,t){return this.add(e,t),e},has:function(e){return this.children().indexOf(e)>=0},children:function(){return this._children||(this._children=[])},each:function(e){var t,n=this.children();for(t=0,length=n.length;t<length;t++)n[t]instanceof SVG.Shape&&e.apply(n[t],[t,n]);return this},remove:function(e){var t=this.children().indexOf(e);return this.children().splice(t,1),this.node.removeChild(e.node),e.parent=null,this},defs:function(){return this._defs||(this._defs=this.put(new SVG.Defs,0))},level:function(){return this.remove(this.defs()).put(this.defs(),0)},group:function(){return this.put(new SVG.G)},rect:function(e,t){return this.put((new SVG.Rect).size(e,t))},circle:function(e){return this.ellipse(e)},ellipse:function(e,t){return this.put((new SVG.Ellipse).size(e,t))},polyline:function(e){return this.put(new SVG.Wrap(new SVG.Polyline)).plot(e)},polygon:function(e){return this.put(new SVG.Wrap(new SVG.Polygon)).plot(e)},path:function(e){return this.put(new SVG.Wrap(new SVG.Path)).plot(e)},image:function(e,t,n){return t=t!=null?t:100,this.put((new SVG.Image).load(e).size(t,n!=null?n:t))},text:function(e){return this.put((new SVG.Text).text(e))},nested:function(){return this.put(new SVG.Nested)},gradient:function(e,t){return this.defs().gradient(e,t)},pattern:function(e,t,n){return this.defs().pattern(e,t,n)},mask:function(){return this.defs().put(new SVG.Mask)},first:function(){return this.children()[0]instanceof SVG.Defs?this.children()[1]:this.children()[0]},last:function(){return this.children()[this.children().length-1]},viewbox:function(){return arguments.length==0?new SVG.ViewBox(this):this.attr("viewBox",Array.prototype.slice.call(arguments).join(" "))},clear:function(){this._children=[];while(this.node.hasChildNodes())this.node.removeChild(this.node.lastChild);return this}}),SVG.FX=function(e){this.target=e},SVG.extend(SVG.FX,{animate:function(e,t){e=e==null?1e3:e,t=t||"<>";var n,r,i,s=this.target,o=this,u=(new Date).getTime(),a=u+e;return this.interval=setInterval(function(){var f,l,c=(new Date).getTime(),h=c>a?1:(c-u)/e;if(n==null){n=[];for(l in o.attrs)n.push(l)}if(r==null){r=[];for(l in o.trans)r.push(l)}if(i==null){i=[];for(l in o.styles)i.push(l)}h=t=="<>"?-Math.cos(h*Math.PI)/2+.5:t==">"?Math.sin(h*Math.PI/2):t=="<"?-Math.cos(h*Math.PI/2)+1:t=="-"?h:typeof t=="function"?t(h):h,o._move?s.move(o._at(o._move.x,h),o._at(o._move.y,h)):o._center&&s.center(o._at(o._center.x,h),o._at(o._center.y,h)),o._size&&s.size(o._at(o._size.width,h),o._at(o._size.height,h));for(f=n.length-1;f>=0;f--)s.attr(n[f],o._at(o.attrs[n[f]],h));for(f=r.length-1;f>=0;f--)s.transform(r[f],o._at(o.trans[r[f]],h));for(f=i.length-1;f>=0;f--)s.style(i[f],o._at(o.styles[i[f]],h));o._during&&o._during.call(s,h,function(e,t){return o._at({from:e,to:t},h)}),c>a&&(clearInterval(o.interval),o._after?o._after.apply(s,[o]):o.stop())},e>10?10:e),this},attr:function(e,t,n){if(typeof e=="object")for(var r in e)this.attr(r,e[r]);else this.attrs[e]={from:this.target.attr(e),to:t};return this},transform:function(e,t){for(var n in e)this.trans[n]={from:this.target.trans[n],to:e[n]};return this},style:function(e,t){if(typeof e=="object")for(var n in e)this.style(n,e[n]);else this.styles[e]={from:this.target.style(e),to:t};return this},move:function(e,t){var n=this.target.bbox();return this._move={x:{from:n.x,to:e},y:{from:n.y,to:t}},this},size:function(e,t){if(this.target instanceof SVG.Text)this.attr("font-size",e);else{var n=this.target.bbox();this._size={width:{from:n.width,to:e},height:{from:n.height,to:t}}}return this},center:function(e,t){var n=this.target.bbox();return this._move={x:{from:n.cx,to:e-n.width/2},y:{from:n.cy,to:t-n.height/2}},this},during:function(e){return this._during=e,this},after:function(e){return this._after=e,this},stop:function(){return clearInterval(this.interval),this.attrs={},this.trans={},this.styles={},this._move=null,this._size=null,this._after=null,this._during=null,this},_at:function(e,t){return typeof e.from=="number"?e.from+(e.to-e.from)*t:SVG.regex.unit.test(e.to)?this._unit(e,t):e.to&&(e.to.r||SVG.Color.test(e.to))?this._color(e,t):t<1?e.from:e.to},_unit:function(e,t){var n,r;return n=SVG.regex.unit.exec(e.from.toString()),r=parseFloat(n[1]),n=SVG.regex.unit.exec(e.to),r+(parseFloat(n[1])-r)*t+n[2]},_color:function(e,t){var n,r;return t=t<0?0:t>1?1:t,n=new SVG.Color(e.from),r=new SVG.Color(e.to),(new SVG.Color({r:~~(n.r+(r.r-n.r)*t),g:~~(n.g+(r.g-n.g)*t),b:~~(n.b+(r.b-n.b)*t)})).toHex()}}),SVG.extend(SVG.Element,{animate:function(e,t){return(this.fx||(this.fx=new SVG.FX(this))).stop().animate(e,t)},stop:function(){return this.fx.stop(),this}}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","mouseenter","mouseleave","touchstart","touchend","touchmove","touchcancel"].forEach(function(e){SVG.Element.prototype[e]=function(t){var n=this;return this.node["on"+e]=typeof t=="function"?function(){return t.apply(n,arguments)}:null,this}}),SVG.on=function(e,t,n){e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},SVG.off=function(e,t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent("on"+t,n)},SVG.extend(SVG.Element,{on:function(e,t){return SVG.on(this.node,e,t),this},off:function(e,t){return SVG.off(this.node,e,t),this}}),SVG.G=function(){this.constructor.call(this,SVG.create("g"))},SVG.G.prototype=new SVG.Container,SVG.extend(SVG.G,{move:function(e,t){return this.transform({x:e,y:t})},defs:function(){return this.doc().defs()}}),SVG.extend(SVG.Element,{siblings:function(){return this.parent.children()},position:function(){return this.siblings().indexOf(this)},next:function(){return this.siblings()[this.position()+1]},previous:function(){return this.siblings()[this.position()-1]},forward:function(){return this.parent.remove(this).put(this,this.position()+1)},backward:function(){this.parent.level();var e=this.position();return e>1&&this.parent.remove(this).add(this,e-1),this},front:function(){return this.parent.remove(this).put(this)},back:function(){return this.parent.level(),this.position()>1&&this.parent.remove(this).add(this,0),this}}),SVG.Defs=function(){this.constructor.call(this,SVG.create("defs"))},SVG.Defs.prototype=new SVG.Container,SVG.Mask=function(){this.constructor.call(this,SVG.create("mask"))},SVG.Mask.prototype=new SVG.Container,SVG.extend(SVG.Element,{maskWith:function(e){return this.mask=e instanceof SVG.Mask?e:this.parent.mask().add(e),this.attr("mask","url(#"+this.mask.attr("id")+")")}}),SVG.Pattern=function(e){this.constructor.call(this,SVG.create("pattern"))},SVG.Pattern.prototype=new SVG.Container,SVG.extend(SVG.Pattern,{fill:function(){return"url(#"+this.attr("id")+")"}}),SVG.extend(SVG.Defs,{pattern:function(e,t,n){var r=this.put(new SVG.Pattern);return n(r),r.attr({x:0,y:0,width:e,height:t,patternUnits:"userSpaceOnUse"})}}),SVG.Gradient=function(e){this.constructor.call(this,SVG.create(e+"Gradient")),this.type=e},SVG.Gradient.prototype=new SVG.Container,SVG.extend(SVG.Gradient,{from:function(e,t){return this.type=="radial"?this.attr({fx:e+"%",fy:t+"%"}):this.attr({x1:e+"%",y1:t+"%"})},to:function(e,t){return this.type=="radial"?this.attr({cx:e+"%",cy:t+"%"}):this.attr({x2:e+"%",y2:t+"%"})},radius:function(e){return this.type=="radial"?this.attr({r:e+"%"}):this},at:function(e){return this.put(new SVG.Stop(e))},update:function(e){while(this.node.hasChildNodes())this.node.removeChild(this.node.lastChild);return e(this),this},fill:function(){return"url(#"+this.attr("id")+")"}}),SVG.extend(SVG.Defs,{gradient:function(e,t){var n=this.put(new SVG.Gradient(e));return t(n),n}}),SVG.Stop=function(e){this.constructor.call(this,SVG.create("stop")),this.update(e)},SVG.Stop.prototype=new SVG.Element,SVG.extend(SVG.Stop,{update:function(e){var t,n=["opacity","color"];for(t=n.length-1;t>=0;t--)e[n[t]]!=null&&this.style("stop-"+n[t],e[n[t]]);return this.attr("offset",(e.offset!=null?e.offset:this.attrs.offset||0)+"%")}}),SVG.Doc=function(e){this.constructor.call(this,SVG.create("svg")),this.parent=typeof e=="string"?document.getElementById(e):e,this.attr({xmlns:SVG.ns,version:"1.1",width:"100%",height:"100%"}).attr("xlink",SVG.xlink,SVG.ns).defs(),this.stage()},SVG.Doc.prototype=new SVG.Container,SVG.Doc.prototype.stage=function(){var e,t=this,n=document.createElement("div");return n.style.cssText="position:relative;height:100%;",t.parent.appendChild(n),n.appendChild(t.node),e=function(){document.readyState==="complete"?(t.style("position:absolute;"),setTimeout(function(){t.style("position:relative;"),t.parent.removeChild(t.node.parentNode),t.node.parentNode.removeChild(t.node),t.parent.appendChild(t.node)},5)):setTimeout(e,10)},e(),this},SVG.Shape=function(e){this.constructor.call(this,e)},SVG.Shape.prototype=new SVG.Element,SVG.Wrap=function(e){this.constructor.call(this,SVG.create("g")),this.node.insertBefore(e.node,null),this.child=e,this.type=e.node.nodeName},SVG.Wrap.prototype=new SVG.Shape,SVG.extend(SVG.Wrap,{move:function(e,t){return this.transform({x:e,y:t})},size:function(e,t){var n=e/this._b.width;return this.child.transform({scaleX:n,scaleY:t!=null?t/this._b.height:n}),this},center:function(e,t){return this.move(e+this._b.width*this.child.trans.scaleX/-2,t+this._b.height*this.child.trans.scaleY/-2)},attr:function(e,t,n){if(typeof e=="object")for(t in e)this.attr(t,e[t]);else{if(arguments.length<2)return e=="transform"?this.attrs[e]:this.child.attrs[e];e=="transform"?(this.attrs[e]=t,n!=null?this.node.setAttributeNS(n,e,t):this.node.setAttribute(e,t)):this.child.attr(e,t,n)}return this},plot:function(e){return this.child.plot(e),this._b=this.child.bbox(),this.child.transform({x:-this._b.x,y:-this._b.y}),this}}),SVG.Rect=function(){this.constructor.call(this,SVG.create("rect"))},SVG.Rect.prototype=new SVG.Shape,SVG.Ellipse=function(){this.constructor.call(this,SVG.create("ellipse"))},SVG.Ellipse.prototype=new SVG.Shape,SVG.extend(SVG.Ellipse,{move:function(e,t){return this.attrs.x=e,this.attrs.y=t,this.center()},size:function(e,t){return this.attr({rx:e/2,ry:(t!=null?t:e)/2}).center()},center:function(e,t){return this.attr({cx:e!=null?e:(this.attrs.x||0)+(this.attrs.rx||0),cy:t!=null?t:(this.attrs.y||0)+(this.attrs.ry||0)})}}),SVG.Line=function(){this.constructor.call(this,SVG.create("line"))},SVG.Line.prototype=new SVG.Shape,SVG.extend(SVG.Line,{move:function(e,t){var n=this.bbox();return this.attr({x1:this.attr("x1")-n.x+e,y1:this.attr("y1")-n.y+t,x2:this.attr("x2")-n.x+e,y2:this.attr("y2")-n.y+t})},center:function(e,t){var n=this.bbox();return this.move(e-n.width/2,t-n.height/2)},size:function(e,t){var n=this.bbox();return this.attr(this.attr("x1")<this.attr("x2")?"x2":"x1",n.x+e).attr(this.attr("y1")<this.attr("y2")?"y2":"y1",n.y+t)}}),SVG.extend(SVG.Container,{line:function(e,t,n,r){return this.put((new SVG.Line).attr({x1:e,y1:t,x2:n,y2:r}))}}),SVG.Poly={plot:function(e){return this.attr("points",e||"0,0"),this}},SVG.Polyline=function(){this.constructor.call(this,SVG.create("polyline"))},SVG.Polyline.prototype=new SVG.Shape,SVG.extend(SVG.Polyline,SVG.Poly),SVG.Polygon=function(){this.constructor.call(this,SVG.create("polygon"))},SVG.Polygon.prototype=new SVG.Shape,SVG.extend(SVG.Polygon,SVG.Poly),SVG.Path=function(){this.constructor.call(this,SVG.create("path"))},SVG.Path.prototype=new SVG.Shape,SVG.extend(SVG.Path,{move:function(e,t){this.transform({x:e,y:t})},plot:function(e){return this.attr("d",e||"M0,0")}}),SVG.Image=function(){this.constructor.call(this,SVG.create("image"))},SVG.Image.prototype=new SVG.Shape,SVG.extend(SVG.Image,{load:function(e){return this.src=e,e?this.attr("xlink:href",e,SVG.xlink):this}});var e="size family weight stretch variant style".split(" ");SVG.Text=function(){this.constructor.call(this,SVG.create("text")),this.styles={"font-size":16,"font-family":"Helvetica","text-anchor":"start"},this._leading=1.2},SVG.Text.prototype=new SVG.Shape,SVG.extend(SVG.Text,{text:function(e){if(e==null)return this.content;this.clear(),this.content=SVG.regex.isBlank.test(e)?"text":e;var t,n,r=e.split("\n");for(t=0,n=r.length;t<n;t++)this.tspan(r[t]);return this.attr("style",this.style())},tspan:function(e){var t=(new SVG.TSpan).text(e);return this.node.appendChild(t.node),this.lines.push(t),t.attr("style",this.style())},center:function(e,t){var n=this.style("text-anchor"),r=this.bbox(),e=n=="start"?e-r.width/2:n=="end"?e+r.width/2:e;return this.move(e,t-r.height/2)},size:function(e){return this.attr("font-size",e)},leading:function(e){return e==null?this._leading:(this._leading=e,this.rebuild())},rebuild:function(){var e,t,n=this.styles["font-size"];for(e=0,t=this.lines.length;e<t;e++)this.lines[e].attr({dy:n*this._leading-(e==0?n*.3:0),x:this.attrs.x||0,style:this.style()});return this},clear:function(){while(this.node.hasChildNodes())this.node.removeChild(this.node.lastChild);return this.lines=[],this}}),SVG.TSpan=function(){this.constructor.call(this,SVG.create("tspan"))},SVG.TSpan.prototype=new SVG.Shape,SVG.extend(SVG.TSpan,{text:function(e){return this.node.appendChild(document.createTextNode(e)),this}}),SVG.Nested=function(){this.constructor.call(this,SVG.create("svg")),this.style("overflow","visible")},SVG.Nested.prototype=new SVG.Container,SVG._stroke=["color","width","opacity","linecap","linejoin","miterlimit","dasharray","dashoffset"],SVG._fill=["color","opacity","rule"];var t=function(e,t){return t=="color"?e:e+"-"+t};["fill","stroke"].forEach(function(e){var n={};n[e]=function(n){var r;if(typeof n=="string"||SVG.Color.isRgb(n)||SVG.Color.isHsb(n))this.attr(e,n);else for(index=SVG["_"+e].length-1;index>=0;index--)n[SVG["_"+e][index]]!=null&&this.attr(t(e,SVG["_"+e][index]),n[SVG["_"+e][index]]);return this},SVG.extend(SVG.Shape,SVG.FX,n)}),SVG.extend(SVG.Element,SVG.FX,{rotate:function(e,t,n){return this.transform({rotation:e||0,cx:t,cy:n})},skew:function(e,t){return this.transform({skewX:e||0,skewY:t||0})},scale:function(e,t){return this.transform({scaleX:e,scaleY:t==null?e:t})},opacity:function(e){return this.attr("opacity",e)}}),SVG.Text&&SVG.extend(SVG.Text,SVG.FX,{font:function(t){for(var n in t)n=="anchor"?this.attr("text-anchor",t[n]):e.indexOf(n)>-1?this.attr("font-"+n,t[n]):this.attr(n,t[n]);return this}})}).call(this);
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644 (file)
index 0000000..a9070d3
--- /dev/null
@@ -0,0 +1,37 @@
+{
+  "name":         "svg.js"
+, "description":  "A lightweight library for manipulating and animating SVG."
+, "url":          "http://svgjs.com"
+, "homepage":     "http://svgjs.com"
+, "keywords":     ["svg", "vector", "graphics", "animation"]
+, "author":       "Wout Fierens <wout@impinc.co.uk>"
+, "main":         "dist/svg.js"
+, "version":      "v0.9"
+, "jam": {
+    "include": [
+      "dist/svg.js"
+    , "README.md"
+    , "MIT-LICENSE"
+    ]
+  }
+, "maintainers": [
+    {
+      "name":     "Wout Fierens"
+    , "email":    "wout@impinc.co.uk"
+    , "web":      "http://impinc.co.uk"
+    }
+  ]
+, "licenses": [
+    {
+      "type":     "MIT"
+    , "url":      "http://www.opensource.org/licenses/mit-license.php"
+    }
+  ]
+, "repositories": [
+    {
+      "type":     "git"
+    , "url":      "https://github.com/wout/svg.js.git"
+    }
+  ]
+, "github":       "https://github.com/wout/svg.js"
+}
\ No newline at end of file
index 47134edee09ddbb146bcb76e30b3c5735a005a1e..3ef486fe749f41b89dd95c69508e33d2cba6ee06 100644 (file)
@@ -24,11 +24,9 @@ SVG.extend(SVG.Element, {
   }
   // Send given element one step backward
 , backward: function() {
-    var i
-    
     this.parent.level()
     
-    i = this.position()
+    var i = this.position()
     
     if (i > 1)
       this.parent.remove(this).add(this, i - 1)
index d70ac6885038c6cf62e82524bf6daac6e001f316..6b9885aeead0640b616bf4d878dc9c0cb5670b72 100644 (file)
@@ -8,7 +8,7 @@ SVG.BBox = function(element) {
   this.y = box.y + element.trans.y
   
   /* add the center */
-  this.cx = box.x + element.trans.x + box.width  / 2
+  this.cx = box.x + element.trans.x + box.width / 2
   this.cy = box.y + element.trans.y + box.height / 2
   
   /* plain width and height */
index dde2c6532a026c0221e2690dee442ac724124fc3..89c811d3e9f2b8c1cc4e98fd1589ff703c5c8742 100644 (file)
@@ -42,7 +42,6 @@ SVG.Color = function(color) {
     this.r = color.r
     this.g = color.g
     this.b = color.b
-    
   }
     
 }
index a2db3a49312b3505cb5ac39fe848bd1fa16bed07..2e2fd0af4e02e727261dd57c5b8a3dab2da88ead 100644 (file)
@@ -26,9 +26,9 @@ SVG.Doc.prototype = new SVG.Container
 // Basically it sets the position of the svg node to absolute
 // when the dom is loaded, and resets it to relative a few milliseconds later.
 SVG.Doc.prototype.stage = function() {
-  var check,
-      element = this,
-      wrapper = document.createElement('div')
+  var check
+    , element = this
+    , wrapper = document.createElement('div')
   
   /* set temp wrapper to position relative */
   wrapper.style.cssText = 'position:relative;height:100%;'
@@ -40,10 +40,10 @@ SVG.Doc.prototype.stage = function() {
   /* check for dom:ready */
   check = function() {
     if (document.readyState === 'complete') {
-      element.attr('style', 'position:absolute;')
+      element.style('position:absolute;')
       setTimeout(function() {
         /* set position back to relative */
-        element.attr('style', 'position:relative;')
+        element.style('position:relative;')
         
         /* remove temp wrapper */
         element.parent.removeChild(element.node.parentNode)
index e11f650f940dad6d5b0c7458a8f7267de7a4c225..2e7ebb29251c09a542ceec9c2464bb60abb5729d 100644 (file)
@@ -23,7 +23,7 @@ SVG.Element = function(node) {
   }
   
   /* initialize style store */
-  this.style = {}
+  this.styles = {}
   
   /* initialize transformation store with defaults */
   this.trans = {
@@ -112,6 +112,7 @@ SVG.extend(SVG.Element, {
 , remove: function() {
     if (this.parent)
       this.parent.remove(this)
+    
     return this
   }
   // Get parent document
@@ -127,24 +128,29 @@ SVG.extend(SVG.Element, {
     if (arguments.length < 2) {
       /* apply every attribute individually if an object is passed */
       if (typeof a == 'object')
-        for (v in a) this.attr(v, a[v])
+        for (v in a)
+          this.attr(v, a[v])
       
       /* act as a getter for style attributes */
       else if (this._isStyle(a))
         return a == 'text' ?
                  this.content :
                a == 'leading' ?
-                 this[a] :
-                 this.style[a]
+                 this.leading() :
+                 this.style(a)
       
       /* act as a getter if the first and only argument is not an object */
       else
-        return this.attrs[a]
+        return this.attrs[a] || this.node.getAttribute(a)
     
     } else if (v === null) {
       /* remove value */
       this.node.removeAttribute(a)
       
+    } else if (a == 'style') {
+      /* redirect to the style method */
+      return this.style(v)
+      
     } else {
       /* store value */
       this.attrs[a] = v
@@ -175,28 +181,38 @@ SVG.extend(SVG.Element, {
         a == 'text' ?
           this.text(v) :
         a == 'leading' ?
-          this[a] = v :
-          this.style[a] = v
-      
-        this.text(this.content)
+          this.leading(v) :
+          this.style(a, v)
+        
+        /* rebuild if required */
+        if (this.rebuild)
+          this.rebuild()
       }
     }
     
     return this
   }
   // Manage transformations
-, transform: function(o) {
-    /* act as a getter if the first argument is a string */
-    if (typeof o === 'string')
-      return this.trans[o]
+, transform: function(o, v) {
+    if (typeof o === 'string') {
+      /* act as a getter if only one string argument is given */
+      if (arguments.length < 2)
+        return this.trans[o]
       
+      /* apply transformations as object if key value arguments are given*/
+      var transform = {}
+      transform[o] = v
+      
+      return this.transform(transform)
+    }
+    
     /* ... otherwise continue as a setter */
-    var key, transform = []
+    var transform = []
     
     /* merge values */
-    for (key in o)
-      if (o[key] != null)
-        this.trans[key] = o[key]
+    for (v in o)
+      if (o[v] != null)
+        this.trans[v] = o[v]
     
     /* alias current transformations */
     o = this.trans
@@ -227,6 +243,52 @@ SVG.extend(SVG.Element, {
     /* add only te required transformations */
     return this.attr('transform', transform.join(' '))
   }
+  // Dynamic style generator
+, style: function(s, v) {
+    if (arguments.length == 0) {
+      /* get full style */
+      return this.attr('style')
+    
+    } 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 if (SVG.regex.isCss.test(s)) {
+        /* parse css string */
+        s = s.split(';')
+
+        /* apply every definition individually */
+        for (var i = 0; i < s.length; i++) {
+          v = s[i].split(':')
+
+          if (v.length == 2)
+            this.style(v[0].replace(/\s+/g, ''), v[1].replace(/^\s+/,'').replace(/\s+$/,''))
+        }
+      } else {
+        /* act as a getter if the first and only argument is not an object */
+        return this.styles[s]
+      }
+    
+    } else if (v === null) {
+      /* remove value */
+      delete this.styles[s]
+      
+    } else {
+      /* store value */
+      this.styles[s] = v
+    }
+    
+    /* rebuild style string */
+    s = ''
+    for (v in this.styles)
+      s += v + ':' + this.styles[v] + ';'
+    
+    /* apply style */
+    this.node.setAttribute('style', s)
+    
+    return this
+  }
   // Store data values on svg nodes
 , data: function(a, v, r) {
     if (arguments.length < 2) {
@@ -257,19 +319,15 @@ SVG.extend(SVG.Element, {
   }
   // Show element
 , show: function() {
-    this.node.style.display = ''
-    
-    return this
+    return this.style('display', '')
   }
   // Hide element
 , hide: function() {
-    this.node.style.display = 'none'
-    
-    return this
+    return this.style('display', 'none')
   }
   // Is element visible?
 , visible: function() {
-    return this.node.style.display != 'none'
+    return this.style('display') != 'none'
   }
   // Private: find svg parent by instance
 , _parent: function(parent) {
@@ -282,7 +340,7 @@ SVG.extend(SVG.Element, {
   }
   // Private: tester method for style detection
 , _isStyle: function(attr) {
-    return typeof attr == 'string' && this._isText() ? (/^font|text|leading/).test(attr) : false
+    return typeof attr == 'string' ? SVG.regex.isStyle.test(attr) : false
   }
   // Private: element type tester
 , _isText: function() {
index f9398cfa5258e9317d9d089d2198bfd96332aa12..6ff56083b1932ff9255f3afd4d1aa54d22dfd1ff 100644 (file)
@@ -17,15 +17,15 @@ SVG.extend(SVG.Ellipse, {
   },
   // Custom size function
   size: function(width, height) {
-    return this.
-      attr({ rx: width / 2, ry: (height != null ? height : width) / 2 }).
-      center()
+    return this
+     .attr({ rx: width / 2, ry: (height != null ? height : width) / 2 })
+     .center()
   },
   // Custom center function
   center: function(x, y) {
     return this.attr({
-      cx: x || (this.attrs.x || 0) + (this.attrs.rx || 0),
-      cy: y || (this.attrs.y || 0) + (this.attrs.ry || 0)
+      cx: x != null ? x : (this.attrs.x || 0) + (this.attrs.rx || 0)
+    , cy: y != null ? y : (this.attrs.y || 0) + (this.attrs.ry || 0)
     })
   }
   
index df3cd6a20f6b8640a0cf6c48f4b3276fa9825b50..84022c758d531909f217fcac1344b1cffa6a5955 100644 (file)
@@ -3,28 +3,27 @@
 //     rect.click(function() {
 //       this.fill({ color: '#f06' })
 //     })
-;[ 'click',
-  'dblclick',
-  'mousedown',
-  'mouseup',
-  'mouseover',
-  'mouseout',
-  'mousemove',
-  'mouseenter',
-  'mouseleave',
-  'touchstart',
-  'touchend',
-  'touchmove',
-  'touchcancel' ].forEach(function(event) {
+;[ 'click'
+, 'dblclick'
+, 'mousedown'
+, 'mouseup'
+, 'mouseover'
+, 'mouseout'
+, 'mousemove'
+, 'mouseenter'
+, 'mouseleave'
+, 'touchstart'
+, 'touchend'
+, 'touchmove'
+, '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
+    this.node['on' + event] = typeof f == 'function' ?
+      function() { return f.apply(self, arguments) } : null
     
     return this
   }
@@ -54,11 +53,11 @@ SVG.extend(SVG.Element, {
     SVG.on(this.node, event, listener)
     
     return this
-  },
+  }
   // Unbind event from listener
-  off: function(event, listener) {
+, off: function(event, listener) {
     SVG.off(this.node, event, listener)
     
     return this
   }
-});
\ No newline at end of file
+})
\ No newline at end of file
index 94a6873b6c82d971e68044c9b146120e3ff1da70..c17dcd8b3caff13c52fc5e66629e5f3dd89be357 100644 (file)
--- a/src/fx.js
+++ b/src/fx.js
@@ -11,7 +11,7 @@ SVG.extend(SVG.FX, {
     duration = duration == null ? 1000 : duration
     ease = ease || '<>'
     
-    var akeys, tkeys, tvalues
+    var akeys, tkeys, skeys
       , element   = this.target
       , fx        = this
       , start     = new Date().getTime()
@@ -20,24 +20,29 @@ SVG.extend(SVG.FX, {
     /* start animation */
     this.interval = setInterval(function(){
       // This code was borrowed from the emile.js micro framework by Thomas Fuchs, aka MadRobby.
-      var index
+      var i, key
         , time = new Date().getTime()
         , pos = time > finish ? 1 : (time - start) / duration
       
       /* collect attribute keys */
       if (akeys == null) {
         akeys = []
-        for (var key in fx.attrs)
+        for (key in fx.attrs)
           akeys.push(key)
       }
       
       /* collect transformation keys */
       if (tkeys == null) {
         tkeys = []
-        for (var key in fx.trans)
+        for (key in fx.trans)
           tkeys.push(key)
-        
-        tvalues = {}
+      }
+      
+      /* collect style keys */
+      if (skeys == null) {
+        skeys = []
+        for (key in fx.styles)
+          skeys.push(key)
       }
       
       /* apply easing */
@@ -57,23 +62,23 @@ SVG.extend(SVG.FX, {
       if (fx._move)
         element.move(fx._at(fx._move.x, pos), fx._at(fx._move.y, pos))
       else if (fx._center)
-        element.move(fx._at(fx._center.x, pos), fx._at(fx._center.y, pos))
+        element.center(fx._at(fx._center.x, pos), fx._at(fx._center.y, pos))
       
       /* run all size properties */
       if (fx._size)
         element.size(fx._at(fx._size.width, pos), fx._at(fx._size.height, pos))
       
       /* animate attributes */
-      for (index = akeys.length - 1; index >= 0; index--)
-        element.attr(akeys[index], fx._at(fx.attrs[akeys[index]], pos))
+      for (i = akeys.length - 1; i >= 0; i--)
+        element.attr(akeys[i], fx._at(fx.attrs[akeys[i]], pos))
       
       /* animate transformations */
-      if (tkeys.length > 0) {
-        for (index = tkeys.length - 1; index >= 0; index--)
-          tvalues[tkeys[index]] = fx._at(fx.trans[tkeys[index]], pos)
-        
-        element.transform(tvalues)
-      }
+      for (i = tkeys.length - 1; i >= 0; i--)
+        element.transform(tkeys[i], fx._at(fx.trans[tkeys[i]], pos))
+      
+      /* animate styles */
+      for (i = skeys.length - 1; i >= 0; i--)
+        element.style(skeys[i], fx._at(fx.styles[skeys[i]], pos))
       
       /* callback for each keyframe */
       if (fx._during)
@@ -100,12 +105,23 @@ SVG.extend(SVG.FX, {
     else
       this.attrs[a] = { from: this.target.attr(a), to: v }
     
-    return this;  
+    return this
   }
   // Add animatable transformations
-, transform: function(o) {
-    for (var key in o)
-      this.trans[key] = { from: this.target.trans[key], to: o[key] }
+, transform: function(t, v) {
+    for (var key in t)
+      this.trans[key] = { from: this.target.trans[key], to: t[key] }
+    
+    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.styles[s] = { from: this.target.style(s), to: v }
     
     return this
   }
@@ -122,11 +138,18 @@ SVG.extend(SVG.FX, {
   }
   // Add animatable size
 , size: function(width, height) {
-    var box = this.target.bbox()
-    
-    this._size = {
-      width:  { from: box.width,  to: width  }
-    , height: { from: box.height, to: 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 = this.target.bbox()
+
+      this._size = {
+        width:  { from: box.width,  to: width  }
+      , height: { from: box.height, to: height }
+      }
     }
     
     return this
@@ -162,6 +185,7 @@ SVG.extend(SVG.FX, {
     /* reset storage for properties that need animation */
     this.attrs    = {}
     this.trans    = {}
+    this.styles   = {}
     this._move    = null
     this._size    = null
     this._after   = null
index 73975c5f431215e6398adccd53809b88fa75c5d9..4c30b43e235e7765801aae18820675d317531bc1 100644 (file)
@@ -15,25 +15,25 @@ SVG.extend(SVG.Gradient, {
     return this.type == 'radial' ?
       this.attr({ fx: x + '%', fy: y + '%' }) :
       this.attr({ x1: x + '%', y1: y + '%' })
-  },
+  }
   // To position
-  to: function(x, y) {
+, to: function(x, y) {
     return this.type == 'radial' ?
       this.attr({ cx: x + '%', cy: y + '%' }) :
       this.attr({ x2: x + '%', y2: y + '%' })
-  },
+  }
   // Radius for radial gradient
-  radius: function(radius) {
+, radius: function(radius) {
     return this.type == 'radial' ?
       this.attr({ r: radius + '%' }) :
       this
-  },
+  }
   // Add a color stop
-  at: function(stop) {
+, at: function(stop) {
     return this.put(new SVG.Stop(stop))
-  },
+  }
   // Update gradient
-  update: function(block) {
+, update: function(block) {
     /* remove all stops */
     while (this.node.hasChildNodes())
       this.node.removeChild(this.node.lastChild)
@@ -42,9 +42,9 @@ SVG.extend(SVG.Gradient, {
     block(this)
     
     return this
-  },
+  }
   // Return the fill id
-  fill: function() {
+, fill: function() {
     return 'url(#' + this.attr('id') + ')'
   }
   
@@ -81,20 +81,16 @@ SVG.extend(SVG.Stop, {
   
   /* add color stops */
   update: function(o) {
-    var index,
-        style = '',
-        attr  = ['opacity', 'color']
+    var index
+      , attr = ['opacity', 'color']
     
     /* build style attribute */
     for (index = attr.length - 1; index >= 0; index--)
       if (o[attr[index]] != null)
-        style += 'stop-' + attr[index] + ':' + o[attr[index]] + ';'
+        this.style('stop-' + attr[index], o[attr[index]])
     
     /* set attributes */
-    return this.attr({
-      offset: (o.offset != null ? o.offset : this.attrs.offset || 0) + '%',
-      style:  style
-    })
+    return this.attr('offset', (o.offset != null ? o.offset : this.attrs.offset || 0) + '%')
   }
   
 })
index 1e783e4b2d5685a3cf0cc7f1849117a15b47beff..0712f1eb77eca1d89a485038e940532bddd97e5f 100644 (file)
@@ -12,24 +12,25 @@ SVG.extend(SVG.Line, {
     var bbox = this.bbox()
     
     return this.attr({
-      x1: this.attr('x1') - bbox.x + x,
-      y1: this.attr('y1') - bbox.y + y,
-      x2: this.attr('x2') - bbox.x + x,
-      y2: this.attr('y2') - bbox.y + y
+      x1: this.attr('x1') - bbox.x + x
+    , y1: this.attr('y1') - bbox.y + y
+    , x2: this.attr('x2') - bbox.x + x
+    , y2: this.attr('y2') - bbox.y + y
     })
-  },
+  }
   // Move element by its center
-  center: function(x, y) {
+, center: function(x, y) {
     var bbox = this.bbox()
     
     return this.move(x - bbox.width / 2, y - bbox.height / 2)
-  },
+  }
   // Set line size by width and height
-  size: function(width, height) {
+, size: function(width, height) {
     var bbox = this.bbox()
     
-    this.attr(this.attr('x1') < this.attr('x2') ? 'x2' : 'x1', bbox.x + width)
-    return this.attr(this.attr('y1') < this.attr('y2') ? 'y2' : 'y1', bbox.y + height)
+    return this
+      .attr(this.attr('x1') < this.attr('x2') ? 'x2' : 'x1', bbox.x + width)
+      .attr(this.attr('y1') < this.attr('y2') ? 'y2' : 'y1', bbox.y + height)
   }
 })
 
@@ -37,10 +38,10 @@ SVG.extend(SVG.Line, {
 SVG.extend(SVG.Container, {
   line: function(x1, y1, x2, y2) {
     return this.put(new SVG.Line().attr({
-      x1: x1,
-      y1: y1,
-      x2: x2,
-      y2: y2
+      x1: x1
+    , y1: y1
+    , x2: x2
+    , y2: y2
     }))
   }
 })
\ No newline at end of file
index 9d4401c6d0c4c87a6bee1c31827abe3729d315d3..537d6108900b9e2e239815d1ca0f6443b9ace4fb 100644 (file)
@@ -1,7 +1,7 @@
 SVG.Nested = function() {
   this.constructor.call(this, SVG.create('svg'))
   
-  this.attr('style', 'overflow:visible')
+  this.style('overflow', 'visible')
 }
 
 // Inherit from SVG.Container
index e62f8d15ebfb6027fc77b4de0bcbf88d6c2aa6eb..2d3558fca9db3dc03859f62bfdf3f5bbbdfc1c53 100644 (file)
@@ -6,18 +6,17 @@ SVG.Path = function() {
 SVG.Path.prototype = new SVG.Shape()
 
 SVG.extend(SVG.Path, {
-  
-  /* move using transform */
+  // Move using transform
   move: function(x, y) {
     this.transform({
       x: x,
       y: y
     })
-  },
+  }
   
-  /* set path data */
-  plot: function(data) {
+  // Set path data
+, plot: function(data) {
     return this.attr('d', data || 'M0,0')
   }
   
-});
\ No newline at end of file
+})
\ No newline at end of file
index 7343d6a9a3c3df467ff9fcfebcd935b58fe7dd6a..c5f51e0c2476a79fb1cb8d7d0e2cb0010d653671 100644 (file)
@@ -25,11 +25,11 @@ SVG.extend(SVG.Defs, {
     block(element)
     
     return element.attr({
-      x:            0,
-      y:            0,
-      width:        width,
-      height:       height,
-      patternUnits: 'userSpaceOnUse'
+      x:            0
+    , y:            0
+    , width:        width
+    , height:       height
+    , patternUnits: 'userSpaceOnUse'
     })
   }
   
index 9e8957088da218c517ab4cd24f413ceee0e12539..ce5a70c891a0cf531707905aa6ba670109b715ac 100644 (file)
@@ -12,7 +12,7 @@ SVG.Polyline = function() {
 }
 
 // Inherit from SVG.Shape
-SVG.Polyline.prototype = new SVG.Shape()
+SVG.Polyline.prototype = new SVG.Shape
 
 // Add polygon-specific functions
 SVG.extend(SVG.Polyline, SVG.Poly)
@@ -22,7 +22,7 @@ SVG.Polygon = function() {
 }
 
 // Inherit from SVG.Shape
-SVG.Polygon.prototype = new SVG.Shape()
+SVG.Polygon.prototype = new SVG.Shape
 
 // Add polygon-specific functions
 SVG.extend(SVG.Polygon, SVG.Poly)
\ No newline at end of file
index 0a398be7aa9c5451e5f8edb04f87339178957505..1a3bf19cb95ccaa86ca3ff22840c5223a2fcc143 100644 (file)
@@ -3,4 +3,4 @@ SVG.Rect = function() {
 }
 
 // Inherit from SVG.Shape
-SVG.Rect.prototype = new SVG.Shape()
\ No newline at end of file
+SVG.Rect.prototype = new SVG.Shape
\ No newline at end of file
index e89dc8545153fc27b626dae54e7756db448cf53f..adf82b49c89f8455d2df2b5b288d011ef86c7b92 100644 (file)
@@ -1,18 +1,33 @@
 // Storage for regular expressions
 SVG.regex = {
+  /* parse unit value */
+  unit:     /^([\d\.]+)([a-z%]{0,2})$/
   
-  unit:   /^([\d\.]+)([a-z%]{0,2})$/
+  /* parse hex value */
+, hex:      /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i
   
-, hex:    /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i
-
-, rgb:    /rgb\((\d+),(\d+),(\d+),([\d\.]+)\)/
-
-, hsb:    /hsb\((\d+),(\d+),(\d+),([\d\.]+)\)/
-
-, isHex:  /^#/i
-
-, isRgb:  /^rgb\(/
+  /* parse rgb value */
+, rgb:      /rgb\((\d+),(\d+),(\d+),([\d\.]+)\)/
+  
+  /* parse hsb value */
+, hsb:      /hsb\((\d+),(\d+),(\d+),([\d\.]+)\)/
   
-, isHsb:  /^hsb\(/
+  /* test hex value */
+, isHex:    /^#[a-f0-9]{3,6}$/i
   
+  /* test rgb value */
+, isRgb:    /^rgb\(/
+  
+  /* test hsb value */
+, isHsb:    /^hsb\(/
+  
+  /* test css declaration */
+, isCss:    /[^:]+:[^;]+;?/
+  
+  /* test css property */
+, isStyle:  /^font|text|leading|cursor/
+  
+  /* test for blank string */
+, isBlank:  /^(\s+)?$/
+
 }
\ No newline at end of file
index a11bbc478666d934514b81364c317c424f3401bc..0594ed75805f09b7afd70fdb782110565178cfae 100644 (file)
@@ -3,4 +3,4 @@ SVG.Shape = function(element) {
 }
 
 // Inherit from SVG.Element
-SVG.Shape.prototype = new SVG.Element()
\ No newline at end of file
+SVG.Shape.prototype = new SVG.Element
\ No newline at end of file
index 14868e30e208d9398c3cb9f821e800e801b053f2..1f7339ad7685b46970ffbb02b74d593931c9b3ea 100644 (file)
@@ -63,23 +63,19 @@ SVG.extend(SVG.Element, SVG.FX, {
 
 
 if (SVG.Text) {
-  SVG.extend(SVG.Text, {
+  SVG.extend(SVG.Text, SVG.FX, {
     // Set font 
     font: function(o) {
-      var key, attr = {}
-
-      for (key in o)
-        key == 'leading' ?
-          attr[key] = o[key] :
+      for (var key in o)
         key == 'anchor' ?
-          attr['text-anchor'] = o[key] :
+          this.attr('text-anchor', o[key]) :
         _styleAttr.indexOf(key) > -1 ?
-          attr['font-'+ key] = o[key] :
-          void 0
-
-      return this.attr(attr).text(this.content)
+          this.attr('font-'+ key, o[key]) :
+          this.attr(key, o[key])
+      
+      return this
     }
-
+    
   })
 }
 
index e7f43637187b0ef8551373c7802cee5c293354e3..ec3ba7138d5a92a3ab9f7a6bef1d86eb340e4da5 100644 (file)
@@ -1,56 +1,60 @@
 
-// Use the `svg()` function to create a SVG document within a given html element. The first argument can either be an id of the element or the selected element itself.
+// Use the `SVG()` function to create a SVG document within a given html element. The first argument can either be an id of the element or the selected element itself.
 //
-//     var draw = svg('paper').size(300, 300)
+//     var draw = SVG('paper').size(300, 300)
 //     var rect = draw.rect(100, 100).attr({ fill: '#f06' })
 
 
 
-// Shortcut for creating a svg document
-this.svg = function(element) {
+// The main wrapping element
+this.SVG = function(element) {
   if (SVG.supported)
     return new SVG.Doc(element)
 }
 
-// The main wrapping element
-this.SVG = {
-  /* default namespaces */
-  ns:    'http://www.w3.org/2000/svg'
-, xlink: 'http://www.w3.org/1999/xlink'
+// DEPRECATED!!! Use SVG() instead
+this.svg = function(element) {
+  console.warn('WARNING: svg() is deprecated, please use SVG() instead.')
+  return SVG(element)
+}
+
+// Default namespaces
+SVG.ns = 'http://www.w3.org/2000/svg'
+SVG.xlink = 'http://www.w3.org/1999/xlink'
+
+// Element id sequence
+SVG.did  = 1000
+
+// Get next named element id
+SVG.eid = function(name) {
+  return 'Svgjs' + name.charAt(0).toUpperCase() + name.slice(1) + 'Element' + (SVG.did++)
+}
+
+// Method for element creation
+SVG.create = function(name) {
+  /* create element */
+  var element = document.createElementNS(this.ns, name)
   
-  /* element id sequence */
-, did: 1000
-
-  // Get next named element id
-, eid: function(name) {
-    return 'Svgjs' + name.charAt(0).toUpperCase() + name.slice(1) + 'Element' + (SVG.did++)
-  }
-  // Method for element creation
-, create: function(name) {
-    /* create element */
-    var element = document.createElementNS(this.ns, name)
-    
-    /* apply unique id */
-    element.setAttribute('id', this.eid(name))
-    
-    return element
-  }
+  /* apply unique id */
+  element.setAttribute('id', this.eid(name))
+  
+  return element
+}
+
   // Method for extending objects
-, extend: function() {
-    var modules, methods, key, i
-    
-    /* get list of modules */
-    modules = Array.prototype.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]
-  }
+SVG.extend = function() {
+  var modules, methods, key, i
+  
+  /* get list of modules */
+  modules = Array.prototype.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]
 }
 
 // svg support test
@@ -59,4 +63,4 @@ SVG.supported = (function() {
          !! document.createElementNS(SVG.ns,'svg').createSVGRect
 })()
 
-if (!SVG.supported) return false;
\ No newline at end of file
+if (!SVG.supported) return false
\ No newline at end of file
index 6201269a6de63d50b62933bbf6a0ddbd442e0c43..3feb514cce7e2375f496d5c056b6fc9b41e2aa53 100644 (file)
 
 // List font style attributes as they should be applied to style 
-var _styleAttr = ['size', 'family', 'weight', 'stretch', 'variant', 'style']
+var _styleAttr = ('size family weight stretch variant style').split(' ')
 
 SVG.Text = function() {
   this.constructor.call(this, SVG.create('text'))
   
   /* define default style */
-  this.style = { 'font-size':  16, 'font-family': 'Helvetica', 'text-anchor': 'start' }
-  this.leading = 1.2
+  this.styles = {
+    'font-size':    16
+  , 'font-family':  'Helvetica'
+  , 'text-anchor':  'start'
+  }
+  
+  this._leading = 1.2
 }
 
 // Inherit from SVG.Element
-SVG.Text.prototype = new SVG.Shape()
+SVG.Text.prototype = new SVG.Shape
 
 SVG.extend(SVG.Text, {
   // Set the text content
   text: function(text) {
-    /* update the content */
-    this.content = text = text || 'text'
-    this.lines = []
+    /* act as getter */
+    if (text == null)
+      return this.content
     
-    var index, length, tspan,
-        style   = this._style(),
-        parent  = this.doc(),
-        lines   = text.split("\n"),
-        size    = this.style['font-size']
+    /* remove existing lines */
+    this.clear()
     
-    /* remove existing child nodes */
-    while (this.node.hasChildNodes())
-      this.node.removeChild(this.node.lastChild)
+    /* update the content */
+    this.content = SVG.regex.isBlank.test(text) ? 'text' : text
+    
+    var i, il
+      , lines = text.split('\n')
     
     /* build new lines */
-    for (index = 0, length = lines.length; index < length; index++) {
-      /* create new tspan and set attributes */
-      tspan = new SVG.TSpan().
-        text(lines[index]).
-        attr({
-          dy:     size * this.leading - (index == 0 ? size * 0.3 : 0),
-          x:      (this.attrs.x || 0),
-          style:  style
-        })
+    for (i = 0, il = lines.length; i < il; i++)
+      this.tspan(lines[i])
       
-      /* add new tspan */
-      this.node.appendChild(tspan.node)
-      this.lines.push(tspan)
-    }
-    
     /* set style */
-    return this.attr('style', style)
-  },
-  
-  // Build style based on _styleAttr
-  _style: function() {
-    var index, style = ''
+    return this.attr('style', this.style())
+  }
+  // Create a tspan
+, tspan: function(text) {
+    var tspan = new SVG.TSpan().text(text)
     
-    for (index = _styleAttr.length - 1; index >= 0; index--)
-      if (this.style['font-' + _styleAttr[index]] != null)
-        style += 'font-' + _styleAttr[index] + ':' + this.style['font-' + _styleAttr[index]] + ';'
+    /* add new tspan */
+    this.node.appendChild(tspan.node)
+    this.lines.push(tspan)
     
-    style += 'text-anchor:' + this.style['text-anchor'] + ';'
-      
-    return style
+    return tspan.attr('style', this.style())
+  }
+  // Move element by its center
+, center: function(x, y) {
+    var anchor = this.style('text-anchor')
+      , box = this.bbox()
+      , x = anchor == 'start' ?
+          x - box.width / 2 :
+        anchor == 'end' ?
+          x + box.width / 2 : x
+    
+    return this.move(x, y - box.height / 2)
+  }
+  // Set font size
+, size: function(size) {
+    return this.attr('font-size', size)
+  }
+  // Set / get leading
+, leading: function(value) {
+    /* act as getter */
+    if (value == null)
+      return this._leading
+    
+    /* act as setter */
+    this._leading = value
+    
+    return this.rebuild()
+  }
+  // rebuild appearance type
+, rebuild: function() {
+    var i, il
+      , size = this.styles['font-size']
+    
+    /* define position of all lines */
+    for (i = 0, il = this.lines.length; i < il; i++)
+      this.lines[i].attr({
+        dy: size * this._leading - (i == 0 ? size * 0.3 : 0)
+      , x: (this.attrs.x || 0)
+      , style: this.style()
+      })
+    
+    return this
+  }
+  // Clear all lines
+, clear: function() {
+    /* remove existing child nodes */
+    while (this.node.hasChildNodes())
+      this.node.removeChild(this.node.lastChild)
+    
+    this.lines = []
+    
+    return this
   }
   
 })
 
-
+// tspan class
 SVG.TSpan = function() {
   this.constructor.call(this, SVG.create('tspan'))
 }
 
 // Inherit from SVG.Shape
-SVG.TSpan.prototype = new SVG.Shape()
+SVG.TSpan.prototype = new SVG.Shape
 
 // Include the container object
 SVG.extend(SVG.TSpan, {
@@ -82,4 +122,4 @@ SVG.extend(SVG.TSpan, {
     return this
   }
   
-});
\ No newline at end of file
+})
\ No newline at end of file
index d3c6b8fa20d17dee9de421d7a2988517a2fcc698..9fa10a2d48a0a29d6f5a045f9ed26b9bb2396047 100644 (file)
@@ -14,30 +14,30 @@ SVG.extend(SVG.Wrap, {
   // Move wrapper around
   move: function(x, y) {
     return this.transform({
-      x: x,
-      y: y
+      x: x
+    , y: y
     })
-  },
+  }
   // Set the actual size in pixels
-  size: function(width, height) {
+, size: function(width, height) {
     var scale = width / this._b.width
     
     this.child.transform({
-      scaleX: scale,
-      scaleY: height != null ? height / this._b.height : scale
+      scaleX: scale
+    , scaleY: height != null ? height / this._b.height : scale
     })
 
     return this
-  },
+  }
   // Move by center
-  center: function(x, y) {
+, center: function(x, y) {
     return this.move(
-      x + (this._b.width  * this.child.trans.scaleX) / -2,
-      y + (this._b.height * this.child.trans.scaleY) / -2
+      x + (this._b.width  * this.child.trans.scaleX) / -2
+    , y + (this._b.height * this.child.trans.scaleY) / -2
     )
-  },
+  }
   // Create distributed attr
-  attr: function(a, v, n) {
+, attr: function(a, v, n) {
     /* call individual attributes if an object is given */
     if (typeof a == 'object') {
       for (v in a) this.attr(v, a[v])
@@ -60,9 +60,9 @@ SVG.extend(SVG.Wrap, {
     }
     
     return this
-  },
+  }
   // Distribute plot method to child
-  plot: function(data) {
+, plot: function(data) {
     /* plot new shape */
     this.child.plot(data)
     
@@ -71,8 +71,8 @@ SVG.extend(SVG.Wrap, {
     
     /* reposition element withing wrapper */
     this.child.transform({
-      x: -this._b.x,
-      y: -this._b.y
+      x: -this._b.x
+    , y: -this._b.y
     })
     
     return this