diff options
author | Saivan <savian@me.com> | 2018-11-25 16:21:53 +1300 |
---|---|---|
committer | Saivan <savian@me.com> | 2018-11-25 16:21:53 +1300 |
commit | 62de7d0a1b994b69032a759b796b486e6bc382e3 (patch) | |
tree | 112b19f2903b4dc5b4cf61ebef0d021c6ca2f14d /src/elements | |
parent | 2b37d7ba5b4267b39c86f9aba5fb14a1b376e846 (diff) | |
download | svg.js-62de7d0a1b994b69032a759b796b486e6bc382e3.tar.gz svg.js-62de7d0a1b994b69032a759b796b486e6bc382e3.zip |
Changed the esLint rules to avoid silly ternary operators, and to let code breathe!
This commit modifies some of the eslint rules, to allow our code to be a little bit more
readable. This came about because we had a particularly pesky problem, where the code
was indenting ternary operators. This fixes that, and makes it easy to add new rules
to eslint as we please in the future.
Changes
=======
- Rebuilt the library with new eslint rules
- Changed the eslintrc file to a yaml file by default
Diffstat (limited to 'src/elements')
30 files changed, 1190 insertions, 610 deletions
diff --git a/src/elements/A.js b/src/elements/A.js index 722deed..ee81975 100644 --- a/src/elements/A.js +++ b/src/elements/A.js @@ -4,40 +4,58 @@ import { xlink } from '../modules/core/namespaces.js' import Container from './Container.js' export default class A extends Container { - constructor (node) { - super(nodeOrNew('a', node), node) + + constructor ( node ) { + + super( nodeOrNew( 'a', node ), node ) + } // Link url - to (url) { - return this.attr('href', url, xlink) + to ( url ) { + + return this.attr( 'href', url, xlink ) + } // Link target attribute - target (target) { - return this.attr('target', target) + target ( target ) { + + return this.attr( 'target', target ) + } + } -registerMethods({ +registerMethods( { Container: { // Create a hyperlink element - link: wrapWithAttrCheck(function (url) { - return this.put(new A()).to(url) - }) + link: wrapWithAttrCheck( function ( url ) { + + return this.put( new A() ).to( url ) + + } ) }, Element: { // Create a hyperlink element - linkTo: function (url) { + linkTo: function ( url ) { + var link = new A() - if (typeof url === 'function') { url.call(link, link) } else { - link.to(url) + if ( typeof url === 'function' ) { + + url.call( link, link ) + + } else { + + link.to( url ) + } - return this.parent().put(link).put(this) + return this.parent().put( link ).put( this ) + } } -}) +} ) -register(A) +register( A ) diff --git a/src/elements/Bare.js b/src/elements/Bare.js index a057634..190aa1f 100644 --- a/src/elements/Bare.js +++ b/src/elements/Bare.js @@ -4,28 +4,38 @@ import Container from './Container.js' import { globals } from '../utils/window.js' export default class Bare extends Container { - constructor (node, attrs) { - super(nodeOrNew(node, typeof node === 'string' ? null : node), attrs) + + constructor ( node, attrs ) { + + super( nodeOrNew( node, typeof node === 'string' ? null : node ), attrs ) + } - words (text) { + words ( text ) { + // remove contents - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) + while ( this.node.hasChildNodes() ) { + + this.node.removeChild( this.node.lastChild ) + } // create text node - this.node.appendChild(globals.document.createTextNode(text)) + this.node.appendChild( globals.document.createTextNode( text ) ) return this + } + } -register(Bare) +register( Bare ) -registerMethods('Container', { +registerMethods( 'Container', { // Create an element that is not described by SVG.js - element: wrapWithAttrCheck(function (node) { - return this.put(new Bare(node)) - }) -}) + element: wrapWithAttrCheck( function ( node ) { + + return this.put( new Bare( node ) ) + + } ) +} ) diff --git a/src/elements/Circle.js b/src/elements/Circle.js index 3135ada..5aa969a 100644 --- a/src/elements/Circle.js +++ b/src/elements/Circle.js @@ -10,40 +10,54 @@ import SVGNumber from '../types/SVGNumber.js' import Shape from './Shape.js' export default class Circle extends Shape { - constructor (node) { - super(nodeOrNew('circle', node), node) + + constructor ( node ) { + + super( nodeOrNew( 'circle', node ), node ) + } - radius (r) { - return this.attr('r', r) + radius ( r ) { + + return this.attr( 'r', r ) + } // Radius x value - rx (rx) { - return this.attr('r', rx) + rx ( rx ) { + + return this.attr( 'r', rx ) + } // Alias radius x value - ry (ry) { - return this.rx(ry) + ry ( ry ) { + + return this.rx( ry ) + } - size (size) { - return this.radius(new SVGNumber(size).divide(2)) + size ( size ) { + + return this.radius( new SVGNumber( size ).divide( 2 ) ) + } + } -extend(Circle, { x, y, cx, cy, width, height }) +extend( Circle, { x, y, cx, cy, width, height } ) -registerMethods({ +registerMethods( { Element: { // Create circle element - circle: wrapWithAttrCheck(function (size) { - return this.put(new Circle()) - .size(size) - .move(0, 0) - }) + circle: wrapWithAttrCheck( function ( size ) { + + return this.put( new Circle() ) + .size( size ) + .move( 0, 0 ) + + } ) } -}) +} ) -register(Circle) +register( Circle ) diff --git a/src/elements/ClipPath.js b/src/elements/ClipPath.js index e545baa..199ee5b 100644 --- a/src/elements/ClipPath.js +++ b/src/elements/ClipPath.js @@ -4,54 +4,72 @@ import Container from './Container.js' import baseFind from '../modules/core/selector.js' export default class ClipPath extends Container { - constructor (node) { - super(nodeOrNew('clipPath', node), node) + + constructor ( node ) { + + super( nodeOrNew( 'clipPath', node ), node ) + } // Unclip all clipped elements and remove itself remove () { + // unclip all targets - this.targets().forEach(function (el) { + this.targets().forEach( function ( el ) { + el.unclip() - }) + + } ) // remove clipPath from parent return super.remove() + } targets () { - return baseFind('svg [clip-path*="' + this.id() + '"]') + + return baseFind( 'svg [clip-path*="' + this.id() + '"]' ) + } + } -registerMethods({ +registerMethods( { Container: { // Create clipping element - clip: wrapWithAttrCheck(function () { - return this.defs().put(new ClipPath()) - }) + clip: wrapWithAttrCheck( function () { + + return this.defs().put( new ClipPath() ) + + } ) }, Element: { // Distribute clipPath to svg element - clipWith (element) { + clipWith ( element ) { + // use given clip or create a new one let clipper = element instanceof ClipPath ? element - : this.parent().clip().add(element) + : this.parent().clip().add( element ) // apply mask - return this.attr('clip-path', 'url("#' + clipper.id() + '")') + return this.attr( 'clip-path', 'url("#' + clipper.id() + '")' ) + }, // Unclip element unclip () { - return this.attr('clip-path', null) + + return this.attr( 'clip-path', null ) + }, clipper () { - return this.reference('clip-path') + + return this.reference( 'clip-path' ) + } } -}) +} ) -register(ClipPath) +register( ClipPath ) diff --git a/src/elements/Container.js b/src/elements/Container.js index b47972e..82ee0ae 100644 --- a/src/elements/Container.js +++ b/src/elements/Container.js @@ -2,29 +2,39 @@ import { register } from '../utils/adopter.js' import Element from './Element.js' export default class Container extends Element { - flatten (parent) { - this.each(function () { - if (this instanceof Container) return this.flatten(parent).ungroup(parent) - return this.toParent(parent) - }) + + flatten ( parent ) { + + this.each( function () { + + if ( this instanceof Container ) return this.flatten( parent ).ungroup( parent ) + return this.toParent( parent ) + + } ) // we need this so that the root does not get removed this.node.firstElementChild || this.remove() return this + } - ungroup (parent) { + ungroup ( parent ) { + parent = parent || this.parent() - this.each(function () { - return this.toParent(parent) - }) + this.each( function () { + + return this.toParent( parent ) + + } ) this.remove() return this + } + } -register(Container) +register( Container ) diff --git a/src/elements/Defs.js b/src/elements/Defs.js index 2826611..bcbea01 100644 --- a/src/elements/Defs.js +++ b/src/elements/Defs.js @@ -2,12 +2,24 @@ import { nodeOrNew, register } from '../utils/adopter.js' import Container from './Container.js' export default class Defs extends Container { - constructor (node) { - super(nodeOrNew('defs', node), node) + + constructor ( node ) { + + super( nodeOrNew( 'defs', node ), node ) + + } + + flatten () { + + return this + + } + ungroup () { + + return this + } - flatten () { return this } - ungroup () { return this } } -register(Defs) +register( Defs ) diff --git a/src/elements/Dom.js b/src/elements/Dom.js index 2fcedce..f3ea467 100644 --- a/src/elements/Dom.js +++ b/src/elements/Dom.js @@ -15,217 +15,294 @@ import List from '../types/List.js' import attr from '../modules/core/attr.js' export default class Dom extends EventTarget { - constructor (node, attrs) { - super(node) + + constructor ( node, attrs ) { + + super( node ) this.node = node this.type = node.nodeName - if (attrs && node !== attrs) { - this.attr(attrs) + if ( attrs && node !== attrs ) { + + this.attr( attrs ) + } + } // Add given element at a position - add (element, i) { - element = makeInstance(element) + add ( element, i ) { + + element = makeInstance( element ) + + if ( i == null ) { + + this.node.appendChild( element.node ) + + } else if ( element.node !== this.node.childNodes[i] ) { + + this.node.insertBefore( element.node, this.node.childNodes[i] ) - if (i == null) { - this.node.appendChild(element.node) - } else if (element.node !== this.node.childNodes[i]) { - this.node.insertBefore(element.node, this.node.childNodes[i]) } return this + } // Add element to given container and return self - addTo (parent) { - return makeInstance(parent).put(this) + addTo ( parent ) { + + return makeInstance( parent ).put( this ) + } // Returns all child elements children () { - return new List(map(this.node.children, function (node) { - return adopt(node) - })) + + return new List( map( this.node.children, function ( node ) { + + return adopt( node ) + + } ) ) + } // Remove all elements in this container clear () { + // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) + while ( this.node.hasChildNodes() ) { + + this.node.removeChild( this.node.lastChild ) + } // remove defs reference delete this._defs return this + } // Clone element clone () { + // write dom data to the dom so the clone can pickup the data this.writeDataToDom() // clone element and assign new id - return assignNewId(this.node.cloneNode(true)) + return assignNewId( this.node.cloneNode( true ) ) + } // Iterates over all children and invokes a given block - each (block, deep) { + each ( block, deep ) { + var children = this.children() var i, il - for (i = 0, il = children.length; i < il; i++) { - block.apply(children[i], [i, children]) + for ( i = 0, il = children.length; i < il; i++ ) { + + block.apply( children[i], [ i, children ] ) + + if ( deep ) { + + children[i].each( block, deep ) - if (deep) { - children[i].each(block, deep) } + } return this + } // Get first child first () { - return adopt(this.node.firstChild) + + return adopt( this.node.firstChild ) + } // Get a element at the given index - get (i) { - return adopt(this.node.childNodes[i]) + get ( i ) { + + return adopt( this.node.childNodes[i] ) + } getEventHolder () { + return this.node + } getEventTarget () { + return this.node + } // Checks if the given element is a child - has (element) { - return this.index(element) >= 0 + has ( element ) { + + return this.index( element ) >= 0 + } // Get / set id - id (id) { + id ( id ) { + // generate new id if no id set - if (typeof id === 'undefined' && !this.node.id) { - this.node.id = eid(this.type) + if ( typeof id === 'undefined' && !this.node.id ) { + + this.node.id = eid( this.type ) + } // dont't set directly width this.node.id to make `null` work correctly - return this.attr('id', id) + return this.attr( 'id', id ) + } // Gets index of given element - index (element) { - return [].slice.call(this.node.childNodes).indexOf(element.node) + index ( element ) { + + return [].slice.call( this.node.childNodes ).indexOf( element.node ) + } // Get the last child last () { - return adopt(this.node.lastChild) + + return adopt( this.node.lastChild ) + } // matches the element vs a css selector - matches (selector) { + matches ( selector ) { + const el = this.node - return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector) + return ( el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector ).call( el, selector ) + } // Returns the parent element instance - parent (type) { + parent ( type ) { + var parent = this // check for parent - if (!parent.node.parentNode) return null + if ( !parent.node.parentNode ) return null // get parent element - parent = adopt(parent.node.parentNode) + parent = adopt( parent.node.parentNode ) - if (!type) return parent + if ( !type ) return parent // loop trough ancestors if type is given - while (parent && parent.node instanceof globals.window.SVGElement) { // FIXME: That shouldnt be neccessary - if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent - parent = adopt(parent.node.parentNode) + while ( parent && parent.node instanceof globals.window.SVGElement ) { // FIXME: That shouldnt be neccessary + + if ( typeof type === 'string' ? parent.matches( type ) : parent instanceof type ) return parent + parent = adopt( parent.node.parentNode ) + } + } // Basically does the same as `add()` but returns the added element instead - put (element, i) { - this.add(element, i) + put ( element, i ) { + + this.add( element, i ) return element + } // Add element to given container and return container - putIn (parent) { - return makeInstance(parent).add(this) + putIn ( parent ) { + + return makeInstance( parent ).add( this ) + } // Remove element remove () { - if (this.parent()) { - this.parent().removeElement(this) + + if ( this.parent() ) { + + this.parent().removeElement( this ) + } return this + } // Remove a given child - removeElement (element) { - this.node.removeChild(element.node) + removeElement ( element ) { + + this.node.removeChild( element.node ) return this + } // Replace this with element - replace (element) { - element = makeInstance(element) - this.node.parentNode.replaceChild(element.node, this.node) + replace ( element ) { + + element = makeInstance( element ) + this.node.parentNode.replaceChild( element.node, this.node ) return element + } - round (precision = 2, map) { + round ( precision = 2, map ) { + const factor = 10 ** precision const attrs = this.attr() // If we have no map, build one from attrs - if (!map) { - map = Object.keys(attrs) + if ( !map ) { + + map = Object.keys( attrs ) + } // Holds rounded attributes const newAttrs = {} - map.forEach((key) => { - newAttrs[key] = Math.round(attrs[key] * factor) / factor - }) + map.forEach( ( key ) => { + + newAttrs[key] = Math.round( attrs[key] * factor ) / factor - this.attr(newAttrs) + } ) + + this.attr( newAttrs ) return this + } // Return id on string conversion toString () { + return this.id() + } // Import raw svg - svg (svgOrFn, outerHTML) { + svg ( svgOrFn, outerHTML ) { + var well, len, fragment - if (svgOrFn === false) { + if ( svgOrFn === false ) { + outerHTML = false svgOrFn = null + } // act as getter if no svg string is given - if (svgOrFn == null || typeof svgOrFn === 'function') { + if ( svgOrFn == null || typeof svgOrFn === 'function' ) { + // The default for exports is, that the outerNode is included outerHTML = outerHTML == null ? true : outerHTML @@ -234,38 +311,49 @@ export default class Dom extends EventTarget { let current = this // An export modifier was passed - if (svgOrFn != null) { - current = adopt(current.node.cloneNode(true)) + if ( svgOrFn != null ) { + + current = adopt( current.node.cloneNode( true ) ) // If the user wants outerHTML we need to process this node, too - if (outerHTML) { - let result = svgOrFn(current) + if ( outerHTML ) { + + let result = svgOrFn( current ) current = result || current // The user does not want this node? Well, then he gets nothing - if (result === false) return '' + if ( result === false ) return '' + } // Deep loop through all children and apply modifier - current.each(function () { - let result = svgOrFn(this) + current.each( function () { + + let result = svgOrFn( this ) let _this = result || this // If modifier returns false, discard node - if (result === false) { + if ( result === false ) { + this.remove() - // If modifier returns new node, use it - } else if (result && this !== _this) { - this.replace(_this) + // If modifier returns new node, use it + + } else if ( result && this !== _this ) { + + this.replace( _this ) + } - }, true) + + }, true ) + } // Return outer or inner content return outerHTML ? current.node.outerHTML : current.node.innerHTML + } // Act as setter if we got a string @@ -274,33 +362,41 @@ export default class Dom extends EventTarget { outerHTML = outerHTML == null ? false : outerHTML // Create temporary holder - well = globals.document.createElementNS(ns, 'svg') + well = globals.document.createElementNS( ns, 'svg' ) fragment = globals.document.createDocumentFragment() // Dump raw svg well.innerHTML = svgOrFn // Transplant nodes into the fragment - for (len = well.children.length; len--;) { - fragment.appendChild(well.firstElementChild) + for ( len = well.children.length; len--; ) { + + fragment.appendChild( well.firstElementChild ) + } // Add the whole fragment at once return outerHTML - ? this.replace(fragment) - : this.add(fragment) + ? this.replace( fragment ) + : this.add( fragment ) + } // write svgjs data to the dom writeDataToDom () { + // dump variables recursively - this.each(function () { + this.each( function () { + this.writeDataToDom() - }) + + } ) return this + } + } -extend(Dom, { attr, find }) -register(Dom) +extend( Dom, { attr, find } ) +register( Dom ) diff --git a/src/elements/Element.js b/src/elements/Element.js index 91aa3e0..169c872 100644 --- a/src/elements/Element.js +++ b/src/elements/Element.js @@ -15,11 +15,13 @@ import Dom from './Dom.js' import List from '../types/List.js' import SVGNumber from '../types/SVGNumber.js' -const Svg = getClass(root) +const Svg = getClass( root ) export default class Element extends Dom { - constructor (node, attrs) { - super(node, attrs) + + constructor ( node, attrs ) { + + super( node, attrs ) // initialize data object this.dom = {} @@ -27,135 +29,177 @@ export default class Element extends Dom { // create circular reference this.node.instance = this - if (node.hasAttribute('svgjs:data')) { + if ( node.hasAttribute( 'svgjs:data' ) ) { + // pull svgjs data from the dom (getAttributeNS doesn't work in html5) - this.setData(JSON.parse(node.getAttribute('svgjs:data')) || {}) + this.setData( JSON.parse( node.getAttribute( 'svgjs:data' ) ) || {} ) + } + } // Move element by its center - center (x, y) { - return this.cx(x).cy(y) + center ( x, y ) { + + return this.cx( x ).cy( y ) + } // Move by center over x-axis - cx (x) { - return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2) + cx ( x ) { + + return x == null ? this.x() + this.width() / 2 : this.x( x - this.width() / 2 ) + } // Move by center over y-axis - cy (y) { + cy ( y ) { + return y == null ? this.y() + this.height() / 2 - : this.y(y - this.height() / 2) + : this.y( y - this.height() / 2 ) + } // Get defs defs () { + return this.root().defs() + } // Get parent document root () { - let p = this.parent(Svg) + + let p = this.parent( Svg ) return p && p.root() + } getEventHolder () { + return this + } // Set height of element - height (height) { - return this.attr('height', height) + height ( height ) { + + return this.attr( 'height', height ) + } // Checks whether the given point inside the bounding box of the element - inside (x, y) { + inside ( x, y ) { + let box = this.bbox() - return x > box.x && - y > box.y && - x < box.x + box.width && - y < box.y + box.height + return x > box.x + && y > box.y + && x < box.x + box.width + && y < box.y + box.height + } // Move element to given x and y values - move (x, y) { - return this.x(x).y(y) + move ( x, y ) { + + return this.x( x ).y( y ) + } // return array of all ancestors of given type up to the root svg - parents (until = globals.document) { - until = makeInstance(until) + parents ( until = globals.document ) { + + until = makeInstance( until ) let parents = new List() let parent = this while ( - (parent = parent.parent()) && - parent.node !== until.node && - parent.node !== globals.document + ( parent = parent.parent() ) + && parent.node !== until.node + && parent.node !== globals.document ) { - parents.push(parent) + + parents.push( parent ) + } return parents + } // Get referenced element form attribute value - reference (attr) { - attr = this.attr(attr) - if (!attr) return null + reference ( attr ) { + + attr = this.attr( attr ) + if ( !attr ) return null + + const m = attr.match( reference ) + return m ? makeInstance( m[1] ) : null - const m = attr.match(reference) - return m ? makeInstance(m[1]) : null } // set given data to the elements data property - setData (o) { + setData ( o ) { + this.dom = o return this + } // Set element size to given width and height - size (width, height) { - let p = proportionalSize(this, width, height) + size ( width, height ) { + + let p = proportionalSize( this, width, height ) return this - .width(new SVGNumber(p.width)) - .height(new SVGNumber(p.height)) + .width( new SVGNumber( p.width ) ) + .height( new SVGNumber( p.height ) ) + } // Set width of element - width (width) { - return this.attr('width', width) + width ( width ) { + + return this.attr( 'width', width ) + } // write svgjs data to the dom writeDataToDom () { + // remove previously set data - this.node.removeAttribute('svgjs:data') + this.node.removeAttribute( 'svgjs:data' ) + + if ( Object.keys( this.dom ).length ) { + + this.node.setAttribute( 'svgjs:data', JSON.stringify( this.dom ) ) // see #428 - if (Object.keys(this.dom).length) { - this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)) // see #428 } return super.writeDataToDom() + } // Move over x-axis - x (x) { - return this.attr('x', x) + x ( x ) { + + return this.attr( 'x', x ) + } // Move over y-axis - y (y) { - return this.attr('y', y) + y ( y ) { + + return this.attr( 'y', y ) + } + } -extend(Element, { +extend( Element, { bbox, rbox, point, ctm, screenCTM -}) +} ) -register(Element) +register( Element ) diff --git a/src/elements/Ellipse.js b/src/elements/Ellipse.js index 0350f1f..e1e1fe0 100644 --- a/src/elements/Ellipse.js +++ b/src/elements/Ellipse.js @@ -11,26 +11,34 @@ import Shape from './Shape.js' import * as circled from '../modules/core/circled.js' export default class Ellipse extends Shape { - constructor (node) { - super(nodeOrNew('ellipse', node), node) + + constructor ( node ) { + + super( nodeOrNew( 'ellipse', node ), node ) + } - size (width, height) { - var p = proportionalSize(this, width, height) + size ( width, height ) { + + var p = proportionalSize( this, width, height ) return this - .rx(new SVGNumber(p.width).divide(2)) - .ry(new SVGNumber(p.height).divide(2)) + .rx( new SVGNumber( p.width ).divide( 2 ) ) + .ry( new SVGNumber( p.height ).divide( 2 ) ) + } + } -extend(Ellipse, circled) +extend( Ellipse, circled ) -registerMethods('Container', { +registerMethods( 'Container', { // Create an ellipse - ellipse: wrapWithAttrCheck(function (width, height) { - return this.put(new Ellipse()).size(width, height).move(0, 0) - }) -}) + ellipse: wrapWithAttrCheck( function ( width, height ) { + + return this.put( new Ellipse() ).size( width, height ).move( 0, 0 ) + + } ) +} ) -register(Ellipse) +register( Ellipse ) diff --git a/src/elements/G.js b/src/elements/G.js index 6a93a3f..a72f1fb 100644 --- a/src/elements/G.js +++ b/src/elements/G.js @@ -3,18 +3,24 @@ import { registerMethods } from '../utils/methods.js' import Container from './Container.js' export default class G extends Container { - constructor (node) { - super(nodeOrNew('g', node), node) + + constructor ( node ) { + + super( nodeOrNew( 'g', node ), node ) + } + } -registerMethods({ +registerMethods( { Element: { // Create a group element - group: wrapWithAttrCheck(function () { - return this.put(new G()) - }) + group: wrapWithAttrCheck( function () { + + return this.put( new G() ) + + } ) } -}) +} ) -register(G) +register( G ) diff --git a/src/elements/Gradient.js b/src/elements/Gradient.js index 23de97d..7116fc8 100644 --- a/src/elements/Gradient.js +++ b/src/elements/Gradient.js @@ -12,71 +12,95 @@ import baseFind from '../modules/core/selector.js' import * as gradiented from '../modules/core/gradiented.js' export default class Gradient extends Container { - constructor (type, attrs) { + + constructor ( type, attrs ) { + super( - nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type), + nodeOrNew( type + 'Gradient', typeof type === 'string' ? null : type ), attrs ) + } // Add a color stop - stop (offset, color, opacity) { - return this.put(new Stop()).update(offset, color, opacity) + stop ( offset, color, opacity ) { + + return this.put( new Stop() ).update( offset, color, opacity ) + } // Update gradient - update (block) { + update ( block ) { + // remove all stops this.clear() // invoke passed block - if (typeof block === 'function') { - block.call(this, this) + if ( typeof block === 'function' ) { + + block.call( this, this ) + } return this + } // Return the fill id url () { + return 'url(#' + this.id() + ')' + } // Alias string convertion to fill toString () { + return this.url() + } // custom attr to handle transform - attr (a, b, c) { - if (a === 'transform') a = 'gradientTransform' - return super.attr(a, b, c) + attr ( a, b, c ) { + + if ( a === 'transform' ) a = 'gradientTransform' + return super.attr( a, b, c ) + } targets () { - return baseFind('svg [fill*="' + this.id() + '"]') + + return baseFind( 'svg [fill*="' + this.id() + '"]' ) + } bbox () { + return new Box() + } + } -extend(Gradient, gradiented) +extend( Gradient, gradiented ) -registerMethods({ +registerMethods( { Container: { // Create gradient element in defs - gradient: wrapWithAttrCheck(function (type, block) { - return this.defs().gradient(type, block) - }) + gradient: wrapWithAttrCheck( function ( type, block ) { + + return this.defs().gradient( type, block ) + + } ) }, // define gradient Defs: { - gradient: wrapWithAttrCheck(function (type, block) { - return this.put(new Gradient(type)).update(block) - }) + gradient: wrapWithAttrCheck( function ( type, block ) { + + return this.put( new Gradient( type ) ).update( block ) + + } ) } -}) +} ) -register(Gradient) +register( Gradient ) diff --git a/src/elements/HtmlNode.js b/src/elements/HtmlNode.js index 009b122..d2299ed 100644 --- a/src/elements/HtmlNode.js +++ b/src/elements/HtmlNode.js @@ -3,4 +3,4 @@ import Dom from './Dom.js' export default class HtmlNode extends Dom {} -register(HtmlNode) +register( HtmlNode ) diff --git a/src/elements/Image.js b/src/elements/Image.js index 8f27470..4945271 100644 --- a/src/elements/Image.js +++ b/src/elements/Image.js @@ -9,69 +9,99 @@ import Shape from './Shape.js' import { globals } from '../utils/window.js' export default class Image extends Shape { - constructor (node) { - super(nodeOrNew('image', node), node) + + constructor ( node ) { + + super( nodeOrNew( 'image', node ), node ) + } // (re)load image - load (url, callback) { - if (!url) return this + load ( url, callback ) { + + if ( !url ) return this var img = new globals.window.Image() - on(img, 'load', function (e) { - var p = this.parent(Pattern) + on( img, 'load', function ( e ) { + + var p = this.parent( Pattern ) // ensure image size - if (this.width() === 0 && this.height() === 0) { - this.size(img.width, img.height) + if ( this.width() === 0 && this.height() === 0 ) { + + this.size( img.width, img.height ) + } - if (p instanceof Pattern) { + if ( p instanceof Pattern ) { + // ensure pattern size if not set - if (p.width() === 0 && p.height() === 0) { - p.size(this.width(), this.height()) + if ( p.width() === 0 && p.height() === 0 ) { + + p.size( this.width(), this.height() ) + } + } - if (typeof callback === 'function') { - callback.call(this, e) + if ( typeof callback === 'function' ) { + + callback.call( this, e ) + } - }, this) - on(img, 'load error', function () { + }, this ) + + on( img, 'load error', function () { + // dont forget to unbind memory leaking events - off(img) - }) + off( img ) + + } ) + + return this.attr( 'href', ( img.src = url ), xlink ) - return this.attr('href', (img.src = url), xlink) } + } -registerAttrHook(function (attr, val, _this) { +registerAttrHook( function ( attr, val, _this ) { + // convert image fill and stroke to patterns - if (attr === 'fill' || attr === 'stroke') { - if (isImage.test(val)) { - val = _this.root().defs().image(val) + if ( attr === 'fill' || attr === 'stroke' ) { + + if ( isImage.test( val ) ) { + + val = _this.root().defs().image( val ) + } + } - if (val instanceof Image) { - val = _this.root().defs().pattern(0, 0, (pattern) => { - pattern.add(val) - }) + if ( val instanceof Image ) { + + val = _this.root().defs().pattern( 0, 0, ( pattern ) => { + + pattern.add( val ) + + } ) + } return val -}) -registerMethods({ +} ) + +registerMethods( { Container: { // create image element, load image and set its size - image: wrapWithAttrCheck(function (source, callback) { - return this.put(new Image()).size(0, 0).load(source, callback) - }) + image: wrapWithAttrCheck( function ( source, callback ) { + + return this.put( new Image() ).size( 0, 0 ).load( source, callback ) + + } ) } -}) +} ) -register(Image) +register( Image ) diff --git a/src/elements/Line.js b/src/elements/Line.js index 99e7497..123f2bb 100644 --- a/src/elements/Line.js +++ b/src/elements/Line.js @@ -11,58 +11,78 @@ import Shape from './Shape.js' import * as pointed from '../modules/core/pointed.js' export default class Line extends Shape { + // Initialize node - constructor (node) { - super(nodeOrNew('line', node), node) + constructor ( node ) { + + super( nodeOrNew( 'line', node ), node ) + } // Get array array () { - return new PointArray([ - [ this.attr('x1'), this.attr('y1') ], - [ this.attr('x2'), this.attr('y2') ] - ]) + + return new PointArray( [ + [ this.attr( 'x1' ), this.attr( 'y1' ) ], + [ this.attr( 'x2' ), this.attr( 'y2' ) ] + ] ) + } // Overwrite native plot() method - plot (x1, y1, x2, y2) { - if (x1 == null) { + plot ( x1, y1, x2, y2 ) { + + if ( x1 == null ) { + return this.array() - } else if (typeof y1 !== 'undefined') { + + } else if ( typeof y1 !== 'undefined' ) { + x1 = { x1: x1, y1: y1, x2: x2, y2: y2 } + } else { - x1 = new PointArray(x1).toLine() + + x1 = new PointArray( x1 ).toLine() + } - return this.attr(x1) + return this.attr( x1 ) + } // Move by left top corner - move (x, y) { - return this.attr(this.array().move(x, y).toLine()) + move ( x, y ) { + + return this.attr( this.array().move( x, y ).toLine() ) + } // Set element size to given width and height - size (width, height) { - var p = proportionalSize(this, width, height) - return this.attr(this.array().size(p.width, p.height).toLine()) + size ( width, height ) { + + var p = proportionalSize( this, width, height ) + return this.attr( this.array().size( p.width, p.height ).toLine() ) + } + } -extend(Line, pointed) +extend( Line, pointed ) -registerMethods({ +registerMethods( { Container: { // Create a line element - line: wrapWithAttrCheck(function (...args) { + line: wrapWithAttrCheck( function ( ...args ) { + // make sure plot is called as a setter // x1 is not necessarily a number, it can also be an array, a string and a PointArray return Line.prototype.plot.apply( - this.put(new Line()) - , args[0] != null ? args : [0, 0, 0, 0] + this.put( new Line() ) + , args[0] != null ? args : [ 0, 0, 0, 0 ] ) - }) + + } ) } -}) +} ) -register(Line) +register( Line ) diff --git a/src/elements/Marker.js b/src/elements/Marker.js index d40d13b..1054987 100644 --- a/src/elements/Marker.js +++ b/src/elements/Marker.js @@ -3,79 +3,103 @@ import { registerMethods } from '../utils/methods.js' import Container from './Container.js' export default class Marker extends Container { + // Initialize node - constructor (node) { - super(nodeOrNew('marker', node), node) + constructor ( node ) { + + super( nodeOrNew( 'marker', node ), node ) + } // Set width of element - width (width) { - return this.attr('markerWidth', width) + width ( width ) { + + return this.attr( 'markerWidth', width ) + } // Set height of element - height (height) { - return this.attr('markerHeight', height) + height ( height ) { + + return this.attr( 'markerHeight', height ) + } // Set marker refX and refY - ref (x, y) { - return this.attr('refX', x).attr('refY', y) + ref ( x, y ) { + + return this.attr( 'refX', x ).attr( 'refY', y ) + } // Update marker - update (block) { + update ( block ) { + // remove all content this.clear() // invoke passed block - if (typeof block === 'function') { block.call(this, this) } + if ( typeof block === 'function' ) { + + block.call( this, this ) + + } return this + } // Return the fill id toString () { + return 'url(#' + this.id() + ')' + } + } -registerMethods({ +registerMethods( { Container: { - marker (...args) { + marker ( ...args ) { + // Create marker element in defs - return this.defs().marker(...args) + return this.defs().marker( ...args ) + } }, Defs: { // Create marker - marker: wrapWithAttrCheck(function (width, height, block) { + marker: wrapWithAttrCheck( function ( width, height, block ) { + // Set default viewbox to match the width and height, set ref to cx and cy and set orient to auto - return this.put(new Marker()) - .size(width, height) - .ref(width / 2, height / 2) - .viewbox(0, 0, width, height) - .attr('orient', 'auto') - .update(block) - }) + return this.put( new Marker() ) + .size( width, height ) + .ref( width / 2, height / 2 ) + .viewbox( 0, 0, width, height ) + .attr( 'orient', 'auto' ) + .update( block ) + + } ) }, marker: { // Create and attach markers - marker (marker, width, height, block) { - var attr = ['marker'] + marker ( marker, width, height, block ) { + + var attr = [ 'marker' ] // Build attribute name - if (marker !== 'all') attr.push(marker) - attr = attr.join('-') + if ( marker !== 'all' ) attr.push( marker ) + attr = attr.join( '-' ) // Set marker attribute marker = arguments[1] instanceof Marker ? arguments[1] - : this.defs().marker(width, height, block) + : this.defs().marker( width, height, block ) + + return this.attr( attr, marker ) - return this.attr(attr, marker) } } -}) +} ) -register(Marker) +register( Marker ) diff --git a/src/elements/Mask.js b/src/elements/Mask.js index 8dfffd6..523b9de 100644 --- a/src/elements/Mask.js +++ b/src/elements/Mask.js @@ -4,54 +4,72 @@ import Container from './Container.js' import baseFind from '../modules/core/selector.js' export default class Mask extends Container { + // Initialize node - constructor (node) { - super(nodeOrNew('mask', node), node) + constructor ( node ) { + + super( nodeOrNew( 'mask', node ), node ) + } // Unmask all masked elements and remove itself remove () { + // unmask all targets - this.targets().forEach(function (el) { + this.targets().forEach( function ( el ) { + el.unmask() - }) + + } ) // remove mask from parent return super.remove() + } targets () { - return baseFind('svg [mask*="' + this.id() + '"]') + + return baseFind( 'svg [mask*="' + this.id() + '"]' ) + } + } -registerMethods({ +registerMethods( { Container: { - mask: wrapWithAttrCheck(function () { - return this.defs().put(new Mask()) - }) + mask: wrapWithAttrCheck( function () { + + return this.defs().put( new Mask() ) + + } ) }, Element: { // Distribute mask to svg element - maskWith (element) { + maskWith ( element ) { + // use given mask or create a new one var masker = element instanceof Mask ? element - : this.parent().mask().add(element) + : this.parent().mask().add( element ) // apply mask - return this.attr('mask', 'url("#' + masker.id() + '")') + return this.attr( 'mask', 'url("#' + masker.id() + '")' ) + }, // Unmask element unmask () { - return this.attr('mask', null) + + return this.attr( 'mask', null ) + }, masker () { - return this.reference('mask') + + return this.reference( 'mask' ) + } } -}) +} ) -register(Mask) +register( Mask ) diff --git a/src/elements/Path.js b/src/elements/Path.js index dc27320..1fe5661 100644 --- a/src/elements/Path.js +++ b/src/elements/Path.js @@ -6,76 +6,102 @@ import Shape from './Shape.js' import baseFind from '../modules/core/selector.js' export default class Path extends Shape { + // Initialize node - constructor (node) { - super(nodeOrNew('path', node), node) + constructor ( node ) { + + super( nodeOrNew( 'path', node ), node ) + } // Get array array () { - return this._array || (this._array = new PathArray(this.attr('d'))) + + return this._array || ( this._array = new PathArray( this.attr( 'd' ) ) ) + } // Plot new path - plot (d) { - return (d == null) ? this.array() - : this.clear().attr('d', typeof d === 'string' ? d : (this._array = new PathArray(d))) + plot ( d ) { + + return ( d == null ) ? this.array() + : this.clear().attr( 'd', typeof d === 'string' ? d : ( this._array = new PathArray( d ) ) ) + } // Clear array cache clear () { + delete this._array return this + } // Move by left top corner - move (x, y) { - return this.attr('d', this.array().move(x, y)) + move ( x, y ) { + + return this.attr( 'd', this.array().move( x, y ) ) + } // Move by left top corner over x-axis - x (x) { - return x == null ? this.bbox().x : this.move(x, this.bbox().y) + x ( x ) { + + return x == null ? this.bbox().x : this.move( x, this.bbox().y ) + } // Move by left top corner over y-axis - y (y) { - return y == null ? this.bbox().y : this.move(this.bbox().x, y) + y ( y ) { + + return y == null ? this.bbox().y : this.move( this.bbox().x, y ) + } // Set element size to given width and height - size (width, height) { - var p = proportionalSize(this, width, height) - return this.attr('d', this.array().size(p.width, p.height)) + size ( width, height ) { + + var p = proportionalSize( this, width, height ) + return this.attr( 'd', this.array().size( p.width, p.height ) ) + } // Set width of element - width (width) { - return width == null ? this.bbox().width : this.size(width, this.bbox().height) + width ( width ) { + + return width == null ? this.bbox().width : this.size( width, this.bbox().height ) + } // Set height of element - height (height) { - return height == null ? this.bbox().height : this.size(this.bbox().width, height) + height ( height ) { + + return height == null ? this.bbox().height : this.size( this.bbox().width, height ) + } targets () { - return baseFind('svg textpath [href*="' + this.id() + '"]') + + return baseFind( 'svg textpath [href*="' + this.id() + '"]' ) + } + } // Define morphable array Path.prototype.MorphArray = PathArray // Add parent method -registerMethods({ +registerMethods( { Container: { // Create a wrapped path element - path: wrapWithAttrCheck(function (d) { + path: wrapWithAttrCheck( function ( d ) { + // make sure plot is called as a setter - return this.put(new Path()).plot(d || new PathArray()) - }) + return this.put( new Path() ).plot( d || new PathArray() ) + + } ) } -}) +} ) -register(Path) +register( Path ) diff --git a/src/elements/Pattern.js b/src/elements/Pattern.js index 6dd4e01..6f7897b 100644 --- a/src/elements/Pattern.js +++ b/src/elements/Pattern.js @@ -5,67 +5,89 @@ import Container from './Container.js' import baseFind from '../modules/core/selector.js' export default class Pattern extends Container { + // Initialize node - constructor (node) { - super(nodeOrNew('pattern', node), node) + constructor ( node ) { + + super( nodeOrNew( 'pattern', node ), node ) + } // Return the fill id url () { + return 'url(#' + this.id() + ')' + } // Update pattern by rebuilding - update (block) { + update ( block ) { + // remove content this.clear() // invoke passed block - if (typeof block === 'function') { - block.call(this, this) + if ( typeof block === 'function' ) { + + block.call( this, this ) + } return this + } // Alias string convertion to fill toString () { + return this.url() + } // custom attr to handle transform - attr (a, b, c) { - if (a === 'transform') a = 'patternTransform' - return super.attr(a, b, c) + attr ( a, b, c ) { + + if ( a === 'transform' ) a = 'patternTransform' + return super.attr( a, b, c ) + } targets () { - return baseFind('svg [fill*="' + this.id() + '"]') + + return baseFind( 'svg [fill*="' + this.id() + '"]' ) + } bbox () { + return new Box() + } + } -registerMethods({ +registerMethods( { Container: { // Create pattern element in defs - pattern (...args) { - return this.defs().pattern(...args) + pattern ( ...args ) { + + return this.defs().pattern( ...args ) + } }, Defs: { - pattern: wrapWithAttrCheck(function (width, height, block) { - return this.put(new Pattern()).update(block).attr({ + pattern: wrapWithAttrCheck( function ( width, height, block ) { + + return this.put( new Pattern() ).update( block ).attr( { x: 0, y: 0, width: width, height: height, patternUnits: 'userSpaceOnUse' - }) - }) + } ) + + } ) } -}) +} ) -register(Pattern) +register( Pattern ) diff --git a/src/elements/Polygon.js b/src/elements/Polygon.js index afa5f31..2288b75 100644 --- a/src/elements/Polygon.js +++ b/src/elements/Polygon.js @@ -11,22 +11,28 @@ import * as pointed from '../modules/core/pointed.js' import * as poly from '../modules/core/poly.js' export default class Polygon extends Shape { + // Initialize node - constructor (node) { - super(nodeOrNew('polygon', node), node) + constructor ( node ) { + + super( nodeOrNew( 'polygon', node ), node ) + } + } -registerMethods({ +registerMethods( { Container: { // Create a wrapped polygon element - polygon: wrapWithAttrCheck(function (p) { + polygon: wrapWithAttrCheck( function ( p ) { + // make sure plot is called as a setter - return this.put(new Polygon()).plot(p || new PointArray()) - }) + return this.put( new Polygon() ).plot( p || new PointArray() ) + + } ) } -}) +} ) -extend(Polygon, pointed) -extend(Polygon, poly) -register(Polygon) +extend( Polygon, pointed ) +extend( Polygon, poly ) +register( Polygon ) diff --git a/src/elements/Polyline.js b/src/elements/Polyline.js index 5897295..3749c93 100644 --- a/src/elements/Polyline.js +++ b/src/elements/Polyline.js @@ -11,22 +11,28 @@ import * as pointed from '../modules/core/pointed.js' import * as poly from '../modules/core/poly.js' export default class Polyline extends Shape { + // Initialize node - constructor (node) { - super(nodeOrNew('polyline', node), node) + constructor ( node ) { + + super( nodeOrNew( 'polyline', node ), node ) + } + } -registerMethods({ +registerMethods( { Container: { // Create a wrapped polygon element - polyline: wrapWithAttrCheck(function (p) { + polyline: wrapWithAttrCheck( function ( p ) { + // make sure plot is called as a setter - return this.put(new Polyline()).plot(p || new PointArray()) - }) + return this.put( new Polyline() ).plot( p || new PointArray() ) + + } ) } -}) +} ) -extend(Polyline, pointed) -extend(Polyline, poly) -register(Polyline) +extend( Polyline, pointed ) +extend( Polyline, poly ) +register( Polyline ) diff --git a/src/elements/Rect.js b/src/elements/Rect.js index 6e161c9..465b52b 100644 --- a/src/elements/Rect.js +++ b/src/elements/Rect.js @@ -9,21 +9,27 @@ import { rx, ry } from '../modules/core/circled.js' import Shape from './Shape.js' export default class Rect extends Shape { + // Initialize node - constructor (node) { - super(nodeOrNew('rect', node), node) + constructor ( node ) { + + super( nodeOrNew( 'rect', node ), node ) + } + } -extend(Rect, { rx, ry }) +extend( Rect, { rx, ry } ) -registerMethods({ +registerMethods( { Container: { // Create a rect element - rect: wrapWithAttrCheck(function (width, height) { - return this.put(new Rect()).size(width, height) - }) + rect: wrapWithAttrCheck( function ( width, height ) { + + return this.put( new Rect() ).size( width, height ) + + } ) } -}) +} ) -register(Rect) +register( Rect ) diff --git a/src/elements/Shape.js b/src/elements/Shape.js index cdddc60..0d5a5b0 100644 --- a/src/elements/Shape.js +++ b/src/elements/Shape.js @@ -3,4 +3,4 @@ import Element from './Element.js' export default class Shape extends Element {} -register(Shape) +register( Shape ) diff --git a/src/elements/Stop.js b/src/elements/Stop.js index 9a5acaa..8838923 100644 --- a/src/elements/Stop.js +++ b/src/elements/Stop.js @@ -3,27 +3,35 @@ import Element from './Element.js' import SVGNumber from '../types/SVGNumber.js' export default class Stop extends Element { - constructor (node) { - super(nodeOrNew('stop', node), node) + + constructor ( node ) { + + super( nodeOrNew( 'stop', node ), node ) + } // add color stops - update (o) { - if (typeof o === 'number' || o instanceof SVGNumber) { + update ( o ) { + + if ( typeof o === 'number' || o instanceof SVGNumber ) { + o = { offset: arguments[0], color: arguments[1], opacity: arguments[2] } + } // 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 SVGNumber(o.offset)) + 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 SVGNumber( o.offset ) ) return this + } + } -register(Stop) +register( Stop ) diff --git a/src/elements/Style.js b/src/elements/Style.js index 50ec50e..643f356 100644 --- a/src/elements/Style.js +++ b/src/elements/Style.js @@ -3,51 +3,69 @@ import { registerMethods } from '../utils/methods.js' import { unCamelCase } from '../utils/utils.js' import Element from './Element.js' -function cssRule (selector, rule) { - if (!selector) return '' - if (!rule) return selector +function cssRule ( selector, rule ) { + + if ( !selector ) return '' + if ( !rule ) return selector var ret = selector + '{' - for (var i in rule) { - ret += unCamelCase(i) + ':' + rule[i] + ';' + for ( var i in rule ) { + + ret += unCamelCase( i ) + ':' + rule[i] + ';' + } ret += '}' return ret + } export default class Style extends Element { - constructor (node) { - super(nodeOrNew('style', node), node) + + constructor ( node ) { + + super( nodeOrNew( 'style', node ), node ) + } - words (w) { - this.node.textContent += (w || '') + words ( w ) { + + this.node.textContent += ( w || '' ) return this + } - font (name, src, params = {}) { - return this.rule('@font-face', { + font ( name, src, params = {} ) { + + return this.rule( '@font-face', { fontFamily: name, src: src, ...params - }) + } ) + } - rule (selector, obj) { - return this.words(cssRule(selector, obj)) + rule ( selector, obj ) { + + return this.words( cssRule( selector, obj ) ) + } + } -registerMethods('Dom', { - style: wrapWithAttrCheck(function (selector, obj) { - return this.put(new Style()).rule(selector, obj) - }), - fontface: wrapWithAttrCheck(function (name, src, params) { - return this.put(new Style()).font(name, src, params) - }) -}) +registerMethods( 'Dom', { + style: wrapWithAttrCheck( function ( selector, obj ) { + + return this.put( new Style() ).rule( selector, obj ) + + } ), + fontface: wrapWithAttrCheck( function ( name, src, params ) { + + return this.put( new Style() ).font( name, src, params ) + + } ) +} ) -register(Style) +register( Style ) diff --git a/src/elements/Svg.js b/src/elements/Svg.js index 6172454..1326900 100644 --- a/src/elements/Svg.js +++ b/src/elements/Svg.js @@ -11,68 +11,90 @@ import Defs from './Defs.js' import { globals } from '../utils/window.js' export default class Svg extends Container { - constructor (node) { - super(nodeOrNew('svg', node), node) + + constructor ( node ) { + + super( nodeOrNew( 'svg', node ), node ) this.namespace() + } isRoot () { - return !this.node.parentNode || - !(this.node.parentNode instanceof globals.window.SVGElement) || - this.node.parentNode.nodeName === '#document' + + return !this.node.parentNode + || !( this.node.parentNode instanceof globals.window.SVGElement ) + || this.node.parentNode.nodeName === '#document' + } // Check if this is a root svg // If not, call docs from this element root () { - if (this.isRoot()) return this + + if ( this.isRoot() ) return this return super.root() + } // Add namespaces namespace () { - if (!this.isRoot()) return this.root().namespace() + + if ( !this.isRoot() ) return this.root().namespace() return this - .attr({ xmlns: ns, version: '1.1' }) - .attr('xmlns:xlink', xlink, xmlns) - .attr('xmlns:svgjs', svgjs, xmlns) + .attr( { xmlns: ns, version: '1.1' } ) + .attr( 'xmlns:xlink', xlink, xmlns ) + .attr( 'xmlns:svgjs', svgjs, xmlns ) + } // Creates and returns defs element defs () { - if (!this.isRoot()) return this.root().defs() - return adopt(this.node.getElementsByTagName('defs')[0]) || - this.put(new Defs()) + if ( !this.isRoot() ) return this.root().defs() + + return adopt( this.node.getElementsByTagName( 'defs' )[0] ) + || this.put( new Defs() ) + } // custom parent method - parent (type) { - if (this.isRoot()) { + parent ( type ) { + + if ( this.isRoot() ) { + return this.node.parentNode.nodeName === '#document' ? null - : adopt(this.node.parentNode) + : adopt( this.node.parentNode ) + } - return super.parent(type) + return super.parent( type ) + } clear () { + // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) + while ( this.node.hasChildNodes() ) { + + this.node.removeChild( this.node.lastChild ) + } return this + } + } -registerMethods({ +registerMethods( { Container: { // Create nested svg document - nested: wrapWithAttrCheck(function () { - return this.put(new Svg()) - }) + nested: wrapWithAttrCheck( function () { + + return this.put( new Svg() ) + + } ) } -}) +} ) -register(Svg, 'Svg', true) +register( Svg, 'Svg', true ) diff --git a/src/elements/Symbol.js b/src/elements/Symbol.js index f44125c..577d1f1 100644 --- a/src/elements/Symbol.js +++ b/src/elements/Symbol.js @@ -3,18 +3,24 @@ import { registerMethods } from '../utils/methods.js' import Container from './Container.js' export default class Symbol extends Container { + // Initialize node - constructor (node) { - super(nodeOrNew('symbol', node), node) + constructor ( node ) { + + super( nodeOrNew( 'symbol', node ), node ) + } + } -registerMethods({ +registerMethods( { Container: { - symbol: wrapWithAttrCheck(function () { - return this.put(new Symbol()) - }) + symbol: wrapWithAttrCheck( function () { + + return this.put( new Symbol() ) + + } ) } -}) +} ) -register(Symbol) +register( Symbol ) diff --git a/src/elements/Text.js b/src/elements/Text.js index db9c2ee..a981d73 100644 --- a/src/elements/Text.js +++ b/src/elements/Text.js @@ -13,175 +13,233 @@ import { globals } from '../utils/window.js' import * as textable from '../modules/core/textable.js' export default class Text extends Shape { + // Initialize node - constructor (node) { - super(nodeOrNew('text', node), node) + constructor ( node ) { + + super( nodeOrNew( 'text', node ), node ) - this.dom.leading = new SVGNumber(1.3) // store leading value for rebuilding + this.dom.leading = new SVGNumber( 1.3 ) // store leading value for rebuilding this._rebuild = true // enable automatic updating of dy values this._build = false // disable build mode for adding multiple lines // set default font - this.attr('font-family', attrs['font-family']) + this.attr( 'font-family', attrs['font-family'] ) + } // Move over x-axis - x (x) { + x ( x ) { + // act as getter - if (x == null) { - return this.attr('x') + if ( x == null ) { + + return this.attr( 'x' ) + } - return this.attr('x', x) + return this.attr( 'x', x ) + } // Move over y-axis - y (y) { - var oy = this.attr('y') + y ( y ) { + + var oy = this.attr( 'y' ) var o = typeof oy === 'number' ? oy - this.bbox().y : 0 // act as getter - if (y == null) { + if ( y == null ) { + return typeof oy === 'number' ? oy - o : oy + } - return this.attr('y', typeof y === 'number' ? y + o : y) + return this.attr( 'y', typeof y === 'number' ? y + o : y ) + } // Move center over x-axis - cx (x) { - return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2) + cx ( x ) { + + return x == null ? this.bbox().cx : this.x( x - this.bbox().width / 2 ) + } // Move center over y-axis - cy (y) { - return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2) + cy ( y ) { + + return y == null ? this.bbox().cy : this.y( y - this.bbox().height / 2 ) + } // Set the text content - text (text) { + text ( text ) { + // act as getter - if (text === undefined) { + if ( text === undefined ) { + var children = this.node.childNodes var firstLine = 0 text = '' - for (var i = 0, len = children.length; i < len; ++i) { + for ( var i = 0, len = children.length; i < len; ++i ) { + // skip textPaths - they are no lines - if (children[i].nodeName === 'textPath') { - if (i === 0) firstLine = 1 + if ( children[i].nodeName === 'textPath' ) { + + if ( i === 0 ) firstLine = 1 continue + } // add newline if its not the first child and newLined is set to true - if (i !== firstLine && children[i].nodeType !== 3 && adopt(children[i]).dom.newLined === true) { + if ( i !== firstLine && children[i].nodeType !== 3 && adopt( children[i] ).dom.newLined === true ) { + text += '\n' + } // add content of this node text += children[i].textContent + } return text + } // remove existing content - this.clear().build(true) + this.clear().build( true ) + + if ( typeof text === 'function' ) { - if (typeof text === 'function') { // call block - text.call(this, this) + text.call( this, this ) + } else { + // store text and make sure text is not blank - text = text.split('\n') + text = text.split( '\n' ) // build new lines - for (var j = 0, jl = text.length; j < jl; j++) { - this.tspan(text[j]).newLine() + for ( var j = 0, jl = text.length; j < jl; j++ ) { + + this.tspan( text[j] ).newLine() + } + } // disable build mode and rebuild lines - return this.build(false).rebuild() + return this.build( false ).rebuild() + } // Set / get leading - leading (value) { + leading ( value ) { + // act as getter - if (value == null) { + if ( value == null ) { + return this.dom.leading + } // act as setter - this.dom.leading = new SVGNumber(value) + this.dom.leading = new SVGNumber( value ) return this.rebuild() + } // Rebuild appearance type - rebuild (rebuild) { + rebuild ( rebuild ) { + // store new rebuild flag if given - if (typeof rebuild === 'boolean') { + if ( typeof rebuild === 'boolean' ) { + this._rebuild = rebuild + } // define position of all lines - if (this._rebuild) { + if ( this._rebuild ) { + var self = this var blankLineOffset = 0 var leading = this.dom.leading - this.each(function () { - var fontSize = globals.window.getComputedStyle(this.node) - .getPropertyValue('font-size') - var dy = leading * new SVGNumber(fontSize) + this.each( function () { + + var fontSize = globals.window.getComputedStyle( this.node ) + .getPropertyValue( 'font-size' ) + var dy = leading * new SVGNumber( fontSize ) + + if ( this.dom.newLined ) { - if (this.dom.newLined) { - this.attr('x', self.attr('x')) + this.attr( 'x', self.attr( 'x' ) ) + + if ( this.text() === '\n' ) { - if (this.text() === '\n') { blankLineOffset += dy + } else { - this.attr('dy', dy + blankLineOffset) + + this.attr( 'dy', dy + blankLineOffset ) blankLineOffset = 0 + } + } - }) - this.fire('rebuild') + } ) + + this.fire( 'rebuild' ) + } return this + } // Enable / disable build mode - build (build) { + build ( build ) { + this._build = !!build return this + } // overwrite method from parent to set data properly - setData (o) { + setData ( o ) { + this.dom = o - this.dom.leading = new SVGNumber(o.leading || 1.3) + this.dom.leading = new SVGNumber( o.leading || 1.3 ) return this + } + } -extend(Text, textable) +extend( Text, textable ) -registerMethods({ +registerMethods( { Container: { // Create text element - text: wrapWithAttrCheck(function (text) { - return this.put(new Text()).text(text) - }), + text: wrapWithAttrCheck( function ( text ) { + + return this.put( new Text() ).text( text ) + + } ), // Create plain text element - plain: wrapWithAttrCheck(function (text) { - return this.put(new Text()).plain(text) - }) + plain: wrapWithAttrCheck( function ( text ) { + + return this.put( new Text() ).plain( text ) + + } ) } -}) +} ) -register(Text) +register( Text ) diff --git a/src/elements/TextPath.js b/src/elements/TextPath.js index 91c48ae..af89ef7 100644 --- a/src/elements/TextPath.js +++ b/src/elements/TextPath.js @@ -7,80 +7,106 @@ import Text from './Text.js' import baseFind from '../modules/core/selector.js' export default class TextPath extends Text { + // Initialize node - constructor (node) { - super(nodeOrNew('textPath', node), node) + constructor ( node ) { + + super( nodeOrNew( 'textPath', node ), node ) + } // return the array of the path track element array () { + var track = this.track() return track ? track.array() : null + } // Plot path if any - plot (d) { + plot ( d ) { + var track = this.track() var pathArray = null - if (track) { - pathArray = track.plot(d) + if ( track ) { + + pathArray = track.plot( d ) + } - return (d == null) ? pathArray : this + return ( d == null ) ? pathArray : this + } // Get the path element track () { - return this.reference('href') + + return this.reference( 'href' ) + } + } -registerMethods({ +registerMethods( { Container: { - textPath: wrapWithAttrCheck(function (text, path) { - return this.defs().path(path).text(text).addTo(this) - }) + textPath: wrapWithAttrCheck( function ( text, path ) { + + return this.defs().path( path ).text( text ).addTo( this ) + + } ) }, Text: { // Create path for text to run on - path: wrapWithAttrCheck(function (track) { + path: wrapWithAttrCheck( function ( track ) { + var path = new TextPath() // if track is a path, reuse it - if (!(track instanceof Path)) { + if ( !( track instanceof Path ) ) { + // create path element - track = this.root().defs().path(track) + track = this.root().defs().path( track ) + } // link textPath to path and add content - path.attr('href', '#' + track, xlink) + path.attr( 'href', '#' + track, xlink ) // add textPath element as child node and return textPath - return this.put(path) - }), + return this.put( path ) + + } ), // Get the textPath children textPath () { - return this.find('textPath')[0] + + return this.find( 'textPath' )[0] + } }, Path: { // creates a textPath from this path - text: wrapWithAttrCheck(function (text) { - if (text instanceof Text) { + text: wrapWithAttrCheck( function ( text ) { + + if ( text instanceof Text ) { + var txt = text.text() - return text.clear().path(this).text(txt) + return text.clear().path( this ).text( txt ) + } - return this.parent().put(new Text()).path(this).text(text) - }), + return this.parent().put( new Text() ).path( this ).text( text ) + + } ), targets () { - return baseFind('svg [href*="' + this.id() + '"]') + + return baseFind( 'svg [href*="' + this.id() + '"]' ) + } } -}) +} ) TextPath.prototype.MorphArray = PathArray -register(TextPath) +register( TextPath ) diff --git a/src/elements/Tspan.js b/src/elements/Tspan.js index abd032f..fcf8cf5 100644 --- a/src/elements/Tspan.js +++ b/src/elements/Tspan.js @@ -9,61 +9,77 @@ import Text from './Text.js' import * as textable from '../modules/core/textable.js' export default class Tspan extends Text { + // Initialize node - constructor (node) { - super(nodeOrNew('tspan', node), node) + constructor ( node ) { + + super( nodeOrNew( 'tspan', node ), node ) + } // Set text content - text (text) { - if (text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '') + text ( text ) { + + if ( text == null ) return this.node.textContent + ( this.dom.newLined ? '\n' : '' ) - typeof text === 'function' ? text.call(this, this) : this.plain(text) + typeof text === 'function' ? text.call( this, this ) : this.plain( text ) return this + } // Shortcut dx - dx (dx) { - return this.attr('dx', dx) + dx ( dx ) { + + return this.attr( 'dx', dx ) + } // Shortcut dy - dy (dy) { - return this.attr('dy', dy) + dy ( dy ) { + + return this.attr( 'dy', dy ) + } // Create new line newLine () { + // fetch text parent - var t = this.parent(Text) + var t = this.parent( Text ) // mark new line this.dom.newLined = true // apply new position - return this.dy(t.dom.leading * t.attr('font-size')).attr('x', t.x()) + return this.dy( t.dom.leading * t.attr( 'font-size' ) ).attr( 'x', t.x() ) + } + } -extend(Tspan, textable) +extend( Tspan, textable ) -registerMethods({ +registerMethods( { Tspan: { - tspan: wrapWithAttrCheck(function (text) { + tspan: wrapWithAttrCheck( function ( text ) { + var tspan = new Tspan() // clear if build mode is disabled - if (!this._build) { + if ( !this._build ) { + this.clear() + } // add new tspan - this.node.appendChild(tspan.node) + this.node.appendChild( tspan.node ) + + return tspan.text( text ) - return tspan.text(text) - }) + } ) } -}) +} ) -register(Tspan) +register( Tspan ) diff --git a/src/elements/Use.js b/src/elements/Use.js index 7921461..9237e08 100644 --- a/src/elements/Use.js +++ b/src/elements/Use.js @@ -4,24 +4,32 @@ import { xlink } from '../modules/core/namespaces.js' import Shape from './Shape.js' export default class Use extends Shape { - constructor (node) { - super(nodeOrNew('use', node), node) + + constructor ( node ) { + + super( nodeOrNew( 'use', node ), node ) + } // Use element as a reference - element (element, file) { + element ( element, file ) { + // Set lined element - return this.attr('href', (file || '') + '#' + element, xlink) + return this.attr( 'href', ( file || '' ) + '#' + element, xlink ) + } + } -registerMethods({ +registerMethods( { Container: { // Create a use element - use: wrapWithAttrCheck(function (element, file) { - return this.put(new Use()).element(element, file) - }) + use: wrapWithAttrCheck( function ( element, file ) { + + return this.put( new Use() ).element( element, file ) + + } ) } -}) +} ) -register(Use) +register( Use ) |