aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--spec/spec/modules/optional/sugar.js430
-rw-r--r--src/modules/optional/arrange.js14
-rw-r--r--src/modules/optional/sugar.js7
3 files changed, 437 insertions, 14 deletions
diff --git a/spec/spec/modules/optional/sugar.js b/spec/spec/modules/optional/sugar.js
new file mode 100644
index 0000000..f762ed0
--- /dev/null
+++ b/spec/spec/modules/optional/sugar.js
@@ -0,0 +1,430 @@
+/* globals describe, expect, it, beforeEach, spyOn, container */
+
+import { Rect, SVG, Matrix, Ellipse, Gradient } from '../../../../src/main.js'
+
+describe('sugar.js', () => {
+ describe('Element/Runner', () => {
+ describe('fill()', () => {
+ describe('as setter', () => {
+ it('returns itself', () => {
+ const rect = new Rect()
+ expect(rect.fill('black')).toBe(rect)
+ })
+
+ it('sets a fill color', () => {
+ const rect = new Rect()
+ expect(rect.fill('black').attr('fill')).toBe('black')
+ })
+
+ it('sets a fill pattern when pattern given', () => {
+ const canvas = SVG().addTo(container)
+ const pattern = canvas.pattern()
+ const rect = canvas.rect(100, 100)
+ expect(rect.fill(pattern).attr('fill')).toBe(pattern.url())
+ })
+
+ it('sets a fill pattern when image given', () => {
+ const canvas = SVG().addTo(container)
+ const image = canvas.image('spec/fictures/pixel.png')
+ const rect = canvas.rect(100, 100)
+ expect(rect.fill(image).attr('fill')).toBe(image.parent().url())
+ })
+
+ it('sets an object of fill properties', () => {
+ const rect = new Rect()
+ expect(rect.fill({
+ color: 'black',
+ opacity: 0.5,
+ rule: 'even-odd'
+ }).attr()).toEqual({
+ fill: 'black',
+ 'fill-opacity': 0.5,
+ 'fill-rule':
+ 'even-odd'
+ })
+ })
+ })
+
+ describe('as getter', () => {
+ it('returns fill color', () => {
+ const rect = new Rect().fill('black')
+ expect(rect.fill()).toBe('black')
+ })
+
+ it('returns default fill color if nothing is set', () => {
+ const rect = new Rect()
+ expect(rect.fill()).toBe('#000000')
+ })
+ })
+ })
+
+ describe('stroke()', () => {
+ describe('as setter', () => {
+ it('returns itself', () => {
+ const rect = new Rect()
+ expect(rect.stroke('black')).toBe(rect)
+ })
+
+ it('sets a stroke color', () => {
+ const rect = new Rect()
+ expect(rect.stroke('black').attr('stroke')).toBe('black')
+ })
+
+ it('sets a stroke pattern when pattern given', () => {
+ const canvas = SVG().addTo(container)
+ const pattern = canvas.pattern()
+ const rect = canvas.rect(100, 100)
+ expect(rect.stroke(pattern).attr('stroke')).toBe(pattern.url())
+ })
+
+ it('sets a stroke pattern when image given', () => {
+ const canvas = SVG().addTo(container)
+ const image = canvas.image('spec/fictures/pixel.png')
+ const rect = canvas.rect(100, 100)
+ expect(rect.stroke(image).attr('stroke')).toBe(image.parent().url())
+ })
+
+ it('sets an object of stroke properties', () => {
+ const rect = new Rect()
+ expect(rect.stroke({
+ color: 'black',
+ width: 2,
+ opacity: 0.5,
+ linecap: 'butt',
+ linejoin: 'miter',
+ miterlimit: 10,
+ dasharray: '2 2',
+ dashoffset: 15
+ }).attr()).toEqual({
+ stroke: 'black',
+ 'stroke-width': 2,
+ 'stroke-opacity': 0.5,
+ 'stroke-linecap': 'butt',
+ 'stroke-linejoin': 'miter',
+ 'stroke-miterlimit': 10,
+ 'stroke-dasharray': '2 2',
+ 'stroke-dashoffset': 15
+ })
+ })
+
+ it('sets stroke dasharray with array passed', () => {
+ const rect = new Rect().stroke({ dasharray: [ 2, 2 ] })
+ expect(rect.attr()).toEqual({ 'stroke-dasharray': '2 2' })
+ })
+ })
+
+ describe('as getter', () => {
+ it('returns stroke color', () => {
+ const rect = new Rect().stroke('black')
+ expect(rect.stroke()).toBe('black')
+ })
+
+ it('returns default stroke color if nothing is set', () => {
+ const rect = new Rect()
+ expect(rect.stroke()).toBe('#000000')
+ })
+ })
+ })
+
+ describe('matrix()', () => {
+ it('gets the matrix with no argument passed', () => {
+ const rect = new Rect().transform(new Matrix(1, 0, 1, 1, 1, 0))
+ expect(rect.matrix()).toEqual(new Matrix(1, 0, 1, 1, 1, 0))
+ })
+
+ it('sets the matrix if matrix given', () => {
+ const rect = new Rect().matrix(new Matrix(1, 0, 1, 1, 1, 0))
+ expect(rect.matrix()).toEqual(new Matrix(1, 0, 1, 1, 1, 0))
+ })
+
+ it('sets the matrix with 6 arguments given', () => {
+ const rect = new Rect().matrix(1, 0, 1, 1, 1, 0)
+ expect(rect.matrix()).toEqual(new Matrix(1, 0, 1, 1, 1, 0))
+ })
+ })
+
+ describe('rotate()', function () {
+ it('redirects to transform()', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.rotate(1, 2, 3)
+ expect(spy).toHaveBeenCalledWith({ rotate: 1, ox: 2, oy: 3 }, true)
+ })
+ })
+
+ describe('skew()', function () {
+ it('redirects to transform() with no argument', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.skew()
+ expect(spy).toHaveBeenCalledWith({ skew: [ undefined, undefined ], ox: undefined, oy: undefined }, true)
+ })
+
+ it('redirects to transform() with one argument', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.skew(5)
+ expect(spy).toHaveBeenCalledWith({ skew: 5, ox: undefined, oy: undefined }, true)
+ })
+
+ it('redirects to transform() with two argument', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.skew(5, 6)
+ expect(spy).toHaveBeenCalledWith({ skew: [ 5, 6 ], ox: undefined, oy: undefined }, true)
+ })
+
+ it('redirects to transform() with three arguments', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.skew(5, 6, 7)
+ expect(spy).toHaveBeenCalledWith({ skew: 5, ox: 6, oy: 7 }, true)
+ })
+
+ it('redirects to transform() with four arguments', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.skew(5, 6, 7, 8)
+ expect(spy).toHaveBeenCalledWith({ skew: [ 5, 6 ], ox: 7, oy: 8 }, true)
+ })
+ })
+
+ describe('shear', () => {
+ it('redirects to transform()', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.shear(1, 2, 3)
+ expect(spy).toHaveBeenCalledWith({ shear: 1, ox: 2, oy: 3 }, true)
+ })
+ })
+
+ describe('scale()', function () {
+ it('redirects to transform() with no argument', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.scale()
+ expect(spy).toHaveBeenCalledWith({ scale: [ undefined, undefined ], ox: undefined, oy: undefined }, true)
+ })
+
+ it('redirects to transform() with one argument', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.scale(5)
+ expect(spy).toHaveBeenCalledWith({ scale: 5, ox: undefined, oy: undefined }, true)
+ })
+
+ it('redirects to transform() with two argument', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.scale(5, 6)
+ expect(spy).toHaveBeenCalledWith({ scale: [ 5, 6 ], ox: undefined, oy: undefined }, true)
+ })
+
+ it('redirects to transform() with three arguments', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.scale(5, 6, 7)
+ expect(spy).toHaveBeenCalledWith({ scale: 5, ox: 6, oy: 7 }, true)
+ })
+
+ it('redirects to transform() with four arguments', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.scale(5, 6, 7, 8)
+ expect(spy).toHaveBeenCalledWith({ scale: [ 5, 6 ], ox: 7, oy: 8 }, true)
+ })
+ })
+
+ describe('translate()', function () {
+ it('redirects to transform()', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.translate(1, 2)
+ expect(spy).toHaveBeenCalledWith({ translate: [ 1, 2 ] }, true)
+ })
+ })
+
+ describe('relative()', () => {
+ it('redirects to transform()', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.relative(1, 2)
+ expect(spy).toHaveBeenCalledWith({ relative: [ 1, 2 ] }, true)
+ })
+ })
+
+ describe('flip()', function () {
+ it('redirects to transform()', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.flip('x', 2)
+ expect(spy).toHaveBeenCalledWith({ flip: 'x', origin: 2 }, true)
+ })
+
+ it('sets flip to "both" when calling without anything', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.flip()
+ expect(spy).toHaveBeenCalledWith({ flip: 'both', origin: 'center' }, true)
+ })
+
+ // this works because only x and y are valid flip values. Evereything else flips on both axis
+ it('sets flip to both and origin to number when called with origin only', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'transform')
+ rect.flip(5)
+ expect(spy).toHaveBeenCalledWith({ flip: 'both', origin: 5 }, true)
+ })
+ })
+
+ describe('opacity()', function () {
+ it('redirects to attr() directly', function () {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'attr')
+ rect.opacity(0.5)
+ expect(spy).toHaveBeenCalledWith('opacity', 0.5)
+ })
+ })
+
+ describe('font()', function () {
+ const txt = 'Some text'
+ let canvas, text
+
+ beforeEach(() => {
+ canvas = SVG().addTo(container)
+ text = canvas.text(txt)
+ })
+
+ it('sets leading when given', function () {
+ const spy = spyOn(text, 'leading')
+ text.font({ leading: 3 })
+ expect(spy).toHaveBeenCalledWith(3)
+ })
+
+ it('sets text-anchor when anchor given', function () {
+ const spy = spyOn(text, 'attr')
+ text.font({ anchor: 'start' })
+ expect(spy).toHaveBeenCalledWith('text-anchor', 'start')
+ })
+
+ it('sets all font properties via attr()', function () {
+ const spy = spyOn(text, 'attr')
+ text.font({
+ size: 20,
+ family: 'Verdana',
+ weight: 'bold',
+ stretch: 'wider',
+ variant: 'small-caps',
+ style: 'italic'
+ })
+ expect(spy).toHaveBeenCalledWith('font-size', 20)
+ expect(spy).toHaveBeenCalledWith('font-family', 'Verdana')
+ expect(spy).toHaveBeenCalledWith('font-weight', 'bold')
+ expect(spy).toHaveBeenCalledWith('font-stretch', 'wider')
+ expect(spy).toHaveBeenCalledWith('font-variant', 'small-caps')
+ expect(spy).toHaveBeenCalledWith('font-style', 'italic')
+ })
+
+ it('redirects all other stuff directly to attr()', function () {
+ const spy = spyOn(text, 'attr')
+ text.font({
+ foo: 'bar',
+ bar: 'baz'
+ })
+ expect(spy).toHaveBeenCalledWith('foo', 'bar')
+ expect(spy).toHaveBeenCalledWith('bar', 'baz')
+ })
+
+ it('sets key value pair when called with 2 parameters', function () {
+ const spy = spyOn(text, 'attr')
+ text.font('size', 20)
+ expect(spy).toHaveBeenCalledWith('font-size', 20)
+ })
+
+ it('gets value if called with one parameter', function () {
+ const spy = spyOn(text, 'attr')
+ text.font('size')
+ expect(spy).toHaveBeenCalledWith('font-size', undefined)
+ })
+ })
+
+ })
+
+ describe('radius()', () => {
+ describe('Rect', () => {
+ it('sets rx and ry on the rectangle', () => {
+ const rect = new Rect().radius(5, 10)
+ expect(rect.attr()).toEqual({ rx: 5, ry: 10 })
+ })
+ })
+
+ describe('Ellipse', () => {
+ it('sets rx and ry on the rectangle', () => {
+ const rect = new Ellipse().radius(5, 10)
+ expect(rect.attr()).toEqual({ rx: 5, ry: 10 })
+ })
+ })
+
+ describe('radialGradient', () => {
+ it('sets rx and ry on the rectangle', () => {
+ const rect = new Gradient('radial').radius(5)
+ expect(rect.attr()).toEqual({ r: 5 })
+ })
+ })
+ })
+
+ describe('Path', () => {
+ describe('length', () => {
+ it('returns the full length of the path', () => {
+ const canvas = SVG().addTo(container)
+ const path = canvas.path('M0 0 L 0 5')
+ expect(path.length()).toBe(5)
+ })
+ })
+
+ describe('pointAt', () => {
+ it('returns a point at a specific length', () => {
+ const canvas = SVG().addTo(container)
+ const path = canvas.path('M0 0 L 0 5')
+ const point = path.pointAt(3)
+
+ expect(point.x).toBeCloseTo(0) // chrome has rounding issues -.-
+ expect(point.y).toBe(3)
+ })
+ })
+ })
+
+ describe('events', () => {
+ [ 'click',
+ 'dblclick',
+ 'mousedown',
+ 'mouseup',
+ 'mouseover',
+ 'mouseout',
+ 'mousemove',
+ 'mouseenter',
+ 'mouseleave',
+ 'touchstart',
+ 'touchmove',
+ 'touchleave',
+ 'touchend',
+ 'touchcancel' ].forEach(ev => {
+ describe(ev, () => {
+ it('calls on() with the eventname set to ' + ev, () => {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'on')
+ const fn = () => {}
+ rect[ev](fn)
+ expect(spy).toHaveBeenCalledWith(ev, fn)
+ })
+
+ it('calls off() with the eventname set to ' + ev + ' when null is passed as second argument', () => {
+ const rect = new Rect()
+ const spy = spyOn(rect, 'off')
+ rect[ev](null)
+ expect(spy).toHaveBeenCalledWith(ev)
+ })
+ })
+ })
+ })
+})
diff --git a/src/modules/optional/arrange.js b/src/modules/optional/arrange.js
index 7db4386..b6c03e0 100644
--- a/src/modules/optional/arrange.js
+++ b/src/modules/optional/arrange.js
@@ -23,16 +23,11 @@ export function prev () {
// Send given element one step forward
export function forward () {
- var i = this.position() + 1
+ var i = this.position()
var p = this.parent()
// move node one step forward
- p.removeElement(this).add(this, i)
-
- // make sure defs node is always at the top
- if (typeof p.isRoot === 'function' && p.isRoot()) {
- p.node.appendChild(p.defs().node)
- }
+ p.add(this.remove(), i + 1)
return this
}
@@ -40,10 +35,9 @@ export function forward () {
// Send given element one step backward
export function backward () {
var i = this.position()
+ var p = this.parent()
- if (i > 0) {
- this.parent().removeElement(this).add(this, i - 1)
- }
+ p.add(this.remove(), i ? i - 1 : 0)
return this
}
diff --git a/src/modules/optional/sugar.js b/src/modules/optional/sugar.js
index 72c02ca..13806f1 100644
--- a/src/modules/optional/sugar.js
+++ b/src/modules/optional/sugar.js
@@ -1,4 +1,3 @@
-import { on, off } from '../core/event.js'
import { registerMethods } from '../../utils/methods.js'
import Color from '../../types/Color.js'
import Element from '../../elements/Element.js'
@@ -106,7 +105,7 @@ registerMethods('radius', {
// Add x and y radius
radius: function (x, y = x) {
var type = (this._element || this).type
- return type === 'radialGradient' || type === 'radialGradient'
+ return type === 'radialGradient'
? this.attr('r', new SVGNumber(x))
: this.rx(x).ry(y)
}
@@ -159,9 +158,9 @@ const methods = [ 'click',
// add event to Element
const fn = function (f) {
if (f === null) {
- off(this, event)
+ this.off(event)
} else {
- on(this, event, f)
+ this.on(event, f)
}
return this
}