aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwout <wout@impinc.co.uk>2013-02-20 19:10:03 +0100
committerwout <wout@impinc.co.uk>2013-02-20 19:10:03 +0100
commitae878fd63077d4c95f2de9053a6f0951b55239eb (patch)
tree5dba7bd42a8b5702faeb6cc12d2b4d4099841e51
parent5020240e4029a61a9620f21d7be4d9764e7723d1 (diff)
downloadsvg.js-ae878fd63077d4c95f2de9053a6f0951b55239eb.tar.gz
svg.js-ae878fd63077d4c95f2de9053a6f0951b55239eb.zip
Created separate classes for SVG.ViewBox anSVG.BBox0.6
-rw-r--r--README.md18
-rw-r--r--Rakefile2
-rw-r--r--dist/svg.js1053
-rw-r--r--dist/svg.min.js4
-rw-r--r--src/arrange.js58
-rw-r--r--src/bbox.js18
-rw-r--r--src/container.js193
-rw-r--r--src/defs.js8
-rw-r--r--src/doc.js42
-rw-r--r--src/element.js137
-rw-r--r--src/ellipse.js22
-rw-r--r--src/event.js36
-rw-r--r--src/fx.js130
-rw-r--r--src/gradient.js56
-rw-r--r--src/group.js12
-rw-r--r--src/image.js14
-rw-r--r--src/line.js28
-rw-r--r--src/mask.js16
-rw-r--r--src/nested.js10
-rw-r--r--src/path.js12
-rw-r--r--src/pattern.js20
-rw-r--r--src/poly.js26
-rw-r--r--src/rect.js8
-rw-r--r--src/shape.js8
-rw-r--r--src/sugar.js48
-rw-r--r--src/svg.js18
-rw-r--r--src/text.js58
-rw-r--r--src/viewbox.js35
-rw-r--r--src/wrap.js46
29 files changed, 1123 insertions, 1013 deletions
diff --git a/README.md b/README.md
index 5c9a8a9..4aec740 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,9 @@ This will generate the following output:
</svg>
</div>
```
+
By default the svg canvas follows the dimensions of its parent, in this case `#paper`:
+
```javascript
var draw = svg('paper').size('100%', '100%');
```
@@ -46,6 +48,20 @@ if (SVG.supported) {
}
```
+### ViewBox
+
+The `viewBox` attribute of an `<svg>` element can be managed with the `viewbox()` method. When supplied with arguments it will act as a setter:
+
+```javascript
+draw.viewbox(0, 0, 297, 210);
+```
+
+Without any attributes a an instance of `SVG.ViewBox` will be returned:
+
+```javascript
+var box = draw.viewbox();
+```
+
## Elements
@@ -274,7 +290,7 @@ draw.clear();
```javascript
path.bbox();
```
-This will return an object with the following values:
+This will return an instance of `SVG.BBox` containing the following values:
```javascript
{ height: 20, width: 20, y: 20, x: 10, cx: 30, cy: 20 }
diff --git a/Rakefile b/Rakefile
index 183b67b..0f2db64 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,7 +1,7 @@
SVGJS_VERSION = '0.5'
# all available modules in the correct loading order
-MODULES = %w[ svg element container fx event group arrange defs mask pattern gradient doc shape wrap rect ellipse line poly path image text nested sugar ]
+MODULES = %w[ svg viewbox bbox element container fx event group arrange defs mask pattern gradient doc shape wrap rect ellipse line poly path image text nested sugar ]
# how many bytes in a "kilobyte"
KILO = 1024
diff --git a/dist/svg.js b/dist/svg.js
index 0ee1a1a..dda9178 100644
--- a/dist/svg.js
+++ b/dist/svg.js
@@ -1,10 +1,10 @@
-/* svg.js v0.5-6-g3ebe05f - svg 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 */
+/* svg.js v0.5-8-g5020240 - svg 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) {
if (SVG.supported)
- return new SVG.Doc(element);
- };
+ return new SVG.Doc(element)
+ }
// The main wrapping element
this.SVG = {
@@ -17,28 +17,81 @@
// Method for element creation
, create: function(element) {
- return document.createElementNS(this.ns, element);
+ return document.createElementNS(this.ns, element)
}
// Method for extending objects
, extend: function(object, module) {
for (var key in module)
- object.prototype[key] = module[key];
+ object.prototype[key] = module[key]
}
- };
+ }
// svg support test
SVG.supported = (function() {
return !! document.createElementNS &&
- !! document.createElementNS(SVG.ns,'svg').createSVGRect;
- })();
+ !! document.createElementNS(SVG.ns,'svg').createSVGRect
+ })()
if (!SVG.supported) return false;
- SVG.Element = function Element(node) {
+ SVG.ViewBox = function(element) {
+ var width, height
+ , box = element.bbox()
+ , view = (element.attr('viewBox') || '').match(/[\d\.]+/g)
+
+ /* clone attributes */
+ this.x = box.x
+ this.y = box.y
+ this.width = box.width
+ this.height = box.height
+
+ if (view) {
+ /* get width and height from viewbox */
+ width = parseFloat(view[2])
+ height = parseFloat(view[3])
+
+ /* calculate real pixel dimensions on parent SVG.Doc element */
+ if (element instanceof SVG.Doc) {
+ this.x = 0
+ this.y = 0
+ this.width = element.node.offsetWidth
+ this.height = element.node.offsetHeight
+ }
+
+ /* calculate zoom accoring to viewbox */
+ this.scale = (this.width / this.height > width / height) ?
+ this.height / height :
+ this.width / width
+
+ } else {
+ this.scale = 1
+ }
+
+ }
+
+ SVG.BBox = function(element) {
+ /* actual, native bounding box */
+ var box = element.node.getBBox()
+
+ /* include translations on x an y */
+ this.x = box.x + element.trans.x
+ this.y = box.y + element.trans.y
+
+ /* add the center */
+ this.cx = box.x + element.trans.x + box.width / 2
+ this.cy = box.y + element.trans.y + box.height / 2
+
+ /* plain width and height */
+ this.width = box.width
+ this.height = box.height
+
+ }
+
+ SVG.Element = function(node) {
/* keep reference to the element node */
if (this.node = node)
- this.type = node.nodeName;
+ this.type = node.nodeName
/* initialize attribute store with defaults */
this.attrs = {
@@ -57,7 +110,7 @@
r: 0,
rx: 0,
ry: 0
- };
+ }
/* initialize transformation store with defaults */
this.trans = {
@@ -68,9 +121,9 @@
rotation: 0,
skewX: 0,
skewY: 0
- };
+ }
- };
+ }
//
SVG.extend(SVG.Element, {
@@ -79,41 +132,41 @@
return this.attr({
x: x,
y: y
- });
+ })
},
// Move element by its center
center: function(x, y) {
- var box = this.bbox();
+ var box = this.bbox()
- return this.move(x - box.width / 2, y - box.height / 2);
+ return this.move(x - box.width / 2, y - box.height / 2)
},
// Set element size to given width and height
size: function(width, height) {
return this.attr({
width: width,
height: height
- });
+ })
},
// Clone element
clone: function() {
- var clone;
+ var clone
/* if this is a wrapped shape */
if (this instanceof SVG.Wrap) {
/* build new wrapped shape */
- clone = this.parent[this.child.node.nodeName]();
- clone.attrs = this.attrs;
+ clone = this.parent[this.child.node.nodeName]()
+ clone.attrs = this.attrs
/* copy child attributes and transformations */
- clone.child.trans = this.child.trans;
- clone.child.attr(this.child.attrs).transform({});
+ clone.child.trans = this.child.trans
+ clone.child.attr(this.child.attrs).transform({})
/* re-plot shape */
if (clone.plot)
- clone.plot(this.child.attrs[this.child instanceof SVG.Path ? 'd' : 'points']);
+ clone.plot(this.child.attrs[this.child instanceof SVG.Path ? 'd' : 'points'])
} else {
- var name = this.node.nodeName;
+ var name = this.node.nodeName
/* invoke shape method with shape-specific arguments */
clone = name == 'rect' ?
@@ -126,35 +179,35 @@
this.parent[name](this.content) :
name == 'g' ?
this.parent.group() :
- this.parent[name]();
+ this.parent[name]()
- clone.attr(this.attrs);
+ clone.attr(this.attrs)
}
/* copy transformations */
- clone.trans = this.trans;
+ clone.trans = this.trans
/* apply attributes and translations */
- return clone.transform({});
+ return clone.transform({})
},
// Remove element
remove: function() {
- return this.parent != null ? this.parent.remove(this) : void 0;
+ return this.parent != null ? this.parent.remove(this) : void 0
},
// Get parent document
doc: function() {
- return this._parent(SVG.Doc);
+ return this._parent(SVG.Doc)
},
// Get parent nested document
nested: function() {
- return this._parent(SVG.Nested);
+ return this._parent(SVG.Nested)
},
// Set svg element attribute
attr: function(a, v, n) {
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))
@@ -162,26 +215,26 @@
this.content :
a == 'leading' ?
this[a] :
- this.style[a];
+ 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]
} else {
/* store value */
- this.attrs[a] = v;
+ this.attrs[a] = v
/* treat x differently on text elements */
if (a == 'x' && this._isText())
for (var i = this.lines.length - 1; i >= 0; i--)
- this.lines[i].attr(a, v);
+ this.lines[i].attr(a, v)
/* set the actual attribute */
else
n != null ?
this.node.setAttributeNS(n, a, v) :
- this.node.setAttribute(a, v);
+ this.node.setAttribute(a, v)
/* if the passed argument belongs to the style as well, add it there */
if (this._isStyle(a)) {
@@ -189,317 +242,311 @@
this.text(v) :
a == 'leading' ?
this[a] = v :
- this.style[a] = v;
+ this.style[a] = v
- this.text(this.content);
+ this.text(this.content)
}
}
- return this;
+ 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];
+ return this.trans[o]
/* ... otherwise continue as a setter */
- var key, transform = [];
+ var key, transform = []
/* merge values */
for (key in o)
if (o[key] != null)
- this.trans[key] = o[key];
+ this.trans[key] = o[key]
/* alias current transformations */
- o = this.trans;
+ o = this.trans
/* add rotation */
if (o.rotation != 0) {
- var box = this.bbox();
- transform.push('rotate(' + o.rotation + ',' + (o.cx != null ? o.cx : box.cx) + ',' + (o.cy != null ? o.cy : box.cy) + ')');
+ var box = this.bbox()
+ transform.push('rotate(' + o.rotation + ',' + (o.cx != null ? o.cx : box.cx) + ',' + (o.cy != null ? o.cy : box.cy) + ')')
}
/* add scale */
- transform.push('scale(' + o.scaleX + ',' + o.scaleY + ')');
+ transform.push('scale(' + o.scaleX + ',' + o.scaleY + ')')
/* add skew on x axis */
if (o.skewX != 0)
- transform.push('skewX(' + o.skewX + ')');
+ transform.push('skewX(' + o.skewX + ')')
/* add skew on y axis */
if (o.skewY != 0)
transform.push('skewY(' + o.skewY + ')')
/* add translation */
- transform.push('translate(' + o.x + ',' + o.y + ')');
+ transform.push('translate(' + o.x + ',' + o.y + ')')
/* add only te required transformations */
- return this.attr('transform', transform.join(' '));
+ return this.attr('transform', transform.join(' '))
},
// Store data values on svg nodes
data: function(a, v, r) {
if (arguments.length < 2) {
try {
- return JSON.parse(this.attr('data-' + a));
+ return JSON.parse(this.attr('data-' + a))
} catch(e) {
- return this.attr('data-' + a);
- };
+ return this.attr('data-' + a)
+ }
} else {
v === null ?
this.node.removeAttribute('data-' + a) :
- this.attr('data-' + a, r === true ? v : JSON.stringify(v));
+ this.attr('data-' + a, r === true ? v : JSON.stringify(v))
}
- return this;
+ return this
},
// Get bounding box
bbox: function() {
- /* actual, native bounding box */
- var box = this.node.getBBox();
-
- return {
- /* include translations on x an y */
- x: box.x + this.trans.x,
- y: box.y + this.trans.y,
-
- /* add the center */
- cx: box.x + this.trans.x + box.width / 2,
- cy: box.y + this.trans.y + box.height / 2,
-
- /* plain width and height */
- width: box.width,
- height: box.height
- };
+ return new SVG.BBox(this)
},
// Checks whether the given point inside the bounding box of the element
inside: function(x, y) {
- var box = this.bbox();
+ var box = this.bbox()
return x > box.x &&
y > box.y &&
x < box.x + box.width &&
- y < box.y + box.height;
+ y < box.y + box.height
},
// Show element
show: function() {
- this.node.style.display = '';
+ this.node.style.display = ''
- return this;
+ return this
},
// Hide element
hide: function() {
- this.node.style.display = 'none';
+ this.node.style.display = 'none'
- return this;
+ return this
},
// Is element visible?
visible: function() {
- return this.node.style.display != 'none';
+ return this.node.style.display != 'none'
},
// Private: find svg parent by instance
_parent: function(parent) {
- var element = this;
+ var element = this
while (element != null && !(element instanceof parent))
- element = element.parent;
+ element = element.parent
- return element;
+ return 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' && this._isText() ? (/^font|text|leading/).test(attr) : false
},
// Private: element type tester
_isText: function() {
- return this instanceof SVG.Text;
+ return this instanceof SVG.Text
}
- });
+ })
- SVG.Container = function Container(element) {
- this.constructor.call(this, element);
- };
+ SVG.Container = function(element) {
+ this.constructor.call(this, element)
+ }
// Inherit from SVG.Element
- SVG.Container.prototype = new SVG.Element();
+ SVG.Container.prototype = new SVG.Element
//
SVG.extend(SVG.Container, {
// Add given element at a position
add: function(element, index) {
if (!this.has(element)) {
- index = index == null ? this.children().length : index;
- this.children().splice(index, 0, element);
- this.node.insertBefore(element.node, this.node.childNodes[index] || null);
- element.parent = this;
+ index = index == null ? this.children().length : index
+ this.children().splice(index, 0, element)
+ this.node.insertBefore(element.node, this.node.childNodes[index] || null)
+ element.parent = this
}
- return this;
- },
+ return this
+ }
// Basically does the same as `add()` but returns the added element
- put: function(element, index) {
- this.add(element, index);
- return element;
- },
+ , put: function(element, index) {
+ this.add(element, index)
+ return element
+ }
// Checks if the given element is a child
- has: function(element) {
- return this.children().indexOf(element) >= 0;
- },
+ , has: function(element) {
+ return this.children().indexOf(element) >= 0
+ }
// Returns all child elements
- children: function() {
- return this._children || (this._children = []);
- },
+ , children: function() {
+ return this._children || (this._children = [])
+ }
// Iterates over all children and invokes a given block
- each: function(block) {
+ , each: function(block) {
var index,
- children = this.children();
+ children = this.children()
for (index = 0, length = children.length; index < length; index++)
if (children[index] instanceof SVG.Shape)
- block.apply(children[index], [index, children]);
+ block.apply(children[index], [index, children])
- return this;
- },
+ return this
+ }
// Remove a given child element
- remove: function(element) {
- return this.removeAt(this.children().indexOf(element));
- },
+ , remove: function(element) {
+ return this.removeAt(this.children().indexOf(element))
+ }
// Remove a child element at a given position
- removeAt: function(index) {
+ , removeAt: function(index) {
if (0 <= index && index < this.children().length) {
- var element = this.children()[index];
- this.children().splice(index, 1);
- this.node.removeChild(element.node);
- element.parent = null;
+ var element = this.children()[index]
+ this.children().splice(index, 1)
+ this.node.removeChild(element.node)
+ element.parent = null
}
- return this;
- },
+ return this
+ }
// Returns defs element
- defs: function() {
- return this._defs || (this._defs = this.put(new SVG.Defs(), 0));
- },
+ , defs: function() {
+ return this._defs || (this._defs = this.put(new SVG.Defs(), 0))
+ }
// Re-level defs to first positon in element stack
- level: function() {
- return this.remove(this.defs()).put(this.defs(), 0);
- },
+ , level: function() {
+ return this.remove(this.defs()).put(this.defs(), 0)
+ }
// Create a group element
- group: function() {
- return this.put(new SVG.G());
- },
+ , group: function() {
+ return this.put(new SVG.G())
+ }
// Create a rect element
- rect: function(width, height) {
- return this.put(new SVG.Rect().size(width, height));
- },
+ , rect: function(width, height) {
+ return this.put(new SVG.Rect().size(width, height))
+ }
// Create circle element, based on ellipse
- circle: function(diameter) {
- return this.ellipse(diameter);
- },
+ , circle: function(diameter) {
+ return this.ellipse(diameter)
+ }
// Create an ellipse
- ellipse: function(width, height) {
- return this.put(new SVG.Ellipse().size(width, height));
- },
+ , ellipse: function(width, height) {
+ return this.put(new SVG.Ellipse().size(width, height))
+ }
// Create a wrapped polyline element
- polyline: function(points) {
- return this.put(new SVG.Wrap(new SVG.Polyline())).plot(points);
- },
+ , polyline: function(points) {
+ return this.put(new SVG.Wrap(new SVG.Polyline())).plot(points)
+ }
// Create a wrapped polygon element
- polygon: function(points) {
- return this.put(new SVG.Wrap(new SVG.Polygon())).plot(points);
- },
+ , polygon: function(points) {
+ return this.put(new SVG.Wrap(new SVG.Polygon())).plot(points)
+ }
// Create a wrapped path element
- path: function(data) {
- return this.put(new SVG.Wrap(new SVG.Path())).plot(data);
- },
+ , path: function(data) {
+ return this.put(new SVG.Wrap(new SVG.Path())).plot(data)
+ }
// Create image element, load image and set its size
- image: function(source, width, height) {
- width = width != null ? width : 100;
- return this.put(new SVG.Image().load(source).size(width, height != null ? height : width));
- },
+ , image: function(source, width, height) {
+ width = width != null ? width : 100
+ return this.put(new SVG.Image().load(source).size(width, height != null ? height : width))
+ }
// Create text element
- text: function(text) {
- return this.put(new SVG.Text().text(text));
- },
+ , text: function(text) {
+ return this.put(new SVG.Text().text(text))
+ }
// Create nested svg document
- nested: function() {
- return this.put(new SVG.Nested());
- },
+ , nested: function() {
+ return this.put(new SVG.Nested())
+ }
// Create gradient element in defs
- gradient: function(type, block) {
- return this.defs().gradient(type, block);
- },
+ , gradient: function(type, block) {
+ return this.defs().gradient(type, block)
+ }
// Create pattern element in defs
- pattern: function(width, height, block) {
- return this.defs().pattern(width, height, block);
- },
+ , pattern: function(width, height, block) {
+ return this.defs().pattern(width, height, block)
+ }
// Create masking element
- mask: function() {
- return this.defs().put(new SVG.Mask());
- },
+ , mask: function() {
+ return this.defs().put(new SVG.Mask())
+ }
// Get first child, skipping the defs node
- first: function() {
- return this.children()[0] instanceof SVG.Defs ? this.children()[1] : this.children()[0];
- },
+ , first: function() {
+ return this.children()[0] instanceof SVG.Defs ? this.children()[1] : this.children()[0]
+ }
// Get the last child
- last: function() {
- return this.children()[this.children().length - 1];
- },
+ , last: function() {
+ return this.children()[this.children().length - 1]
+ }
+ // Get the viewBox and calculate the zoom value
+ , viewbox: function() {
+ /* act as a getter if there are no arguments */
+ if (arguments.length == 0)
+ return new SVG.ViewBox(this)
+
+ /* otherwise act as a setter */
+ return this.attr('viewBox', Array.prototype.slice.call(arguments).join(' '))
+ }
// Remove all elements in this container
- clear: function() {
- this._children = [];
+ , clear: function() {
+ this._children = []
while (this.node.hasChildNodes())
- this.node.removeChild(this.node.lastChild);
+ this.node.removeChild(this.node.lastChild)
- return this;
+ return this
}
- });
+ })
- SVG.FX = function FX(element) {
+ SVG.FX = function(element) {
/* store target element */
- this.target = element;
- };
+ this.target = element
+ }
//
SVG.extend(SVG.FX, {
// Add animation parameters and start animation
animate: function(duration, ease) {
/* ensure default duration and easing */
- duration = duration == null ? 1000 : duration;
- ease = ease || '<>';
+ duration = duration == null ? 1000 : duration
+ ease = ease || '<>'
var akeys, tkeys, tvalues,
element = this.target,
fx = this,
start = (new Date).getTime(),
- finish = start + duration;
+ finish = start + duration
/* start animation */
this.interval = setInterval(function(){
// This code was borrowed from the emile.js micro framework by Thomas Fuchs, aka MadRobby.
var index,
time = (new Date).getTime(),
- pos = time > finish ? 1 : (time - start) / duration;
+ pos = time > finish ? 1 : (time - start) / duration
/* collect attribute keys */
if (akeys == null) {
- akeys = [];
+ akeys = []
for (var key in fx.attrs)
- akeys.push(key);
- };
+ akeys.push(key)
+ }
/* collect transformation keys */
if (tkeys == null) {
- tkeys = [];
+ tkeys = []
for (var key in fx.trans)
- tkeys.push(key);
+ tkeys.push(key)
- tvalues = {};
- };
+ tvalues = {}
+ }
/* apply easing */
pos = ease == '<>' ?
@@ -512,110 +559,110 @@
pos :
typeof ease == 'function' ?
ease(pos) :
- pos;
+ pos
/* run all position properties */
if (fx._move)
- element.move(fx._at(fx._move.x, pos), fx._at(fx._move.y, pos));
+ 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.move(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));
+ 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));
+ element.attr(akeys[index], fx._at(fx.attrs[akeys[index]], 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);
+ tvalues[tkeys[index]] = fx._at(fx.trans[tkeys[index]], pos)
- element.transform(tvalues);
+ element.transform(tvalues)
}
/* finish off animation */
if (time > finish) {
- clearInterval(fx.interval);
- fx._after ? fx._after.apply(element, [fx]) : fx.stop();
+ clearInterval(fx.interval)
+ fx._after ? fx._after.apply(element, [fx]) : fx.stop()
}
- }, duration > 10 ? 10 : duration);
+ }, duration > 10 ? 10 : duration)
- return this;
+ return this
},
// Add animatable attributes
attr: function(a, v, n) {
if (typeof a == 'object')
for (var key in a)
- this.attr(key, a[key]);
+ this.attr(key, a[key])
else
- this.attrs[a] = { from: this.target.attr(a), to: v };
+ this.attrs[a] = { from: this.target.attr(a), to: v }
return this;
},
// Add animatable transformations
transform: function(o) {
for (var key in o)
- this.trans[key] = { from: this.target.trans[key], to: o[key] };
+ this.trans[key] = { from: this.target.trans[key], to: o[key] }
- return this;
+ return this
},
// Add animatable move
move: function(x, y) {
- var box = this.target.bbox();
+ var box = this.target.bbox()
this._move = {
x: { from: box.x, to: x },
y: { from: box.y, to: y }
- };
+ }
- return this;
+ return this
},
// Add animatable size
size: function(width, height) {
- var box = this.target.bbox();
+ var box = this.target.bbox()
this._size = {
width: { from: box.width, to: width },
height: { from: box.height, to: height }
- };
+ }
- return this;
+ return this
},
// Add animatable center
center: function(x, y) {
- var box = this.target.bbox();
+ var box = this.target.bbox()
this._move = {
x: { from: box.cx, to: x },
y: { from: box.cy, to: y }
- };
+ }
- return this;
+ return this
},
// Callback after animation
after: function(after) {
- this._after = after;
+ this._after = after
- return this;
+ return this
},
// Stop running animation
stop: function() {
/* stop current animation */
- clearInterval(this.interval);
+ clearInterval(this.interval)
/* reset storage for properties that need animation */
- this.attrs = {};
- this.trans = {};
- this._move = null;
- this._size = null;
- this._after = null;
+ this.attrs = {}
+ this.trans = {}
+ this._move = null
+ this._size = null
+ this._after = null
- return this;
+ return this
},
// Private: at position according to from and to
_at: function(o, pos) {
@@ -628,45 +675,45 @@
this._color(o, pos) :
/* for all other values wait until pos has reached 1 to return the final value */
- pos < 1 ? o.from : o.to;
+ pos < 1 ? o.from : o.to
},
// Private: tween color
_color: function(o, pos) {
- var from, to;
+ var from, to
/* convert FROM hex to rgb */
- from = this._h2r(o.from || '#000');
+ from = this._h2r(o.from || '#000')
/* convert TO hex to rgb */
- to = this._h2r(o.to);
+ to = this._h2r(o.to)
/* tween color and return hex */
return this._r2h({
r: ~~(from.r + (to.r - from.r) * pos),
g: ~~(from.g + (to.g - from.g) * pos),
b: ~~(from.b + (to.b - from.b) * pos)
- });
+ })
},
// Private: convert hex to rgb object
_h2r: function(hex) {
/* parse full hex */
- var match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(this._fh(hex));
+ var match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(this._fh(hex))
/* if the hex is successfully parsed, return it in rgb, otherwise return black */
return match ? {
r: parseInt(match[1], 16),
g: parseInt(match[2], 16),
b: parseInt(match[3], 16)
- } : { r: 0, g: 0, b: 0 };
+ } : { r: 0, g: 0, b: 0 }
},
// Private: convert rgb object to hex string
_r2h: function(rgb) {
- return '#' + this._c2h(rgb.r) + this._c2h(rgb.g) + this._c2h(rgb.b);
+ return '#' + this._c2h(rgb.r) + this._c2h(rgb.g) + this._c2h(rgb.b)
},
// Private: convert component to hex
_c2h: function(c) {
- var hex = c.toString(16);
- return hex.length == 1 ? '0' + hex : hex;
+ var hex = c.toString(16)
+ return hex.length == 1 ? '0' + hex : hex
},
// Private: force potential 3-based hex to 6-based
_fh: function(hex) {
@@ -675,32 +722,32 @@
hex.substring(1, 2), hex.substring(1, 2),
hex.substring(2, 3), hex.substring(2, 3),
hex.substring(3, 4), hex.substring(3, 4)
- ].join('') : hex;
+ ].join('') : hex
}
- });
+ })
//
SVG.extend(SVG.Element, {
// Get fx module or create a new one, then animate with given duration and ease
animate: function(duration, ease) {
- return (this.fx || (this.fx = new SVG.FX(this))).stop().animate(duration, ease);
+ return (this.fx || (this.fx = new SVG.FX(this))).stop().animate(duration, ease)
},
// Stop current animation; this is an alias to the fx instance
stop: function() {
- this.fx.stop();
+ this.fx.stop()
- return this;
+ return this
}
- });
+ })
// Usage:
// rect.animate(1500, '>').move(200, 300).after(function() {
- // this.fill({ color: '#f06' });
- // });
+ // this.fill({ color: '#f06' })
+ // })
- [ 'click',
+ ;[ 'click',
'dblclick',
'mousedown',
'mouseup',
@@ -716,172 +763,172 @@
/* add event to SVG.Element */
SVG.Element.prototype[event] = function(f) {
- var self = this;
+ 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;
+ : null
- return this;
- };
+ return this
+ }
- });
+ })
// Add event binder in the SVG namespace
SVG.on = function(node, event, listener) {
if (node.addEventListener)
- node.addEventListener(event, listener, false);
+ node.addEventListener(event, listener, false)
else
- node.attachEvent('on' + event, listener);
- };
+ node.attachEvent('on' + event, listener)
+ }
// Add event unbinder in the SVG namespace
SVG.off = function(node, event, listener) {
if (node.removeEventListener)
- node.removeEventListener(event, listener, false);
+ node.removeEventListener(event, listener, false)
else
- node.detachEvent('on' + event, listener);
- };
+ node.detachEvent('on' + event, listener)
+ }
//
SVG.extend(SVG.Element, {
// Bind given event to listener
on: function(event, listener) {
- SVG.on(this.node, event, listener);
+ SVG.on(this.node, event, listener)
- return this;
+ return this
},
// Unbind event from listener
off: function(event, listener) {
- SVG.off(this.node, event, listener);
+ SVG.off(this.node, event, listener)
- return this;
+ return this
}
});
- SVG.G = function G() {
- this.constructor.call(this, SVG.create('g'));
- };
+ SVG.G = function() {
+ this.constructor.call(this, SVG.create('g'))
+ }
// Inherit from SVG.Container
- SVG.G.prototype = new SVG.Container();
+ SVG.G.prototype = new SVG.Container
SVG.extend(SVG.G, {
// Get defs
defs: function() {
- return this.doc().defs();
+ return this.doc().defs()
}
- });
+ })
SVG.extend(SVG.Element, {
// Get all siblings, including myself
siblings: function() {
- return this.parent.children();
- },
+ return this.parent.children()
+ }
// Get the curent position siblings
- position: function() {
- return this.siblings().indexOf(this);
- },
+ , position: function() {
+ return this.siblings().indexOf(this)
+ }
// Get the next element (will return null if there is none)
- next: function() {
- return this.siblings()[this.position() + 1];
- },
+ , next: function() {
+ return this.siblings()[this.position() + 1]
+ }
// Get the next element (will return null if there is none)
- previous: function() {
- return this.siblings()[this.position() - 1];
- },
+ , previous: function() {
+ return this.siblings()[this.position() - 1]
+ }
// Send given element one step forward
- forward: function() {
- return this.parent.remove(this).put(this, this.position() + 1);
- },
+ , forward: function() {
+ return this.parent.remove(this).put(this, this.position() + 1)
+ }
// Send given element one step backward
- backward: function() {
- var i;
+ , backward: function() {
+ var i
- this.parent.level();
+ this.parent.level()
- i = this.position();
+ i = this.position()
if (i > 1)
- this.parent.remove(this).add(this, i - 1);
+ this.parent.remove(this).add(this, i - 1)
- return this;
- },
+ return this
+ }
// Send given element all the way to the front
- front: function() {
- return this.parent.remove(this).put(this);
- },
+ , front: function() {
+ return this.parent.remove(this).put(this)
+ }
// Send given element all the way to the back
- back: function() {
- this.parent.level();
+ , back: function() {
+ this.parent.level()
if (this.position() > 1)
- this.parent.remove(this).add(this, 0);
+ this.parent.remove(this).add(this, 0)
- return this;
+ return this
}
- });
+ })
- SVG.Defs = function Defs() {
- this.constructor.call(this, SVG.create('defs'));
- };
+ SVG.Defs = function() {
+ this.constructor.call(this, SVG.create('defs'))
+ }
// Inherits from SVG.Container
- SVG.Defs.prototype = new SVG.Container();
+ SVG.Defs.prototype = new SVG.Container
- SVG.Mask = function Mask() {
- this.constructor.call(this, SVG.create('mask'));
+ SVG.Mask = function() {
+ this.constructor.call(this, SVG.create('mask'))
/* set unique id */
- this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)));
- };
+ this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)))
+ }
// Inherit from SVG.Container
- SVG.Mask.prototype = new SVG.Container();
+ SVG.Mask.prototype = new SVG.Container
SVG.extend(SVG.Element, {
// Distribute mask to svg element
maskWith: function(element) {
/* use given mask or create a new one */
- this.mask = element instanceof SVG.Mask ? element : this.parent.mask().add(element);
+ this.mask = element instanceof SVG.Mask ? element : this.parent.mask().add(element)
- return this.attr('mask', 'url(#' + this.mask.id + ')');
+ return this.attr('mask', 'url(#' + this.mask.id + ')')
}
- });
+ })
- SVG.Pattern = function Pattern(type) {
- this.constructor.call(this, SVG.create('pattern'));
+ SVG.Pattern = function(type) {
+ this.constructor.call(this, SVG.create('pattern'))
/* set unique id */
- this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)));
- };
+ this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)))
+ }
// Inherit from SVG.Container
- SVG.Pattern.prototype = new SVG.Container();
+ SVG.Pattern.prototype = new SVG.Container
//
SVG.extend(SVG.Pattern, {
// Return the fill id
fill: function() {
- return 'url(#' + this.id + ')';
+ return 'url(#' + this.id + ')'
}
- });
+ })
//
SVG.extend(SVG.Defs, {
/* define gradient */
pattern: function(width, height, block) {
- var element = this.put(new SVG.Pattern());
+ var element = this.put(new SVG.Pattern())
/* invoke passed block */
- block(element);
+ block(element)
return element.attr({
x: 0,
@@ -889,23 +936,23 @@
width: width,
height: height,
patternUnits: 'userSpaceOnUse'
- });
+ })
}
});
- SVG.Gradient = function Gradient(type) {
- this.constructor.call(this, SVG.create(type + 'Gradient'));
+ SVG.Gradient = function(type) {
+ this.constructor.call(this, SVG.create(type + 'Gradient'))
/* set unique id */
- this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)));
+ this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)))
/* store type */
- this.type = type;
- };
+ this.type = type
+ }
// Inherit from SVG.Container
- SVG.Gradient.prototype = new SVG.Container();
+ SVG.Gradient.prototype = new SVG.Container
//
SVG.extend(SVG.Gradient, {
@@ -913,67 +960,67 @@
from: function(x, y) {
return this.type == 'radial' ?
this.attr({ fx: x + '%', fy: y + '%' }) :
- this.attr({ x1: x + '%', y1: y + '%' });
+ this.attr({ x1: x + '%', y1: y + '%' })
},
// To position
to: function(x, y) {
return this.type == 'radial' ?
this.attr({ cx: x + '%', cy: y + '%' }) :
- this.attr({ x2: x + '%', y2: y + '%' });
+ this.attr({ x2: x + '%', y2: y + '%' })
},
// Radius for radial gradient
radius: function(radius) {
return this.type == 'radial' ?
this.attr({ r: radius + '%' }) :
- this;
+ this
},
// Add a color stop
at: function(stop) {
- return this.put(new SVG.Stop(stop));
+ return this.put(new SVG.Stop(stop))
},
// Update gradient
update: function(block) {
/* remove all stops */
while (this.node.hasChildNodes())
- this.node.removeChild(this.node.lastChild);
+ this.node.removeChild(this.node.lastChild)
/* invoke passed block */
- block(this);
+ block(this)
- return this;
+ return this
},
// Return the fill id
fill: function() {
- return 'url(#' + this.id + ')';
+ return 'url(#' + this.id + ')'
}
- });
+ })
//
SVG.extend(SVG.Defs, {
/* define gradient */
gradient: function(type, block) {
- var element = this.put(new SVG.Gradient(type));
+ var element = this.put(new SVG.Gradient(type))
/* invoke passed block */
- block(element);
+ block(element)
- return element;
+ return element
}
- });
+ })
- SVG.Stop = function Stop(stop) {
- this.constructor.call(this, SVG.create('stop'));
+ SVG.Stop = function(stop) {
+ this.constructor.call(this, SVG.create('stop'))
/* immediatelly build stop */
- this.update(stop);
- };
+ this.update(stop)
+ }
// Inherit from SVG.Element
- SVG.Stop.prototype = new SVG.Element();
+ SVG.Stop.prototype = new SVG.Element()
//
SVG.extend(SVG.Stop, {
@@ -982,44 +1029,44 @@
update: function(o) {
var index,
style = '',
- attr = ['opacity', 'color'];
+ 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]] + ';';
+ style += 'stop-' + attr[index] + ':' + o[attr[index]] + ';'
/* set attributes */
return this.attr({
offset: (o.offset != null ? o.offset : this.attrs.offset || 0) + '%',
style: style
- });
+ })
}
- });
+ })
- SVG.Doc = function Doc(element) {
- this.constructor.call(this, SVG.create('svg'));
+ SVG.Doc = function(element) {
+ this.constructor.call(this, SVG.create('svg'))
/* ensure the presence of a html element */
this.parent = typeof element == 'string' ?
document.getElementById(element) :
- element;
+ element
/* set svg element attributes and create the <defs> node */
this.
attr({ xmlns: SVG.ns, version: '1.1', width: '100%', height: '100%' }).
attr('xlink', SVG.xlink, SVG.ns).
- defs();
+ defs()
/* ensure correct rendering for safari */
this.stage();
- };
+ }
// Inherits from SVG.Container
- SVG.Doc.prototype = new SVG.Container();
+ SVG.Doc.prototype = new SVG.Container
// Hack for safari preventing text to be rendered in one line.
// Basically it sets the position of the svg node to absolute
@@ -1027,57 +1074,57 @@
SVG.Doc.prototype.stage = function() {
var check,
element = this,
- wrapper = document.createElement('div');
+ wrapper = document.createElement('div')
/* set temp wrapper to position relative */
- wrapper.style.cssText = 'position:relative;height:100%;';
+ wrapper.style.cssText = 'position:relative;height:100%;'
/* put element into wrapper */
- element.parent.appendChild(wrapper);
- wrapper.appendChild(element.node);
+ element.parent.appendChild(wrapper)
+ wrapper.appendChild(element.node)
/* check for dom:ready */
check = function() {
if (document.readyState === 'complete') {
- element.attr('style', 'position:absolute;');
+ element.attr('style', 'position:absolute;')
setTimeout(function() {
/* set position back to relative */
- element.attr('style', 'position:relative;');
+ element.attr('style', 'position:relative;')
/* remove temp wrapper */
- element.parent.removeChild(element.node.parentNode);
- element.node.parentNode.removeChild(element.node);
- element.parent.appendChild(element.node);
+ element.parent.removeChild(element.node.parentNode)
+ element.node.parentNode.removeChild(element.node)
+ element.parent.appendChild(element.node)
- }, 5);
+ }, 5)
} else {
- setTimeout(check, 10);
+ setTimeout(check, 10)
}
- };
+ }
- check();
+ check()
- return this;
- };
+ return this
+ }
- SVG.Shape = function Shape(element) {
- this.constructor.call(this, element);
- };
+ SVG.Shape = function(element) {
+ this.constructor.call(this, element)
+ }
// Inherit from SVG.Element
- SVG.Shape.prototype = new SVG.Element();
+ SVG.Shape.prototype = new SVG.Element()
- SVG.Wrap = function Wrap(element) {
- this.constructor.call(this, SVG.create('g'));
+ SVG.Wrap = function(element) {
+ this.constructor.call(this, SVG.create('g'))
/* insert and store child */
- this.node.insertBefore(element.node, null);
- this.child = element;
- this.type = element.node.nodeName;
- };
+ this.node.insertBefore(element.node, null)
+ this.child = element
+ this.type = element.node.nodeName
+ }
// inherit from SVG.Shape
- SVG.Wrap.prototype = new SVG.Shape();
+ SVG.Wrap.prototype = new SVG.Shape()
SVG.extend(SVG.Wrap, {
// Move wrapper around
@@ -1085,147 +1132,147 @@
return this.transform({
x: x,
y: y
- });
+ })
},
// Set the actual size in pixels
size: function(width, height) {
- var scale = width / this._b.width;
+ var scale = width / this._b.width
this.child.transform({
scaleX: scale,
scaleY: height != null ? height / this._b.height : scale
- });
+ })
- return this;
+ return this
},
// Move by center
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
- );
+ )
},
// Create distributed attr
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]);
+ for (v in a) this.attr(v, a[v])
/* act as a getter if only one argument is given */
} else if (arguments.length < 2) {
- return a == 'transform' ? this.attrs[a] : this.child.attrs[a];
+ return a == 'transform' ? this.attrs[a] : this.child.attrs[a]
/* apply locally for certain attributes */
} else if (a == 'transform') {
- this.attrs[a] = v;
+ this.attrs[a] = v
n != null ?
this.node.setAttributeNS(n, a, v) :
- this.node.setAttribute(a, v);
+ this.node.setAttribute(a, v)
/* apply attributes to child */
} else {
- this.child.attr(a, v, n);
+ this.child.attr(a, v, n)
}
- return this;
+ return this
},
// Distribute plot method to child
plot: function(data) {
/* plot new shape */
- this.child.plot(data);
+ this.child.plot(data)
/* get and store new bbox */
- this._b = this.child.bbox();
+ this._b = this.child.bbox()
/* reposition element withing wrapper */
this.child.transform({
x: -this._b.x,
y: -this._b.y
- });
+ })
- return this;
+ return this
}
- });
+ })
- SVG.Rect = function Rect() {
- this.constructor.call(this, SVG.create('rect'));
- };
+ SVG.Rect = function() {
+ this.constructor.call(this, SVG.create('rect'))
+ }
// Inherit from SVG.Shape
- SVG.Rect.prototype = new SVG.Shape();
+ SVG.Rect.prototype = new SVG.Shape()
- SVG.Ellipse = function Ellipse() {
- this.constructor.call(this, SVG.create('ellipse'));
- };
+ SVG.Ellipse = function() {
+ this.constructor.call(this, SVG.create('ellipse'))
+ }
// Inherit from SVG.Shape
- SVG.Ellipse.prototype = new SVG.Shape();
+ SVG.Ellipse.prototype = new SVG.Shape()
//
SVG.extend(SVG.Ellipse, {
// Custom move function
move: function(x, y) {
- this.attrs.x = x;
- this.attrs.y = y;
+ this.attrs.x = x
+ this.attrs.y = y
- return this.center();
+ return this.center()
},
// Custom size function
size: function(width, height) {
return this.
attr({ rx: width / 2, ry: (height != null ? height : width) / 2 }).
- center();
+ 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)
- });
+ })
}
- });
+ })
// Usage:
- // draw.ellipse(200, 100);
+ // draw.ellipse(200, 100)
- SVG.Line = function Line() {
- this.constructor.call(this, SVG.create('line'));
- };
+ SVG.Line = function() {
+ this.constructor.call(this, SVG.create('line'))
+ }
// Inherit from SVG.Shape
- SVG.Line.prototype = new SVG.Shape();
+ SVG.Line.prototype = new SVG.Shape()
// Add required methods
SVG.extend(SVG.Line, {
// Move line
move: function(x, y) {
- var bbox = this.bbox();
+ 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
- });
+ })
},
// Move element by its center
center: function(x, y) {
- var bbox = this.bbox();
+ var bbox = this.bbox()
- return this.move(x - bbox.width / 2, y - bbox.height / 2);
+ return this.move(x - bbox.width / 2, y - bbox.height / 2)
},
// Set line size by width and height
size: function(width, height) {
- var bbox = this.bbox();
+ 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);
+ 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)
}
- });
+ })
// Extend all container modules
SVG.extend(SVG.Container, {
@@ -1235,45 +1282,45 @@
y1: y1,
x2: x2,
y2: y2
- }));
+ }))
}
- });
+ })
SVG.Poly = {
// Set polygon data with default zero point if no data is passed
plot: function(points) {
- this.attr('points', points || '0,0');
+ this.attr('points', points || '0,0')
- return this;
+ return this
}
- };
+ }
- SVG.Polyline = function Polyline() {
- this.constructor.call(this, SVG.create('polyline'));
- };
+ SVG.Polyline = function() {
+ this.constructor.call(this, SVG.create('polyline'))
+ }
// 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);
+ SVG.extend(SVG.Polyline, SVG.Poly)
- SVG.Polygon = function Polygon() {
- this.constructor.call(this, SVG.create('polygon'));
- };
+ SVG.Polygon = function() {
+ this.constructor.call(this, SVG.create('polygon'))
+ }
// 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.extend(SVG.Polygon, SVG.Poly)
- SVG.Path = function Path() {
- this.constructor.call(this, SVG.create('path'));
- };
+ SVG.Path = function() {
+ this.constructor.call(this, SVG.create('path'))
+ }
// Inherit from SVG.Shape
- SVG.Path.prototype = new SVG.Shape();
+ SVG.Path.prototype = new SVG.Shape()
SVG.extend(SVG.Path, {
@@ -1282,186 +1329,186 @@
this.transform({
x: x,
y: y
- });
+ })
},
/* set path data */
plot: function(data) {
- return this.attr('d', data || 'M0,0');
+ return this.attr('d', data || 'M0,0')
}
});
- SVG.Image = function Image() {
- this.constructor.call(this, SVG.create('image'));
- };
+ SVG.Image = function() {
+ this.constructor.call(this, SVG.create('image'))
+ }
// Inherit from SVG.Element
- SVG.Image.prototype = new SVG.Shape();
+ SVG.Image.prototype = new SVG.Shape()
SVG.extend(SVG.Image, {
/* (re)load image */
load: function(url) {
- this.src = url;
- return (url ? this.attr('xlink:href', url, SVG.xlink) : this);
+ this.src = url
+ return (url ? this.attr('xlink:href', url, SVG.xlink) : this)
}
- });
+ })
- var _styleAttr = ['size', 'family', 'weight', 'stretch', 'variant', 'style'];
+ var _styleAttr = ['size', 'family', 'weight', 'stretch', 'variant', 'style']
- SVG.Text = function Text() {
- this.constructor.call(this, SVG.create('text'));
+ 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.style = { '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 = [];
+ this.content = text = text || 'text'
+ this.lines = []
var index, length, tspan,
style = this._style(),
parent = this.doc(),
lines = text.split("\n"),
- size = this.style['font-size'];
+ size = this.style['font-size']
/* remove existing child nodes */
while (this.node.hasChildNodes())
- this.node.removeChild(this.node.lastChild);
+ this.node.removeChild(this.node.lastChild)
/* build new lines */
for (index = 0, length = lines.length; index < length; index++) {
/* create new tspan and set attributes */
- tspan = new TSpan().
+ 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
- });
+ })
/* add new tspan */
- this.node.appendChild(tspan.node);
- this.lines.push(tspan);
- };
+ this.node.appendChild(tspan.node)
+ this.lines.push(tspan)
+ }
/* set style */
- return this.attr('style', style);
+ return this.attr('style', style)
},
// Build style based on _styleAttr
_style: function() {
- var index, style = '';
+ var index, style = ''
for (index = _styleAttr.length - 1; index >= 0; index--)
if (this.style['font-' + _styleAttr[index]] != null)
- style += 'font-' + _styleAttr[index] + ':' + this.style['font-' + _styleAttr[index]] + ';';
+ style += 'font-' + _styleAttr[index] + ':' + this.style['font-' + _styleAttr[index]] + ';'
- style += 'text-anchor:' + this.style['text-anchor'] + ';';
+ style += 'text-anchor:' + this.style['text-anchor'] + ';'
- return style;
+ return style
}
- });
+ })
- function TSpan() {
- this.constructor.call(this, SVG.create('tspan'));
- };
+ SVG.TSpan = function() {
+ this.constructor.call(this, SVG.create('tspan'))
+ }
// Inherit from SVG.Shape
- TSpan.prototype = new SVG.Shape();
+ SVG.TSpan.prototype = new SVG.Shape()
// Include the container object
- SVG.extend(TSpan, {
+ SVG.extend(SVG.TSpan, {
// Set text content
text: function(text) {
- this.node.appendChild(document.createTextNode(text));
+ this.node.appendChild(document.createTextNode(text))
- return this;
+ return this
}
});
- SVG.Nested = function Nested() {
- this.constructor.call(this, SVG.create('svg'));
- this.attr('overflow', 'visible');
- };
+ SVG.Nested = function() {
+ this.constructor.call(this, SVG.create('svg'))
+ this.attr('overflow', 'visible')
+ }
// Inherit from SVG.Container
- SVG.Nested.prototype = new SVG.Container();
+ SVG.Nested.prototype = new SVG.Container
- SVG._stroke = ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'];
- SVG._fill = ['color', 'opacity', 'rule'];
+ SVG._stroke = ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset']
+ SVG._fill = ['color', 'opacity', 'rule']
// Prepend correct color prefix
var _colorPrefix = function(type, attr) {
- return attr == 'color' ? type : type + '-' + attr;
- };
+ return attr == 'color' ? type : type + '-' + attr
+ }
/* Add sugar for fill and stroke */
- ['fill', 'stroke'].forEach(function(method) {
+ ;['fill', 'stroke'].forEach(function(method) {
// Set fill color and opacity
SVG.Shape.prototype[method] = function(o) {
- var index;
+ var indexOf
if (typeof o == 'string')
- this.attr(method, o);
+ this.attr(method, o)
else
/* set all attributes from _fillAttr and _strokeAttr list */
for (index = SVG['_' + method].length - 1; index >= 0; index--)
if (o[SVG['_' + method][index]] != null)
- this.attr(_colorPrefix(method, SVG['_' + method][index]), o[SVG['_' + method][index]]);
+ this.attr(_colorPrefix(method, SVG['_' + method][index]), o[SVG['_' + method][index]])
- return this;
- };
+ return this
+ }
- });
+ })
- [SVG.Element, SVG.FX].forEach(function(module) {
+ ;[SVG.Element, SVG.FX].forEach(function(module) {
if (module) {
SVG.extend(module, {
// Rotation
rotate: function(angle) {
return this.transform({
rotation: angle || 0
- });
+ })
},
// Skew
skew: function(x, y) {
return this.transform({
skewX: x || 0,
skewY: y || 0
- });
+ })
},
// Scale
scale: function(x, y) {
return this.transform({
scaleX: x,
scaleY: y == null ? x : y
- });
+ })
},
// Opacity
opacity: function(value) {
- return this.attr('opacity', value);
+ return this.attr('opacity', value)
}
- });
+ })
}
- });
+ })
if (SVG.G) {
SVG.extend(SVG.G, {
@@ -1470,17 +1517,17 @@
return this.transform({
x: x,
y: y
- });
+ })
}
- });
+ })
}
if (SVG.Text) {
SVG.extend(SVG.Text, {
// Set font
font: function(o) {
- var key, attr = {};
+ var key, attr = {}
for (key in o)
key == 'leading' ?
@@ -1489,12 +1536,12 @@
attr['text-anchor'] = o[key] :
_styleAttr.indexOf(key) > -1 ?
attr['font-'+ key] = o[key] :
- void 0;
+ void 0
- return this.attr(attr).text(this.content);
+ return this.attr(attr).text(this.content)
}
- });
+ })
}
diff --git a/dist/svg.min.js b/dist/svg.min.js
index 3247907..70f0bab 100644
--- a/dist/svg.min.js
+++ b/dist/svg.min.js
@@ -1,2 +1,2 @@
-/* svg.js v0.5-6-g3ebe05f - svg 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(){function t(){this.constructor.call(this,SVG.create("tspan"))}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:0,create:function(e){return document.createElementNS(this.ns,e)},extend:function(e,t){for(var n in t)e.prototype[n]=t[n]}},SVG.supported=function(){return!!document.createElementNS&&!!document.createElementNS(SVG.ns,"svg").createSVGRect}();if(!SVG.supported)return!1;SVG.Element=function(t){if(this.node=t)this.type=t.nodeName;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.trans={x:0,y:0,scaleX:1,scaleY:1,rotation:0,skewX:0,skewY:0}},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!=null?this.parent.remove(this):void 0},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{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 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]);e=this.trans;if(e.rotation!=0){var r=this.bbox();n.push("rotate("+e.rotation+","+(e.cx!=null?e.cx:r.cx)+","+(e.cy!=null?e.cy:r.cy)+")")}return 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 t===null?this.node.removeAttribute("data-"+e):this.attr("data-"+e,n===!0?t:JSON.stringify(t));return this},bbox:function(){var e=this.node.getBBox();return{x:e.x+this.trans.x,y:e.y+this.trans.y,cx:e.x+this.trans.x+e.width/2,cy:e.y+this.trans.y+e.height/2,width:e.width,height:e.height}},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(t){this.constructor.call(this,t)},SVG.Container.prototype=new SVG.Element,SVG.extend(SVG.Container,{add:function(e,t){return this.has(e)||(t=t==null?this.children().length:t,this.children().splice(t,0,e),this.node.insertBefore(e.node,this.node.childNodes[t]||null),e.parent=this),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){return this.removeAt(this.children().indexOf(e))},removeAt:function(e){if(0<=e&&e<this.children().length){var t=this.children()[e];this.children().splice(e,1),this.node.removeChild(t.node),t.parent=null}return 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]},clear:function(){this._children=[];while(this.node.hasChildNodes())this.node.removeChild(this.node.lastChild);return this}}),SVG.FX=function(t){this.target=t},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)}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},y:{from:n.cy,to:t}},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},_at:function(e,t){return typeof e.from=="number"?e.from+(e.to-e.from)*t:e.to.r||/^#/.test(e.to)?this._color(e,t):t<1?e.from:e.to},_color:function(e,t){var n,r;return n=this._h2r(e.from||"#000"),r=this._h2r(e.to),this._r2h({r:~~(n.r+(r.r-n.r)*t),g:~~(n.g+(r.g-n.g)*t),b:~~(n.b+(r.b-n.b)*t)})},_h2r:function(e){var t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(this._fh(e));return t?{r:parseInt(t[1],16),g:parseInt(t[2],16),b:parseInt(t[3],16)}:{r:0,g:0,b:0}},_r2h:function(e){return"#"+this._c2h(e.r)+this._c2h(e.g)+this._c2h(e.b)},_c2h:function(e){var t=e.toString(16);return t.length==1?"0"+t:t},_fh: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}}),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,{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")),this.attr("id",this.id="svgjs_element_"+SVG.did++)},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.id+")")}}),SVG.Pattern=function(t){this.constructor.call(this,SVG.create("pattern")),this.attr("id",this.id="svgjs_element_"+SVG.did++)},SVG.Pattern.prototype=new SVG.Container,SVG.extend(SVG.Pattern,{fill:function(){return"url(#"+this.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(t){this.constructor.call(this,SVG.create(t+"Gradient")),this.attr("id",this.id="svgjs_element_"+SVG.did++),this.type=t},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.id+")"}}),SVG.extend(SVG.Defs,{gradient:function(e,t){var n=this.put(new SVG.Gradient(e));return t(n),n}}),SVG.Stop=function(t){this.constructor.call(this,SVG.create("stop")),this.update(t)},SVG.Stop.prototype=new SVG.Element,SVG.extend(SVG.Stop,{update:function(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(t){this.constructor.call(this,SVG.create("svg")),this.parent=typeof t=="string"?document.getElementById(t):t,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(t){this.constructor.call(this,t)},SVG.Shape.prototype=new SVG.Element,SVG.Wrap=function(t){this.constructor.call(this,SVG.create("g")),this.node.insertBefore(t.node,null),this.child=t,this.type=t.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 n,r,i,s=this._style(),o=this.doc(),u=e.split("\n"),a=this.style["font-size"];while(this.node.hasChildNodes())this.node.removeChild(this.node.lastChild);for(n=0,r=u.length;n<r;n++)i=(new t).text(u[n]).attr({dy:a*this.leading-(n==0?a*.3:0),x:this.attrs.x||0,style:s}),this.node.appendChild(i.node),this.lines.push(i);return this.attr("style",s)},_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}}),t.prototype=new SVG.Shape,SVG.extend(t,{text:function(e){return this.node.appendChild(document.createTextNode(e)),this}}),SVG.Nested=function(){this.constructor.call(this,SVG.create("svg")),this.attr("overflow","visible")},SVG.Nested.prototype=new SVG.Container,SVG._stroke=["color","width","opacity","linecap","linejoin","miterlimit","dasharray","dashoffset"],SVG._fill=["color","opacity","rule"];var n=function(e,t){return t=="color"?e:e+"-"+t};["fill","stroke"].forEach(function(e){SVG.Shape.prototype[e]=function(t){var r;if(typeof t=="string")this.attr(e,t);else for(r=SVG["_"+e].length-1;r>=0;r--)t[SVG["_"+e][r]]!=null&&this.attr(n(e,SVG["_"+e][r]),t[SVG["_"+e][r]]);return this}}),[SVG.Element,SVG.FX].forEach(function(e){e&&SVG.extend(e,{rotate:function(e){return this.transform({rotation:e||0})},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.G&&SVG.extend(SVG.G,{move:function(e,t){return this.transform({x:e,y:t})}}),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.5-8-g5020240 - svg 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:0,create:function(e){return document.createElementNS(this.ns,e)},extend:function(e,t){for(var n in t)e.prototype[n]=t[n]}},SVG.supported=function(){return!!document.createElementNS&&!!document.createElementNS(SVG.ns,"svg").createSVGRect}();if(!SVG.supported)return!1;SVG.ViewBox=function(e){var t,n,r=e.bbox(),i=(e.attr("viewBox")||"").match(/[\d\.]+/g);this.x=r.x,this.y=r.y,this.width=r.width,this.height=r.height,i?(t=parseFloat(i[2]),n=parseFloat(i[3]),e instanceof SVG.Doc&&(this.x=0,this.y=0,this.width=e.node.offsetWidth,this.height=e.node.offsetHeight),this.scale=this.width/this.height>t/n?this.height/n:this.width/t):this.scale=1},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){if(this.node=e)this.type=e.nodeName;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.trans={x:0,y:0,scaleX:1,scaleY:1,rotation:0,skewX:0,skewY:0}},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!=null?this.parent.remove(this):void 0},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{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 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]);e=this.trans;if(e.rotation!=0){var r=this.bbox();n.push("rotate("+e.rotation+","+(e.cx!=null?e.cx:r.cx)+","+(e.cy!=null?e.cy:r.cy)+")")}return 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 t===null?this.node.removeAttribute("data-"+e):this.attr("data-"+e,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){return this.has(e)||(t=t==null?this.children().length:t,this.children().splice(t,0,e),this.node.insertBefore(e.node,this.node.childNodes[t]||null),e.parent=this),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){return this.removeAt(this.children().indexOf(e))},removeAt:function(e){if(0<=e&&e<this.children().length){var t=this.children()[e];this.children().splice(e,1),this.node.removeChild(t.node),t.parent=null}return 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)}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},y:{from:n.cy,to:t}},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},_at:function(e,t){return typeof e.from=="number"?e.from+(e.to-e.from)*t:e.to.r||/^#/.test(e.to)?this._color(e,t):t<1?e.from:e.to},_color:function(e,t){var n,r;return n=this._h2r(e.from||"#000"),r=this._h2r(e.to),this._r2h({r:~~(n.r+(r.r-n.r)*t),g:~~(n.g+(r.g-n.g)*t),b:~~(n.b+(r.b-n.b)*t)})},_h2r:function(e){var t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(this._fh(e));return t?{r:parseInt(t[1],16),g:parseInt(t[2],16),b:parseInt(t[3],16)}:{r:0,g:0,b:0}},_r2h:function(e){return"#"+this._c2h(e.r)+this._c2h(e.g)+this._c2h(e.b)},_c2h:function(e){var t=e.toString(16);return t.length==1?"0"+t:t},_fh: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}}),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,{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")),this.attr("id",this.id="svgjs_element_"+SVG.did++)},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.id+")")}}),SVG.Pattern=function(e){this.constructor.call(this,SVG.create("pattern")),this.attr("id",this.id="svgjs_element_"+SVG.did++)},SVG.Pattern.prototype=new SVG.Container,SVG.extend(SVG.Pattern,{fill:function(){return"url(#"+this.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.attr("id",this.id="svgjs_element_"+SVG.did++),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.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("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){SVG.Shape.prototype[e]=function(n){var r;if(typeof n=="string")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.Element,SVG.FX].forEach(function(e){e&&SVG.extend(e,{rotate:function(e){return this.transform({rotation:e||0})},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.G&&SVG.extend(SVG.G,{move:function(e,t){return this.transform({x:e,y:t})}}),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
diff --git a/src/arrange.js b/src/arrange.js
index 441a9c3..47134ed 100644
--- a/src/arrange.js
+++ b/src/arrange.js
@@ -4,49 +4,49 @@
SVG.extend(SVG.Element, {
// Get all siblings, including myself
siblings: function() {
- return this.parent.children();
- },
+ return this.parent.children()
+ }
// Get the curent position siblings
- position: function() {
- return this.siblings().indexOf(this);
- },
+, position: function() {
+ return this.siblings().indexOf(this)
+ }
// Get the next element (will return null if there is none)
- next: function() {
- return this.siblings()[this.position() + 1];
- },
+, next: function() {
+ return this.siblings()[this.position() + 1]
+ }
// Get the next element (will return null if there is none)
- previous: function() {
- return this.siblings()[this.position() - 1];
- },
+, previous: function() {
+ return this.siblings()[this.position() - 1]
+ }
// Send given element one step forward
- forward: function() {
- return this.parent.remove(this).put(this, this.position() + 1);
- },
+, forward: function() {
+ return this.parent.remove(this).put(this, this.position() + 1)
+ }
// Send given element one step backward
- backward: function() {
- var i;
+, backward: function() {
+ var i
- this.parent.level();
+ this.parent.level()
- i = this.position();
+ i = this.position()
if (i > 1)
- this.parent.remove(this).add(this, i - 1);
+ this.parent.remove(this).add(this, i - 1)
- return this;
- },
+ return this
+ }
// Send given element all the way to the front
- front: function() {
- return this.parent.remove(this).put(this);
- },
+, front: function() {
+ return this.parent.remove(this).put(this)
+ }
// Send given element all the way to the back
- back: function() {
- this.parent.level();
+, back: function() {
+ this.parent.level()
if (this.position() > 1)
- this.parent.remove(this).add(this, 0);
+ this.parent.remove(this).add(this, 0)
- return this;
+ return this
}
-}); \ No newline at end of file
+}) \ No newline at end of file
diff --git a/src/bbox.js b/src/bbox.js
new file mode 100644
index 0000000..d70ac68
--- /dev/null
+++ b/src/bbox.js
@@ -0,0 +1,18 @@
+
+SVG.BBox = function(element) {
+ /* actual, native bounding box */
+ var box = element.node.getBBox()
+
+ /* include translations on x an y */
+ this.x = box.x + element.trans.x
+ this.y = box.y + element.trans.y
+
+ /* add the center */
+ this.cx = box.x + element.trans.x + box.width / 2
+ this.cy = box.y + element.trans.y + box.height / 2
+
+ /* plain width and height */
+ this.width = box.width
+ this.height = box.height
+
+} \ No newline at end of file
diff --git a/src/container.js b/src/container.js
index 1f0998a..a78d93f 100644
--- a/src/container.js
+++ b/src/container.js
@@ -1,139 +1,148 @@
-SVG.Container = function Container(element) {
- this.constructor.call(this, element);
-};
+SVG.Container = function(element) {
+ this.constructor.call(this, element)
+}
// Inherit from SVG.Element
-SVG.Container.prototype = new SVG.Element();
+SVG.Container.prototype = new SVG.Element
//
SVG.extend(SVG.Container, {
// Add given element at a position
add: function(element, index) {
if (!this.has(element)) {
- index = index == null ? this.children().length : index;
- this.children().splice(index, 0, element);
- this.node.insertBefore(element.node, this.node.childNodes[index] || null);
- element.parent = this;
+ index = index == null ? this.children().length : index
+ this.children().splice(index, 0, element)
+ this.node.insertBefore(element.node, this.node.childNodes[index] || null)
+ element.parent = this
}
- return this;
- },
+ return this
+ }
// Basically does the same as `add()` but returns the added element
- put: function(element, index) {
- this.add(element, index);
- return element;
- },
+, put: function(element, index) {
+ this.add(element, index)
+ return element
+ }
// Checks if the given element is a child
- has: function(element) {
- return this.children().indexOf(element) >= 0;
- },
+, has: function(element) {
+ return this.children().indexOf(element) >= 0
+ }
// Returns all child elements
- children: function() {
- return this._children || (this._children = []);
- },
+, children: function() {
+ return this._children || (this._children = [])
+ }
// Iterates over all children and invokes a given block
- each: function(block) {
+, each: function(block) {
var index,
- children = this.children();
+ children = this.children()
for (index = 0, length = children.length; index < length; index++)
if (children[index] instanceof SVG.Shape)
- block.apply(children[index], [index, children]);
+ block.apply(children[index], [index, children])
- return this;
- },
+ return this
+ }
// Remove a given child element
- remove: function(element) {
- return this.removeAt(this.children().indexOf(element));
- },
+, remove: function(element) {
+ return this.removeAt(this.children().indexOf(element))
+ }
// Remove a child element at a given position
- removeAt: function(index) {
+, removeAt: function(index) {
if (0 <= index && index < this.children().length) {
- var element = this.children()[index];
- this.children().splice(index, 1);
- this.node.removeChild(element.node);
- element.parent = null;
+ var element = this.children()[index]
+ this.children().splice(index, 1)
+ this.node.removeChild(element.node)
+ element.parent = null
}
- return this;
- },
+ return this
+ }
// Returns defs element
- defs: function() {
- return this._defs || (this._defs = this.put(new SVG.Defs(), 0));
- },
+, defs: function() {
+ return this._defs || (this._defs = this.put(new SVG.Defs(), 0))
+ }
// Re-level defs to first positon in element stack
- level: function() {
- return this.remove(this.defs()).put(this.defs(), 0);
- },
+, level: function() {
+ return this.remove(this.defs()).put(this.defs(), 0)
+ }
// Create a group element
- group: function() {
- return this.put(new SVG.G());
- },
+, group: function() {
+ return this.put(new SVG.G())
+ }
// Create a rect element
- rect: function(width, height) {
- return this.put(new SVG.Rect().size(width, height));
- },
+, rect: function(width, height) {
+ return this.put(new SVG.Rect().size(width, height))
+ }
// Create circle element, based on ellipse
- circle: function(diameter) {
- return this.ellipse(diameter);
- },
+, circle: function(diameter) {
+ return this.ellipse(diameter)
+ }
// Create an ellipse
- ellipse: function(width, height) {
- return this.put(new SVG.Ellipse().size(width, height));
- },
+, ellipse: function(width, height) {
+ return this.put(new SVG.Ellipse().size(width, height))
+ }
// Create a wrapped polyline element
- polyline: function(points) {
- return this.put(new SVG.Wrap(new SVG.Polyline())).plot(points);
- },
+, polyline: function(points) {
+ return this.put(new SVG.Wrap(new SVG.Polyline())).plot(points)
+ }
// Create a wrapped polygon element
- polygon: function(points) {
- return this.put(new SVG.Wrap(new SVG.Polygon())).plot(points);
- },
+, polygon: function(points) {
+ return this.put(new SVG.Wrap(new SVG.Polygon())).plot(points)
+ }
// Create a wrapped path element
- path: function(data) {
- return this.put(new SVG.Wrap(new SVG.Path())).plot(data);
- },
+, path: function(data) {
+ return this.put(new SVG.Wrap(new SVG.Path())).plot(data)
+ }
// Create image element, load image and set its size
- image: function(source, width, height) {
- width = width != null ? width : 100;
- return this.put(new SVG.Image().load(source).size(width, height != null ? height : width));
- },
+, image: function(source, width, height) {
+ width = width != null ? width : 100
+ return this.put(new SVG.Image().load(source).size(width, height != null ? height : width))
+ }
// Create text element
- text: function(text) {
- return this.put(new SVG.Text().text(text));
- },
+, text: function(text) {
+ return this.put(new SVG.Text().text(text))
+ }
// Create nested svg document
- nested: function() {
- return this.put(new SVG.Nested());
- },
+, nested: function() {
+ return this.put(new SVG.Nested())
+ }
// Create gradient element in defs
- gradient: function(type, block) {
- return this.defs().gradient(type, block);
- },
+, gradient: function(type, block) {
+ return this.defs().gradient(type, block)
+ }
// Create pattern element in defs
- pattern: function(width, height, block) {
- return this.defs().pattern(width, height, block);
- },
+, pattern: function(width, height, block) {
+ return this.defs().pattern(width, height, block)
+ }
// Create masking element
- mask: function() {
- return this.defs().put(new SVG.Mask());
- },
+, mask: function() {
+ return this.defs().put(new SVG.Mask())
+ }
// Get first child, skipping the defs node
- first: function() {
- return this.children()[0] instanceof SVG.Defs ? this.children()[1] : this.children()[0];
- },
+, first: function() {
+ return this.children()[0] instanceof SVG.Defs ? this.children()[1] : this.children()[0]
+ }
// Get the last child
- last: function() {
- return this.children()[this.children().length - 1];
- },
+, last: function() {
+ return this.children()[this.children().length - 1]
+ }
+ // Get the viewBox and calculate the zoom value
+, viewbox: function() {
+ /* act as a getter if there are no arguments */
+ if (arguments.length == 0)
+ return new SVG.ViewBox(this)
+
+ /* otherwise act as a setter */
+ return this.attr('viewBox', Array.prototype.slice.call(arguments).join(' '))
+ }
// Remove all elements in this container
- clear: function() {
- this._children = [];
+, clear: function() {
+ this._children = []
while (this.node.hasChildNodes())
- this.node.removeChild(this.node.lastChild);
+ this.node.removeChild(this.node.lastChild)
- return this;
+ return this
}
-}); \ No newline at end of file
+}) \ No newline at end of file
diff --git a/src/defs.js b/src/defs.js
index 8714663..48a8f28 100644
--- a/src/defs.js
+++ b/src/defs.js
@@ -1,9 +1,9 @@
// ### The defs node
//
-SVG.Defs = function Defs() {
- this.constructor.call(this, SVG.create('defs'));
-};
+SVG.Defs = function() {
+ this.constructor.call(this, SVG.create('defs'))
+}
// Inherits from SVG.Container
-SVG.Defs.prototype = new SVG.Container(); \ No newline at end of file
+SVG.Defs.prototype = new SVG.Container \ No newline at end of file
diff --git a/src/doc.js b/src/doc.js
index ce67b1c..ac314f3 100644
--- a/src/doc.js
+++ b/src/doc.js
@@ -1,26 +1,26 @@
// ### This module accounts for the main svg document
//
-SVG.Doc = function Doc(element) {
- this.constructor.call(this, SVG.create('svg'));
+SVG.Doc = function(element) {
+ this.constructor.call(this, SVG.create('svg'))
/* ensure the presence of a html element */
this.parent = typeof element == 'string' ?
document.getElementById(element) :
- element;
+ element
/* set svg element attributes and create the <defs> node */
this.
attr({ xmlns: SVG.ns, version: '1.1', width: '100%', height: '100%' }).
attr('xlink', SVG.xlink, SVG.ns).
- defs();
+ defs()
/* ensure correct rendering for safari */
this.stage();
-};
+}
// Inherits from SVG.Container
-SVG.Doc.prototype = new SVG.Container();
+SVG.Doc.prototype = new SVG.Container
// Hack for safari preventing text to be rendered in one line.
// Basically it sets the position of the svg node to absolute
@@ -28,35 +28,35 @@ SVG.Doc.prototype = new SVG.Container();
SVG.Doc.prototype.stage = function() {
var check,
element = this,
- wrapper = document.createElement('div');
+ wrapper = document.createElement('div')
/* set temp wrapper to position relative */
- wrapper.style.cssText = 'position:relative;height:100%;';
+ wrapper.style.cssText = 'position:relative;height:100%;'
/* put element into wrapper */
- element.parent.appendChild(wrapper);
- wrapper.appendChild(element.node);
+ element.parent.appendChild(wrapper)
+ wrapper.appendChild(element.node)
/* check for dom:ready */
check = function() {
if (document.readyState === 'complete') {
- element.attr('style', 'position:absolute;');
+ element.attr('style', 'position:absolute;')
setTimeout(function() {
/* set position back to relative */
- element.attr('style', 'position:relative;');
+ element.attr('style', 'position:relative;')
/* remove temp wrapper */
- element.parent.removeChild(element.node.parentNode);
- element.node.parentNode.removeChild(element.node);
- element.parent.appendChild(element.node);
+ element.parent.removeChild(element.node.parentNode)
+ element.node.parentNode.removeChild(element.node)
+ element.parent.appendChild(element.node)
- }, 5);
+ }, 5)
} else {
- setTimeout(check, 10);
+ setTimeout(check, 10)
}
- };
+ }
- check();
+ check()
- return this;
-}; \ No newline at end of file
+ return this
+} \ No newline at end of file
diff --git a/src/element.js b/src/element.js
index cced952..a44547c 100644
--- a/src/element.js
+++ b/src/element.js
@@ -2,10 +2,10 @@
// ### Used by nearly every other module
//
-SVG.Element = function Element(node) {
+SVG.Element = function(node) {
/* keep reference to the element node */
if (this.node = node)
- this.type = node.nodeName;
+ this.type = node.nodeName
/* initialize attribute store with defaults */
this.attrs = {
@@ -24,7 +24,7 @@ SVG.Element = function Element(node) {
r: 0,
rx: 0,
ry: 0
- };
+ }
/* initialize transformation store with defaults */
this.trans = {
@@ -35,9 +35,9 @@ SVG.Element = function Element(node) {
rotation: 0,
skewX: 0,
skewY: 0
- };
+ }
-};
+}
//
SVG.extend(SVG.Element, {
@@ -46,41 +46,41 @@ SVG.extend(SVG.Element, {
return this.attr({
x: x,
y: y
- });
+ })
},
// Move element by its center
center: function(x, y) {
- var box = this.bbox();
+ var box = this.bbox()
- return this.move(x - box.width / 2, y - box.height / 2);
+ return this.move(x - box.width / 2, y - box.height / 2)
},
// Set element size to given width and height
size: function(width, height) {
return this.attr({
width: width,
height: height
- });
+ })
},
// Clone element
clone: function() {
- var clone;
+ var clone
/* if this is a wrapped shape */
if (this instanceof SVG.Wrap) {
/* build new wrapped shape */
- clone = this.parent[this.child.node.nodeName]();
- clone.attrs = this.attrs;
+ clone = this.parent[this.child.node.nodeName]()
+ clone.attrs = this.attrs
/* copy child attributes and transformations */
- clone.child.trans = this.child.trans;
- clone.child.attr(this.child.attrs).transform({});
+ clone.child.trans = this.child.trans
+ clone.child.attr(this.child.attrs).transform({})
/* re-plot shape */
if (clone.plot)
- clone.plot(this.child.attrs[this.child instanceof SVG.Path ? 'd' : 'points']);
+ clone.plot(this.child.attrs[this.child instanceof SVG.Path ? 'd' : 'points'])
} else {
- var name = this.node.nodeName;
+ var name = this.node.nodeName
/* invoke shape method with shape-specific arguments */
clone = name == 'rect' ?
@@ -93,35 +93,35 @@ SVG.extend(SVG.Element, {
this.parent[name](this.content) :
name == 'g' ?
this.parent.group() :
- this.parent[name]();
+ this.parent[name]()
- clone.attr(this.attrs);
+ clone.attr(this.attrs)
}
/* copy transformations */
- clone.trans = this.trans;
+ clone.trans = this.trans
/* apply attributes and translations */
- return clone.transform({});
+ return clone.transform({})
},
// Remove element
remove: function() {
- return this.parent != null ? this.parent.remove(this) : void 0;
+ return this.parent != null ? this.parent.remove(this) : void 0
},
// Get parent document
doc: function() {
- return this._parent(SVG.Doc);
+ return this._parent(SVG.Doc)
},
// Get parent nested document
nested: function() {
- return this._parent(SVG.Nested);
+ return this._parent(SVG.Nested)
},
// Set svg element attribute
attr: function(a, v, n) {
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))
@@ -129,26 +129,26 @@ SVG.extend(SVG.Element, {
this.content :
a == 'leading' ?
this[a] :
- this.style[a];
+ 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]
} else {
/* store value */
- this.attrs[a] = v;
+ this.attrs[a] = v
/* treat x differently on text elements */
if (a == 'x' && this._isText())
for (var i = this.lines.length - 1; i >= 0; i--)
- this.lines[i].attr(a, v);
+ this.lines[i].attr(a, v)
/* set the actual attribute */
else
n != null ?
this.node.setAttributeNS(n, a, v) :
- this.node.setAttribute(a, v);
+ this.node.setAttribute(a, v)
/* if the passed argument belongs to the style as well, add it there */
if (this._isStyle(a)) {
@@ -156,131 +156,116 @@ SVG.extend(SVG.Element, {
this.text(v) :
a == 'leading' ?
this[a] = v :
- this.style[a] = v;
+ this.style[a] = v
- this.text(this.content);
+ this.text(this.content)
}
}
- return this;
+ 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];
+ return this.trans[o]
/* ... otherwise continue as a setter */
- var key, transform = [];
+ var key, transform = []
/* merge values */
for (key in o)
if (o[key] != null)
- this.trans[key] = o[key];
+ this.trans[key] = o[key]
/* alias current transformations */
- o = this.trans;
+ o = this.trans
/* add rotation */
if (o.rotation != 0) {
- var box = this.bbox();
- transform.push('rotate(' + o.rotation + ',' + (o.cx != null ? o.cx : box.cx) + ',' + (o.cy != null ? o.cy : box.cy) + ')');
+ var box = this.bbox()
+ transform.push('rotate(' + o.rotation + ',' + (o.cx != null ? o.cx : box.cx) + ',' + (o.cy != null ? o.cy : box.cy) + ')')
}
/* add scale */
- transform.push('scale(' + o.scaleX + ',' + o.scaleY + ')');
+ transform.push('scale(' + o.scaleX + ',' + o.scaleY + ')')
/* add skew on x axis */
if (o.skewX != 0)
- transform.push('skewX(' + o.skewX + ')');
+ transform.push('skewX(' + o.skewX + ')')
/* add skew on y axis */
if (o.skewY != 0)
transform.push('skewY(' + o.skewY + ')')
/* add translation */
- transform.push('translate(' + o.x + ',' + o.y + ')');
+ transform.push('translate(' + o.x + ',' + o.y + ')')
/* add only te required transformations */
- return this.attr('transform', transform.join(' '));
+ return this.attr('transform', transform.join(' '))
},
// Store data values on svg nodes
data: function(a, v, r) {
if (arguments.length < 2) {
try {
- return JSON.parse(this.attr('data-' + a));
+ return JSON.parse(this.attr('data-' + a))
} catch(e) {
- return this.attr('data-' + a);
- };
+ return this.attr('data-' + a)
+ }
} else {
v === null ?
this.node.removeAttribute('data-' + a) :
- this.attr('data-' + a, r === true ? v : JSON.stringify(v));
+ this.attr('data-' + a, r === true ? v : JSON.stringify(v))
}
- return this;
+ return this
},
// Get bounding box
bbox: function() {
- /* actual, native bounding box */
- var box = this.node.getBBox();
-
- return {
- /* include translations on x an y */
- x: box.x + this.trans.x,
- y: box.y + this.trans.y,
-
- /* add the center */
- cx: box.x + this.trans.x + box.width / 2,
- cy: box.y + this.trans.y + box.height / 2,
-
- /* plain width and height */
- width: box.width,
- height: box.height
- };
+ return new SVG.BBox(this)
},
// Checks whether the given point inside the bounding box of the element
inside: function(x, y) {
- var box = this.bbox();
+ var box = this.bbox()
return x > box.x &&
y > box.y &&
x < box.x + box.width &&
- y < box.y + box.height;
+ y < box.y + box.height
},
// Show element
show: function() {
- this.node.style.display = '';
+ this.node.style.display = ''
- return this;
+ return this
},
// Hide element
hide: function() {
- this.node.style.display = 'none';
+ this.node.style.display = 'none'
- return this;
+ return this
},
// Is element visible?
visible: function() {
- return this.node.style.display != 'none';
+ return this.node.style.display != 'none'
},
// Private: find svg parent by instance
_parent: function(parent) {
- var element = this;
+ var element = this
while (element != null && !(element instanceof parent))
- element = element.parent;
+ element = element.parent
- return element;
+ return 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' && this._isText() ? (/^font|text|leading/).test(attr) : false
},
// Private: element type tester
_isText: function() {
- return this instanceof SVG.Text;
+ return this instanceof SVG.Text
}
-});
+})
diff --git a/src/ellipse.js b/src/ellipse.js
index ad3e02e..f9398cf 100644
--- a/src/ellipse.js
+++ b/src/ellipse.js
@@ -1,36 +1,36 @@
//
-SVG.Ellipse = function Ellipse() {
- this.constructor.call(this, SVG.create('ellipse'));
-};
+SVG.Ellipse = function() {
+ this.constructor.call(this, SVG.create('ellipse'))
+}
// Inherit from SVG.Shape
-SVG.Ellipse.prototype = new SVG.Shape();
+SVG.Ellipse.prototype = new SVG.Shape()
//
SVG.extend(SVG.Ellipse, {
// Custom move function
move: function(x, y) {
- this.attrs.x = x;
- this.attrs.y = y;
+ this.attrs.x = x
+ this.attrs.y = y
- return this.center();
+ return this.center()
},
// Custom size function
size: function(width, height) {
return this.
attr({ rx: width / 2, ry: (height != null ? height : width) / 2 }).
- center();
+ 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)
- });
+ })
}
-});
+})
// Usage:
-// draw.ellipse(200, 100); \ No newline at end of file
+// draw.ellipse(200, 100) \ No newline at end of file
diff --git a/src/event.js b/src/event.js
index a2bb3f0..df3cd6a 100644
--- a/src/event.js
+++ b/src/event.js
@@ -1,9 +1,9 @@
// ### Manage events on elements
// rect.click(function() {
-// this.fill({ color: '#f06' });
-// });
-[ 'click',
+// this.fill({ color: '#f06' })
+// })
+;[ 'click',
'dblclick',
'mousedown',
'mouseup',
@@ -19,46 +19,46 @@
/* add event to SVG.Element */
SVG.Element.prototype[event] = function(f) {
- var self = this;
+ 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;
+ : null
- return this;
- };
+ return this
+ }
-});
+})
// Add event binder in the SVG namespace
SVG.on = function(node, event, listener) {
if (node.addEventListener)
- node.addEventListener(event, listener, false);
+ node.addEventListener(event, listener, false)
else
- node.attachEvent('on' + event, listener);
-};
+ node.attachEvent('on' + event, listener)
+}
// Add event unbinder in the SVG namespace
SVG.off = function(node, event, listener) {
if (node.removeEventListener)
- node.removeEventListener(event, listener, false);
+ node.removeEventListener(event, listener, false)
else
- node.detachEvent('on' + event, listener);
-};
+ node.detachEvent('on' + event, listener)
+}
//
SVG.extend(SVG.Element, {
// Bind given event to listener
on: function(event, listener) {
- SVG.on(this.node, event, listener);
+ SVG.on(this.node, event, listener)
- return this;
+ return this
},
// Unbind event from listener
off: function(event, listener) {
- SVG.off(this.node, event, listener);
+ SVG.off(this.node, event, listener)
- return this;
+ return this
}
}); \ No newline at end of file
diff --git a/src/fx.js b/src/fx.js
index a3ae5ec..7aa60a9 100644
--- a/src/fx.js
+++ b/src/fx.js
@@ -1,44 +1,44 @@
-SVG.FX = function FX(element) {
+SVG.FX = function(element) {
/* store target element */
- this.target = element;
-};
+ this.target = element
+}
//
SVG.extend(SVG.FX, {
// Add animation parameters and start animation
animate: function(duration, ease) {
/* ensure default duration and easing */
- duration = duration == null ? 1000 : duration;
- ease = ease || '<>';
+ duration = duration == null ? 1000 : duration
+ ease = ease || '<>'
var akeys, tkeys, tvalues,
element = this.target,
fx = this,
start = (new Date).getTime(),
- finish = start + duration;
+ finish = start + duration
/* start animation */
this.interval = setInterval(function(){
// This code was borrowed from the emile.js micro framework by Thomas Fuchs, aka MadRobby.
var index,
time = (new Date).getTime(),
- pos = time > finish ? 1 : (time - start) / duration;
+ pos = time > finish ? 1 : (time - start) / duration
/* collect attribute keys */
if (akeys == null) {
- akeys = [];
+ akeys = []
for (var key in fx.attrs)
- akeys.push(key);
- };
+ akeys.push(key)
+ }
/* collect transformation keys */
if (tkeys == null) {
- tkeys = [];
+ tkeys = []
for (var key in fx.trans)
- tkeys.push(key);
+ tkeys.push(key)
- tvalues = {};
- };
+ tvalues = {}
+ }
/* apply easing */
pos = ease == '<>' ?
@@ -51,110 +51,110 @@ SVG.extend(SVG.FX, {
pos :
typeof ease == 'function' ?
ease(pos) :
- pos;
+ pos
/* run all position properties */
if (fx._move)
- element.move(fx._at(fx._move.x, pos), fx._at(fx._move.y, pos));
+ 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.move(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));
+ 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));
+ element.attr(akeys[index], fx._at(fx.attrs[akeys[index]], 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);
+ tvalues[tkeys[index]] = fx._at(fx.trans[tkeys[index]], pos)
- element.transform(tvalues);
+ element.transform(tvalues)
}
/* finish off animation */
if (time > finish) {
- clearInterval(fx.interval);
- fx._after ? fx._after.apply(element, [fx]) : fx.stop();
+ clearInterval(fx.interval)
+ fx._after ? fx._after.apply(element, [fx]) : fx.stop()
}
- }, duration > 10 ? 10 : duration);
+ }, duration > 10 ? 10 : duration)
- return this;
+ return this
},
// Add animatable attributes
attr: function(a, v, n) {
if (typeof a == 'object')
for (var key in a)
- this.attr(key, a[key]);
+ this.attr(key, a[key])
else
- this.attrs[a] = { from: this.target.attr(a), to: v };
+ this.attrs[a] = { from: this.target.attr(a), to: v }
return this;
},
// Add animatable transformations
transform: function(o) {
for (var key in o)
- this.trans[key] = { from: this.target.trans[key], to: o[key] };
+ this.trans[key] = { from: this.target.trans[key], to: o[key] }
- return this;
+ return this
},
// Add animatable move
move: function(x, y) {
- var box = this.target.bbox();
+ var box = this.target.bbox()
this._move = {
x: { from: box.x, to: x },
y: { from: box.y, to: y }
- };
+ }
- return this;
+ return this
},
// Add animatable size
size: function(width, height) {
- var box = this.target.bbox();
+ var box = this.target.bbox()
this._size = {
width: { from: box.width, to: width },
height: { from: box.height, to: height }
- };
+ }
- return this;
+ return this
},
// Add animatable center
center: function(x, y) {
- var box = this.target.bbox();
+ var box = this.target.bbox()
this._move = {
x: { from: box.cx, to: x },
y: { from: box.cy, to: y }
- };
+ }
- return this;
+ return this
},
// Callback after animation
after: function(after) {
- this._after = after;
+ this._after = after
- return this;
+ return this
},
// Stop running animation
stop: function() {
/* stop current animation */
- clearInterval(this.interval);
+ clearInterval(this.interval)
/* reset storage for properties that need animation */
- this.attrs = {};
- this.trans = {};
- this._move = null;
- this._size = null;
- this._after = null;
+ this.attrs = {}
+ this.trans = {}
+ this._move = null
+ this._size = null
+ this._after = null
- return this;
+ return this
},
// Private: at position according to from and to
_at: function(o, pos) {
@@ -167,45 +167,45 @@ SVG.extend(SVG.FX, {
this._color(o, pos) :
/* for all other values wait until pos has reached 1 to return the final value */
- pos < 1 ? o.from : o.to;
+ pos < 1 ? o.from : o.to
},
// Private: tween color
_color: function(o, pos) {
- var from, to;
+ var from, to
/* convert FROM hex to rgb */
- from = this._h2r(o.from || '#000');
+ from = this._h2r(o.from || '#000')
/* convert TO hex to rgb */
- to = this._h2r(o.to);
+ to = this._h2r(o.to)
/* tween color and return hex */
return this._r2h({
r: ~~(from.r + (to.r - from.r) * pos),
g: ~~(from.g + (to.g - from.g) * pos),
b: ~~(from.b + (to.b - from.b) * pos)
- });
+ })
},
// Private: convert hex to rgb object
_h2r: function(hex) {
/* parse full hex */
- var match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(this._fh(hex));
+ var match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(this._fh(hex))
/* if the hex is successfully parsed, return it in rgb, otherwise return black */
return match ? {
r: parseInt(match[1], 16),
g: parseInt(match[2], 16),
b: parseInt(match[3], 16)
- } : { r: 0, g: 0, b: 0 };
+ } : { r: 0, g: 0, b: 0 }
},
// Private: convert rgb object to hex string
_r2h: function(rgb) {
- return '#' + this._c2h(rgb.r) + this._c2h(rgb.g) + this._c2h(rgb.b);
+ return '#' + this._c2h(rgb.r) + this._c2h(rgb.g) + this._c2h(rgb.b)
},
// Private: convert component to hex
_c2h: function(c) {
- var hex = c.toString(16);
- return hex.length == 1 ? '0' + hex : hex;
+ var hex = c.toString(16)
+ return hex.length == 1 ? '0' + hex : hex
},
// Private: force potential 3-based hex to 6-based
_fh: function(hex) {
@@ -214,26 +214,26 @@ SVG.extend(SVG.FX, {
hex.substring(1, 2), hex.substring(1, 2),
hex.substring(2, 3), hex.substring(2, 3),
hex.substring(3, 4), hex.substring(3, 4)
- ].join('') : hex;
+ ].join('') : hex
}
-});
+})
//
SVG.extend(SVG.Element, {
// Get fx module or create a new one, then animate with given duration and ease
animate: function(duration, ease) {
- return (this.fx || (this.fx = new SVG.FX(this))).stop().animate(duration, ease);
+ return (this.fx || (this.fx = new SVG.FX(this))).stop().animate(duration, ease)
},
// Stop current animation; this is an alias to the fx instance
stop: function() {
- this.fx.stop();
+ this.fx.stop()
- return this;
+ return this
}
-});
+})
// Usage:
// rect.animate(1500, '>').move(200, 300).after(function() {
-// this.fill({ color: '#f06' });
-// });
+// this.fill({ color: '#f06' })
+// })
diff --git a/src/gradient.js b/src/gradient.js
index 07bb748..f3ba85c 100644
--- a/src/gradient.js
+++ b/src/gradient.js
@@ -1,15 +1,15 @@
-SVG.Gradient = function Gradient(type) {
- this.constructor.call(this, SVG.create(type + 'Gradient'));
+SVG.Gradient = function(type) {
+ this.constructor.call(this, SVG.create(type + 'Gradient'))
/* set unique id */
- this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)));
+ this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)))
/* store type */
- this.type = type;
-};
+ this.type = type
+}
// Inherit from SVG.Container
-SVG.Gradient.prototype = new SVG.Container();
+SVG.Gradient.prototype = new SVG.Container
//
SVG.extend(SVG.Gradient, {
@@ -17,67 +17,67 @@ SVG.extend(SVG.Gradient, {
from: function(x, y) {
return this.type == 'radial' ?
this.attr({ fx: x + '%', fy: y + '%' }) :
- this.attr({ x1: x + '%', y1: y + '%' });
+ this.attr({ x1: x + '%', y1: y + '%' })
},
// To position
to: function(x, y) {
return this.type == 'radial' ?
this.attr({ cx: x + '%', cy: y + '%' }) :
- this.attr({ x2: x + '%', y2: y + '%' });
+ this.attr({ x2: x + '%', y2: y + '%' })
},
// Radius for radial gradient
radius: function(radius) {
return this.type == 'radial' ?
this.attr({ r: radius + '%' }) :
- this;
+ this
},
// Add a color stop
at: function(stop) {
- return this.put(new SVG.Stop(stop));
+ return this.put(new SVG.Stop(stop))
},
// Update gradient
update: function(block) {
/* remove all stops */
while (this.node.hasChildNodes())
- this.node.removeChild(this.node.lastChild);
+ this.node.removeChild(this.node.lastChild)
/* invoke passed block */
- block(this);
+ block(this)
- return this;
+ return this
},
// Return the fill id
fill: function() {
- return 'url(#' + this.id + ')';
+ return 'url(#' + this.id + ')'
}
-});
+})
//
SVG.extend(SVG.Defs, {
/* define gradient */
gradient: function(type, block) {
- var element = this.put(new SVG.Gradient(type));
+ var element = this.put(new SVG.Gradient(type))
/* invoke passed block */
- block(element);
+ block(element)
- return element;
+ return element
}
-});
+})
-SVG.Stop = function Stop(stop) {
- this.constructor.call(this, SVG.create('stop'));
+SVG.Stop = function(stop) {
+ this.constructor.call(this, SVG.create('stop'))
/* immediatelly build stop */
- this.update(stop);
-};
+ this.update(stop)
+}
// Inherit from SVG.Element
-SVG.Stop.prototype = new SVG.Element();
+SVG.Stop.prototype = new SVG.Element()
//
SVG.extend(SVG.Stop, {
@@ -86,19 +86,19 @@ SVG.extend(SVG.Stop, {
update: function(o) {
var index,
style = '',
- attr = ['opacity', 'color'];
+ 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]] + ';';
+ style += 'stop-' + attr[index] + ':' + o[attr[index]] + ';'
/* set attributes */
return this.attr({
offset: (o.offset != null ? o.offset : this.attrs.offset || 0) + '%',
style: style
- });
+ })
}
-});
+})
diff --git a/src/group.js b/src/group.js
index 5c6df10..3fc8f88 100644
--- a/src/group.js
+++ b/src/group.js
@@ -1,14 +1,14 @@
-SVG.G = function G() {
- this.constructor.call(this, SVG.create('g'));
-};
+SVG.G = function() {
+ this.constructor.call(this, SVG.create('g'))
+}
// Inherit from SVG.Container
-SVG.G.prototype = new SVG.Container();
+SVG.G.prototype = new SVG.Container
SVG.extend(SVG.G, {
// Get defs
defs: function() {
- return this.doc().defs();
+ return this.doc().defs()
}
-}); \ No newline at end of file
+}) \ No newline at end of file
diff --git a/src/image.js b/src/image.js
index b9340e4..bc60c0e 100644
--- a/src/image.js
+++ b/src/image.js
@@ -1,16 +1,16 @@
-SVG.Image = function Image() {
- this.constructor.call(this, SVG.create('image'));
-};
+SVG.Image = function() {
+ this.constructor.call(this, SVG.create('image'))
+}
// Inherit from SVG.Element
-SVG.Image.prototype = new SVG.Shape();
+SVG.Image.prototype = new SVG.Shape()
SVG.extend(SVG.Image, {
/* (re)load image */
load: function(url) {
- this.src = url;
- return (url ? this.attr('xlink:href', url, SVG.xlink) : this);
+ this.src = url
+ return (url ? this.attr('xlink:href', url, SVG.xlink) : this)
}
-}); \ No newline at end of file
+}) \ No newline at end of file
diff --git a/src/line.js b/src/line.js
index b5dd2ef..1e783e4 100644
--- a/src/line.js
+++ b/src/line.js
@@ -1,37 +1,37 @@
-SVG.Line = function Line() {
- this.constructor.call(this, SVG.create('line'));
-};
+SVG.Line = function() {
+ this.constructor.call(this, SVG.create('line'))
+}
// Inherit from SVG.Shape
-SVG.Line.prototype = new SVG.Shape();
+SVG.Line.prototype = new SVG.Shape()
// Add required methods
SVG.extend(SVG.Line, {
// Move line
move: function(x, y) {
- var bbox = this.bbox();
+ 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
- });
+ })
},
// Move element by its center
center: function(x, y) {
- var bbox = this.bbox();
+ var bbox = this.bbox()
- return this.move(x - bbox.width / 2, y - bbox.height / 2);
+ return this.move(x - bbox.width / 2, y - bbox.height / 2)
},
// Set line size by width and height
size: function(width, height) {
- var bbox = this.bbox();
+ 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);
+ 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)
}
-});
+})
// Extend all container modules
SVG.extend(SVG.Container, {
@@ -41,6 +41,6 @@ SVG.extend(SVG.Container, {
y1: y1,
x2: x2,
y2: y2
- }));
+ }))
}
-}); \ No newline at end of file
+}) \ No newline at end of file
diff --git a/src/mask.js b/src/mask.js
index c33b93a..708b982 100644
--- a/src/mask.js
+++ b/src/mask.js
@@ -1,21 +1,21 @@
-SVG.Mask = function Mask() {
- this.constructor.call(this, SVG.create('mask'));
+SVG.Mask = function() {
+ this.constructor.call(this, SVG.create('mask'))
/* set unique id */
- this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)));
-};
+ this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)))
+}
// Inherit from SVG.Container
-SVG.Mask.prototype = new SVG.Container();
+SVG.Mask.prototype = new SVG.Container
SVG.extend(SVG.Element, {
// Distribute mask to svg element
maskWith: function(element) {
/* use given mask or create a new one */
- this.mask = element instanceof SVG.Mask ? element : this.parent.mask().add(element);
+ this.mask = element instanceof SVG.Mask ? element : this.parent.mask().add(element)
- return this.attr('mask', 'url(#' + this.mask.id + ')');
+ return this.attr('mask', 'url(#' + this.mask.id + ')')
}
-}); \ No newline at end of file
+}) \ No newline at end of file
diff --git a/src/nested.js b/src/nested.js
index d2aafdb..45820f2 100644
--- a/src/nested.js
+++ b/src/nested.js
@@ -1,7 +1,7 @@
-SVG.Nested = function Nested() {
- this.constructor.call(this, SVG.create('svg'));
- this.attr('overflow', 'visible');
-};
+SVG.Nested = function() {
+ this.constructor.call(this, SVG.create('svg'))
+ this.attr('overflow', 'visible')
+}
// Inherit from SVG.Container
-SVG.Nested.prototype = new SVG.Container(); \ No newline at end of file
+SVG.Nested.prototype = new SVG.Container \ No newline at end of file
diff --git a/src/path.js b/src/path.js
index 5d7a3a5..e62f8d1 100644
--- a/src/path.js
+++ b/src/path.js
@@ -1,9 +1,9 @@
-SVG.Path = function Path() {
- this.constructor.call(this, SVG.create('path'));
-};
+SVG.Path = function() {
+ this.constructor.call(this, SVG.create('path'))
+}
// Inherit from SVG.Shape
-SVG.Path.prototype = new SVG.Shape();
+SVG.Path.prototype = new SVG.Shape()
SVG.extend(SVG.Path, {
@@ -12,12 +12,12 @@ SVG.extend(SVG.Path, {
this.transform({
x: x,
y: y
- });
+ })
},
/* set path data */
plot: function(data) {
- return this.attr('d', data || 'M0,0');
+ return this.attr('d', data || 'M0,0')
}
}); \ No newline at end of file
diff --git a/src/pattern.js b/src/pattern.js
index c12978e..82a2339 100644
--- a/src/pattern.js
+++ b/src/pattern.js
@@ -1,31 +1,31 @@
-SVG.Pattern = function Pattern(type) {
- this.constructor.call(this, SVG.create('pattern'));
+SVG.Pattern = function(type) {
+ this.constructor.call(this, SVG.create('pattern'))
/* set unique id */
- this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)));
-};
+ this.attr('id', (this.id = 'svgjs_element_' + (SVG.did++)))
+}
// Inherit from SVG.Container
-SVG.Pattern.prototype = new SVG.Container();
+SVG.Pattern.prototype = new SVG.Container
//
SVG.extend(SVG.Pattern, {
// Return the fill id
fill: function() {
- return 'url(#' + this.id + ')';
+ return 'url(#' + this.id + ')'
}
-});
+})
//
SVG.extend(SVG.Defs, {
/* define gradient */
pattern: function(width, height, block) {
- var element = this.put(new SVG.Pattern());
+ var element = this.put(new SVG.Pattern())
/* invoke passed block */
- block(element);
+ block(element)
return element.attr({
x: 0,
@@ -33,7 +33,7 @@ SVG.extend(SVG.Defs, {
width: width,
height: height,
patternUnits: 'userSpaceOnUse'
- });
+ })
}
}); \ No newline at end of file
diff --git a/src/poly.js b/src/poly.js
index 395b0bf..9e89570 100644
--- a/src/poly.js
+++ b/src/poly.js
@@ -1,28 +1,28 @@
SVG.Poly = {
// Set polygon data with default zero point if no data is passed
plot: function(points) {
- this.attr('points', points || '0,0');
+ this.attr('points', points || '0,0')
- return this;
+ return this
}
-};
+}
-SVG.Polyline = function Polyline() {
- this.constructor.call(this, SVG.create('polyline'));
-};
+SVG.Polyline = function() {
+ this.constructor.call(this, SVG.create('polyline'))
+}
// 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);
+SVG.extend(SVG.Polyline, SVG.Poly)
-SVG.Polygon = function Polygon() {
- this.constructor.call(this, SVG.create('polygon'));
-};
+SVG.Polygon = function() {
+ this.constructor.call(this, SVG.create('polygon'))
+}
// 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
+SVG.extend(SVG.Polygon, SVG.Poly) \ No newline at end of file
diff --git a/src/rect.js b/src/rect.js
index 3f42558..0a398be 100644
--- a/src/rect.js
+++ b/src/rect.js
@@ -1,6 +1,6 @@
-SVG.Rect = function Rect() {
- this.constructor.call(this, SVG.create('rect'));
-};
+SVG.Rect = function() {
+ this.constructor.call(this, SVG.create('rect'))
+}
// 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
diff --git a/src/shape.js b/src/shape.js
index a6be4c7..a11bbc4 100644
--- a/src/shape.js
+++ b/src/shape.js
@@ -1,6 +1,6 @@
-SVG.Shape = function Shape(element) {
- this.constructor.call(this, element);
-};
+SVG.Shape = function(element) {
+ this.constructor.call(this, 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
diff --git a/src/sugar.js b/src/sugar.js
index c8b71fb..e076491 100644
--- a/src/sugar.js
+++ b/src/sugar.js
@@ -1,65 +1,65 @@
// Define list of available attributes for stroke and fill
-SVG._stroke = ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'];
-SVG._fill = ['color', 'opacity', 'rule'];
+SVG._stroke = ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset']
+SVG._fill = ['color', 'opacity', 'rule']
// Prepend correct color prefix
var _colorPrefix = function(type, attr) {
- return attr == 'color' ? type : type + '-' + attr;
-};
+ return attr == 'color' ? type : type + '-' + attr
+}
/* Add sugar for fill and stroke */
-['fill', 'stroke'].forEach(function(method) {
+;['fill', 'stroke'].forEach(function(method) {
// Set fill color and opacity
SVG.Shape.prototype[method] = function(o) {
- var index;
+ var indexOf
if (typeof o == 'string')
- this.attr(method, o);
+ this.attr(method, o)
else
/* set all attributes from _fillAttr and _strokeAttr list */
for (index = SVG['_' + method].length - 1; index >= 0; index--)
if (o[SVG['_' + method][index]] != null)
- this.attr(_colorPrefix(method, SVG['_' + method][index]), o[SVG['_' + method][index]]);
+ this.attr(_colorPrefix(method, SVG['_' + method][index]), o[SVG['_' + method][index]])
- return this;
- };
+ return this
+ }
-});
+})
-[SVG.Element, SVG.FX].forEach(function(module) {
+;[SVG.Element, SVG.FX].forEach(function(module) {
if (module) {
SVG.extend(module, {
// Rotation
rotate: function(angle) {
return this.transform({
rotation: angle || 0
- });
+ })
},
// Skew
skew: function(x, y) {
return this.transform({
skewX: x || 0,
skewY: y || 0
- });
+ })
},
// Scale
scale: function(x, y) {
return this.transform({
scaleX: x,
scaleY: y == null ? x : y
- });
+ })
},
// Opacity
opacity: function(value) {
- return this.attr('opacity', value);
+ return this.attr('opacity', value)
}
- });
+ })
}
-});
+})
if (SVG.G) {
SVG.extend(SVG.G, {
@@ -68,17 +68,17 @@ if (SVG.G) {
return this.transform({
x: x,
y: y
- });
+ })
}
- });
+ })
}
if (SVG.Text) {
SVG.extend(SVG.Text, {
// Set font
font: function(o) {
- var key, attr = {};
+ var key, attr = {}
for (key in o)
key == 'leading' ?
@@ -87,11 +87,11 @@ if (SVG.Text) {
attr['text-anchor'] = o[key] :
_styleAttr.indexOf(key) > -1 ?
attr['font-'+ key] = o[key] :
- void 0;
+ void 0
- return this.attr(attr).text(this.content);
+ return this.attr(attr).text(this.content)
}
- });
+ })
}
diff --git a/src/svg.js b/src/svg.js
index d8088be..f017e77 100644
--- a/src/svg.js
+++ b/src/svg.js
@@ -1,16 +1,16 @@
// 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 rect = draw.rect(100, 100).attr({ fill: '#f06' });
+// 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) {
if (SVG.supported)
- return new SVG.Doc(element);
-};
+ return new SVG.Doc(element)
+}
// The main wrapping element
this.SVG = {
@@ -23,20 +23,20 @@ this.SVG = {
// Method for element creation
, create: function(element) {
- return document.createElementNS(this.ns, element);
+ return document.createElementNS(this.ns, element)
}
// Method for extending objects
, extend: function(object, module) {
for (var key in module)
- object.prototype[key] = module[key];
+ object.prototype[key] = module[key]
}
-};
+}
// svg support test
SVG.supported = (function() {
return !! document.createElementNS &&
- !! document.createElementNS(SVG.ns,'svg').createSVGRect;
-})();
+ !! document.createElementNS(SVG.ns,'svg').createSVGRect
+})()
if (!SVG.supported) return false; \ No newline at end of file
diff --git a/src/text.js b/src/text.js
index ecd8811..6201269 100644
--- a/src/text.js
+++ b/src/text.js
@@ -1,85 +1,85 @@
// 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']
-SVG.Text = function Text() {
- this.constructor.call(this, SVG.create('text'));
+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.style = { '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 = [];
+ this.content = text = text || 'text'
+ this.lines = []
var index, length, tspan,
style = this._style(),
parent = this.doc(),
lines = text.split("\n"),
- size = this.style['font-size'];
+ size = this.style['font-size']
/* remove existing child nodes */
while (this.node.hasChildNodes())
- this.node.removeChild(this.node.lastChild);
+ this.node.removeChild(this.node.lastChild)
/* build new lines */
for (index = 0, length = lines.length; index < length; index++) {
/* create new tspan and set attributes */
- tspan = new TSpan().
+ 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
- });
+ })
/* add new tspan */
- this.node.appendChild(tspan.node);
- this.lines.push(tspan);
- };
+ this.node.appendChild(tspan.node)
+ this.lines.push(tspan)
+ }
/* set style */
- return this.attr('style', style);
+ return this.attr('style', style)
},
// Build style based on _styleAttr
_style: function() {
- var index, style = '';
+ var index, style = ''
for (index = _styleAttr.length - 1; index >= 0; index--)
if (this.style['font-' + _styleAttr[index]] != null)
- style += 'font-' + _styleAttr[index] + ':' + this.style['font-' + _styleAttr[index]] + ';';
+ style += 'font-' + _styleAttr[index] + ':' + this.style['font-' + _styleAttr[index]] + ';'
- style += 'text-anchor:' + this.style['text-anchor'] + ';';
+ style += 'text-anchor:' + this.style['text-anchor'] + ';'
- return style;
+ return style
}
-});
+})
-function TSpan() {
- this.constructor.call(this, SVG.create('tspan'));
-};
+SVG.TSpan = function() {
+ this.constructor.call(this, SVG.create('tspan'))
+}
// Inherit from SVG.Shape
-TSpan.prototype = new SVG.Shape();
+SVG.TSpan.prototype = new SVG.Shape()
// Include the container object
-SVG.extend(TSpan, {
+SVG.extend(SVG.TSpan, {
// Set text content
text: function(text) {
- this.node.appendChild(document.createTextNode(text));
+ this.node.appendChild(document.createTextNode(text))
- return this;
+ return this
}
}); \ No newline at end of file
diff --git a/src/viewbox.js b/src/viewbox.js
new file mode 100644
index 0000000..b6ccfab
--- /dev/null
+++ b/src/viewbox.js
@@ -0,0 +1,35 @@
+
+SVG.ViewBox = function(element) {
+ var width, height
+ , box = element.bbox()
+ , view = (element.attr('viewBox') || '').match(/[\d\.]+/g)
+
+ /* clone attributes */
+ this.x = box.x
+ this.y = box.y
+ this.width = box.width
+ this.height = box.height
+
+ if (view) {
+ /* get width and height from viewbox */
+ width = parseFloat(view[2])
+ height = parseFloat(view[3])
+
+ /* calculate real pixel dimensions on parent SVG.Doc element */
+ if (element instanceof SVG.Doc) {
+ this.x = 0
+ this.y = 0
+ this.width = element.node.offsetWidth
+ this.height = element.node.offsetHeight
+ }
+
+ /* calculate zoom accoring to viewbox */
+ this.scale = (this.width / this.height > width / height) ?
+ this.height / height :
+ this.width / width
+
+ } else {
+ this.scale = 1
+ }
+
+} \ No newline at end of file
diff --git a/src/wrap.js b/src/wrap.js
index be343a3..d3c6b8f 100644
--- a/src/wrap.js
+++ b/src/wrap.js
@@ -1,14 +1,14 @@
-SVG.Wrap = function Wrap(element) {
- this.constructor.call(this, SVG.create('g'));
+SVG.Wrap = function(element) {
+ this.constructor.call(this, SVG.create('g'))
/* insert and store child */
- this.node.insertBefore(element.node, null);
- this.child = element;
- this.type = element.node.nodeName;
-};
+ this.node.insertBefore(element.node, null)
+ this.child = element
+ this.type = element.node.nodeName
+}
// inherit from SVG.Shape
-SVG.Wrap.prototype = new SVG.Shape();
+SVG.Wrap.prototype = new SVG.Shape()
SVG.extend(SVG.Wrap, {
// Move wrapper around
@@ -16,66 +16,66 @@ SVG.extend(SVG.Wrap, {
return this.transform({
x: x,
y: y
- });
+ })
},
// Set the actual size in pixels
size: function(width, height) {
- var scale = width / this._b.width;
+ var scale = width / this._b.width
this.child.transform({
scaleX: scale,
scaleY: height != null ? height / this._b.height : scale
- });
+ })
- return this;
+ return this
},
// Move by center
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
- );
+ )
},
// Create distributed attr
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]);
+ for (v in a) this.attr(v, a[v])
/* act as a getter if only one argument is given */
} else if (arguments.length < 2) {
- return a == 'transform' ? this.attrs[a] : this.child.attrs[a];
+ return a == 'transform' ? this.attrs[a] : this.child.attrs[a]
/* apply locally for certain attributes */
} else if (a == 'transform') {
- this.attrs[a] = v;
+ this.attrs[a] = v
n != null ?
this.node.setAttributeNS(n, a, v) :
- this.node.setAttribute(a, v);
+ this.node.setAttribute(a, v)
/* apply attributes to child */
} else {
- this.child.attr(a, v, n);
+ this.child.attr(a, v, n)
}
- return this;
+ return this
},
// Distribute plot method to child
plot: function(data) {
/* plot new shape */
- this.child.plot(data);
+ this.child.plot(data)
/* get and store new bbox */
- this._b = this.child.bbox();
+ this._b = this.child.bbox()
/* reposition element withing wrapper */
this.child.transform({
x: -this._b.x,
y: -this._b.y
- });
+ })
- return this;
+ return this
}
-}); \ No newline at end of file
+}) \ No newline at end of file