SVG.Element = SVG.invent({ // Initialize node create: function(node) { // make stroke value accessible dynamically this._stroke = SVG.defaults.attrs.stroke // initialize data object this.dom = {} // create circular reference if (this.node = node) { this.type = node.nodeName this.node.instance = this // store current attribute value this._stroke = node.getAttribute('stroke') || this._stroke } } // Add class methods , extend: { // Move over x-axis x: function(x) { return this.attr('x', x) } // Move over y-axis , y: function(y) { return this.attr('y', y) } // Move by center over x-axis , cx: function(x) { return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2) } // Move by center over y-axis , cy: function(y) { return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2) } // Move element to given x and y values , move: function(x, y) { return this.x(x).y(y) } // Move element by its center , center: function(x, y) { return this.cx(x).cy(y) } // Set width of element , width: function(width) { return this.attr('width', width) } // Set height of element , height: function(height) { return this.attr('height', height) } // Set element size to given width and height , size: function(width, height) { var p = proportionalSize(this, width, height) return this .width(new SVG.Number(p.width)) .height(new SVG.Number(p.height)) } // Clone element , clone: function(parent) { // clone element and assign new id var clone = assignNewId(this.node.cloneNode(true)) // insert the clone in the given parent or after myself if(parent) parent.add(clone) else this.after(clone) return clone } // Remove element , remove: function() { if (this.parent()) this.parent().removeElement(this) return this } // Replace element , replace: function(element) { this.after(element).remove() return element } // Add element to given container and return self , addTo: function(parent) { return parent.put(this) } // Add element to given container and return container , putIn: function(parent) { return parent.add(this) } // Get / set id , id: function(id) { return this.attr('id', id) } // Checks whether the given point inside the bounding box of the element , inside: function(x, y) { var box = this.bbox() return x > box.x && y > box.y && x < box.x + box.width && y < box.y + box.height } // Show element , show: function() { return this.style('display', '') } // Hide element , hide: function() { return this.style('display', 'none') } // Is element visible? , visible: function() { return this.style('display') != 'none' } // Return id on string conversion , toString: function() { return this.attr('id') } // Return array of classes on the node , classes: function() { var attr = this.attr('class') return attr == null ? [] : attr.trim().split(/\s+/) } // Return true if class exists on the node, false otherwise , hasClass: function(name) { return this.classes().indexOf(name) != -1 } // Add class to the node , addClass: function(name) { if (!this.hasClass(name)) { var array = this.classes() array.push(name) this.attr('class', array.join(' ')) } return this } // Remove class from the node , removeClass: function(name) { if (this.hasClass(name)) { this.attr('class', this.classes().filter(function(c) { return c != name }).join(' ')) } return this } // Toggle the presence of a class on the node , toggleClass: function(name) { return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) } // Get referenced element form attribute value , reference: function(attr) { return SVG.get(this.attr(attr)) } // Returns the parent element instance , parent: function(type) { var parent = this // check for parent if(!parent.node.parentNode) return null // get parent element parent = SVG.adopt(parent.node.parentNode) if(!type) return parent // loop trough ancestors if type is given while(parent && parent.node instanceof SVGElement){ if(typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent parent = SVG.adopt(parent.node.parentNode) } } // Get parent document , doc: function() { return this instanceof SVG.Doc ? this : this.parent(SVG.Doc) } // return array of all ancestors of given type up to the root svg , parents: function(type) { var parents = [], parent = this do{ parent = parent.parent(type) if(!parent || !parent.node) break parents.push(parent) } while(parent.parent) return parents } // matches the element vs a css selector , matches: function(selector){ return matches(this.node, selector) } // Returns the svg node to call native svg methods on it , native: function() { return this.node } // Import raw svg , svg: function(svg) { // create temporary holder var well = document.createElement('svg') // act as a setter if svg is given if (svg && this instanceof SVG.Parent) { // dump raw svg well.innerHTML = '' + svg.replace(/\n/, '').replace(/<(\w+)([^<]+?)\/>/g, '<$1$2>') + '' // transplant nodes for (var i = 0, il = well.firstChild.childNodes.length; i < il; i++) this.node.appendChild(well.firstChild.firstChild) // otherwise act as a getter } else { // create a wrapping svg element in case of partial content well.appendChild(svg = document.createElement('svg')) // write svgjs data to the dom this.writeDataToDom() // insert a copy of this node svg.appendChild(this.node.cloneNode(true)) // return target element return well.innerHTML.replace(/^/, '').replace(/<\/svg>$/, '') } return this } // write svgjs data to the dom , writeDataToDom: function() { // dump variables recursively if(this.each || this.lines){ var fn = this.each ? this : this.lines(); fn.each(function(){ this.writeDataToDom() }) } // remove previously set data this.node.removeAttribute('svgjs:data') if(Object.keys(this.dom).length) this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)) // see #428 return this } // set given data to the elements data property , setData: function(o){ this.dom = o return this } , is: function(obj){ return is(this, obj) } } })