summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/adopter.js23
-rwxr-xr-xsrc/arrange.js16
-rwxr-xr-xsrc/clip.js8
-rwxr-xr-xsrc/doc.js81
-rwxr-xr-xsrc/element.js85
-rwxr-xr-xsrc/event.js11
-rw-r--r--src/helpers.js5
-rwxr-xr-xsrc/hyperlink.js2
-rwxr-xr-xsrc/mask.js4
-rwxr-xr-xsrc/parent.js31
-rw-r--r--src/polyfill.js14
-rwxr-xr-xsrc/rbox.js4
-rw-r--r--src/selector.js19
-rw-r--r--src/spof.js31
-rwxr-xr-xsrc/svg.js2
-rwxr-xr-xsrc/text.js1
-rw-r--r--src/utilities.js14
-rwxr-xr-xsrc/viewbox.js8
18 files changed, 209 insertions, 150 deletions
diff --git a/src/adopter.js b/src/adopter.js
new file mode 100644
index 0000000..c762a2b
--- /dev/null
+++ b/src/adopter.js
@@ -0,0 +1,23 @@
+// Adopt existing svg elements
+SVG.adopt = function(node) {
+ // Make sure a node isn't already adopted
+ if (node.instance) return node.instance
+
+ // Initialize variables
+ var element
+
+ // Adopt with element-specific settings
+ if (node.nodeName == 'svg')
+ element = node.parentNode instanceof SVGElement ? new SVG.Nested : new SVG.Doc
+ else if (node.nodeName == 'lineairGradient')
+ element = new SVG.Gradient('lineair')
+ else if (node.nodeName == 'radialGradient')
+ element = new SVG.Gradient('radial')
+ else
+ element = new SVG[capitalize(node.nodeName)]
+
+ // Ensure references
+ element.type = node.nodeName
+ element.node = node
+ return node.instance = element
+} \ No newline at end of file
diff --git a/src/arrange.js b/src/arrange.js
index a48ec5d..5c4e878 100755
--- a/src/arrange.js
+++ b/src/arrange.js
@@ -4,11 +4,11 @@
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.parent.index(this)
+ return this.parent().index(this)
}
// Get the next element (will return null if there is none)
, next: function() {
@@ -21,25 +21,25 @@ SVG.extend(SVG.Element, {
// Send given element one step forward
, forward: function() {
var i = this.position()
- return this.parent.removeElement(this).put(this, i + 1)
+ return this.parent().removeElement(this).put(this, i + 1)
}
// Send given element one step backward
, backward: function() {
var i = this.position()
if (i > 0)
- this.parent.removeElement(this).add(this, i - 1)
+ this.parent().removeElement(this).add(this, i - 1)
return this
}
// Send given element all the way to the front
, front: function() {
- return this.parent.removeElement(this).put(this)
+ return this.parent().removeElement(this).put(this)
}
// Send given element all the way to the back
, back: function() {
if (this.position() > 0)
- this.parent.removeElement(this).add(this, 0)
+ this.parent().removeElement(this).add(this, 0)
return this
}
@@ -49,7 +49,7 @@ SVG.extend(SVG.Element, {
var i = this.position()
- this.parent.add(element, i)
+ this.parent().add(element, i)
return this
}
@@ -59,7 +59,7 @@ SVG.extend(SVG.Element, {
var i = this.position()
- this.parent.add(element, i + 1)
+ this.parent().add(element, i + 1)
return this
}
diff --git a/src/clip.js b/src/clip.js
index e8a5e35..3fb5daa 100755
--- a/src/clip.js
+++ b/src/clip.js
@@ -1,4 +1,4 @@
-SVG.Clip = SVG.invent({
+SVG.ClipPath = SVG.invent({
// Initialize node
create: function() {
this.constructor.call(this, SVG.create('clipPath'))
@@ -21,7 +21,7 @@ SVG.Clip = SVG.invent({
delete this.targets
/* remove clipPath from parent */
- this.parent.removeElement(this)
+ this.parent().removeElement(this)
return this
}
@@ -31,7 +31,7 @@ SVG.Clip = SVG.invent({
, construct: {
// Create clipping element
clip: function() {
- return this.defs().put(new SVG.Clip)
+ return this.defs().put(new SVG.ClipPath)
}
}
})
@@ -41,7 +41,7 @@ SVG.extend(SVG.Element, {
// Distribute clipPath to svg element
clipWith: function(element) {
/* use given clip or create a new one */
- this.clipper = element instanceof SVG.Clip ? element : this.parent.clip().add(element)
+ this.clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element)
/* store reverence on self in mask */
this.clipper.targets.push(this)
diff --git a/src/doc.js b/src/doc.js
index a10bffe..54b7c70 100755
--- a/src/doc.js
+++ b/src/doc.js
@@ -1,32 +1,24 @@
SVG.Doc = SVG.invent({
// Initialize node
create: function(element) {
- /* ensure the presence of a html element */
- this.parent = typeof element == 'string' ?
+ /* ensure the presence of a dom element */
+ element = typeof element == 'string' ?
document.getElementById(element) :
element
/* If the target is an svg element, use that element as the main wrapper.
This allows svg.js to work with svg documents as well. */
- this.constructor
- .call(this, this.parent.nodeName == 'svg' ? this.parent : SVG.create('svg'))
+ if (element.nodeName == 'svg') {
+ this.constructor.call(this, element)
+ } else {
+ this.constructor.call(this, SVG.create('svg'))
+ element.appendChild(this.node)
+ }
/* 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)
-
- /* turn off sub pixel offset by default */
- this.doSpof = false
-
- /* ensure correct rendering */
- if (this.parent != this.node)
- this.stage()
}
// Inherit from
@@ -34,49 +26,26 @@ SVG.Doc = SVG.invent({
// Add class methods
, extend: {
- /* enable drawing */
- stage: function() {
- var element = this
-
- /* insert element */
- this.parent.appendChild(this.node)
-
- /* fix sub-pixel offset */
- element.spof()
-
- /* make sure sub-pixel offset is fixed every time the window is resized */
- SVG.on(window, 'resize', function() {
- element.spof()
- })
-
- return this
- }
-
// Creates and returns defs element
- , defs: function() {
- return this._defs
- }
-
- // Fix for possible sub-pixel offset. See:
- // https://bugzilla.mozilla.org/show_bug.cgi?id=608812
- , spof: function() {
- if (this.doSpof) {
- var pos = this.node.getScreenCTM()
-
- if (pos)
- this
- .style('left', (-pos.e % 1) + 'px')
- .style('top', (-pos.f % 1) + 'px')
+ defs: function() {
+ if (!this._defs) {
+ var defs
+
+ // Find or create a defs element in this instance
+ if (defs = this.node.getElementsByTagName('defs')[0])
+ this._defs = SVG.adopt(defs)
+ else
+ this._defs = new SVG.Defs
+
+ // Make sure the defs node is at the end of the stack
+ this.node.appendChild(this._defs.node)
}
-
- return this
- }
-
- // Enable sub-pixel offset
- , fixSubPixelOffset: function() {
- this.doSpof = true
- return this
+ return this._defs
+ }
+ // custom parent method
+ , parent: function() {
+ return this.node.parentNode.nodeName == '#document' ? null : this.node.parentNode
}
}
diff --git a/src/element.js b/src/element.js
index b12947b..c8eb5de 100755
--- a/src/element.js
+++ b/src/element.js
@@ -72,20 +72,20 @@ SVG.Element = SVG.invent({
/* invoke shape method with shape-specific arguments */
clone = type == 'rect' || type == 'ellipse' ?
- this.parent[type](0,0) :
+ this.parent()[type](0,0) :
type == 'line' ?
- this.parent[type](0,0,0,0) :
+ this.parent()[type](0,0,0,0) :
type == 'image' ?
- this.parent[type](this.src) :
+ this.parent()[type](this.src) :
type == 'text' ?
- this.parent[type](this.content) :
+ this.parent()[type](this.content) :
type == 'path' ?
- this.parent[type](this.attr('d')) :
+ this.parent()[type](this.attr('d')) :
type == 'polyline' || type == 'polygon' ?
- this.parent[type](this.attr('points')) :
+ this.parent()[type](this.attr('points')) :
type == 'g' ?
- this.parent.group() :
- this.parent[type]()
+ this.parent().group() :
+ this.parent()[type]()
/* apply attributes attributes */
attr = this.attr()
@@ -100,8 +100,8 @@ SVG.Element = SVG.invent({
}
// Remove element
, remove: function() {
- if (this.parent)
- this.parent.removeElement(this)
+ if (this.parent())
+ this.parent().removeElement(this)
return this
}
@@ -121,7 +121,7 @@ SVG.Element = SVG.invent({
}
// Get parent document
, doc: function(type) {
- return this._parent(type || SVG.Doc)
+ return this.parent(type || SVG.Doc)
}
// Set svg element attribute
, attr: function(a, v, n) {
@@ -346,59 +346,54 @@ SVG.Element = SVG.invent({
}
// Return array of classes on the node
, classes: function() {
- var classAttr = this.node.getAttribute('class')
- if (classAttr === null) {
- return []
- } else {
- return classAttr.trim().split(/\s+/)
- }
+ var attr = this.attr('class')
+
+ return attr == null ? [] : attr.trim().split(/\s+/)
}
// Return true if class exists on the node, false otherwise
- , hasClass: function(className) {
- return this.classes().indexOf(className) != -1
+ , hasClass: function(name) {
+ return this.classes().indexOf(name) != -1
}
// Add class to the node
- , addClass: function(className) {
- var classArray
- if (!(this.hasClass(className))) {
- classArray = this.classes()
- classArray.push(className)
- this.node.setAttribute('class', classArray.join(' '))
+ , addClass: function(name) {
+ if (!this.hasClass(name)) {
+ var array = this.classes()
+ array.push(name)
+ this.attr('class', array.join(' '))
}
+
return this
}
// Remove class from the node
- , removeClass: function(className) {
- var classArray
- if (this.hasClass(className)) {
- classArray = this.classes().filter(function(c) {
- return c != className
+ , removeClass: function(name) {
+ if (this.hasClass(name)) {
+ var array = this.classes().filter(function(c) {
+ return c != name
})
- this.node.setAttribute('class', classArray.join(' '))
+ this.attr('class', array.join(' '))
}
+
return this
}
// Toggle the presence of a class on the node
- , toggleClass: function(className) {
- if (this.hasClass(className)) {
- this.removeClass(className)
- } else {
- this.addClass(className)
- }
- return this
+ , toggleClass: function(name) {
+ return this.hasClass(name) ? this.removeClass(name) : this.addClass(name)
}
// Get referenced element form attribute value
, reference: function(attr) {
return SVG.get(this.attr(attr))
}
- // Private: find svg parent by instance
- , _parent: function(parent) {
- var element = this
-
- while (element != null && !(element instanceof parent))
- element = element.parent
+ // Returns the parent element instance
+ , parent: function(type) {
+ // Get parent element
+ var parent = SVG.adopt(this.node.parentNode)
- return element
+ // If a specific type is given, find a parent with that class
+ if (type)
+ while (!(parent instanceof type))
+ parent = SVG.adopt(parent.node.parentNode)
+
+ return parent
}
}
})
diff --git a/src/event.js b/src/event.js
index 8430fa0..6108155 100755
--- a/src/event.js
+++ b/src/event.js
@@ -34,7 +34,7 @@ SVG.listeners = {}
// Event constructor
SVG.registerEvent = function(event) {
if (!SVG.events[event])
- SVG.events[event] = new Event(event)
+ SVG.events[event] = new CustomEvent(event)
}
// Add event binder in the SVG namespace
@@ -65,9 +65,16 @@ SVG.extend(SVG.Element, {
return this
}
// Fire given event
-, fire: function(event) {
+, fire: function(event, data) {
+ // Add detail data to event
+ SVG.events[event].detail = data
+
+ // Dispatch event
this.node.dispatchEvent(SVG.events[event])
+ // Remove detail
+ delete SVG.events[event].detail
+
return this
}
}) \ No newline at end of file
diff --git a/src/helpers.js b/src/helpers.js
index c63c215..492039c 100644
--- a/src/helpers.js
+++ b/src/helpers.js
@@ -5,6 +5,11 @@ function camelCase(s) {
})
}
+// Capitalize first letter of a string
+function capitalize(s) {
+ return s.charAt(0).toUpperCase() + s.slice(1)
+}
+
// Ensure to six-based hex
function fullHex(hex) {
return hex.length == 4 ?
diff --git a/src/hyperlink.js b/src/hyperlink.js
index 1981d52..a967707 100755
--- a/src/hyperlink.js
+++ b/src/hyperlink.js
@@ -40,7 +40,7 @@ SVG.extend(SVG.Element, {
else
link.to(url)
- return this.parent.put(link).put(this)
+ return this.parent().put(link).put(this)
}
}) \ No newline at end of file
diff --git a/src/mask.js b/src/mask.js
index 84d75b8..73f29c2 100755
--- a/src/mask.js
+++ b/src/mask.js
@@ -21,7 +21,7 @@ SVG.Mask = SVG.invent({
delete this.targets
/* remove mask from parent */
- this.parent.removeElement(this)
+ this.parent().removeElement(this)
return this
}
@@ -41,7 +41,7 @@ SVG.extend(SVG.Element, {
// Distribute mask to svg element
maskWith: function(element) {
/* use given mask or create a new one */
- this.masker = element instanceof SVG.Mask ? element : this.parent.mask().add(element)
+ this.masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element)
/* store reverence on self in mask */
this.masker.targets.push(this)
diff --git a/src/parent.js b/src/parent.js
index 44514c2..55878ec 100755
--- a/src/parent.js
+++ b/src/parent.js
@@ -11,7 +11,9 @@ SVG.Parent = SVG.invent({
, extend: {
// Returns all child elements
children: function() {
- return this._children || (this._children = [])
+ return SVG.utils.map(this.node.childNodes, function(node) {
+ return SVG.adopt(node)
+ })
}
// Add given element at a position
, add: function(element, i) {
@@ -19,22 +21,10 @@ SVG.Parent = SVG.invent({
/* 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)
- }
-
return this
}
// Basically does the same as `add()` but returns the added element instead
@@ -79,25 +69,22 @@ SVG.Parent = SVG.invent({
}
// 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 children
+ while(this.node.hasChildNodes())
+ this.node.removeChild(this.node.lastChild)
- /* remove defs node */
- if (this._defs)
- this._defs.clear()
+ // Remove defs cache reference
+ delete this._defs
return this
}
- , // Get defs
+ , // Get defs
defs: function() {
return this.doc().defs()
}
diff --git a/src/polyfill.js b/src/polyfill.js
new file mode 100644
index 0000000..3a3c25c
--- /dev/null
+++ b/src/polyfill.js
@@ -0,0 +1,14 @@
+// Add CustomEvent to IE9 and IE10
+if (typeof CustomEvent !== 'function') {
+ // Code from: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
+ function CustomEvent (event, options) {
+ options = options || { bubbles: false, cancelable: false, detail: undefined }
+ var e = document.createEvent('CustomEvent')
+ e.initCustomEvent(event, options.bubbles, options.cancelable, options.detail)
+ return e
+ }
+
+ CustomEvent.prototype = window.Event.prototype
+
+ window.CustomEvent = CustomEvent
+} \ No newline at end of file
diff --git a/src/rbox.js b/src/rbox.js
index 54e08cb..598b3b4 100755
--- a/src/rbox.js
+++ b/src/rbox.js
@@ -10,7 +10,7 @@ SVG.RBox = function(element) {
this.height = 0
if (element) {
- e = element.doc().parent
+ e = element.doc().parent()
zoom = element.doc().viewbox().zoom
/* actual, native bounding box */
@@ -31,7 +31,7 @@ SVG.RBox = function(element) {
/* calculate cumulative zoom from svg documents */
e = element
- while (e = e.parent) {
+ while (e = e.parent()) {
if (e.type == 'svg' && e.viewbox) {
zoom *= e.viewbox().zoom
this.x -= e.x() || 0
diff --git a/src/selector.js b/src/selector.js
index 905e9f9..82aca37 100644
--- a/src/selector.js
+++ b/src/selector.js
@@ -1,5 +1,20 @@
// Method for getting an element by id
SVG.get = function(id) {
var node = document.getElementById(idFromReference(id) || id)
- if (node) return node.instance
-} \ No newline at end of file
+ if (node) return SVG.adopt(node)
+}
+
+// Select elements by query string
+SVG.select = function(query, parent) {
+ return SVG.utils.map((parent || document).querySelectorAll(query), function(node) {
+ return SVG.adopt(node)
+ })
+}
+
+SVG.extend(SVG.Parent, {
+ // Scoped select method
+ select: function(query) {
+ return SVG.select(query, this.node)
+ }
+
+}) \ No newline at end of file
diff --git a/src/spof.js b/src/spof.js
new file mode 100644
index 0000000..cf4fe2f
--- /dev/null
+++ b/src/spof.js
@@ -0,0 +1,31 @@
+// Fix for possible sub-pixel offset. See:
+// https://bugzilla.mozilla.org/show_bug.cgi?id=608812
+SVG.extend(SVG.Doc, {
+ // Callback
+ spof: function() {
+ if (this.doSpof) {
+ var pos = this.node.getScreenCTM()
+
+ if (pos)
+ this
+ .style('left', (-pos.e % 1) + 'px')
+ .style('top', (-pos.f % 1) + 'px')
+ }
+
+ return this
+ }
+
+ // Sub-pixel offset enabler
+, fixSubPixelOffset: function() {
+ var self = this
+
+ // Enable spof
+ this.doSpof = true
+
+ // Make sure sub-pixel offset is fixed every time the window is resized
+ SVG.on(window, 'resize', function() { self.spof() })
+
+ return this.spof()
+ }
+
+}) \ No newline at end of file
diff --git a/src/svg.js b/src/svg.js
index eb0185d..3c25288 100755
--- a/src/svg.js
+++ b/src/svg.js
@@ -67,7 +67,7 @@ SVG.prepare = function(element) {
/* create parser object */
SVG.parser = {
- body: body || element.parent
+ body: body || element.parent()
, draw: draw.style('opacity:0;position:fixed;left:100%;top:100%;overflow:hidden')
, poly: draw.polyline().node
, path: path
diff --git a/src/text.js b/src/text.js
index 1b6bd94..0581f88 100755
--- a/src/text.js
+++ b/src/text.js
@@ -192,7 +192,6 @@ SVG.extend(SVG.Text, SVG.TSpan, {
/* add new tspan and reference */
node.appendChild(tspan.node)
- tspan.parent = this
/* only first level tspans are considered to be "lines" */
if (this instanceof SVG.Text)
diff --git a/src/utilities.js b/src/utilities.js
new file mode 100644
index 0000000..4770f9b
--- /dev/null
+++ b/src/utilities.js
@@ -0,0 +1,14 @@
+SVG.utils = {
+ // Map function
+ map: function(array, block) {
+ var i
+ , il = array.length
+ , result = []
+
+ for (i = 0; i < il; i++)
+ result.push(block(array[i]))
+
+ return result
+ }
+
+} \ No newline at end of file
diff --git a/src/viewbox.js b/src/viewbox.js
index e8736aa..11a7138 100755
--- a/src/viewbox.js
+++ b/src/viewbox.js
@@ -15,13 +15,13 @@ SVG.ViewBox = function(element) {
/* find nearest non-percentual dimensions */
while (width.unit == '%') {
wm *= width.value
- width = new SVG.Number(we instanceof SVG.Doc ? we.parent.offsetWidth : we.parent.width())
- we = we.parent
+ width = new SVG.Number(we instanceof SVG.Doc ? we.parent().offsetWidth : we.parent().width())
+ we = we.parent()
}
while (height.unit == '%') {
hm *= height.value
- height = new SVG.Number(he instanceof SVG.Doc ? he.parent.offsetHeight : he.parent.height())
- he = he.parent
+ height = new SVG.Number(he instanceof SVG.Doc ? he.parent().offsetHeight : he.parent().height())
+ he = he.parent()
}
/* ensure defaults */