summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorwout <wout@impinc.co.uk>2014-02-03 15:14:47 +0100
committerwout <wout@impinc.co.uk>2014-02-03 15:14:47 +0100
commite2304534e0cfb6f6f4ab8c37ea5275ae26cd455a (patch)
tree2386e9f361d9c5fa1308387aeeaf33f00241b3c5 /src
parent7a29817ffd764cf7ab6906250b57f234801c94e0 (diff)
downloadsvg.js-e2304534e0cfb6f6f4ab8c37ea5275ae26cd455a.tar.gz
svg.js-e2304534e0cfb6f6f4ab8c37ea5275ae26cd455a.zip
Implemented SVG.invent function and bumped to v1.0rc3
Diffstat (limited to 'src')
-rwxr-xr-xsrc/clip.js64
-rwxr-xr-xsrc/container.js41
-rwxr-xr-xsrc/defs.js13
-rwxr-xr-xsrc/doc.js184
-rwxr-xr-xsrc/element.js764
-rwxr-xr-xsrc/ellipse.js107
-rwxr-xr-xsrc/gradient.js154
-rwxr-xr-xsrc/group.js61
-rw-r--r--src/hyperlink.js54
-rwxr-xr-xsrc/image.js38
-rw-r--r--src/inventor.js23
-rwxr-xr-xsrc/line.js131
-rwxr-xr-xsrc/mask.js62
-rwxr-xr-xsrc/nested.js28
-rwxr-xr-xsrc/parent.js188
-rwxr-xr-xsrc/path.js90
-rwxr-xr-xsrc/poly.js51
-rwxr-xr-xsrc/rect.js28
-rwxr-xr-xsrc/set.js175
-rwxr-xr-xsrc/shape.js14
-rwxr-xr-xsrc/svg.js30
-rwxr-xr-xsrc/text.js362
-rwxr-xr-xsrc/textpath.js77
-rwxr-xr-xsrc/use.js41
24 files changed, 1408 insertions, 1372 deletions
diff --git a/src/clip.js b/src/clip.js
index 54f9d37..e8a5e35 100755
--- a/src/clip.js
+++ b/src/clip.js
@@ -1,27 +1,38 @@
-SVG.Clip = function() {
- this.constructor.call(this, SVG.create('clipPath'))
+SVG.Clip = SVG.invent({
+ // Initialize node
+ create: function() {
+ this.constructor.call(this, SVG.create('clipPath'))
- /* keep references to clipped elements */
- this.targets = []
-}
-
-// Inherit from SVG.Container
-SVG.Clip.prototype = new SVG.Container
-
-//
-SVG.extend(SVG.Clip, {
- // Unclip all clipped elements and remove itself
- remove: function() {
- /* unclip all targets */
- for (var i = this.targets.length - 1; i >= 0; i--)
- if (this.targets[i])
- this.targets[i].unclip()
- delete this.targets
+ /* keep references to clipped elements */
+ this.targets = []
+ }
- /* remove clipPath from parent */
- this.parent.removeElement(this)
-
- return this
+ // Inherit from
+, inherit: SVG.Container
+
+ // Add class methods
+, extend: {
+ // Unclip all clipped elements and remove itself
+ remove: function() {
+ /* unclip all targets */
+ for (var i = this.targets.length - 1; i >= 0; i--)
+ if (this.targets[i])
+ this.targets[i].unclip()
+ delete this.targets
+
+ /* remove clipPath from parent */
+ this.parent.removeElement(this)
+
+ return this
+ }
+ }
+
+ // Add parent method
+, construct: {
+ // Create clipping element
+ clip: function() {
+ return this.defs().put(new SVG.Clip)
+ }
}
})
@@ -44,13 +55,4 @@ SVG.extend(SVG.Element, {
return this.attr('clip-path', null)
}
-})
-
-//
-SVG.extend(SVG.Container, {
- // Create clipping element
- clip: function() {
- return this.defs().put(new SVG.Clip)
- }
-
}) \ No newline at end of file
diff --git a/src/container.js b/src/container.js
index 60f62c4..e63f2ae 100755
--- a/src/container.js
+++ b/src/container.js
@@ -1,24 +1,27 @@
-SVG.Container = function(element) {
- this.constructor.call(this, element)
-}
+SVG.Container = SVG.invent({
+ // Initialize node
+ create: function(element) {
+ this.constructor.call(this, element)
+ }
-// Inherit from SVG.Parent
-SVG.Container.prototype = new SVG.Parent
+ // Inherit from
+, inherit: SVG.Parent
-//
-SVG.extend(SVG.Container, {
- // Get the viewBox and calculate the zoom value
- viewbox: function(v) {
- if (arguments.length == 0)
- /* act as a getter if there are no arguments */
- return new SVG.ViewBox(this)
-
- /* otherwise act as a setter */
- v = arguments.length == 1 ?
- [v.x, v.y, v.width, v.height] :
- [].slice.call(arguments)
-
- return this.attr('viewBox', v)
+ // Add class methods
+, extend: {
+ // Get the viewBox and calculate the zoom value
+ viewbox: function(v) {
+ if (arguments.length == 0)
+ /* act as a getter if there are no arguments */
+ return new SVG.ViewBox(this)
+
+ /* otherwise act as a setter */
+ v = arguments.length == 1 ?
+ [v.x, v.y, v.width, v.height] :
+ [].slice.call(arguments)
+
+ return this.attr('viewBox', v)
+ }
}
}) \ No newline at end of file
diff --git a/src/defs.js b/src/defs.js
index 48a8f28..a50ad94 100755
--- a/src/defs.js
+++ b/src/defs.js
@@ -1,9 +1,8 @@
-// ### The defs node
-//
-SVG.Defs = function() {
- this.constructor.call(this, SVG.create('defs'))
-}
+SVG.Defs = SVG.invent({
+ // Initialize node
+ create: 'defs'
-// Inherits from SVG.Container
-SVG.Defs.prototype = new SVG.Container \ No newline at end of file
+ // Inherit from
+, inherit: SVG.Container
+}) \ No newline at end of file
diff --git a/src/doc.js b/src/doc.js
index 7e9eef3..5129dd9 100755
--- a/src/doc.js
+++ b/src/doc.js
@@ -1,112 +1,112 @@
-// ### This module accounts for the main svg document
-
-//
-SVG.Doc = function(element) {
- /* ensure the presence of a html element */
- this.parent = typeof element == 'string' ?
- document.getElementById(element) :
- element
-
- /* If the target is an svg element, use that element as the main wrapper.
- This allows svg.js to work with svg documents as well. */
- this.constructor
- .call(this, this.parent.nodeName == 'svg' ? this.parent : SVG.create('svg'))
-
- /* set svg element attributes */
- this
- .attr({ xmlns: SVG.ns, version: '1.1', width: '100%', height: '100%' })
- .attr('xmlns:xlink', SVG.xlink, SVG.xmlns)
-
- /* create the <defs> node */
- this._defs = new SVG.Defs
- this._defs.parent = this
- this.node.appendChild(this._defs.node)
+SVG.Doc = SVG.invent({
+ // Initialize node
+ create: function(element) {
+ /* ensure the presence of a html element */
+ this.parent = typeof element == 'string' ?
+ document.getElementById(element) :
+ element
+
+ /* If the target is an svg element, use that element as the main wrapper.
+ This allows svg.js to work with svg documents as well. */
+ this.constructor
+ .call(this, this.parent.nodeName == 'svg' ? this.parent : SVG.create('svg'))
+
+ /* set svg element attributes */
+ this
+ .attr({ xmlns: SVG.ns, version: '1.1', width: '100%', height: '100%' })
+ .attr('xmlns:xlink', SVG.xlink, SVG.xmlns)
+
+ /* create the <defs> node */
+ this._defs = new SVG.Defs
+ this._defs.parent = this
+ this.node.appendChild(this._defs.node)
- /* turno of sub pixel offset by default */
- this.doSubPixelOffsetFix = false
-
- /* ensure correct rendering */
- if (this.parent.nodeName != 'svg')
- this.stage()
-}
+ /* turno of sub pixel offset by default */
+ this.doSubPixelOffsetFix = false
+
+ /* ensure correct rendering */
+ if (this.parent.nodeName != 'svg')
+ this.stage()
+ }
-// Inherits from SVG.Container
-SVG.Doc.prototype = new SVG.Container
+ // Inherit from
+, inherit: SVG.Container
-//
-SVG.extend(SVG.Doc, {
- // Hack for safari preventing text to be rendered in one line.
- // Basically it sets the position of the svg node to absolute
- // when the dom is loaded, and resets it to relative a few milliseconds later.
- // It also handles sub-pixel offset rendering properly.
- stage: function() {
- var check
- , element = this
- , wrapper = document.createElement('div')
+ // Add class methods
+, extend: {
+ // Hack for safari preventing text to be rendered in one line.
+ // Basically it sets the position of the svg node to absolute
+ // when the dom is loaded, and resets it to relative a few milliseconds later.
+ // It also handles sub-pixel offset rendering properly.
+ stage: function() {
+ var check
+ , element = this
+ , wrapper = document.createElement('div')
- /* set temporary wrapper to position relative */
- wrapper.style.cssText = 'position:relative;height:100%;'
+ /* set temporary wrapper to position relative */
+ wrapper.style.cssText = 'position:relative;height:100%;'
- /* put element into wrapper */
- element.parent.appendChild(wrapper)
- wrapper.appendChild(element.node)
+ /* put element into wrapper */
+ element.parent.appendChild(wrapper)
+ wrapper.appendChild(element.node)
- /* check for dom:ready */
- check = function() {
- if (document.readyState === 'complete') {
- element.style('position:absolute;')
- setTimeout(function() {
- /* set position back to relative */
- element.style('position:relative;overflow:hidden;')
+ /* check for dom:ready */
+ check = function() {
+ if (document.readyState === 'complete') {
+ element.style('position:absolute;')
+ setTimeout(function() {
+ /* set position back to relative */
+ element.style('position:relative;overflow:hidden;')
- /* remove temporary wrapper */
- element.parent.removeChild(element.node.parentNode)
- element.node.parentNode.removeChild(element.node)
- element.parent.appendChild(element.node)
+ /* remove temporary wrapper */
+ element.parent.removeChild(element.node.parentNode)
+ element.node.parentNode.removeChild(element.node)
+ element.parent.appendChild(element.node)
- /* after wrapping is done, fix sub-pixel offset */
- element.subPixelOffsetFix()
-
- /* make sure sub-pixel offset is fixed every time the window is resized */
- SVG.on(window, 'resize', function() {
+ /* after wrapping is done, fix sub-pixel offset */
element.subPixelOffsetFix()
- })
-
- }, 5)
- } else {
- setTimeout(check, 10)
+
+ /* make sure sub-pixel offset is fixed every time the window is resized */
+ SVG.on(window, 'resize', function() {
+ element.subPixelOffsetFix()
+ })
+
+ }, 5)
+ } else {
+ setTimeout(check, 10)
+ }
}
- }
- check()
+ check()
- return this
- }
+ return this
+ }
- // Creates and returns defs element
-, defs: function() {
- return this._defs
- }
+ // Creates and returns defs element
+ , defs: function() {
+ return this._defs
+ }
- // Fix for possible sub-pixel offset. See:
- // https://bugzilla.mozilla.org/show_bug.cgi?id=608812
-, subPixelOffsetFix: function() {
- if (this.doSubPixelOffsetFix) {
- var pos = this.node.getScreenCTM()
+ // Fix for possible sub-pixel offset. See:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=608812
+ , subPixelOffsetFix: function() {
+ if (this.doSubPixelOffsetFix) {
+ var pos = this.node.getScreenCTM()
+
+ if (pos)
+ this
+ .style('left', (-pos.e % 1) + 'px')
+ .style('top', (-pos.f % 1) + 'px')
+ }
- if (pos)
- this
- .style('left', (-pos.e % 1) + 'px')
- .style('top', (-pos.f % 1) + 'px')
+ return this
}
-
- return this
- }
-, fixSubPixelOffset: function() {
- this.doSubPixelOffsetFix = true
+ , fixSubPixelOffset: function() {
+ this.doSubPixelOffsetFix = true
- return this
+ return this
+ }
}
-}) \ No newline at end of file
+})
diff --git a/src/element.js b/src/element.js
index b75ed32..01146ab 100755
--- a/src/element.js
+++ b/src/element.js
@@ -1,420 +1,420 @@
-// ### Used by nearly every other module
-
-//
-SVG.Element = function(node) {
- /* make stroke value accessible dynamically */
- this._stroke = SVG.defaults.attrs.stroke
-
- /* initialize style store */
- this.styles = {}
-
- /* initialize transformation store with defaults */
- this.trans = SVG.defaults.trans()
-
- /* keep reference to the element node */
- if (this.node = node) {
- this.type = node.nodeName
- this.node.instance = this
- }
-}
-
-//
-SVG.extend(SVG.Element, {
- // Move over x-axis
- x: function(x) {
- if (x) {
- x = new SVG.Number(x)
- x.value /= this.trans.scaleX
- }
- return this.attr('x', x)
- }
- // Move over y-axis
-, y: function(y) {
- if (y) {
- y = new SVG.Number(y)
- y.value /= this.trans.scaleY
- }
- return this.attr('y', y)
- }
- // Move by center over x-axis
-, cx: function(x) {
- return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2)
- }
- // Move by center over y-axis
-, cy: function(y) {
- return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2)
- }
- // Move element to given x and y values
-, move: function(x, y) {
- return this.x(x).y(y)
- }
- // Move element by its center
-, center: function(x, y) {
- return this.cx(x).cy(y)
- }
- // Set width of element
-, width: function(width) {
- return this.attr('width', width)
- }
- // Set height of element
-, height: function(height) {
- return this.attr('height', height)
- }
- // Set element size to given width and height
-, size: function(width, height) {
- var p = this._proportionalSize(width, height)
-
- return this.attr({
- width: new SVG.Number(p.width)
- , height: new SVG.Number(p.height)
- })
- }
- // Clone element
-, clone: function() {
- var clone , attr
- , type = this.type
+SVG.Element = SVG.invent({
+ // Initialize node
+ create: function(node) {
+ /* make stroke value accessible dynamically */
+ this._stroke = SVG.defaults.attrs.stroke
- /* invoke shape method with shape-specific arguments */
- clone = type == 'rect' || type == 'ellipse' ?
- this.parent[type](0,0) :
- type == 'line' ?
- this.parent[type](0,0,0,0) :
- type == 'image' ?
- this.parent[type](this.src) :
- type == 'text' ?
- this.parent[type](this.content) :
- type == 'path' ?
- this.parent[type](this.attr('d')) :
- type == 'polyline' || type == 'polygon' ?
- this.parent[type](this.attr('points')) :
- type == 'g' ?
- this.parent.group() :
- this.parent[type]()
+ /* initialize style store */
+ this.styles = {}
- /* apply attributes attributes */
- attr = this.attr()
- delete attr.id
- clone.attr(attr)
+ /* initialize transformation store with defaults */
+ this.trans = SVG.defaults.trans()
- /* copy transformations */
- clone.trans = this.trans
-
- /* apply attributes and translations */
- return clone.transform({})
- }
- // Remove element
-, remove: function() {
- if (this.parent)
- this.parent.removeElement(this)
-
- return this
+ /* keep reference to the element node */
+ if (this.node = node) {
+ this.type = node.nodeName
+ this.node.instance = this
+ }
}
- // Replace element
-, replace: function(element) {
- this.after(element).remove()
- return element
- }
- // Add element to given container and return self
-, addTo: function(parent) {
- return parent.put(this)
- }
- // Add element to given container and return container
-, putIn: function(parent) {
- return parent.add(this)
- }
- // Get parent document
-, doc: function(type) {
- return this._parent(type || SVG.Doc)
- }
- // Set svg element attribute
-, attr: function(a, v, n) {
- if (a == null) {
- /* get an object of attributes */
- a = {}
- v = this.node.attributes
- for (n = v.length - 1; n >= 0; n--)
- a[v[n].nodeName] = SVG.regex.test(v[n].nodeValue, 'isNumber') ? parseFloat(v[n].nodeValue) : v[n].nodeValue
+ // Add class methods
+, extend: {
+ // Move over x-axis
+ x: function(x) {
+ if (x) {
+ x = new SVG.Number(x)
+ x.value /= this.trans.scaleX
+ }
+ return this.attr('x', x)
+ }
+ // Move over y-axis
+ , y: function(y) {
+ if (y) {
+ y = new SVG.Number(y)
+ y.value /= this.trans.scaleY
+ }
+ return this.attr('y', y)
+ }
+ // Move by center over x-axis
+ , cx: function(x) {
+ return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2)
+ }
+ // Move by center over y-axis
+ , cy: function(y) {
+ return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2)
+ }
+ // Move element to given x and y values
+ , move: function(x, y) {
+ return this.x(x).y(y)
+ }
+ // Move element by its center
+ , center: function(x, y) {
+ return this.cx(x).cy(y)
+ }
+ // Set width of element
+ , width: function(width) {
+ return this.attr('width', width)
+ }
+ // Set height of element
+ , height: function(height) {
+ return this.attr('height', height)
+ }
+ // Set element size to given width and height
+ , size: function(width, height) {
+ var p = this._proportionalSize(width, height)
+
+ return this.attr({
+ width: new SVG.Number(p.width)
+ , height: new SVG.Number(p.height)
+ })
+ }
+ // Clone element
+ , clone: function() {
+ var clone , attr
+ , type = this.type
- return a
+ /* invoke shape method with shape-specific arguments */
+ clone = type == 'rect' || type == 'ellipse' ?
+ this.parent[type](0,0) :
+ type == 'line' ?
+ this.parent[type](0,0,0,0) :
+ type == 'image' ?
+ this.parent[type](this.src) :
+ type == 'text' ?
+ this.parent[type](this.content) :
+ type == 'path' ?
+ this.parent[type](this.attr('d')) :
+ type == 'polyline' || type == 'polygon' ?
+ this.parent[type](this.attr('points')) :
+ type == 'g' ?
+ this.parent.group() :
+ this.parent[type]()
- } else if (typeof a == 'object') {
- /* apply every attribute individually if an object is passed */
- for (v in a) this.attr(v, a[v])
+ /* apply attributes attributes */
+ attr = this.attr()
+ delete attr.id
+ clone.attr(attr)
- } else if (v === null) {
- /* remove value */
- this.node.removeAttribute(a)
+ /* copy transformations */
+ clone.trans = this.trans
- } else if (v == null) {
- /* act as a getter for style attributes */
- if (this._isStyle(a)) {
- return a == 'text' ?
- this.content :
- a == 'leading' && this.leading ?
- this.leading() :
- this.style(a)
+ /* apply attributes and translations */
+ return clone.transform({})
+ }
+ // Remove element
+ , remove: function() {
+ if (this.parent)
+ this.parent.removeElement(this)
- /* act as a getter if the first and only argument is not an object */
- } else {
- v = this.node.getAttribute(a)
- return v == null ?
- SVG.defaults.attrs[a] :
- SVG.regex.test(v, 'isNumber') ?
- parseFloat(v) : v
- }
-
- } else if (a == 'style') {
- /* redirect to the style method */
- return this.style(v)
-
- } else {
- /* treat x differently on text elements */
- if (a == 'x' && Array.isArray(this.lines))
- for (n = this.lines.length - 1; n >= 0; n--)
- this.lines[n].attr(a, v)
+ return this
+ }
+ // Replace element
+ , replace: function(element) {
+ this.after(element).remove()
+
+ return element
+ }
+ // Add element to given container and return self
+ , addTo: function(parent) {
+ return parent.put(this)
+ }
+ // Add element to given container and return container
+ , putIn: function(parent) {
+ return parent.add(this)
+ }
+ // Get parent document
+ , doc: function(type) {
+ return this._parent(type || SVG.Doc)
+ }
+ // Set svg element attribute
+ , attr: function(a, v, n) {
+ if (a == null) {
+ /* get an object of attributes */
+ a = {}
+ v = this.node.attributes
+ for (n = v.length - 1; n >= 0; n--)
+ a[v[n].nodeName] = SVG.regex.test(v[n].nodeValue, 'isNumber') ? parseFloat(v[n].nodeValue) : v[n].nodeValue
+
+ return a
+
+ } else if (typeof a == 'object') {
+ /* apply every attribute individually if an object is passed */
+ for (v in a) this.attr(v, a[v])
+
+ } else if (v === null) {
+ /* remove value */
+ this.node.removeAttribute(a)
+
+ } else if (v == null) {
+ /* act as a getter for style attributes */
+ if (this._isStyle(a)) {
+ return a == 'text' ?
+ this.content :
+ a == 'leading' && this.leading ?
+ this.leading() :
+ this.style(a)
+
+ /* act as a getter if the first and only argument is not an object */
+ } else {
+ v = this.node.getAttribute(a)
+ return v == null ?
+ SVG.defaults.attrs[a] :
+ SVG.regex.test(v, 'isNumber') ?
+ parseFloat(v) : v
+ }
- /* BUG FIX: some browsers will render a stroke if a color is given even though stroke width is 0 */
- if (a == 'stroke-width')
- this.attr('stroke', parseFloat(v) > 0 ? this._stroke : null)
- else if (a == 'stroke')
- this._stroke = v
+ } else if (a == 'style') {
+ /* redirect to the style method */
+ return this.style(v)
- /* ensure full hex color */
- if (SVG.Color.test(v) || SVG.Color.isRgb(v))
- v = new SVG.Color(v)
+ } else {
+ /* treat x differently on text elements */
+ if (a == 'x' && Array.isArray(this.lines))
+ for (n = this.lines.length - 1; n >= 0; n--)
+ this.lines[n].attr(a, v)
+
+ /* BUG FIX: some browsers will render a stroke if a color is given even though stroke width is 0 */
+ if (a == 'stroke-width')
+ this.attr('stroke', parseFloat(v) > 0 ? this._stroke : null)
+ else if (a == 'stroke')
+ this._stroke = v
+
+ /* ensure full hex color */
+ if (SVG.Color.test(v) || SVG.Color.isRgb(v))
+ v = new SVG.Color(v)
- /* ensure correct numeric values */
- else if (typeof v === 'number')
- v = new SVG.Number(v)
+ /* ensure correct numeric values */
+ else if (typeof v === 'number')
+ v = new SVG.Number(v)
- /* parse array values */
- else if (Array.isArray(v))
- v = new SVG.Array(v)
+ /* parse array values */
+ else if (Array.isArray(v))
+ v = new SVG.Array(v)
- /* set give attribute on node */
- n != null ?
- this.node.setAttributeNS(n, a, v.toString()) :
- this.node.setAttribute(a, v.toString())
-
- /* if the passed argument belongs in the style as well, add it there */
- if (this._isStyle(a)) {
- a == 'text' ?
- this.text(v) :
- a == 'leading' && this.leading ?
- this.leading(v) :
- this.style(a, v)
+ /* set give attribute on node */
+ n != null ?
+ this.node.setAttributeNS(n, a, v.toString()) :
+ this.node.setAttribute(a, v.toString())
- /* rebuild if required */
- if (this.rebuild)
- this.rebuild(a, v)
+ /* if the passed argument belongs in the style as well, add it there */
+ if (this._isStyle(a)) {
+ a == 'text' ?
+ this.text(v) :
+ a == 'leading' && this.leading ?
+ this.leading(v) :
+ this.style(a, v)
+
+ /* rebuild if required */
+ if (this.rebuild)
+ this.rebuild(a, v)
+ }
}
+
+ return this
}
-
- return this
- }
- // Manage transformations
-, transform: function(o, v) {
-
- if (arguments.length == 0) {
- /* act as a getter if no argument is given */
- return this.trans
+ // Manage transformations
+ , transform: function(o, v) {
+
+ if (arguments.length == 0) {
+ /* act as a getter if no argument is given */
+ return this.trans
+
+ } else if (typeof o === 'string') {
+ /* act as a getter if only one string argument is given */
+ if (arguments.length < 2)
+ return this.trans[o]
+
+ /* apply transformations as object if key value arguments are given*/
+ var transform = {}
+ transform[o] = v
+
+ return this.transform(transform)
+ }
+
+ /* ... otherwise continue as a setter */
+ var transform = []
- } else if (typeof o === 'string') {
- /* act as a getter if only one string argument is given */
- if (arguments.length < 2)
- return this.trans[o]
+ /* parse matrix */
+ o = this._parseMatrix(o)
- /* apply transformations as object if key value arguments are given*/
- var transform = {}
- transform[o] = v
+ /* merge values */
+ for (v in o)
+ if (o[v] != null)
+ this.trans[v] = o[v]
- return this.transform(transform)
+ /* compile matrix */
+ this.trans.matrix = this.trans.a
+ + ' ' + this.trans.b
+ + ' ' + this.trans.c
+ + ' ' + this.trans.d
+ + ' ' + this.trans.e
+ + ' ' + this.trans.f
+
+ /* alias current transformations */
+ o = this.trans
+
+ /* add matrix */
+ if (o.matrix != SVG.defaults.matrix)
+ transform.push('matrix(' + o.matrix + ')')
+
+ /* add rotation */
+ if (o.rotation != 0)
+ transform.push('rotate(' + o.rotation + ' ' + (o.cx == null ? this.bbox().cx : o.cx) + ' ' + (o.cy == null ? this.bbox().cy : o.cy) + ')')
+
+ /* add scale */
+ if (o.scaleX != 1 || o.scaleY != 1)
+ transform.push('scale(' + o.scaleX + ' ' + o.scaleY + ')')
+
+ /* add skew on x axis */
+ if (o.skewX != 0)
+ transform.push('skewX(' + o.skewX + ')')
+
+ /* add skew on y axis */
+ if (o.skewY != 0)
+ transform.push('skewY(' + o.skewY + ')')
+
+ /* add translation */
+ if (o.x != 0 || o.y != 0)
+ transform.push('translate(' + new SVG.Number(o.x / o.scaleX) + ' ' + new SVG.Number(o.y / o.scaleY) + ')')
+
+ /* update transformations, even if there are none */
+ if (transform.length == 0)
+ this.node.removeAttribute('transform')
+ else
+ this.node.setAttribute('transform', transform.join(' '))
+
+ return this
}
-
- /* ... otherwise continue as a setter */
- var transform = []
-
- /* parse matrix */
- o = this._parseMatrix(o)
-
- /* merge values */
- for (v in o)
- if (o[v] != null)
- this.trans[v] = o[v]
-
- /* compile matrix */
- this.trans.matrix = this.trans.a
- + ' ' + this.trans.b
- + ' ' + this.trans.c
- + ' ' + this.trans.d
- + ' ' + this.trans.e
- + ' ' + this.trans.f
-
- /* alias current transformations */
- o = this.trans
-
- /* add matrix */
- if (o.matrix != SVG.defaults.matrix)
- transform.push('matrix(' + o.matrix + ')')
-
- /* add rotation */
- if (o.rotation != 0)
- transform.push('rotate(' + o.rotation + ' ' + (o.cx == null ? this.bbox().cx : o.cx) + ' ' + (o.cy == null ? this.bbox().cy : o.cy) + ')')
-
- /* add scale */
- if (o.scaleX != 1 || o.scaleY != 1)
- transform.push('scale(' + o.scaleX + ' ' + o.scaleY + ')')
-
- /* add skew on x axis */
- if (o.skewX != 0)
- transform.push('skewX(' + o.skewX + ')')
-
- /* add skew on y axis */
- if (o.skewY != 0)
- transform.push('skewY(' + o.skewY + ')')
-
- /* add translation */
- if (o.x != 0 || o.y != 0)
- transform.push('translate(' + new SVG.Number(o.x / o.scaleX) + ' ' + new SVG.Number(o.y / o.scaleY) + ')')
-
- /* update transformations, even if there are none */
- if (transform.length == 0)
- this.node.removeAttribute('transform')
- else
- this.node.setAttribute('transform', transform.join(' '))
-
- return this
- }
- // Dynamic style generator
-, style: function(s, v) {
- if (arguments.length == 0) {
- /* get full style */
- return this.attr('style') || ''
-
- } else if (arguments.length < 2) {
- /* apply every style individually if an object is passed */
- if (typeof s == 'object') {
- for (v in s) this.style(v, s[v])
+ // Dynamic style generator
+ , style: function(s, v) {
+ if (arguments.length == 0) {
+ /* get full style */
+ return this.attr('style') || ''
- } else if (SVG.regex.isCss.test(s)) {
- /* parse css string */
- s = s.split(';')
+ } else if (arguments.length < 2) {
+ /* apply every style individually if an object is passed */
+ if (typeof s == 'object') {
+ for (v in s) this.style(v, s[v])
+
+ } else if (SVG.regex.isCss.test(s)) {
+ /* parse css string */
+ s = s.split(';')
- /* apply every definition individually */
- for (var i = 0; i < s.length; i++) {
- v = s[i].split(':')
+ /* apply every definition individually */
+ for (var i = 0; i < s.length; i++) {
+ v = s[i].split(':')
- if (v.length == 2)
- this.style(v[0].replace(/\s+/g, ''), v[1].replace(/^\s+/,'').replace(/\s+$/,''))
+ if (v.length == 2)
+ this.style(v[0].replace(/\s+/g, ''), v[1].replace(/^\s+/,'').replace(/\s+$/,''))
+ }
+ } else {
+ /* act as a getter if the first and only argument is not an object */
+ return this.styles[s]
}
+
+ } else if (v === null || SVG.regex.test(v, 'isBlank')) {
+ /* remove value */
+ delete this.styles[s]
+
} else {
- /* act as a getter if the first and only argument is not an object */
- return this.styles[s]
+ /* store value */
+ this.styles[s] = v
}
-
- } else if (v === null || SVG.regex.test(v, 'isBlank')) {
- /* remove value */
- delete this.styles[s]
- } else {
- /* store value */
- this.styles[s] = v
- }
-
- /* rebuild style string */
- s = ''
- for (v in this.styles)
- s += v + ':' + this.styles[v] + ';'
-
- /* apply style */
- if (s == '')
- this.node.removeAttribute('style')
- else
- this.node.setAttribute('style', s)
-
- return this
- }
- // Get bounding box
-, bbox: function() {
- return new SVG.BBox(this)
- }
- // Get rect box
-, rbox: function() {
- return new SVG.RBox(this)
- }
- // Checks whether the given point inside the bounding box of the element
-, inside: function(x, y) {
- var box = this.bbox()
-
- return x > box.x
- && y > box.y
- && x < box.x + box.width
- && y < box.y + box.height
- }
- // Show element
-, show: function() {
- return this.style('display', '')
- }
- // Hide element
-, hide: function() {
- return this.style('display', 'none')
- }
- // Is element visible?
-, visible: function() {
- return this.style('display') != 'none'
- }
- // Return id on string conversion
-, toString: function() {
- return this.attr('id')
- }
- // Private: find svg parent by instance
-, _parent: function(parent) {
- var element = this
-
- while (element != null && !(element instanceof parent))
- element = element.parent
-
- return element
- }
- // Private: tester method for style detection
-, _isStyle: function(a) {
- return typeof a == 'string' ? SVG.regex.test(a, 'isStyle') : false
- }
- // Private: parse a matrix string
-, _parseMatrix: function(o) {
- if (o.matrix) {
- /* split matrix string */
- var m = o.matrix.replace(/\s/g, '').split(',')
+ /* rebuild style string */
+ s = ''
+ for (v in this.styles)
+ s += v + ':' + this.styles[v] + ';'
- /* pasrse values */
- if (m.length == 6) {
- o.a = parseFloat(m[0])
- o.b = parseFloat(m[1])
- o.c = parseFloat(m[2])
- o.d = parseFloat(m[3])
- o.e = parseFloat(m[4])
- o.f = parseFloat(m[5])
- }
+ /* apply style */
+ if (s == '')
+ this.node.removeAttribute('style')
+ else
+ this.node.setAttribute('style', s)
+
+ return this
}
-
- return o
- }
- // Private: calculate proportional width and height values when necessary
-, _proportionalSize: function(width, height) {
- if (width == null || height == null) {
+ // Get bounding box
+ , bbox: function() {
+ return new SVG.BBox(this)
+ }
+ // Get rect box
+ , rbox: function() {
+ return new SVG.RBox(this)
+ }
+ // Checks whether the given point inside the bounding box of the element
+ , inside: function(x, y) {
var box = this.bbox()
+
+ return x > box.x
+ && y > box.y
+ && x < box.x + box.width
+ && y < box.y + box.height
+ }
+ // Show element
+ , show: function() {
+ return this.style('display', '')
+ }
+ // Hide element
+ , hide: function() {
+ return this.style('display', 'none')
+ }
+ // Is element visible?
+ , visible: function() {
+ return this.style('display') != 'none'
+ }
+ // Return id on string conversion
+ , toString: function() {
+ return this.attr('id')
+ }
+ // Private: find svg parent by instance
+ , _parent: function(parent) {
+ var element = this
+
+ while (element != null && !(element instanceof parent))
+ element = element.parent
- if (height == null)
- height = box.height / box.width * width
- else if (width == null)
- width = box.width / box.height * height
+ return element
}
-
- return {
- width: width
- , height: height
+ // Private: tester method for style detection
+ , _isStyle: function(a) {
+ return typeof a == 'string' ? SVG.regex.test(a, 'isStyle') : false
+ }
+ // Private: parse a matrix string
+ , _parseMatrix: function(o) {
+ if (o.matrix) {
+ /* split matrix string */
+ var m = o.matrix.replace(/\s/g, '').split(',')
+
+ /* pasrse values */
+ if (m.length == 6) {
+ o.a = parseFloat(m[0])
+ o.b = parseFloat(m[1])
+ o.c = parseFloat(m[2])
+ o.d = parseFloat(m[3])
+ o.e = parseFloat(m[4])
+ o.f = parseFloat(m[5])
+ }
+ }
+
+ return o
+ }
+ // Private: calculate proportional width and height values when necessary
+ , _proportionalSize: function(width, height) {
+ if (width == null || height == null) {
+ var box = this.bbox()
+
+ if (height == null)
+ height = box.height / box.width * width
+ else if (width == null)
+ width = box.width / box.height * height
+ }
+
+ return {
+ width: width
+ , height: height
+ }
}
}
diff --git a/src/ellipse.js b/src/ellipse.js
index 237a5ca..d84f988 100755
--- a/src/ellipse.js
+++ b/src/ellipse.js
@@ -1,62 +1,59 @@
-//
-SVG.Ellipse = function() {
- this.constructor.call(this, SVG.create('ellipse'))
-}
+SVG.Ellipse = SVG.invent({
+ // Initialize node
+ create: 'ellipse'
-// Inherit from SVG.Shape
-SVG.Ellipse.prototype = new SVG.Shape
+ // Inherit from
+, inherit: SVG.Shape
-//
-SVG.extend(SVG.Ellipse, {
- // Move over x-axis
- x: function(x) {
- return x == null ? this.cx() - this.attr('rx') : this.cx(x + this.attr('rx'))
- }
- // Move over y-axis
-, y: function(y) {
- return y == null ? this.cy() - this.attr('ry') : this.cy(y + this.attr('ry'))
- }
- // Move by center over x-axis
-, cx: function(x) {
- return x == null ? this.attr('cx') : this.attr('cx', new SVG.Number(x).divide(this.trans.scaleX))
- }
- // Move by center over y-axis
-, cy: function(y) {
- return y == null ? this.attr('cy') : this.attr('cy', new SVG.Number(y).divide(this.trans.scaleY))
- }
- // Set width of element
-, width: function(width) {
- return width == null ? this.attr('rx') * 2 : this.attr('rx', new SVG.Number(width).divide(2))
- }
- // Set height of element
-, height: function(height) {
- return height == null ? this.attr('ry') * 2 : this.attr('ry', new SVG.Number(height).divide(2))
- }
- // Custom size function
-, size: function(width, height) {
- var p = this._proportionalSize(width, height)
+ // Add class methods
+, extend: {
+ // Move over x-axis
+ x: function(x) {
+ return x == null ? this.cx() - this.attr('rx') : this.cx(x + this.attr('rx'))
+ }
+ // Move over y-axis
+ , y: function(y) {
+ return y == null ? this.cy() - this.attr('ry') : this.cy(y + this.attr('ry'))
+ }
+ // Move by center over x-axis
+ , cx: function(x) {
+ return x == null ? this.attr('cx') : this.attr('cx', new SVG.Number(x).divide(this.trans.scaleX))
+ }
+ // Move by center over y-axis
+ , cy: function(y) {
+ return y == null ? this.attr('cy') : this.attr('cy', new SVG.Number(y).divide(this.trans.scaleY))
+ }
+ // Set width of element
+ , width: function(width) {
+ return width == null ? this.attr('rx') * 2 : this.attr('rx', new SVG.Number(width).divide(2))
+ }
+ // Set height of element
+ , height: function(height) {
+ return height == null ? this.attr('ry') * 2 : this.attr('ry', new SVG.Number(height).divide(2))
+ }
+ // Custom size function
+ , size: function(width, height) {
+ var p = this._proportionalSize(width, height)
- return this.attr({
- rx: new SVG.Number(p.width).divide(2)
- , ry: new SVG.Number(p.height).divide(2)
- })
+ return this.attr({
+ rx: new SVG.Number(p.width).divide(2)
+ , ry: new SVG.Number(p.height).divide(2)
+ })
+ }
+
}
-
-})
-//
-SVG.extend(SVG.Container, {
- // Create circle element, based on ellipse
- circle: function(size) {
- return this.ellipse(size, size)
+ // Add parent method
+, construct: {
+ // Create circle element, based on ellipse
+ circle: function(size) {
+ return this.ellipse(size, size)
+ }
+ // Create an ellipse
+ , ellipse: function(width, height) {
+ return this.put(new SVG.Ellipse).size(width, height).move(0, 0)
+ }
+
}
- // Create an ellipse
-, ellipse: function(width, height) {
- return this.put(new SVG.Ellipse).size(width, height).move(0, 0)
- }
-
-})
-
-// Usage:
-// draw.ellipse(200, 100) \ No newline at end of file
+}) \ No newline at end of file
diff --git a/src/gradient.js b/src/gradient.js
index c5c51d1..e95e18b 100755
--- a/src/gradient.js
+++ b/src/gradient.js
@@ -1,59 +1,68 @@
-SVG.Gradient = function(type) {
- this.constructor.call(this, SVG.create(type + 'Gradient'))
-
- /* store type */
- this.type = type
-}
-
-// Inherit from SVG.Container
-SVG.Gradient.prototype = new SVG.Container
-
-//
-SVG.extend(SVG.Gradient, {
- // From position
- from: function(x, y) {
- return this.type == 'radial' ?
- this.attr({ fx: new SVG.Number(x), fy: new SVG.Number(y) }) :
- this.attr({ x1: new SVG.Number(x), y1: new SVG.Number(y) })
- }
- // To position
-, to: function(x, y) {
- return this.type == 'radial' ?
- this.attr({ cx: new SVG.Number(x), cy: new SVG.Number(y) }) :
- this.attr({ x2: new SVG.Number(x), y2: new SVG.Number(y) })
- }
- // Radius for radial gradient
-, radius: function(r) {
- return this.type == 'radial' ?
- this.attr({ r: new SVG.Number(r) }) :
- this
- }
- // Add a color stop
-, at: function(stop) {
- return this.put(new SVG.Stop(stop))
- }
- // Update gradient
-, update: function(block) {
- /* remove all stops */
- this.clear()
-
- /* invoke passed block */
- block(this)
+SVG.Gradient = SVG.invent({
+ // Initialize node
+ create: function(type) {
+ this.constructor.call(this, SVG.create(type + 'Gradient'))
- return this
+ /* store type */
+ this.type = type
}
- // Return the fill id
-, fill: function() {
- return 'url(#' + this.attr('id') + ')'
- }
- // Alias string convertion to fill
-, toString: function() {
- return this.fill()
+
+ // Inherit from
+, inherit: SVG.Container
+
+ // Add class methods
+, extend: {
+ // From position
+ from: function(x, y) {
+ return this.type == 'radial' ?
+ this.attr({ fx: new SVG.Number(x), fy: new SVG.Number(y) }) :
+ this.attr({ x1: new SVG.Number(x), y1: new SVG.Number(y) })
+ }
+ // To position
+ , to: function(x, y) {
+ return this.type == 'radial' ?
+ this.attr({ cx: new SVG.Number(x), cy: new SVG.Number(y) }) :
+ this.attr({ x2: new SVG.Number(x), y2: new SVG.Number(y) })
+ }
+ // Radius for radial gradient
+ , radius: function(r) {
+ return this.type == 'radial' ?
+ this.attr({ r: new SVG.Number(r) }) :
+ this
+ }
+ // Add a color stop
+ , at: function(stop) {
+ return this.put(new SVG.Stop().update(stop))
+ }
+ // Update gradient
+ , update: function(block) {
+ /* remove all stops */
+ this.clear()
+
+ /* invoke passed block */
+ block(this)
+
+ return this
+ }
+ // Return the fill id
+ , fill: function() {
+ return 'url(#' + this.attr('id') + ')'
+ }
+ // Alias string convertion to fill
+ , toString: function() {
+ return this.fill()
+ }
}
+ // Add parent method
+, construct: {
+ // Create gradient element in defs
+ gradient: function(type, block) {
+ return this.defs().gradient(type, block)
+ }
+ }
})
-//
SVG.extend(SVG.Defs, {
// define gradient
gradient: function(type, block) {
@@ -67,37 +76,24 @@ SVG.extend(SVG.Defs, {
})
-//
-SVG.extend(SVG.Container, {
- // Create gradient element in defs
- gradient: function(type, block) {
- return this.defs().gradient(type, block)
- }
-
-})
+SVG.Stop = SVG.invent({
+ // Initialize node
+ create: 'stop'
+ // Inherit from
+, inherit: SVG.Element
-SVG.Stop = function(stop) {
- this.constructor.call(this, SVG.create('stop'))
-
- /* immediatelly build stop */
- this.update(stop)
-}
+ // Add class methods
+, extend: {
+ // add color stops
+ update: function(o) {
+ /* set attributes */
+ if (o.opacity != null) this.attr('stop-opacity', o.opacity)
+ if (o.color != null) this.attr('stop-color', o.color)
+ if (o.offset != null) this.attr('offset', new SVG.Number(o.offset))
-// Inherit from SVG.Element
-SVG.Stop.prototype = new SVG.Element
-
-//
-SVG.extend(SVG.Stop, {
- // add color stops
- update: function(o) {
- /* set attributes */
- if (o.opacity != null) this.attr('stop-opacity', o.opacity)
- if (o.color != null) this.attr('stop-color', o.color)
- if (o.offset != null) this.attr('offset', new SVG.Number(o.offset))
-
- return this
+ return this
+ }
}
-
-})
+})
diff --git a/src/group.js b/src/group.js
index 6f2d502..cfb99ac 100755
--- a/src/group.js
+++ b/src/group.js
@@ -1,36 +1,35 @@
-SVG.G = function() {
- this.constructor.call(this, SVG.create('g'))
-}
+SVG.G = SVG.invent({
+ // Initialize node
+ create: 'g'
-// Inherit from SVG.Container
-SVG.G.prototype = new SVG.Container
-
-//
-SVG.extend(SVG.G, {
- // Move over x-axis
- x: function(x) {
- return x == null ? this.trans.x : this.transform('x', x)
- }
- // Move over y-axis
-, y: function(y) {
- return y == null ? this.trans.y : this.transform('y', y)
- }
- // Move by center over x-axis
-, cx: function(x) {
- return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2)
- }
- // Move by center over y-axis
-, cy: function(y) {
- return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2)
- }
+ // Inherit from
+, inherit: SVG.Container
-})
-
-//
-SVG.extend(SVG.Container, {
- // Create a group element
- group: function() {
- return this.put(new SVG.G)
+ // Add class methods
+, extend: {
+ // Move over x-axis
+ x: function(x) {
+ return x == null ? this.trans.x : this.transform('x', x)
+ }
+ // Move over y-axis
+ , y: function(y) {
+ return y == null ? this.trans.y : this.transform('y', y)
+ }
+ // Move by center over x-axis
+ , cx: function(x) {
+ return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2)
+ }
+ // Move by center over y-axis
+ , cy: function(y) {
+ return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2)
+ }
}
+ // Add parent method
+, construct: {
+ // Create a group element
+ group: function() {
+ return this.put(new SVG.G)
+ }
+ }
}) \ No newline at end of file
diff --git a/src/hyperlink.js b/src/hyperlink.js
index 7b9d986..1981d52 100644
--- a/src/hyperlink.js
+++ b/src/hyperlink.js
@@ -1,37 +1,35 @@
-SVG.A = function() {
- this.constructor.call(this, SVG.create('a'))
-}
+SVG.A = SVG.invent({
+ // Initialize node
+ create: 'a'
-// Inherit from SVG.Parent
-SVG.A.prototype = new SVG.Container
+ // Inherit from
+, inherit: SVG.Container
-//
-SVG.extend(SVG.A, {
- // Link url
- to: function(url) {
- return this.attr('href', url, SVG.xlink)
- }
- // Link show attribute
-, show: function(target) {
- return this.attr('show', target, SVG.xlink)
- }
- // Link target attribute
-, target: function(target) {
- return this.attr('target', target)
- }
-
-})
-
-//
-SVG.extend(SVG.Container, {
- // Create a hyperlink element
- link: function(url) {
- return this.put(new SVG.A).to(url)
+ // Add class methods
+, extend: {
+ // Link url
+ to: function(url) {
+ return this.attr('href', url, SVG.xlink)
+ }
+ // Link show attribute
+ , show: function(target) {
+ return this.attr('show', target, SVG.xlink)
+ }
+ // Link target attribute
+ , target: function(target) {
+ return this.attr('target', target)
+ }
}
+ // Add parent method
+, construct: {
+ // Create a hyperlink element
+ link: function(url) {
+ return this.put(new SVG.A).to(url)
+ }
+ }
})
-//
SVG.extend(SVG.Element, {
// Create a hyperlink element
linkTo: function(url) {
diff --git a/src/image.js b/src/image.js
index d0a1b40..24333c7 100755
--- a/src/image.js
+++ b/src/image.js
@@ -1,24 +1,24 @@
-SVG.Image = function() {
- this.constructor.call(this, SVG.create('image'))
-}
+SVG.Image = SVG.invent({
+ // Initialize node
+ create: 'image'
-// Inherit from SVG.Element
-SVG.Image.prototype = new SVG.Shape
+ // Inherit from
+, inherit: SVG.Shape
-//
-SVG.extend(SVG.Image, {
- // (re)load image
- load: function(url) {
- return (url ? this.attr('href', (this.src = url), SVG.xlink) : this)
+ // Add class methods
+, extend: {
+ // (re)load image
+ load: function(url) {
+ return (url ? this.attr('href', (this.src = url), SVG.xlink) : this)
+ }
}
-})
-
-//
-SVG.extend(SVG.Container, {
- // 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))
+
+ // Add parent method
+, construct: {
+ // 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))
+ }
}
-
}) \ No newline at end of file
diff --git a/src/inventor.js b/src/inventor.js
new file mode 100644
index 0000000..f8244f5
--- /dev/null
+++ b/src/inventor.js
@@ -0,0 +1,23 @@
+// Invent new element
+SVG.invent = function(config) {
+ /* create element initializer */
+ var initializer = typeof config.create == 'function' ?
+ config.create :
+ function() {
+ this.constructor.call(this, SVG.create(config.create))
+ }
+
+ /* inherit prototype */
+ if (config.inherit)
+ initializer.prototype = new config.inherit
+
+ /* extend with methods */
+ if (config.extend)
+ SVG.extend(initializer, config.extend)
+
+ /* attach construct method to parent */
+ if (config.construct)
+ SVG.extend(config.parent || SVG.Container, config.construct)
+
+ return initializer
+} \ No newline at end of file
diff --git a/src/line.js b/src/line.js
index e049ccb..bdbbcde 100755
--- a/src/line.js
+++ b/src/line.js
@@ -1,75 +1,74 @@
-SVG.Line = function() {
- this.constructor.call(this, SVG.create('line'))
-}
+SVG.Line = SVG.invent({
+ // Initialize node
+ create: 'line'
-// Inherit from SVG.Shape
-SVG.Line.prototype = new SVG.Shape
+ // Inherit from
+, inherit: SVG.Shape
-// Add required methods
-SVG.extend(SVG.Line, {
- // Move over x-axis
- x: function(x) {
- var b = this.bbox()
-
- return x == null ? b.x : this.attr({
- x1: this.attr('x1') - b.x + x
- , x2: this.attr('x2') - b.x + x
- })
- }
- // Move over y-axis
-, y: function(y) {
- var b = this.bbox()
-
- return y == null ? b.y : this.attr({
- y1: this.attr('y1') - b.y + y
- , y2: this.attr('y2') - b.y + y
- })
- }
- // Move by center over x-axis
-, cx: function(x) {
- var half = this.bbox().width / 2
- return x == null ? this.x() + half : this.x(x - half)
- }
- // Move by center over y-axis
-, cy: function(y) {
- var half = this.bbox().height / 2
- return y == null ? this.y() + half : this.y(y - half)
- }
- // Set width of element
-, width: function(width) {
- var b = this.bbox()
+ // Add class methods
+, extend: {
+ // Move over x-axis
+ x: function(x) {
+ var b = this.bbox()
+
+ return x == null ? b.x : this.attr({
+ x1: this.attr('x1') - b.x + x
+ , x2: this.attr('x2') - b.x + x
+ })
+ }
+ // Move over y-axis
+ , y: function(y) {
+ var b = this.bbox()
+
+ return y == null ? b.y : this.attr({
+ y1: this.attr('y1') - b.y + y
+ , y2: this.attr('y2') - b.y + y
+ })
+ }
+ // Move by center over x-axis
+ , cx: function(x) {
+ var half = this.bbox().width / 2
+ return x == null ? this.x() + half : this.x(x - half)
+ }
+ // Move by center over y-axis
+ , cy: function(y) {
+ var half = this.bbox().height / 2
+ return y == null ? this.y() + half : this.y(y - half)
+ }
+ // Set width of element
+ , width: function(width) {
+ var b = this.bbox()
- return width == null ? b.width : this.attr(this.attr('x1') < this.attr('x2') ? 'x2' : 'x1', b.x + width)
- }
- // Set height of element
-, height: function(height) {
- var b = this.bbox()
+ return width == null ? b.width : this.attr(this.attr('x1') < this.attr('x2') ? 'x2' : 'x1', b.x + width)
+ }
+ // Set height of element
+ , height: function(height) {
+ var b = this.bbox()
- return height == null ? b.height : this.attr(this.attr('y1') < this.attr('y2') ? 'y2' : 'y1', b.y + height)
- }
- // Set line size by width and height
-, size: function(width, height) {
- var p = this._proportionalSize(width, height)
+ return height == null ? b.height : this.attr(this.attr('y1') < this.attr('y2') ? 'y2' : 'y1', b.y + height)
+ }
+ // Set line size by width and height
+ , size: function(width, height) {
+ var p = this._proportionalSize(width, height)
- return this.width(p.width).height(p.height)
- }
- // Set path data
-, plot: function(x1, y1, x2, y2) {
- return this.attr({
- x1: x1
- , y1: y1
- , x2: x2
- , y2: y2
- })
+ return this.width(p.width).height(p.height)
+ }
+ // Set path data
+ , plot: function(x1, y1, x2, y2) {
+ return this.attr({
+ x1: x1
+ , y1: y1
+ , x2: x2
+ , y2: y2
+ })
+ }
}
-})
-
-//
-SVG.extend(SVG.Container, {
- // Create a line element
- line: function(x1, y1, x2, y2) {
- return this.put(new SVG.Line().plot(x1, y1, x2, y2))
+ // Add parent method
+, construct: {
+ // Create a line element
+ line: function(x1, y1, x2, y2) {
+ return this.put(new SVG.Line().plot(x1, y1, x2, y2))
+ }
}
-
})
diff --git a/src/mask.js b/src/mask.js
index 2aa53d7..84d75b8 100755
--- a/src/mask.js
+++ b/src/mask.js
@@ -1,31 +1,42 @@
-SVG.Mask = function() {
- this.constructor.call(this, SVG.create('mask'))
+SVG.Mask = SVG.invent({
+ // Initialize node
+ create: function() {
+ this.constructor.call(this, SVG.create('mask'))
- /* keep references to masked elements */
- this.targets = []
-}
+ /* keep references to masked elements */
+ this.targets = []
+ }
-// Inherit from SVG.Container
-SVG.Mask.prototype = new SVG.Container
+ // Inherit from
+, inherit: SVG.Container
-//
-SVG.extend(SVG.Mask, {
- // Unmask all masked elements and remove itself
- remove: function() {
- /* unmask all targets */
- for (var i = this.targets.length - 1; i >= 0; i--)
- if (this.targets[i])
- this.targets[i].unmask()
- delete this.targets
+ // Add class methods
+, extend: {
+ // Unmask all masked elements and remove itself
+ remove: function() {
+ /* unmask all targets */
+ for (var i = this.targets.length - 1; i >= 0; i--)
+ if (this.targets[i])
+ this.targets[i].unmask()
+ delete this.targets
- /* remove mask from parent */
- this.parent.removeElement(this)
-
- return this
+ /* remove mask from parent */
+ this.parent.removeElement(this)
+
+ return this
+ }
+ }
+
+ // Add parent method
+, construct: {
+ // Create masking element
+ mask: function() {
+ return this.defs().put(new SVG.Mask)
+ }
}
})
-//
+
SVG.extend(SVG.Element, {
// Distribute mask to svg element
maskWith: function(element) {
@@ -45,12 +56,3 @@ SVG.extend(SVG.Element, {
}
})
-
-//
-SVG.extend(SVG.Container, {
- // Create masking element
- mask: function() {
- return this.defs().put(new SVG.Mask)
- }
-
-}) \ No newline at end of file
diff --git a/src/nested.js b/src/nested.js
index d42abf9..cd3a0e0 100755
--- a/src/nested.js
+++ b/src/nested.js
@@ -1,17 +1,19 @@
-SVG.Nested = function() {
- this.constructor.call(this, SVG.create('svg'))
-
- this.style('overflow', 'visible')
-}
-
-// Inherit from SVG.Container
-SVG.Nested.prototype = new SVG.Container
+SVG.Nested = SVG.invent({
+ // Initialize node
+ create: function() {
+ this.constructor.call(this, SVG.create('svg'))
+
+ this.style('overflow', 'visible')
+ }
-//
-SVG.extend(SVG.Container, {
- // Create nested svg document
+ // Inherit from
+, inherit: SVG.Container
+
+ // Add parent method
+, construct: {
+ // Create nested svg document
nested: function() {
- return this.put(new SVG.Nested)
+ return this.put(new SVG.Nested)
+ }
}
-
}) \ No newline at end of file
diff --git a/src/parent.js b/src/parent.js
index 4436d72..44514c2 100755
--- a/src/parent.js
+++ b/src/parent.js
@@ -1,102 +1,106 @@
-SVG.Parent = function(element) {
- this.constructor.call(this, element)
-}
+SVG.Parent = SVG.invent({
+ // Initialize node
+ create: function(element) {
+ this.constructor.call(this, element)
+ }
-// Inherit from SVG.Element
-SVG.Parent.prototype = new SVG.Element
+ // Inherit from
+, inherit: SVG.Element
-//
-SVG.extend(SVG.Parent, {
- // Returns all child elements
- children: function() {
- return this._children || (this._children = [])
- }
- // Add given element at a position
-, add: function(element, i) {
- if (!this.has(element)) {
- /* define insertion index if none given */
- i = i == null ? this.children().length : i
-
- /* remove references from previous parent */
- if (element.parent)
- element.parent.children().splice(element.parent.index(element), 1)
-
- /* add element references */
- this.children().splice(i, 0, element)
- this.node.insertBefore(element.node, this.node.childNodes[i] || null)
- element.parent = this
+ // Add class methods
+, extend: {
+ // Returns all child elements
+ children: function() {
+ return this._children || (this._children = [])
}
+ // Add given element at a position
+ , add: function(element, i) {
+ if (!this.has(element)) {
+ /* define insertion index if none given */
+ i = i == null ? this.children().length : i
+
+ /* remove references from previous parent */
+ if (element.parent)
+ element.parent.children().splice(element.parent.index(element), 1)
+
+ /* add element references */
+ this.children().splice(i, 0, element)
+ this.node.insertBefore(element.node, this.node.childNodes[i] || null)
+ element.parent = this
+ }
- /* reposition defs */
- if (this._defs) {
- this.node.removeChild(this._defs.node)
- this.node.appendChild(this._defs.node)
+ /* reposition defs */
+ if (this._defs) {
+ this.node.removeChild(this._defs.node)
+ this.node.appendChild(this._defs.node)
+ }
+
+ return this
}
-
- return this
- }
- // Basically does the same as `add()` but returns the added element instead
-, put: function(element, i) {
- this.add(element, i)
- return element
- }
- // Checks if the given element is a child
-, has: function(element) {
- return this.index(element) >= 0
- }
- // Gets index of given element
-, index: function(element) {
- return this.children().indexOf(element)
- }
- // Get a element at the given index
-, get: function(i) {
- return this.children()[i]
- }
- // Get first child, skipping the defs node
-, first: function() {
- return this.children()[0]
- }
- // Get the last child
-, last: function() {
- return this.children()[this.children().length - 1]
- }
- // Iterates over all children and invokes a given block
-, each: function(block, deep) {
- var i, il
- , children = this.children()
-
- for (i = 0, il = children.length; i < il; i++) {
- if (children[i] instanceof SVG.Element)
- block.apply(children[i], [i, children])
-
- if (deep && (children[i] instanceof SVG.Container))
- children[i].each(block, deep)
+ // Basically does the same as `add()` but returns the added element instead
+ , put: function(element, i) {
+ this.add(element, i)
+ return element
}
-
- return this
- }
- // Remove a child element at a position
-, removeElement: function(element) {
- this.children().splice(this.index(element), 1)
- this.node.removeChild(element.node)
- element.parent = null
+ // Checks if the given element is a child
+ , has: function(element) {
+ return this.index(element) >= 0
+ }
+ // Gets index of given element
+ , index: function(element) {
+ return this.children().indexOf(element)
+ }
+ // Get a element at the given index
+ , get: function(i) {
+ return this.children()[i]
+ }
+ // Get first child, skipping the defs node
+ , first: function() {
+ return this.children()[0]
+ }
+ // Get the last child
+ , last: function() {
+ return this.children()[this.children().length - 1]
+ }
+ // Iterates over all children and invokes a given block
+ , each: function(block, deep) {
+ var i, il
+ , children = this.children()
+
+ for (i = 0, il = children.length; i < il; i++) {
+ if (children[i] instanceof SVG.Element)
+ block.apply(children[i], [i, children])
+
+ if (deep && (children[i] instanceof SVG.Container))
+ children[i].each(block, deep)
+ }
- return this
- }
- // Remove all elements in this container
-, clear: function() {
- /* remove children */
- for (var i = this.children().length - 1; i >= 0; i--)
- this.removeElement(this.children()[i])
+ return this
+ }
+ // Remove a child element at a position
+ , removeElement: function(element) {
+ this.children().splice(this.index(element), 1)
+ this.node.removeChild(element.node)
+ element.parent = null
+
+ return this
+ }
+ // Remove all elements in this container
+ , clear: function() {
+ /* remove children */
+ for (var i = this.children().length - 1; i >= 0; i--)
+ this.removeElement(this.children()[i])
- /* remove defs node */
- if (this._defs)
- this._defs.clear()
+ /* remove defs node */
+ if (this._defs)
+ this._defs.clear()
- return this
- }
- , // Get defs
- defs: function() {
- return this.doc().defs()
+ return this
+ }
+ , // Get defs
+ defs: function() {
+ return this.doc().defs()
+ }
}
-}) \ No newline at end of file
+
+})
diff --git a/src/path.js b/src/path.js
index 60e6c73..4ce57f6 100755
--- a/src/path.js
+++ b/src/path.js
@@ -1,49 +1,49 @@
-SVG.Path = function() {
- this.constructor.call(this, SVG.create('path'))
-}
+SVG.Path = SVG.invent({
+ // Initialize node
+ create: 'path'
-// Inherit from SVG.Shape
-SVG.Path.prototype = new SVG.Shape
+ // Inherit from
+, inherit: SVG.Shape
-SVG.extend(SVG.Path, {
- // Plot new poly points
- plot: function(p) {
- return this.attr('d', (this.array = new SVG.PathArray(p, [{ type:'M',x:0,y:0 }])))
+ // Add class methods
+, extend: {
+ // Plot new poly points
+ plot: function(p) {
+ return this.attr('d', (this.array = new SVG.PathArray(p, [{ type:'M',x:0,y:0 }])))
+ }
+ // Move by left top corner
+ , move: function(x, y) {
+ return this.attr('d', this.array.move(x, y))
+ }
+ // Move by left top corner over x-axis
+ , x: function(x) {
+ return x == null ? this.bbox().x : this.move(x, this.bbox().y)
+ }
+ // Move by left top corner over y-axis
+ , y: function(y) {
+ return y == null ? this.bbox().y : this.move(this.bbox().x, y)
+ }
+ // Set element size to given width and height
+ , size: function(width, height) {
+ var p = this._proportionalSize(width, height)
+
+ return this.attr('d', this.array.size(p.width, p.height))
+ }
+ // Set width of element
+ , width: function(width) {
+ return width == null ? this.bbox().width : this.size(width, this.bbox().height)
+ }
+ // Set height of element
+ , height: function(height) {
+ return height == null ? this.bbox().height : this.size(this.bbox().width, height)
+ }
+ }
+
+ // Add parent method
+, construct: {
+ // Create a wrapped path element
+ path: function(d) {
+ return this.put(new SVG.Path).plot(d)
+ }
}
- // Move by left top corner
-, move: function(x, y) {
- return this.attr('d', this.array.move(x, y))
- }
- // Move by left top corner over x-axis
-, x: function(x) {
- return x == null ? this.bbox().x : this.move(x, this.bbox().y)
- }
- // Move by left top corner over y-axis
-, y: function(y) {
- return y == null ? this.bbox().y : this.move(this.bbox().x, y)
- }
- // Set element size to given width and height
-, size: function(width, height) {
- var p = this._proportionalSize(width, height)
-
- return this.attr('d', this.array.size(p.width, p.height))
- }
- // Set width of element
-, width: function(width) {
- return width == null ? this.bbox().width : this.size(width, this.bbox().height)
- }
- // Set height of element
-, height: function(height) {
- return height == null ? this.bbox().height : this.size(this.bbox().width, height)
- }
-
-})
-
-//
-SVG.extend(SVG.Container, {
- // Create a wrapped path element
- path: function(d) {
- return this.put(new SVG.Path).plot(d)
- }
-
}) \ No newline at end of file
diff --git a/src/poly.js b/src/poly.js
index 247ab8f..5a0f9b2 100755
--- a/src/poly.js
+++ b/src/poly.js
@@ -1,16 +1,34 @@
-SVG.Polyline = function() {
- this.constructor.call(this, SVG.create('polyline'))
-}
+SVG.Polyline = SVG.invent({
+ // Initialize node
+ create: 'polyline'
-// Inherit from SVG.Shape
-SVG.Polyline.prototype = new SVG.Shape
+ // Inherit from
+, inherit: SVG.Shape
+
+ // Add parent method
+, construct: {
+ // Create a wrapped polyline element
+ polyline: function(p) {
+ return this.put(new SVG.Polyline).plot(p)
+ }
+ }
+})
-SVG.Polygon = function() {
- this.constructor.call(this, SVG.create('polygon'))
-}
+SVG.Polygon = SVG.invent({
+ // Initialize node
+ create: 'polygon'
-// Inherit from SVG.Shape
-SVG.Polygon.prototype = new SVG.Shape
+ // Inherit from
+, inherit: SVG.Shape
+
+ // Add parent method
+, construct: {
+ // Create a wrapped polygon element
+ polygon: function(p) {
+ return this.put(new SVG.Polygon).plot(p)
+ }
+ }
+})
// Add polygon-specific functions
SVG.extend(SVG.Polyline, SVG.Polygon, {
@@ -51,17 +69,4 @@ SVG.extend(SVG.Polyline, SVG.Polygon, {
return this.attr('points', this.array.size(p.width, p.height))
}
-})
-
-//
-SVG.extend(SVG.Container, {
- // Create a wrapped polyline element
- polyline: function(p) {
- return this.put(new SVG.Polyline).plot(p)
- }
- // Create a wrapped polygon element
-, polygon: function(p) {
- return this.put(new SVG.Polygon).plot(p)
- }
-
}) \ No newline at end of file
diff --git a/src/rect.js b/src/rect.js
index 583556d..313c96d 100755
--- a/src/rect.js
+++ b/src/rect.js
@@ -1,15 +1,17 @@
-SVG.Rect = function() {
- this.constructor.call(this, SVG.create('rect'))
-}
-
-// Inherit from SVG.Shape
-SVG.Rect.prototype = new SVG.Shape
-
-//
-SVG.extend(SVG.Container, {
- // Create a rect element
- rect: function(width, height) {
- return this.put(new SVG.Rect().size(width, height))
- }
+SVG.Rect = SVG.invent({
+ // Initialize node
+ create: 'rect'
+ // Inherit from
+, inherit: SVG.Shape
+
+ // Add parent method
+, construct: {
+ // Create a rect element
+ rect: function(width, height) {
+ return this.put(new SVG.Rect().size(width, height))
+ }
+
+ }
+
}) \ No newline at end of file
diff --git a/src/set.js b/src/set.js
index 9a6addc..38251f5 100755
--- a/src/set.js
+++ b/src/set.js
@@ -1,91 +1,102 @@
-SVG.Set = function() {
- /* set initial state */
- this.clear()
-}
-
-// Set FX class
-SVG.SetFX = function(set) {
- /* store reference to set */
- this.set = set
-}
-
-//
-SVG.extend(SVG.Set, {
- // Add element to set
- add: function() {
- var i, il, elements = [].slice.call(arguments)
-
- for (i = 0, il = elements.length; i < il; i++)
- this.members.push(elements[i])
-
- return this
+SVG.Set = SVG.invent({
+ // Initialize
+ create: function() {
+ /* set initial state */
+ this.clear()
}
- // Remove element from set
-, remove: function(element) {
- var i = this.index(element)
-
- /* remove given child */
- if (i > -1)
- this.members.splice(i, 1)
-
- return this
- }
- // Iterate over all members
-, each: function(block) {
- for (var i = 0, il = this.members.length; i < il; i++)
- block.apply(this.members[i], [i, this.members])
- return this
- }
- // Restore to defaults
-, clear: function() {
- /* initialize store */
- this.members = []
+ // Add class methods
+, extend: {
+ // Add element to set
+ add: function() {
+ var i, il, elements = [].slice.call(arguments)
- return this
- }
- // Checks if a given element is present in set
-, has: function(element) {
- return this.index(element) >= 0
- }
- // retuns index of given element in set
-, index: function(element) {
- return this.members.indexOf(element)
- }
- // Get member at given index
-, get: function(i) {
- return this.members[i]
- }
- // Default value
-, valueOf: function() {
- return this.members
- }
- // Get the bounding box of all members included or empty box if set has no items
-, bbox: function(){
- var box = new SVG.BBox()
+ for (i = 0, il = elements.length; i < il; i++)
+ this.members.push(elements[i])
+
+ return this
+ }
+ // Remove element from set
+ , remove: function(element) {
+ var i = this.index(element)
+
+ /* remove given child */
+ if (i > -1)
+ this.members.splice(i, 1)
- /* return an empty box of there are no members */
- if (this.members.length == 0)
- return box
+ return this
+ }
+ // Iterate over all members
+ , each: function(block) {
+ for (var i = 0, il = this.members.length; i < il; i++)
+ block.apply(this.members[i], [i, this.members])
- /* get the first rbox and update the target bbox */
- var rbox = this.members[0].rbox()
- box.x = rbox.x
- box.y = rbox.y
- box.width = rbox.width
- box.height = rbox.height
+ return this
+ }
+ // Restore to defaults
+ , clear: function() {
+ /* initialize store */
+ this.members = []
- this.each(function() {
- /* user rbox for correct position and visual representation */
- box = box.merge(this.rbox())
- })
+ return this
+ }
+ // Checks if a given element is present in set
+ , has: function(element) {
+ return this.index(element) >= 0
+ }
+ // retuns index of given element in set
+ , index: function(element) {
+ return this.members.indexOf(element)
+ }
+ // Get member at given index
+ , get: function(i) {
+ return this.members[i]
+ }
+ // Default value
+ , valueOf: function() {
+ return this.members
+ }
+ // Get the bounding box of all members included or empty box if set has no items
+ , bbox: function(){
+ var box = new SVG.BBox()
+
+ /* return an empty box of there are no members */
+ if (this.members.length == 0)
+ return box
+
+ /* get the first rbox and update the target bbox */
+ var rbox = this.members[0].rbox()
+ box.x = rbox.x
+ box.y = rbox.y
+ box.width = rbox.width
+ box.height = rbox.height
+
+ this.each(function() {
+ /* user rbox for correct position and visual representation */
+ box = box.merge(this.rbox())
+ })
- return box
+ return box
+ }
+ }
+
+ // Add parent method
+, construct: {
+ // Create a new set
+ set: function() {
+ return new SVG.Set
+ }
}
-
})
+SVG.SetFX = SVG.invent({
+ // Initialize node
+ create: function(set) {
+ /* store reference to set */
+ this.set = set
+ }
+})
// Alias methods
SVG.Set.inherit = function() {
@@ -127,14 +138,4 @@ SVG.Set.inherit = function() {
})
}
-//
-SVG.extend(SVG.Container, {
- // Create a new set
- set: function() {
- return new SVG.Set
- }
-
-})
-
-
diff --git a/src/shape.js b/src/shape.js
index 0594ed7..15c1fa9 100755
--- a/src/shape.js
+++ b/src/shape.js
@@ -1,6 +1,10 @@
-SVG.Shape = function(element) {
- this.constructor.call(this, element)
-}
+SVG.Shape = SVG.invent({
+ // Initialize node
+ create: function(element) {
+ this.constructor.call(this, element)
+ }
-// Inherit from SVG.Element
-SVG.Shape.prototype = new SVG.Element \ No newline at end of file
+ // Inherit from
+, inherit: SVG.Element
+
+}) \ No newline at end of file
diff --git a/src/svg.js b/src/svg.js
index b0f6ecd..364a786 100755
--- a/src/svg.js
+++ b/src/svg.js
@@ -1,18 +1,14 @@
-// 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('drawing').size(300, 300)
-// var rect = draw.rect(100, 100).attr({ fill: '#f06' })
-
-
-
// The main wrapping element
this.SVG = function(element) {
- if (!SVG.parser)
- SVG.prepare()
+ if (SVG.supported) {
+ element = new SVG.Doc(element)
- if (SVG.supported)
- return new SVG.Doc(element)
+ if (!SVG.parser)
+ SVG.prepare(element)
+
+ return element
+ }
}
// Default namespaces
@@ -66,15 +62,15 @@ SVG.get = function(id) {
}
// Initialize parsing element
-SVG.prepare = function() {
- /* select document body and create svg element*/
- var body = document.getElementsByTagName('body')[0] || document.getElementsByTagName('svg')[0]
- , draw = new SVG.Doc(body).size(2, 2).style('opacity:0;position:fixed;left:100%;top:100%;')
+SVG.prepare = function(element) {
+ /* select document body and create invisible svg element */
+ var body = document.getElementsByTagName('body')[0]
+ , draw = (body ? new SVG.Doc(body) : element.nested()).size(2, 2)
/* create parser object */
SVG.parser = {
- body: body
- , draw: draw
+ body: body || element.parent
+ , draw: draw.style('opacity:0;position:fixed;left:100%;top:100%;overflow:hidden')
, poly: draw.polygon().node
, path: draw.path().node
}
diff --git a/src/text.js b/src/text.js
index 5fc9ece..73ef290 100755
--- a/src/text.js
+++ b/src/text.js
@@ -2,209 +2,211 @@
// List font style attributes as they should be applied to style
var _styleAttr = ('size family weight stretch variant style').split(' ')
-SVG.Text = function() {
- this.constructor.call(this, SVG.create('text'))
-
- /* define default style */
- this.styles = {
- 'font-size': 16
- , 'font-family': 'Helvetica, Arial, sans-serif'
- , 'text-anchor': 'start'
- }
-
- this._leading = new SVG.Number('1.2em')
- this._rebuild = true
-}
-
-// Inherit from SVG.Element
-SVG.Text.prototype = new SVG.Shape
-
-//
-SVG.extend(SVG.Text, {
- // Move over x-axis
- x: function(x, a) {
- /* act as getter */
- if (x == null)
- return a ? this.attr('x') : this.bbox().x
+SVG.Text = SVG.invent({
+ // Initialize node
+ create: function() {
+ this.constructor.call(this, SVG.create('text'))
- /* set x taking anchor in mind */
- if (!a) {
- a = this.style('text-anchor')
- x = a == 'start' ? x : a == 'end' ? x + this.bbox().width : x + this.bbox().width / 2
+ /* define default style */
+ this.styles = {
+ 'font-size': 16
+ , 'font-family': 'Helvetica, Arial, sans-serif'
+ , 'text-anchor': 'start'
}
-
- /* move lines as well if no textPath si present */
- if (!this.textPath)
- this.lines.each(function() { if (this.newLined) this.x(x) })
-
- return this.attr('x', x)
- }
- // Move center over x-axis
-, cx: function(x, a) {
- return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2)
- }
- // Move center over y-axis
-, cy: function(y, a) {
- return y == null ? this.bbox().cy : this.y(a ? y : y - this.bbox().height / 2)
- }
- // Move element to given x and y values
-, move: function(x, y, a) {
- return this.x(x, a).y(y)
- }
- // Move element by its center
-, center: function(x, y, a) {
- return this.cx(x, a).cy(y, a)
- }
- // Set the text content
-, text: function(text) {
- /* act as getter */
- if (text == null)
- return this.content
- /* remove existing lines */
- this.clear()
-
- if (typeof text === 'function') {
- this._rebuild = false
+ this._leading = new SVG.Number('1.2em')
+ this._rebuild = true
+ }
- text.call(this, this)
+ // Inherit from
+, inherit: SVG.Shape
- } else {
- this._rebuild = true
+ // Add class methods
+, extend: {
+ // Move over x-axis
+ x: function(x, a) {
+ /* act as getter */
+ if (x == null)
+ return a ? this.attr('x') : this.bbox().x
+
+ /* set x taking anchor in mind */
+ if (!a) {
+ a = this.style('text-anchor')
+ x = a == 'start' ? x : a == 'end' ? x + this.bbox().width : x + this.bbox().width / 2
+ }
+
+ /* move lines as well if no textPath si present */
+ if (!this.textPath)
+ this.lines.each(function() { if (this.newLined) this.x(x) })
- /* make sure text is not blank */
- text = SVG.regex.isBlank.test(text) ? 'text' : text
+ return this.attr('x', x)
+ }
+ // Move center over x-axis
+ , cx: function(x, a) {
+ return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2)
+ }
+ // Move center over y-axis
+ , cy: function(y, a) {
+ return y == null ? this.bbox().cy : this.y(a ? y : y - this.bbox().height / 2)
+ }
+ // Move element to given x and y values
+ , move: function(x, y, a) {
+ return this.x(x, a).y(y)
+ }
+ // Move element by its center
+ , center: function(x, y, a) {
+ return this.cx(x, a).cy(y, a)
+ }
+ // Set the text content
+ , text: function(text) {
+ /* act as getter */
+ if (text == null)
+ return this.content
- var i, il
- , lines = text.split('\n')
+ /* remove existing lines */
+ this.clear()
- /* build new lines */
- for (i = 0, il = lines.length; i < il; i++)
- this.tspan(lines[i]).newLine()
-
- this.rebuild()
+ if (typeof text === 'function') {
+ this._rebuild = false
+
+ text.call(this, this)
+
+ } else {
+ this._rebuild = true
+
+ /* make sure text is not blank */
+ text = SVG.regex.isBlank.test(text) ? 'text' : text
+
+ var i, il
+ , lines = text.split('\n')
+
+ /* build new lines */
+ for (i = 0, il = lines.length; i < il; i++)
+ this.tspan(lines[i]).newLine()
+
+ this.rebuild()
+ }
+
+ return this
}
-
- return this
- }
- // Create a tspan
-, tspan: function(text) {
- var node = this.textPath ? this.textPath.node : this.node
- , tspan = new SVG.TSpan().text(text)
- , style = this.style()
-
- /* add new tspan */
- node.appendChild(tspan.node)
- this.lines.add(tspan)
-
- /* add style if any */
- if (!SVG.regex.isBlank.test(style))
- tspan.style(style)
+ // Create a tspan
+ , tspan: function(text) {
+ var node = this.textPath ? this.textPath.node : this.node
+ , tspan = new SVG.TSpan().text(text)
+ , style = this.style()
+
+ /* add new tspan */
+ node.appendChild(tspan.node)
+ this.lines.add(tspan)
- /* store content */
- this.content += text
+ /* add style if any */
+ if (!SVG.regex.isBlank.test(style))
+ tspan.style(style)
- /* store text parent */
- tspan.parent = this
+ /* store content */
+ this.content += text
- return tspan
- }
- // Set font size
-, size: function(size) {
- return this.attr('font-size', size)
- }
- // Set / get leading
-, leading: function(value) {
- /* act as getter */
- if (value == null)
- return this._leading
-
- /* act as setter */
- value = new SVG.Number(value)
- this._leading = value
-
- /* apply leading */
- this.lines.each(function() {
- if (this.newLined)
- this.attr('dy', value)
- })
+ /* store text parent */
+ tspan.parent = this
- return this
- }
- // rebuild appearance type
-, rebuild: function() {
- var self = this
-
- /* define position of all lines */
- if (this._rebuild) {
- this.lines.attr({
- x: this.attr('x')
- , dy: this._leading
- , style: this.style()
- })
+ return tspan
}
+ // Set font size
+ , size: function(size) {
+ return this.attr('font-size', size)
+ }
+ // Set / get leading
+ , leading: function(value) {
+ /* act as getter */
+ if (value == null)
+ return this._leading
+
+ /* act as setter */
+ value = new SVG.Number(value)
+ this._leading = value
+
+ /* apply leading */
+ this.lines.each(function() {
+ if (this.newLined)
+ this.attr('dy', value)
+ })
- return this
- }
- // Clear all lines
-, clear: function() {
- var node = this.textPath ? this.textPath.node : this.node
+ return this
+ }
+ // rebuild appearance type
+ , rebuild: function() {
+ var self = this
+
+ /* define position of all lines */
+ if (this._rebuild) {
+ this.lines.attr({
+ x: this.attr('x')
+ , dy: this._leading
+ , style: this.style()
+ })
+ }
+
+ return this
+ }
+ // Clear all lines
+ , clear: function() {
+ var node = this.textPath ? this.textPath.node : this.node
- /* remove existing child nodes */
- while (node.hasChildNodes())
- node.removeChild(node.lastChild)
-
- /* refresh lines */
- delete this.lines
- this.lines = new SVG.Set
-
- /* initialize content */
- this.content = ''
+ /* remove existing child nodes */
+ while (node.hasChildNodes())
+ node.removeChild(node.lastChild)
+
+ /* refresh lines */
+ delete this.lines
+ this.lines = new SVG.Set
+
+ /* initialize content */
+ this.content = ''
- return this
+ return this
+ }
}
-})
-
-//
-SVG.extend(SVG.Container, {
- // Create text element
- text: function(text) {
- return this.put(new SVG.Text).text(text)
+ // Add parent method
+, construct: {
+ // Create text element
+ text: function(text) {
+ return this.put(new SVG.Text).text(text)
+ }
}
-
})
-// tspan class
-SVG.TSpan = function() {
- this.constructor.call(this, SVG.create('tspan'))
-}
+SVG.TSpan = SVG.invent({
+ // Initialize node
+ create: 'tspan'
-// Inherit from SVG.Shape
-SVG.TSpan.prototype = new SVG.Shape
+ // Inherit from
+, inherit: SVG.Shape
-// Include the container object
-SVG.extend(SVG.TSpan, {
- // Set text content
- text: function(text) {
- this.node.appendChild(document.createTextNode(text))
-
- return this
- }
- // Shortcut dx
-, dx: function(dx) {
- return this.attr('dx', dx)
- }
- // Shortcut dy
-, dy: function(dy) {
- return this.attr('dy', dy)
- }
- // Create new line
-, newLine: function() {
- this.newLined = true
- this.parent.content += '\n'
- this.dy(this.parent._leading)
- return this.attr('x', this.parent.x())
+ // Add class methods
+, extend: {
+ // Set text content
+ text: function(text) {
+ this.node.appendChild(document.createTextNode(text))
+
+ return this
+ }
+ // Shortcut dx
+ , dx: function(dx) {
+ return this.attr('dx', dx)
+ }
+ // Shortcut dy
+ , dy: function(dy) {
+ return this.attr('dy', dy)
+ }
+ // Create new line
+ , newLine: function() {
+ this.newLined = true
+ this.parent.content += '\n'
+ this.dy(this.parent._leading)
+ return this.attr('x', this.parent.x())
+ }
}
-
+
})
+
diff --git a/src/textpath.js b/src/textpath.js
index 04d7bde..9f7b088 100755
--- a/src/textpath.js
+++ b/src/textpath.js
@@ -1,39 +1,42 @@
-SVG.TextPath = function() {
- this.constructor.call(this, SVG.create('textPath'))
-}
-
-// Inherit from SVG.Element
-SVG.TextPath.prototype = new SVG.Element
-
-//
-SVG.extend(SVG.Text, {
- // Create path for text to run on
- path: function(d) {
- /* create textPath element */
- this.textPath = new SVG.TextPath
-
- /* move lines to textpath */
- while(this.node.hasChildNodes())
- this.textPath.node.appendChild(this.node.firstChild)
-
- /* add textPath element as child node */
- this.node.appendChild(this.textPath.node)
-
- /* create path in defs */
- this.track = this.doc().defs().path(d, true)
-
- /* create circular reference */
- this.textPath.parent = this
-
- /* link textPath to path and add content */
- this.textPath.attr('href', '#' + this.track, SVG.xlink)
-
- return this
+SVG.TextPath = SVG.invent({
+ // Initialize node
+ create: 'textPath'
+
+ // Inherit from
+, inherit: SVG.Element
+
+ // Define parent class
+, parent: SVG.Text
+
+ // Add parent method
+, construct: {
+ // Create path for text to run on
+ path: function(d) {
+ /* create textPath element */
+ this.textPath = new SVG.TextPath
+
+ /* move lines to textpath */
+ while(this.node.hasChildNodes())
+ this.textPath.node.appendChild(this.node.firstChild)
+
+ /* add textPath element as child node */
+ this.node.appendChild(this.textPath.node)
+
+ /* create path in defs */
+ this.track = this.doc().defs().path(d, true)
+
+ /* create circular reference */
+ this.textPath.parent = this
+
+ /* link textPath to path and add content */
+ this.textPath.attr('href', '#' + this.track, SVG.xlink)
+
+ return this
+ }
+ // Plot path if any
+ , plot: function(d) {
+ if (this.track) this.track.plot(d)
+ return this
+ }
}
- // Plot path if any
-, plot: function(d) {
- if (this.track) this.track.plot(d)
- return this
- }
-
}) \ No newline at end of file
diff --git a/src/use.js b/src/use.js
index 0a8bb90..2690468 100755
--- a/src/use.js
+++ b/src/use.js
@@ -1,28 +1,27 @@
-SVG.Use = function() {
- this.constructor.call(this, SVG.create('use'))
-}
+SVG.Use = SVG.invent({
+ // Initialize node
+ create: 'use'
-// Inherit from SVG.Shape
-SVG.Use.prototype = new SVG.Shape
+ // Inherit from
+, inherit: SVG.Shape
-//
-SVG.extend(SVG.Use, {
- // Use element as a reference
- element: function(element) {
- /* store target element */
- this.target = element
+ // Add class methods
+, extend: {
+ // Use element as a reference
+ element: function(element) {
+ /* store target element */
+ this.target = element
- /* set lined element */
- return this.attr('href', '#' + element, SVG.xlink)
+ /* set lined element */
+ return this.attr('href', '#' + element, SVG.xlink)
+ }
}
-})
-
-//
-SVG.extend(SVG.Container, {
- // Create a use element
- use: function(element) {
- return this.put(new SVG.Use).element(element)
+ // Add parent method
+, construct: {
+ // Create a use element
+ use: function(element) {
+ return this.put(new SVG.Use).element(element)
+ }
}
-
}) \ No newline at end of file