From 464af8b747389b7fdb569a933591c863b9be0f6b Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Thu, 25 Oct 2018 23:26:38 +0200 Subject: Rename files so that they reflect their exported classes (see next commit) --- src/A.js | 41 +++ src/Animator.js | 83 +++++ src/Bare.js | 43 +++ src/Box.js | 141 ++++++++ src/ClipPath.js | 53 +++ src/Color.js | 148 +++++++++ src/Container.js | 9 + src/Controller.js | 193 +++++++++++ src/Defs.js | 7 + src/Doc.js | 70 ++++ src/Element.js | 316 ++++++++++++++++++ src/Ellipse.js | 91 ++++++ src/EventTarget.js | 23 ++ src/G.js | 19 ++ src/Gradient.js | 104 ++++++ src/Image.js | 57 ++++ src/Line.js | 57 ++++ src/Marker.js | 78 +++++ src/Mask.js | 51 +++ src/Matrix.js | 472 +++++++++++++++++++++++++++ src/Morphable.js | 231 +++++++++++++ src/Parent.js | 92 ++++++ src/Path.js | 63 ++++ src/PathArray.js | 289 +++++++++++++++++ src/Pattern.js | 59 ++++ src/Point.js | 74 +++++ src/PointArray.js | 128 ++++++++ src/Polygon.js | 67 ++++ src/Queue.js | 61 ++++ src/Rect.js | 16 + src/Runner.js | 928 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/SVGArray.js | 92 ++++++ src/SVGNumber.js | 99 ++++++ src/Shape.js | 10 + src/Symbol.js | 15 + src/Text.js | 234 ++++++++++++++ src/TextPath.js | 77 +++++ src/Timeline.js | 282 ++++++++++++++++ src/animator.js | 83 ----- src/array.js | 92 ------ src/bare.js | 43 --- src/boxes.js | 141 -------- src/clip.js | 53 --- src/color.js | 148 --------- src/container.js | 9 - src/controller.js | 193 ----------- src/defs.js | 7 - src/doc.js | 70 ---- src/element.js | 316 ------------------ src/ellipse.js | 91 ------ src/eventtarget.js | 23 -- src/gradient.js | 104 ------ src/group.js | 19 -- src/hyperlink.js | 41 --- src/image.js | 57 ---- src/line.js | 57 ---- src/marker.js | 78 ----- src/mask.js | 51 --- src/matrix.js | 472 --------------------------- src/morph.js | 231 ------------- src/number.js | 99 ------ src/parent.js | 92 ------ src/path.js | 63 ---- src/patharray.js | 289 ----------------- src/pattern.js | 59 ---- src/point.js | 74 ----- src/pointarray.js | 128 -------- src/poly.js | 67 ---- src/queue.js | 61 ---- src/rect.js | 16 - src/runner.js | 928 ----------------------------------------------------- src/shape.js | 10 - src/symbol.js | 15 - src/text.js | 234 -------------- src/textpath.js | 77 ----- src/timeline.js | 282 ---------------- 76 files changed, 4873 insertions(+), 4873 deletions(-) create mode 100644 src/A.js create mode 100644 src/Animator.js create mode 100644 src/Bare.js create mode 100644 src/Box.js create mode 100644 src/ClipPath.js create mode 100644 src/Color.js create mode 100644 src/Container.js create mode 100644 src/Controller.js create mode 100644 src/Defs.js create mode 100644 src/Doc.js create mode 100644 src/Element.js create mode 100644 src/Ellipse.js create mode 100644 src/EventTarget.js create mode 100644 src/G.js create mode 100644 src/Gradient.js create mode 100644 src/Image.js create mode 100644 src/Line.js create mode 100644 src/Marker.js create mode 100644 src/Mask.js create mode 100644 src/Matrix.js create mode 100644 src/Morphable.js create mode 100644 src/Parent.js create mode 100644 src/Path.js create mode 100644 src/PathArray.js create mode 100644 src/Pattern.js create mode 100644 src/Point.js create mode 100644 src/PointArray.js create mode 100644 src/Polygon.js create mode 100644 src/Queue.js create mode 100644 src/Rect.js create mode 100644 src/Runner.js create mode 100644 src/SVGArray.js create mode 100644 src/SVGNumber.js create mode 100644 src/Shape.js create mode 100644 src/Symbol.js create mode 100644 src/Text.js create mode 100644 src/TextPath.js create mode 100644 src/Timeline.js delete mode 100644 src/animator.js delete mode 100644 src/array.js delete mode 100644 src/bare.js delete mode 100644 src/boxes.js delete mode 100644 src/clip.js delete mode 100644 src/color.js delete mode 100644 src/container.js delete mode 100644 src/controller.js delete mode 100644 src/defs.js delete mode 100644 src/doc.js delete mode 100644 src/element.js delete mode 100644 src/ellipse.js delete mode 100644 src/eventtarget.js delete mode 100644 src/gradient.js delete mode 100644 src/group.js delete mode 100644 src/hyperlink.js delete mode 100644 src/image.js delete mode 100644 src/line.js delete mode 100644 src/marker.js delete mode 100644 src/mask.js delete mode 100644 src/matrix.js delete mode 100644 src/morph.js delete mode 100644 src/number.js delete mode 100644 src/parent.js delete mode 100644 src/path.js delete mode 100644 src/patharray.js delete mode 100644 src/pattern.js delete mode 100644 src/point.js delete mode 100644 src/pointarray.js delete mode 100644 src/poly.js delete mode 100644 src/queue.js delete mode 100644 src/rect.js delete mode 100644 src/runner.js delete mode 100644 src/shape.js delete mode 100644 src/symbol.js delete mode 100644 src/text.js delete mode 100644 src/textpath.js delete mode 100644 src/timeline.js (limited to 'src') diff --git a/src/A.js b/src/A.js new file mode 100644 index 0000000..cb0a341 --- /dev/null +++ b/src/A.js @@ -0,0 +1,41 @@ +SVG.A = SVG.invent({ + // Initialize node + create: 'a', + + // Inherit from + inherit: SVG.Container, + + // Add class methods + extend: { + // Link url + to: function (url) { + return this.attr('href', url, SVG.xlink) + }, + // Link target attribute + target: function (target) { + return this.attr('target', target) + } + }, + + // Add parent method + construct: { + // Create a hyperlink element + link: function (url) { + return this.put(new SVG.A()).to(url) + } + } +}) + +SVG.extend(SVG.Element, { + // Create a hyperlink element + linkTo: function (url) { + var link = new SVG.A() + + if (typeof url === 'function') { url.call(link, link) } else { + link.to(url) + } + + return this.parent().put(link).put(this) + } + +}) diff --git a/src/Animator.js b/src/Animator.js new file mode 100644 index 0000000..eb8ca72 --- /dev/null +++ b/src/Animator.js @@ -0,0 +1,83 @@ +/* global requestAnimationFrame */ + +SVG.Animator = { + nextDraw: null, + frames: new SVG.Queue(), + timeouts: new SVG.Queue(), + timer: window.performance || window.Date, + transforms: [], + + frame: function (fn) { + // Store the node + var node = SVG.Animator.frames.push({ run: fn }) + + // Request an animation frame if we don't have one + if (SVG.Animator.nextDraw === null) { + SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw) + } + + // Return the node so we can remove it easily + return node + }, + + transform_frame: function (fn, id) { + SVG.Animator.transforms[id] = fn + }, + + timeout: function (fn, delay) { + delay = delay || 0 + + // Work out when the event should fire + var time = SVG.Animator.timer.now() + delay + + // Add the timeout to the end of the queue + var node = SVG.Animator.timeouts.push({ run: fn, time: time }) + + // Request another animation frame if we need one + if (SVG.Animator.nextDraw === null) { + SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw) + } + + return node + }, + + cancelFrame: function (node) { + SVG.Animator.frames.remove(node) + }, + + clearTimeout: function (node) { + SVG.Animator.timeouts.remove(node) + }, + + _draw: function (now) { + // Run all the timeouts we can run, if they are not ready yet, add them + // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) + var nextTimeout = null + var lastTimeout = SVG.Animator.timeouts.last() + while ((nextTimeout = SVG.Animator.timeouts.shift())) { + // Run the timeout if its time, or push it to the end + if (now >= nextTimeout.time) { + nextTimeout.run() + } else { + SVG.Animator.timeouts.push(nextTimeout) + } + + // If we hit the last item, we should stop shifting out more items + if (nextTimeout === lastTimeout) break + } + + // Run all of the animation frames + var nextFrame = null + var lastFrame = SVG.Animator.frames.last() + while ((nextFrame !== lastFrame) && (nextFrame = SVG.Animator.frames.shift())) { + nextFrame.run() + } + + SVG.Animator.transforms.forEach(function (el) { el() }) + + // If we have remaining timeouts or frames, draw until we don't anymore + SVG.Animator.nextDraw = SVG.Animator.timeouts.first() || SVG.Animator.frames.first() + ? requestAnimationFrame(SVG.Animator._draw) + : null + } +} diff --git a/src/Bare.js b/src/Bare.js new file mode 100644 index 0000000..393ce6e --- /dev/null +++ b/src/Bare.js @@ -0,0 +1,43 @@ + +SVG.Bare = SVG.invent({ + // Initialize + create: function (element, inherit) { + // construct element + SVG.Element.call(this, SVG.create(element)) + + // inherit custom methods + if (inherit) { + for (var method in inherit.prototype) { + if (typeof inherit.prototype[method] === 'function') { + this[method] = inherit.prototype[method] + } + } + } + }, + + // Inherit from + inherit: SVG.Element, + + // Add methods + extend: { + // Insert some plain text + words: function (text) { + // remove contents + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild) + } + + // create text node + this.node.appendChild(document.createTextNode(text)) + + return this + } + } +}) + +SVG.extend(SVG.Parent, { + // Create an element that is not described by SVG.js + element: function (element, inherit) { + return this.put(new SVG.Bare(element, inherit)) + } +}) diff --git a/src/Box.js b/src/Box.js new file mode 100644 index 0000000..a9247ef --- /dev/null +++ b/src/Box.js @@ -0,0 +1,141 @@ +/* globals fullBox, domContains, isNulledBox, Exception */ + +SVG.Box = SVG.invent({ + create: function (source) { + var base = [0, 0, 0, 0] + source = typeof source === 'string' ? source.split(SVG.regex.delimiter).map(parseFloat) + : Array.isArray(source) ? source + : typeof source === 'object' ? [source.left != null ? source.left + : source.x, source.top != null ? source.top : source.y, source.width, source.height] + : arguments.length === 4 ? [].slice.call(arguments) + : base + + this.x = source[0] + this.y = source[1] + this.width = source[2] + this.height = source[3] + + // add center, right, bottom... + fullBox(this) + }, + extend: { + // Merge rect box with another, return a new instance + merge: function (box) { + var x = Math.min(this.x, box.x) + var y = Math.min(this.y, box.y) + + return new SVG.Box( + x, y, + Math.max(this.x + this.width, box.x + box.width) - x, + Math.max(this.y + this.height, box.y + box.height) - y + ) + }, + + transform: function (m) { + var xMin = Infinity + var xMax = -Infinity + var yMin = Infinity + var yMax = -Infinity + + var pts = [ + new SVG.Point(this.x, this.y), + new SVG.Point(this.x2, this.y), + new SVG.Point(this.x, this.y2), + new SVG.Point(this.x2, this.y2) + ] + + pts.forEach(function (p) { + p = p.transform(m) + xMin = Math.min(xMin, p.x) + xMax = Math.max(xMax, p.x) + yMin = Math.min(yMin, p.y) + yMax = Math.max(yMax, p.y) + }) + + return new SVG.Box( + xMin, yMin, + xMax - xMin, + yMax - yMin + ) + }, + + addOffset: function () { + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset + this.y += window.pageYOffset + return this + }, + toString: function () { + return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height + }, + toArray: function () { + return [this.x, this.y, this.width, this.height] + }, + morph: function (x, y, width, height) { + this.destination = new SVG.Box(x, y, width, height) + return this + }, + + at: function (pos) { + if (!this.destination) return this + + return new SVG.Box( + this.x + (this.destination.x - this.x) * pos + , this.y + (this.destination.y - this.y) * pos + , this.width + (this.destination.width - this.width) * pos + , this.height + (this.destination.height - this.height) * pos + ) + } + }, + + // Define Parent + parent: SVG.Element, + + // Constructor + construct: { + // Get bounding box + bbox: function () { + var box + + try { + // find native bbox + box = this.node.getBBox() + + if (isNulledBox(box) && !domContains(this.node)) { + throw new Exception('Element not in the dom') + } + } catch (e) { + try { + var clone = this.clone(SVG.parser().svg).show() + box = clone.node.getBBox() + clone.remove() + } catch (e) { + console.warn('Getting a bounding box of this element is not possible') + } + } + + return new SVG.Box(box) + }, + + rbox: function (el) { + // IE11 throws an error when element not in dom + try { + var box = new SVG.Box(this.node.getBoundingClientRect()) + if (el) return box.transform(el.screenCTM().inverse()) + return box.addOffset() + } catch (e) { + return new SVG.Box() + } + } + } +}) + +SVG.extend([SVG.Doc, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View], { + viewbox: function (x, y, width, height) { + // act as getter + if (x == null) return new SVG.Box(this.attr('viewBox')) + + // act as setter + return this.attr('viewBox', new SVG.Box(x, y, width, height)) + } +}) diff --git a/src/ClipPath.js b/src/ClipPath.js new file mode 100644 index 0000000..63fff74 --- /dev/null +++ b/src/ClipPath.js @@ -0,0 +1,53 @@ +SVG.ClipPath = SVG.invent({ + // Initialize node + create: 'clipPath', + + // Inherit from + inherit: SVG.Container, + + // Add class methods + extend: { + // Unclip all clipped elements and remove itself + remove: function () { + // unclip all targets + this.targets().forEach(function (el) { + el.unclip() + }) + + // remove clipPath from parent + return SVG.Element.prototype.remove.call(this) + }, + + targets: function () { + return SVG.select('svg [clip-path*="' + this.id() + '"]') + } + }, + + // Add parent method + construct: { + // Create clipping element + clip: function () { + return this.defs().put(new SVG.ClipPath()) + } + } +}) + +// +SVG.extend(SVG.Element, { + // Distribute clipPath to svg element + clipWith: function (element) { + // use given clip or create a new one + var clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element) + + // apply mask + return this.attr('clip-path', 'url("#' + clipper.id() + '")') + }, + // Unclip element + unclip: function () { + return this.attr('clip-path', null) + }, + clipper: function () { + return this.reference('clip-path') + } + +}) diff --git a/src/Color.js b/src/Color.js new file mode 100644 index 0000000..43bafcb --- /dev/null +++ b/src/Color.js @@ -0,0 +1,148 @@ +/* globals fullHex, compToHex */ + +/* + +Color { + constructor (a, b, c, space) { + space: 'hsl' + a: 30 + b: 20 + c: 10 + }, + + toRgb () { return new Color in rgb space } + toHsl () { return new Color in hsl space } + toLab () { return new Color in lab space } + + toArray () { [space, a, b, c] } + fromArray () { convert it back } +} + +// Conversions aren't always exact because of monitor profiles etc... +new Color(h, s, l, 'hsl') !== new Color(r, g, b).hsl() +new Color(100, 100, 100, [space]) +new Color('hsl(30, 20, 10)') + +// Sugar +SVG.rgb(30, 20, 50).lab() +SVG.hsl() +SVG.lab('rgb(100, 100, 100)') +*/ + +// Module for color convertions +SVG.Color = function (color, g, b) { + var match + + // initialize defaults + this.r = 0 + this.g = 0 + this.b = 0 + + if (!color) return + + // parse color + if (typeof color === 'string') { + if (SVG.regex.isRgb.test(color)) { + // get rgb values + match = SVG.regex.rgb.exec(color.replace(SVG.regex.whitespace, '')) + + // parse numeric values + this.r = parseInt(match[1]) + this.g = parseInt(match[2]) + this.b = parseInt(match[3]) + } else if (SVG.regex.isHex.test(color)) { + // get hex values + match = SVG.regex.hex.exec(fullHex(color)) + + // parse numeric values + this.r = parseInt(match[1], 16) + this.g = parseInt(match[2], 16) + this.b = parseInt(match[3], 16) + } + } else if (Array.isArray(color)) { + this.r = color[0] + this.g = color[1] + this.b = color[2] + } else if (typeof color === 'object') { + this.r = color.r + this.g = color.g + this.b = color.b + } else if (arguments.length === 3) { + this.r = color + this.g = g + this.b = b + } +} + +SVG.extend(SVG.Color, { + // Default to hex conversion + toString: function () { + return this.toHex() + }, + toArray: function () { + return [this.r, this.g, this.b] + }, + fromArray: function (a) { + return new SVG.Color(a) + }, + // Build hex value + toHex: function () { + return '#' + + compToHex(Math.round(this.r)) + + compToHex(Math.round(this.g)) + + compToHex(Math.round(this.b)) + }, + // Build rgb value + toRgb: function () { + return 'rgb(' + [this.r, this.g, this.b].join() + ')' + }, + // Calculate true brightness + brightness: function () { + return (this.r / 255 * 0.30) + + (this.g / 255 * 0.59) + + (this.b / 255 * 0.11) + }, + // Make color morphable + morph: function (color) { + this.destination = new SVG.Color(color) + + return this + }, + // Get morphed color at given position + at: function (pos) { + // make sure a destination is defined + if (!this.destination) return this + + // normalise pos + pos = pos < 0 ? 0 : pos > 1 ? 1 : pos + + // generate morphed color + return new SVG.Color({ + r: ~~(this.r + (this.destination.r - this.r) * pos), + g: ~~(this.g + (this.destination.g - this.g) * pos), + b: ~~(this.b + (this.destination.b - this.b) * pos) + }) + } + +}) + +// Testers + +// Test if given value is a color string +SVG.Color.test = function (color) { + color += '' + return SVG.regex.isHex.test(color) || + SVG.regex.isRgb.test(color) +} + +// Test if given value is a rgb object +SVG.Color.isRgb = function (color) { + return color && typeof color.r === 'number' && + typeof color.g === 'number' && + typeof color.b === 'number' +} + +// Test if given value is a color +SVG.Color.isColor = function (color) { + return SVG.Color.isRgb(color) || SVG.Color.test(color) +} diff --git a/src/Container.js b/src/Container.js new file mode 100644 index 0000000..8b324bd --- /dev/null +++ b/src/Container.js @@ -0,0 +1,9 @@ +SVG.Container = SVG.invent({ + // Initialize node + create: function (node) { + SVG.Element.call(this, node) + }, + + // Inherit from + inherit: SVG.Parent +}) diff --git a/src/Controller.js b/src/Controller.js new file mode 100644 index 0000000..842c772 --- /dev/null +++ b/src/Controller.js @@ -0,0 +1,193 @@ + +// c = { +// finished: Whether or not we are finished +// } + +/*** +Base Class +========== +The base stepper class that will be +***/ + +function makeSetterGetter (k, f) { + return function (v) { + if (v == null) return this[v] + this[k] = v + if (f) f.call(this) + return this + } +} + +SVG.Stepper = SVG.invent({ + create: function () {} +}) + +/*** +Easing Functions +================ +***/ + +SVG.Ease = SVG.invent({ + inherit: SVG.Stepper, + + create: function (fn) { + SVG.Stepper.call(this, fn) + + this.ease = SVG.easing[fn || SVG.defaults.timeline.ease] || fn + }, + + extend: { + + step: function (from, to, pos) { + if (typeof from !== 'number') { + return pos < 1 ? from : to + } + return from + (to - from) * this.ease(pos) + }, + + done: function (dt, c) { + return false + } + } +}) + +SVG.easing = { + '-': function (pos) { return pos }, + '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, + '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, + '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }, + bezier: function (t0, x0, t1, x1) { + return function (t) { + // TODO: FINISH + } + } +} + +/*** +Controller Types +================ +***/ + +SVG.Controller = SVG.invent({ + inherit: SVG.Stepper, + + create: function (fn) { + SVG.Stepper.call(this, fn) + this.stepper = fn + }, + + extend: { + + step: function (current, target, dt, c) { + return this.stepper(current, target, dt, c) + }, + + done: function (c) { + return c.done + } + } +}) + +function recalculate () { + // Apply the default parameters + var duration = (this._duration || 500) / 1000 + var overshoot = this._overshoot || 0 + + // Calculate the PID natural response + var eps = 1e-10 + var pi = Math.PI + var os = Math.log(overshoot / 100 + eps) + var zeta = -os / Math.sqrt(pi * pi + os * os) + var wn = 3.9 / (zeta * duration) + + // Calculate the Spring values + this.d = 2 * zeta * wn + this.k = wn * wn +} + +SVG.Spring = SVG.invent({ + inherit: SVG.Controller, + + create: function (duration, overshoot) { + this.duration(duration || 500) + .overshoot(overshoot || 0) + }, + + extend: { + step: function (current, target, dt, c) { + if (typeof current === 'string') return current + c.done = dt === Infinity + if (dt === Infinity) return target + if (dt === 0) return current + + if (dt > 100) dt = 16 + + dt /= 1000 + + // Get the previous velocity + var velocity = c.velocity || 0 + + // Apply the control to get the new position and store it + var acceleration = -this.d * velocity - this.k * (current - target) + var newPosition = current + + velocity * dt + + acceleration * dt * dt / 2 + + // Store the velocity + c.velocity = velocity + acceleration * dt + + // Figure out if we have converged, and if so, pass the value + c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002 + return c.done ? target : newPosition + }, + + duration: makeSetterGetter('_duration', recalculate), + overshoot: makeSetterGetter('_overshoot', recalculate) + } +}) + +SVG.PID = SVG.invent({ + inherit: SVG.Controller, + + create: function (p, i, d, windup) { + SVG.Controller.call(this) + + p = p == null ? 0.1 : p + i = i == null ? 0.01 : i + d = d == null ? 0 : d + windup = windup == null ? 1000 : windup + this.p(p).i(i).d(d).windup(windup) + }, + + extend: { + step: function (current, target, dt, c) { + if (typeof current === 'string') return current + c.done = dt === Infinity + + if (dt === Infinity) return target + if (dt === 0) return current + + var p = target - current + var i = (c.integral || 0) + p * dt + var d = (p - (c.error || 0)) / dt + var windup = this.windup + + // antiwindup + if (windup !== false) { + i = Math.max(-windup, Math.min(i, windup)) + } + + c.error = p + c.integral = i + + c.done = Math.abs(p) < 0.001 + + return c.done ? target : current + (this.P * p + this.I * i + this.D * d) + }, + + windup: makeSetterGetter('windup'), + p: makeSetterGetter('P'), + i: makeSetterGetter('I'), + d: makeSetterGetter('D') + } +}) diff --git a/src/Defs.js b/src/Defs.js new file mode 100644 index 0000000..3d6ebb9 --- /dev/null +++ b/src/Defs.js @@ -0,0 +1,7 @@ +SVG.Defs = SVG.invent({ + // Initialize node + create: 'defs', + + // Inherit from + inherit: SVG.Container +}) diff --git a/src/Doc.js b/src/Doc.js new file mode 100644 index 0000000..423204f --- /dev/null +++ b/src/Doc.js @@ -0,0 +1,70 @@ +SVG.Doc = SVG.invent({ + // Initialize node + create: function (node) { + SVG.Element.call(this, node || SVG.create('svg')) + + // set svg element attributes and ensure defs node + this.namespace() + }, + + // Inherit from + inherit: SVG.Container, + + // Add class methods + extend: { + isRoot: function () { + return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document' + }, + // Check if this is a root svg. If not, call docs from this element + doc: function () { + if (this.isRoot()) return this + return SVG.Element.prototype.doc.call(this) + }, + // Add namespaces + namespace: function () { + if (!this.isRoot()) return this.doc().namespace() + return this + .attr({ xmlns: SVG.ns, version: '1.1' }) + .attr('xmlns:xlink', SVG.xlink, SVG.xmlns) + .attr('xmlns:svgjs', SVG.svgjs, SVG.xmlns) + }, + // Creates and returns defs element + defs: function () { + if (!this.isRoot()) return this.doc().defs() + return SVG.adopt(this.node.getElementsByTagName('defs')[0]) || this.put(new SVG.Defs()) + }, + // custom parent method + parent: function (type) { + if (this.isRoot()) { + return this.node.parentNode.nodeName === '#document' ? null : this.node.parentNode + } + + return SVG.Element.prototype.parent.call(this, type) + }, + // Removes the doc from the DOM + remove: function () { + if (!this.isRoot()) { + return SVG.Element.prototype.remove.call(this) + } + + if (this.parent()) { + this.parent().removeChild(this.node) + } + + return this + }, + clear: function () { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild) + } + return this + } + }, + construct: { + // Create nested svg document + nested: function () { + return this.put(new SVG.Doc()) + } + } +}) diff --git a/src/Element.js b/src/Element.js new file mode 100644 index 0000000..f0d9e8e --- /dev/null +++ b/src/Element.js @@ -0,0 +1,316 @@ +/* global proportionalSize, assignNewId, createElement, matches, is */ + +SVG.Element = SVG.invent({ + inherit: SVG.EventTarget, + + // Initialize node + create: function (node) { + // event listener + this.events = {} + + // initialize data object + this.dom = {} + + // create circular reference + this.node = node + if (this.node) { + this.type = node.nodeName + this.node.instance = this + this.events = node.events || {} + + 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')) || {}) + } + } + }, + + // 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) { + // write dom data to the dom so the clone can pickup the data + this.writeDataToDom() + + // 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 createElement(parent).put(this) + }, + + // Add element to given container and return container + putIn: function (parent) { + return createElement(parent).add(this) + }, + + // Get / set id + id: function (id) { + // generate new id if no id set + if (typeof id === 'undefined' && !this.node.id) { + this.node.id = SVG.eid(this.type) + } + + // dont't set directly width this.node.id to make `null` work correctly + 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.css('display', '') + }, + + // Hide element + hide: function () { + return this.css('display', 'none') + }, + + // Is element visible? + visible: function () { + return this.css('display') !== 'none' + }, + + // Return id on string conversion + toString: function () { + return this.id() + }, + + // Return array of classes on the node + classes: function () { + var attr = this.attr('class') + return attr == null ? [] : attr.trim().split(SVG.regex.delimiter) + }, + + // 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 window.SVGElement) { + if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent + parent = SVG.adopt(parent.node.parentNode) + } + }, + + // Get parent document + doc: function () { + var p = this.parent(SVG.Doc) + return p && p.doc() + }, + + // Get defs + defs: function () { + return this.doc().defs() + }, + + // return array of all ancestors of given type up to the root svg + parents: function (type) { + var parents = [] + var 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) { + var well, len + + // act as a setter if svg is given + if (svg && this instanceof SVG.Parent) { + // create temporary holder + well = document.createElementNS(SVG.ns, 'svg') + // dump raw svg + well.innerHTML = svg + + // transplant nodes + for (len = well.children.length; len--;) { + this.node.appendChild(well.firstElementChild) + } + + // otherwise act as a getter + } else { + // write svgjs data to the dom + this.writeDataToDom() + + return this.node.outerHTML + } + + return this + }, + + // write svgjs data to the dom + writeDataToDom: function () { + // dump variables recursively + if (this.is(SVG.Parent)) { + this.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) + }, + getEventTarget: function () { + return this.node + } + } +}) diff --git a/src/Ellipse.js b/src/Ellipse.js new file mode 100644 index 0000000..8a8f027 --- /dev/null +++ b/src/Ellipse.js @@ -0,0 +1,91 @@ +/* global proportionalSize */ + +SVG.Circle = SVG.invent({ + // Initialize node + create: 'circle', + + // Inherit from + inherit: SVG.Shape, + + // Add parent method + construct: { + // Create circle element, based on ellipse + circle: function (size) { + return this.put(new SVG.Circle()).rx(new SVG.Number(size).divide(2)).move(0, 0) + } + } +}) + +SVG.extend([SVG.Circle, SVG.Timeline], { + // Radius x value + rx: function (rx) { + return this.attr('r', rx) + }, + // Alias radius x value + ry: function (ry) { + return this.rx(ry) + } +}) + +SVG.Ellipse = SVG.invent({ + // Initialize node + create: 'ellipse', + + // Inherit from + inherit: SVG.Shape, + + // Add parent method + construct: { + // Create an ellipse + ellipse: function (width, height) { + return this.put(new SVG.Ellipse()).size(width, height).move(0, 0) + } + } +}) + +SVG.extend([SVG.Ellipse, SVG.Rect, SVG.Timeline], { + // Radius x value + rx: function (rx) { + return this.attr('rx', rx) + }, + // Radius y value + ry: function (ry) { + return this.attr('ry', ry) + } +}) + +// Add common method +SVG.extend([SVG.Circle, SVG.Ellipse], { + // Move over x-axis + x: function (x) { + return x == null ? this.cx() - this.rx() : this.cx(x + this.rx()) + }, + // Move over y-axis + y: function (y) { + return y == null ? this.cy() - this.ry() : this.cy(y + this.ry()) + }, + // Move by center over x-axis + cx: function (x) { + return x == null ? this.attr('cx') : this.attr('cx', x) + }, + // Move by center over y-axis + cy: function (y) { + return y == null ? this.attr('cy') : this.attr('cy', y) + }, + // Set width of element + width: function (width) { + return width == null ? this.rx() * 2 : this.rx(new SVG.Number(width).divide(2)) + }, + // Set height of element + height: function (height) { + return height == null ? this.ry() * 2 : this.ry(new SVG.Number(height).divide(2)) + }, + // Custom size function + size: function (width, height) { + var p = proportionalSize(this, width, height) + + return this + .rx(new SVG.Number(p.width).divide(2)) + .ry(new SVG.Number(p.height).divide(2)) + } +}) diff --git a/src/EventTarget.js b/src/EventTarget.js new file mode 100644 index 0000000..fbe4781 --- /dev/null +++ b/src/EventTarget.js @@ -0,0 +1,23 @@ +SVG.EventTarget = SVG.invent({ + create: function () {}, + extend: { + // Bind given event to listener + on: function (event, listener, binding, options) { + SVG.on(this, event, listener, binding, options) + return this + }, + // Unbind event from listener + off: function (event, listener) { + SVG.off(this, event, listener) + return this + }, + dispatch: function (event, data) { + return SVG.dispatch(this, event, data) + }, + // Fire given event + fire: function (event, data) { + this.dispatch(event, data) + return this + } + } +}) diff --git a/src/G.js b/src/G.js new file mode 100644 index 0000000..0088a1c --- /dev/null +++ b/src/G.js @@ -0,0 +1,19 @@ +SVG.G = SVG.invent({ + // Initialize node + create: 'g', + + // Inherit from + inherit: SVG.Container, + + // Add class methods + extend: { + }, + + // Add parent method + construct: { + // Create a group element + group: function () { + return this.put(new SVG.G()) + } + } +}) diff --git a/src/Gradient.js b/src/Gradient.js new file mode 100644 index 0000000..45a4e08 --- /dev/null +++ b/src/Gradient.js @@ -0,0 +1,104 @@ +SVG.Gradient = SVG.invent({ + // Initialize node + create: function (type) { + SVG.Element.call(this, typeof type === 'object' ? type : SVG.create(type + 'Gradient')) + }, + + // Inherit from + inherit: SVG.Container, + + // Add class methods + extend: { + // Add a color stop + stop: function (offset, color, opacity) { + return this.put(new SVG.Stop()).update(offset, color, opacity) + }, + // Update gradient + update: function (block) { + // remove all stops + this.clear() + + // invoke passed block + if (typeof block === 'function') { + block.call(this, this) + } + + return this + }, + // Return the fill id + url: function () { + return 'url(#' + this.id() + ')' + }, + // Alias string convertion to fill + toString: function () { + return this.url() + }, + // custom attr to handle transform + attr: function (a, b, c) { + if (a === 'transform') a = 'gradientTransform' + return SVG.Container.prototype.attr.call(this, a, b, c) + } + }, + + // Add parent method + construct: { + // Create gradient element in defs + gradient: function (type, block) { + return this.defs().gradient(type, block) + } + } +}) + +// Add animatable methods to both gradient and fx module +SVG.extend([SVG.Gradient, SVG.Timeline], { + // From position + from: function (x, y) { + return (this._target || this).type === 'radialGradient' + ? this.attr({ fx: new SVG.Number(x), fy: new SVG.Number(y) }) + : this.attr({ x1: new SVG.Number(x), y1: new SVG.Number(y) }) + }, + // To position + to: function (x, y) { + return (this._target || this).type === 'radialGradient' + ? this.attr({ cx: new SVG.Number(x), cy: new SVG.Number(y) }) + : this.attr({ x2: new SVG.Number(x), y2: new SVG.Number(y) }) + } +}) + +// Base gradient generation +SVG.extend(SVG.Defs, { + // define gradient + gradient: function (type, block) { + return this.put(new SVG.Gradient(type)).update(block) + } + +}) + +SVG.Stop = SVG.invent({ + // Initialize node + create: 'stop', + + // Inherit from + inherit: SVG.Element, + + // Add class methods + extend: { + // add color stops + update: function (o) { + if (typeof o === 'number' || o instanceof SVG.Number) { + 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 SVG.Number(o.offset)) + + return this + } + } +}) diff --git a/src/Image.js b/src/Image.js new file mode 100644 index 0000000..f9395eb --- /dev/null +++ b/src/Image.js @@ -0,0 +1,57 @@ +SVG.Image = SVG.invent({ + // Initialize node + create: 'image', + + // Inherit from + inherit: SVG.Shape, + + // Add class methods + extend: { + // (re)load image + load: function (url, callback) { + if (!url) return this + + var img = new window.Image() + + SVG.on(img, 'load', function (e) { + var p = this.parent(SVG.Pattern) + + // ensure image size + if (this.width() === 0 && this.height() === 0) { + this.size(img.width, img.height) + } + + if (p instanceof SVG.Pattern) { + // ensure pattern size if not set + if (p.width() === 0 && p.height() === 0) { + p.size(this.width(), this.height()) + } + } + + if (typeof callback === 'function') { + callback.call(this, { + width: img.width, + height: img.height, + ratio: img.width / img.height, + url: url + }) + } + }, this) + + SVG.on(img, 'load error', function () { + // dont forget to unbind memory leaking events + SVG.off(img) + }) + + return this.attr('href', (img.src = url), SVG.xlink) + } + }, + + // Add parent method + construct: { + // create image element, load image and set its size + image: function (source, callback) { + return this.put(new SVG.Image()).size(0, 0).load(source, callback) + } + } +}) diff --git a/src/Line.js b/src/Line.js new file mode 100644 index 0000000..da0c0ca --- /dev/null +++ b/src/Line.js @@ -0,0 +1,57 @@ +/* global proportionalSize */ + +SVG.Line = SVG.invent({ + // Initialize node + create: 'line', + + // Inherit from + inherit: SVG.Shape, + + // Add class methods + extend: { + // Get array + array: function () { + return new SVG.PointArray([ + [ this.attr('x1'), this.attr('y1') ], + [ this.attr('x2'), this.attr('y2') ] + ]) + }, + + // Overwrite native plot() method + plot: function (x1, y1, x2, y2) { + if (x1 == null) { + return this.array() + } else if (typeof y1 !== 'undefined') { + x1 = { x1: x1, y1: y1, x2: x2, y2: y2 } + } else { + x1 = new SVG.PointArray(x1).toLine() + } + + return this.attr(x1) + }, + + // Move by left top corner + move: function (x, y) { + return this.attr(this.array().move(x, y).toLine()) + }, + + // Set element size to given width and height + size: function (width, height) { + var p = proportionalSize(this, width, height) + return this.attr(this.array().size(p.width, p.height).toLine()) + } + }, + + // Add parent method + construct: { + // Create a line element + line: function (x1, y1, x2, y2) { + // make sure plot is called as a setter + // x1 is not necessarily a number, it can also be an array, a string and a SVG.PointArray + return SVG.Line.prototype.plot.apply( + this.put(new SVG.Line()) + , x1 != null ? [x1, y1, x2, y2] : [0, 0, 0, 0] + ) + } + } +}) diff --git a/src/Marker.js b/src/Marker.js new file mode 100644 index 0000000..32f8e4e --- /dev/null +++ b/src/Marker.js @@ -0,0 +1,78 @@ +SVG.Marker = SVG.invent({ + // Initialize node + create: 'marker', + + // Inherit from + inherit: SVG.Container, + + // Add class methods + extend: { + // Set width of element + width: function (width) { + return this.attr('markerWidth', width) + }, + // Set height of element + height: function (height) { + return this.attr('markerHeight', height) + }, + // Set marker refX and refY + ref: function (x, y) { + return this.attr('refX', x).attr('refY', y) + }, + // Update marker + update: function (block) { + // remove all content + this.clear() + + // invoke passed block + if (typeof block === 'function') { block.call(this, this) } + + return this + }, + // Return the fill id + toString: function () { + return 'url(#' + this.id() + ')' + } + }, + + // Add parent method + construct: { + marker: function (width, height, block) { + // Create marker element in defs + return this.defs().marker(width, height, block) + } + } + +}) + +SVG.extend(SVG.Defs, { + // Create marker + marker: 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 SVG.Marker()) + .size(width, height) + .ref(width / 2, height / 2) + .viewbox(0, 0, width, height) + .attr('orient', 'auto') + .update(block) + } + +}) + +SVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon, SVG.Path], { + // Create and attach markers + marker: function (marker, width, height, block) { + var attr = ['marker'] + + // Build attribute name + if (marker !== 'all') attr.push(marker) + attr = attr.join('-') + + // Set marker attribute + marker = arguments[1] instanceof SVG.Marker + ? arguments[1] + : this.doc().marker(width, height, block) + + return this.attr(attr, marker) + } +}) diff --git a/src/Mask.js b/src/Mask.js new file mode 100644 index 0000000..e40d80f --- /dev/null +++ b/src/Mask.js @@ -0,0 +1,51 @@ +SVG.Mask = SVG.invent({ + // Initialize node + create: 'mask', + + // Inherit from + inherit: SVG.Container, + + // Add class methods + extend: { + // Unmask all masked elements and remove itself + remove: function () { + // unmask all targets + this.targets().forEach(function (el) { + el.unmask() + }) + + // remove mask from parent + return SVG.Element.prototype.remove.call(this) + }, + + targets: function () { + return SVG.select('svg [mask*="' + this.id() + '"]') + } + }, + + // Add parent method + construct: { + // Create masking element + mask: function () { + return this.defs().put(new SVG.Mask()) + } + } +}) + +SVG.extend(SVG.Element, { + // Distribute mask to svg element + maskWith: function (element) { + // use given mask or create a new one + var masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element) + + // apply mask + return this.attr('mask', 'url("#' + masker.id() + '")') + }, + // Unmask element + unmask: function () { + return this.attr('mask', null) + }, + masker: function () { + return this.reference('mask') + } +}) diff --git a/src/Matrix.js b/src/Matrix.js new file mode 100644 index 0000000..666b898 --- /dev/null +++ b/src/Matrix.js @@ -0,0 +1,472 @@ +/* global abcdef arrayToMatrix closeEnough formatTransforms isMatrixLike matrixMultiply */ + +SVG.Matrix = SVG.invent({ + // Initialize + create: function (source) { + var base = arrayToMatrix([1, 0, 0, 1, 0, 0]) + + // ensure source as object + source = source instanceof SVG.Element ? source.matrixify() + : typeof source === 'string' ? arrayToMatrix(source.split(SVG.regex.delimiter).map(parseFloat)) + : Array.isArray(source) ? arrayToMatrix(source) + : (typeof source === 'object' && isMatrixLike(source)) ? source + : (typeof source === 'object') ? new SVG.Matrix().transform(source) + : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) + : base + + // Merge the source matrix with the base matrix + this.a = source.a != null ? source.a : base.a + this.b = source.b != null ? source.b : base.b + this.c = source.c != null ? source.c : base.c + this.d = source.d != null ? source.d : base.d + this.e = source.e != null ? source.e : base.e + this.f = source.f != null ? source.f : base.f + }, + + // Add methods + extend: { + + // Clones this matrix + clone: function () { + return new SVG.Matrix(this) + }, + + // Transform a matrix into another matrix by manipulating the space + transform: function (o) { + // Check if o is a matrix and then left multiply it directly + if (isMatrixLike(o)) { + var matrix = new SVG.Matrix(o) + return matrix.multiplyO(this) + } + + // Get the proposed transformations and the current transformations + var t = formatTransforms(o) + var current = this + let { x: ox, y: oy } = new SVG.Point(t.ox, t.oy).transform(current) + + // Construct the resulting matrix + var transformer = new SVG.Matrix() + .translateO(t.rx, t.ry) + .lmultiplyO(current) + .translateO(-ox, -oy) + .scaleO(t.scaleX, t.scaleY) + .skewO(t.skewX, t.skewY) + .shearO(t.shear) + .rotateO(t.theta) + .translateO(ox, oy) + + // If we want the origin at a particular place, we force it there + if (isFinite(t.px) || isFinite(t.py)) { + const origin = new SVG.Point(ox, oy).transform(transformer) + // TODO: Replace t.px with isFinite(t.px) + const dx = t.px ? t.px - origin.x : 0 + const dy = t.py ? t.py - origin.y : 0 + transformer.translateO(dx, dy) + } + + // Translate now after positioning + transformer.translateO(t.tx, t.ty) + return transformer + }, + + // Applies a matrix defined by its affine parameters + compose: function (o) { + if (o.origin) { + o.originX = o.origin[0] + o.originY = o.origin[1] + } + // Get the parameters + var ox = o.originX || 0 + var oy = o.originY || 0 + var sx = o.scaleX || 1 + var sy = o.scaleY || 1 + var lam = o.shear || 0 + var theta = o.rotate || 0 + var tx = o.translateX || 0 + var ty = o.translateY || 0 + + // Apply the standard matrix + var result = new SVG.Matrix() + .translateO(-ox, -oy) + .scaleO(sx, sy) + .shearO(lam) + .rotateO(theta) + .translateO(tx, ty) + .lmultiplyO(this) + .translateO(ox, oy) + return result + }, + + // Decomposes this matrix into its affine parameters + decompose: function (cx = 0, cy = 0) { + // Get the parameters from the matrix + var a = this.a + var b = this.b + var c = this.c + var d = this.d + var e = this.e + var f = this.f + + // Figure out if the winding direction is clockwise or counterclockwise + var determinant = a * d - b * c + var ccw = determinant > 0 ? 1 : -1 + + // Since we only shear in x, we can use the x basis to get the x scale + // and the rotation of the resulting matrix + var sx = ccw * Math.sqrt(a * a + b * b) + var thetaRad = Math.atan2(ccw * b, ccw * a) + var theta = 180 / Math.PI * thetaRad + var ct = Math.cos(thetaRad) + var st = Math.sin(thetaRad) + + // We can then solve the y basis vector simultaneously to get the other + // two affine parameters directly from these parameters + var lam = (a * c + b * d) / determinant + var sy = ((c * sx) / (lam * a - b)) || ((d * sx) / (lam * b + a)) + + // Use the translations + let tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy) + let ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy) + + // Construct the decomposition and return it + return { + // Return the affine parameters + scaleX: sx, + scaleY: sy, + shear: lam, + rotate: theta, + translateX: tx, + translateY: ty, + originX: cx, + originY: cy, + + // Return the matrix parameters + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + } + }, + + // Morph one matrix into another + morph: function (matrix) { + // Store new destination + this.destination = new SVG.Matrix(matrix) + return this + }, + + // Get morphed matrix at a given position + at: function (pos) { + // Make sure a destination is defined + if (!this.destination) return this + + // Calculate morphed matrix at a given position + var matrix = new SVG.Matrix({ + a: this.a + (this.destination.a - this.a) * pos, + b: this.b + (this.destination.b - this.b) * pos, + c: this.c + (this.destination.c - this.c) * pos, + d: this.d + (this.destination.d - this.d) * pos, + e: this.e + (this.destination.e - this.e) * pos, + f: this.f + (this.destination.f - this.f) * pos + }) + + return matrix + }, + + // Left multiplies by the given matrix + multiply: function (matrix) { + return this.clone().multiplyO(matrix) + }, + + multiplyO: function (matrix) { + // Get the matrices + var l = this + var r = matrix instanceof SVG.Matrix + ? matrix + : new SVG.Matrix(matrix) + + return matrixMultiply(l, r, this) + }, + + lmultiply: function (matrix) { + return this.clone().lmultiplyO(matrix) + }, + + lmultiplyO: function (matrix) { + var r = this + var l = matrix instanceof SVG.Matrix + ? matrix + : new SVG.Matrix(matrix) + + return matrixMultiply(l, r, this) + }, + + // Inverses matrix + inverseO: function () { + // Get the current parameters out of the matrix + var a = this.a + var b = this.b + var c = this.c + var d = this.d + var e = this.e + var f = this.f + + // Invert the 2x2 matrix in the top left + var det = a * d - b * c + if (!det) throw new Error('Cannot invert ' + this) + + // Calculate the top 2x2 matrix + var na = d / det + var nb = -b / det + var nc = -c / det + var nd = a / det + + // Apply the inverted matrix to the top right + var ne = -(na * e + nc * f) + var nf = -(nb * e + nd * f) + + // Construct the inverted matrix + this.a = na + this.b = nb + this.c = nc + this.d = nd + this.e = ne + this.f = nf + + return this + }, + + inverse: function () { + return this.clone().inverseO() + }, + + // Translate matrix + translate: function (x, y) { + return this.clone().translateO(x, y) + }, + + translateO: function (x, y) { + this.e += x || 0 + this.f += y || 0 + return this + }, + + // Scale matrix + scale: function (x, y, cx, cy) { + return this.clone().scaleO(...arguments) + }, + + scaleO: function (x, y = x, cx = 0, cy = 0) { + // Support uniform scaling + if (arguments.length === 3) { + cy = cx + cx = y + y = x + } + + let {a, b, c, d, e, f} = this + + this.a = a * x + this.b = b * y + this.c = c * x + this.d = d * y + this.e = e * x - cx * x + cx + this.f = f * y - cy * y + cy + + return this + }, + + // Rotate matrix + rotate: function (r, cx, cy) { + return this.clone().rotateO(r, cx, cy) + }, + + rotateO: function (r, cx = 0, cy = 0) { + // Convert degrees to radians + r = SVG.utils.radians(r) + + let cos = Math.cos(r) + let sin = Math.sin(r) + + let {a, b, c, d, e, f} = this + + this.a = a * cos - b * sin + this.b = b * cos + a * sin + this.c = c * cos - d * sin + this.d = d * cos + c * sin + this.e = e * cos - f * sin + cy * sin - cx * cos + cx + this.f = f * cos + e * sin - cx * sin - cy * cos + cy + + return this + }, + + // Flip matrix on x or y, at a given offset + flip: function (axis, around) { + return this.clone().flipO(axis, around) + }, + + flipO: function (axis, around) { + return axis === 'x' ? this.scaleO(-1, 1, around, 0) + : axis === 'y' ? this.scaleO(1, -1, 0, around) + : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point + }, + + // Shear matrix + shear: function (a, cx, cy) { + return this.clone().shearO(a, cx, cy) + }, + + shearO: function (lx, cx = 0, cy = 0) { + let {a, b, c, d, e, f} = this + + this.a = a + b * lx + this.c = c + d * lx + this.e = e + f * lx - cy * lx + + return this + }, + + // Skew Matrix + skew: function (x, y, cx, cy) { + return this.clone().skewO(...arguments) + }, + + skewO: function (x, y = x, cx = 0, cy = 0) { + // support uniformal skew + if (arguments.length === 3) { + cy = cx + cx = y + y = x + } + + // Convert degrees to radians + x = SVG.utils.radians(x) + y = SVG.utils.radians(y) + + let lx = Math.tan(x) + let ly = Math.tan(y) + + let {a, b, c, d, e, f} = this + + this.a = a + b * lx + this.b = b + a * ly + this.c = c + d * lx + this.d = d + c * ly + this.e = e + f * lx - cy * lx + this.f = f + e * ly - cx * ly + + return this + }, + + // SkewX + skewX: function (x, cx, cy) { + return this.skew(x, 0, cx, cy) + }, + + skewXO: function (x, cx, cy) { + return this.skewO(x, 0, cx, cy) + }, + + // SkewY + skewY: function (y, cx, cy) { + return this.skew(0, y, cx, cy) + }, + + skewYO: function (y, cx, cy) { + return this.skewO(0, y, cx, cy) + }, + + // Transform around a center point + aroundO: function (cx, cy, matrix) { + var dx = cx || 0 + var dy = cy || 0 + return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy) + }, + + around: function (cx, cy, matrix) { + return this.clone().aroundO(cx, cy, matrix) + }, + + // Convert to native SVGMatrix + native: function () { + // create new matrix + var matrix = SVG.parser.nodes.svg.node.createSVGMatrix() + + // update with current values + for (var i = abcdef.length - 1; i >= 0; i--) { + matrix[abcdef[i]] = this[abcdef[i]] + } + + return matrix + }, + + // Check if two matrices are equal + equals: function (other) { + var comp = new SVG.Matrix(other) + return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && + closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && + closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f) + }, + + // Convert matrix to string + toString: function () { + return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')' + }, + + toArray: function () { + return [this.a, this.b, this.c, this.d, this.e, this.f] + }, + + valueOf: function () { + return { + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + } + } + }, + + // Define parent + parent: SVG.Element, + + // Add parent method + construct: { + // Get current matrix + ctm: function () { + return new SVG.Matrix(this.node.getCTM()) + }, + // Get current screen matrix + screenCTM: function () { + /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 + This is needed because FF does not return the transformation matrix + for the inner coordinate system when getScreenCTM() is called on nested svgs. + However all other Browsers do that */ + if (this instanceof SVG.Doc && !this.isRoot()) { + var rect = this.rect(1, 1) + var m = rect.node.getScreenCTM() + rect.remove() + return new SVG.Matrix(m) + } + return new SVG.Matrix(this.node.getScreenCTM()) + } + } +}) + +// let extensions = {} +// ['rotate'].forEach((method) => { +// let methodO = method + 'O' +// extensions[method] = function (...args) { +// return new SVG.Matrix(this)[methodO](...args) +// } +// }) +// +// SVG.extend(SVG.Matrix, extensions) + +// function matrixMultiplyParams (matrix, a, b, c, d, e, f) { +// return matrixMultiply({a, b, c, d, e, f}, matrix, matrix) +// } diff --git a/src/Morphable.js b/src/Morphable.js new file mode 100644 index 0000000..acb9e21 --- /dev/null +++ b/src/Morphable.js @@ -0,0 +1,231 @@ + +SVG.Morphable = SVG.invent({ + create: function (stepper) { + // FIXME: the default stepper does not know about easing + this._stepper = stepper || new SVG.Ease('-') + + this._from = null + this._to = null + this._type = null + this._context = null + this._morphObj = null + }, + + extend: { + + from: function (val) { + if (val == null) { + return this._from + } + + this._from = this._set(val) + return this + }, + + to: function (val) { + if (val == null) { + return this._to + } + + this._to = this._set(val) + return this + }, + + type: function (type) { + // getter + if (type == null) { + return this._type + } + + // setter + this._type = type + return this + }, + + _set: function (value) { + if (!this._type) { + var type = typeof value + + if (type === 'number') { + this.type(SVG.Number) + } else if (type === 'string') { + if (SVG.Color.isColor(value)) { + this.type(SVG.Color) + } else if (SVG.regex.delimiter.test(value)) { + this.type(SVG.regex.pathLetters.test(value) + ? SVG.PathArray + : SVG.Array + ) + } else if (SVG.regex.numberAndUnit.test(value)) { + this.type(SVG.Number) + } else { + this.type(SVG.Morphable.NonMorphable) + } + } else if (SVG.MorphableTypes.indexOf(value.constructor) > -1) { + this.type(value.constructor) + } else if (Array.isArray(value)) { + this.type(SVG.Array) + } else if (type === 'object') { + this.type(SVG.Morphable.ObjectBag) + } else { + this.type(SVG.Morphable.NonMorphable) + } + } + + var result = (new this._type(value)).toArray() + this._morphObj = this._morphObj || new this._type() + this._context = this._context || + Array.apply(null, Array(result.length)).map(Object) + return result + }, + + stepper: function (stepper) { + if (stepper == null) return this._stepper + this._stepper = stepper + return this + }, + + done: function () { + var complete = this._context + .map(this._stepper.done) + .reduce(function (last, curr) { + return last && curr + }, true) + return complete + }, + + at: function (pos) { + var _this = this + + return this._morphObj.fromArray( + this._from.map(function (i, index) { + return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context) + }) + ) + } + } +}) + +SVG.Morphable.NonMorphable = SVG.invent({ + create: function (val) { + val = Array.isArray(val) ? val[0] : val + this.value = val + }, + + extend: { + valueOf: function () { + return this.value + }, + + toArray: function () { + return [this.value] + } + } +}) + +SVG.Morphable.TransformBag = SVG.invent({ + create: function (obj) { + if (Array.isArray(obj)) { + obj = { + scaleX: obj[0], + scaleY: obj[1], + shear: obj[2], + rotate: obj[3], + translateX: obj[4], + translateY: obj[5], + originX: obj[6], + originY: obj[7] + } + } + + Object.assign(this, SVG.Morphable.TransformBag.defaults, obj) + }, + + extend: { + toArray: function () { + var v = this + + return [ + v.scaleX, + v.scaleY, + v.shear, + v.rotate, + v.translateX, + v.translateY, + v.originX, + v.originY + ] + } + } +}) + +SVG.Morphable.TransformBag.defaults = { + scaleX: 1, + scaleY: 1, + shear: 0, + rotate: 0, + translateX: 0, + translateY: 0, + originX: 0, + originY: 0 +} + +SVG.Morphable.ObjectBag = SVG.invent({ + create: function (objOrArr) { + this.values = [] + + if (Array.isArray(objOrArr)) { + this.values = objOrArr + return + } + + var entries = Object.entries(objOrArr || {}).sort((a, b) => { + return a[0] - b[0] + }) + + this.values = entries.reduce((last, curr) => last.concat(curr), []) + }, + + extend: { + valueOf: function () { + var obj = {} + var arr = this.values + + for (var i = 0, len = arr.length; i < len; i += 2) { + obj[arr[i]] = arr[i + 1] + } + + return obj + }, + + toArray: function () { + return this.values + } + } +}) + +SVG.MorphableTypes = [ + SVG.Number, + SVG.Color, + SVG.Box, + SVG.Matrix, + SVG.Array, + SVG.PointArray, + SVG.PathArray, + SVG.Morphable.NonMorphable, + SVG.Morphable.TransformBag, + SVG.Morphable.ObjectBag +] + +SVG.extend(SVG.MorphableTypes, { + to: function (val, args) { + return new SVG.Morphable() + .type(this.constructor) + .from(this.valueOf()) + .to(val, args) + }, + fromArray: function (arr) { + this.constructor(arr) + return this + } +}) diff --git a/src/Parent.js b/src/Parent.js new file mode 100644 index 0000000..6bdad58 --- /dev/null +++ b/src/Parent.js @@ -0,0 +1,92 @@ +/* global createElement */ + +SVG.Parent = SVG.invent({ + // Initialize node + create: function (node) { + SVG.Element.call(this, node) + }, + + // Inherit from + inherit: SVG.Element, + + // Add class methods + extend: { + // Returns all child elements + children: function () { + return SVG.utils.map(this.node.children, function (node) { + return SVG.adopt(node) + }) + }, + // Add given element at a position + add: function (element, i) { + element = createElement(element) + + if (element.node !== this.node.children[i]) { + this.node.insertBefore(element.node, this.node.children[i] || null) + } + + return this + }, + // Basically does the same as `add()` but returns the added element instead + put: function (element, i) { + this.add(element, i) + return element.instance || element + }, + // Checks if the given element is a child + has: function (element) { + return this.index(element) >= 0 + }, + // Gets index of given element + index: function (element) { + return [].slice.call(this.node.children).indexOf(element.node) + }, + // Get a element at the given index + get: function (i) { + return SVG.adopt(this.node.children[i]) + }, + // Get first child + first: function () { + return this.get(0) + }, + // Get the last child + last: function () { + return this.get(this.node.children.length - 1) + }, + // Iterates over all children and invokes a given block + each: function (block, deep) { + var children = this.children() + var i, il + + for (i = 0, il = children.length; i < il; i++) { + if (children[i] instanceof SVG.Element) { + block.apply(children[i], [i, children]) + } + + if (deep && (children[i] instanceof SVG.Parent)) { + children[i].each(block, deep) + } + } + + return this + }, + // Remove a given child + removeElement: function (element) { + this.node.removeChild(element.node) + + return this + }, + // Remove all elements in this container + clear: function () { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild) + } + + // remove defs reference + delete this._defs + + return this + } + } + +}) diff --git a/src/Path.js b/src/Path.js new file mode 100644 index 0000000..db3929b --- /dev/null +++ b/src/Path.js @@ -0,0 +1,63 @@ +/* global proportionalSize */ + +SVG.Path = SVG.invent({ + // Initialize node + create: 'path', + + // Inherit from + inherit: SVG.Shape, + + // Add class methods + extend: { + // Define morphable array + MorphArray: SVG.PathArray, + // Get array + array: function () { + return this._array || (this._array = new SVG.PathArray(this.attr('d'))) + }, + // Plot new path + plot: function (d) { + return (d == null) ? this.array() + : this.clear().attr('d', typeof d === 'string' ? d : (this._array = new SVG.PathArray(d))) + }, + // Clear array cache + clear: function () { + delete this._array + return this + }, + // Move by left top corner + move: function (x, y) { + return this.attr('d', this.array().move(x, y)) + }, + // Move by left top corner over x-axis + x: function (x) { + return x == null ? this.bbox().x : this.move(x, this.bbox().y) + }, + // Move by left top corner over y-axis + y: function (y) { + return y == null ? this.bbox().y : this.move(this.bbox().x, y) + }, + // Set element size to given width and height + size: function (width, height) { + var p = proportionalSize(this, width, height) + return this.attr('d', this.array().size(p.width, p.height)) + }, + // Set width of element + width: function (width) { + return width == null ? this.bbox().width : this.size(width, this.bbox().height) + }, + // Set height of element + height: function (height) { + return height == null ? this.bbox().height : this.size(this.bbox().width, height) + } + }, + + // Add parent method + construct: { + // Create a wrapped path element + path: function (d) { + // make sure plot is called as a setter + return this.put(new SVG.Path()).plot(d || new SVG.PathArray()) + } + } +}) diff --git a/src/PathArray.js b/src/PathArray.js new file mode 100644 index 0000000..4432df3 --- /dev/null +++ b/src/PathArray.js @@ -0,0 +1,289 @@ +/* globals arrayToString, pathRegReplace */ + +var pathHandlers = { + M: function (c, p, p0) { + p.x = p0.x = c[0] + p.y = p0.y = c[1] + + return ['M', p.x, p.y] + }, + L: function (c, p) { + p.x = c[0] + p.y = c[1] + return ['L', c[0], c[1]] + }, + H: function (c, p) { + p.x = c[0] + return ['H', c[0]] + }, + V: function (c, p) { + p.y = c[0] + return ['V', c[0]] + }, + C: function (c, p) { + p.x = c[4] + p.y = c[5] + return ['C', c[0], c[1], c[2], c[3], c[4], c[5]] + }, + S: function (c, p) { + p.x = c[2] + p.y = c[3] + return ['S', c[0], c[1], c[2], c[3]] + }, + Q: function (c, p) { + p.x = c[2] + p.y = c[3] + return ['Q', c[0], c[1], c[2], c[3]] + }, + T: function (c, p) { + p.x = c[0] + p.y = c[1] + return ['T', c[0], c[1]] + }, + Z: function (c, p, p0) { + p.x = p0.x + p.y = p0.y + return ['Z'] + }, + A: function (c, p) { + p.x = c[5] + p.y = c[6] + return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]] + } +} + +var mlhvqtcsaz = 'mlhvqtcsaz'.split('') + +for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { + pathHandlers[mlhvqtcsaz[i]] = (function (i) { + return function (c, p, p0) { + if (i === 'H') c[0] = c[0] + p.x + else if (i === 'V') c[0] = c[0] + p.y + else if (i === 'A') { + c[5] = c[5] + p.x + c[6] = c[6] + p.y + } else { + for (var j = 0, jl = c.length; j < jl; ++j) { + c[j] = c[j] + (j % 2 ? p.y : p.x) + } + } + + return pathHandlers[i](c, p, p0) + } + })(mlhvqtcsaz[i].toUpperCase()) +} + +// Path points array +SVG.PathArray = function (array, fallback) { + SVG.Array.call(this, array, fallback || [['M', 0, 0]]) +} + +// Inherit from SVG.Array +SVG.PathArray.prototype = new SVG.Array() +SVG.PathArray.prototype.constructor = SVG.PathArray + +SVG.extend(SVG.PathArray, { + // Convert array to string + toString: function () { + return arrayToString(this.value) + }, + toArray: function () { + return this.value.reduce(function (prev, curr) { + return [].concat.call(prev, curr) + }, []) + }, + // Move path string + move: function (x, y) { + // get bounding box of current situation + var box = this.bbox() + + // get relative offset + x -= box.x + y -= box.y + + if (!isNaN(x) && !isNaN(y)) { + // move every point + for (var l, i = this.value.length - 1; i >= 0; i--) { + l = this.value[i][0] + + if (l === 'M' || l === 'L' || l === 'T') { + this.value[i][1] += x + this.value[i][2] += y + } else if (l === 'H') { + this.value[i][1] += x + } else if (l === 'V') { + this.value[i][1] += y + } else if (l === 'C' || l === 'S' || l === 'Q') { + this.value[i][1] += x + this.value[i][2] += y + this.value[i][3] += x + this.value[i][4] += y + + if (l === 'C') { + this.value[i][5] += x + this.value[i][6] += y + } + } else if (l === 'A') { + this.value[i][6] += x + this.value[i][7] += y + } + } + } + + return this + }, + // Resize path string + size: function (width, height) { + // get bounding box of current situation + var box = this.bbox() + var i, l + + // recalculate position of all points according to new size + for (i = this.value.length - 1; i >= 0; i--) { + l = this.value[i][0] + + if (l === 'M' || l === 'L' || l === 'T') { + this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x + this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y + } else if (l === 'H') { + this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x + } else if (l === 'V') { + this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y + } else if (l === 'C' || l === 'S' || l === 'Q') { + this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x + this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y + this.value[i][3] = ((this.value[i][3] - box.x) * width) / box.width + box.x + this.value[i][4] = ((this.value[i][4] - box.y) * height) / box.height + box.y + + if (l === 'C') { + this.value[i][5] = ((this.value[i][5] - box.x) * width) / box.width + box.x + this.value[i][6] = ((this.value[i][6] - box.y) * height) / box.height + box.y + } + } else if (l === 'A') { + // resize radii + this.value[i][1] = (this.value[i][1] * width) / box.width + this.value[i][2] = (this.value[i][2] * height) / box.height + + // move position values + this.value[i][6] = ((this.value[i][6] - box.x) * width) / box.width + box.x + this.value[i][7] = ((this.value[i][7] - box.y) * height) / box.height + box.y + } + } + + return this + }, + // Test if the passed path array use the same path data commands as this path array + equalCommands: function (pathArray) { + var i, il, equalCommands + + pathArray = new SVG.PathArray(pathArray) + + equalCommands = this.value.length === pathArray.value.length + for (i = 0, il = this.value.length; equalCommands && i < il; i++) { + equalCommands = this.value[i][0] === pathArray.value[i][0] + } + + return equalCommands + }, + // Make path array morphable + morph: function (pathArray) { + pathArray = new SVG.PathArray(pathArray) + + if (this.equalCommands(pathArray)) { + this.destination = pathArray + } else { + this.destination = null + } + + return this + }, + // Get morphed path array at given position + at: function (pos) { + // make sure a destination is defined + if (!this.destination) return this + + var sourceArray = this.value + var destinationArray = this.destination.value + var array = [] + var pathArray = new SVG.PathArray() + var i, il, j, jl + + // Animate has specified in the SVG spec + // See: https://www.w3.org/TR/SVG11/paths.html#PathElement + for (i = 0, il = sourceArray.length; i < il; i++) { + array[i] = [sourceArray[i][0]] + for (j = 1, jl = sourceArray[i].length; j < jl; j++) { + array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos + } + // For the two flags of the elliptical arc command, the SVG spec say: + // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true + // Elliptical arc command as an array followed by corresponding indexes: + // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // 0 1 2 3 4 5 6 7 + if (array[i][0] === 'A') { + array[i][4] = +(array[i][4] !== 0) + array[i][5] = +(array[i][5] !== 0) + } + } + + // Directly modify the value of a path array, this is done this way for performance + pathArray.value = array + return pathArray + }, + // Absolutize and parse path to array + parse: function (array) { + // if it's already a patharray, no need to parse it + if (array instanceof SVG.PathArray) return array.valueOf() + + // prepare for parsing + var s + var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 } + + if (typeof array === 'string') { + array = array + .replace(SVG.regex.numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 + .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers + .replace(SVG.regex.hyphen, '$1 -') // add space before hyphen + .trim() // trim + .split(SVG.regex.delimiter) // split into array + } else { + array = array.reduce(function (prev, curr) { + return [].concat.call(prev, curr) + }, []) + } + + // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] + var result = [] + var p = new SVG.Point() + var p0 = new SVG.Point() + var index = 0 + var len = array.length + + do { + // Test if we have a path letter + if (SVG.regex.isPathLetter.test(array[index])) { + s = array[index] + ++index + // If last letter was a move command and we got no new, it defaults to [L]ine + } else if (s === 'M') { + s = 'L' + } else if (s === 'm') { + s = 'l' + } + + result.push(pathHandlers[s].call(null, + array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), + p, p0 + ) + ) + } while (len > index) + + return result + }, + // Get bounding box of path + bbox: function () { + SVG.parser().path.setAttribute('d', this.toString()) + return SVG.parser.nodes.path.getBBox() + } + +}) diff --git a/src/Pattern.js b/src/Pattern.js new file mode 100644 index 0000000..d4c4116 --- /dev/null +++ b/src/Pattern.js @@ -0,0 +1,59 @@ +SVG.Pattern = SVG.invent({ + // Initialize node + create: 'pattern', + + // Inherit from + inherit: SVG.Container, + + // Add class methods + extend: { + // Return the fill id + url: function () { + return 'url(#' + this.id() + ')' + }, + // Update pattern by rebuilding + update: function (block) { + // remove content + this.clear() + + // invoke passed block + if (typeof block === 'function') { + block.call(this, this) + } + + return this + }, + // Alias string convertion to fill + toString: function () { + return this.url() + }, + // custom attr to handle transform + attr: function (a, b, c) { + if (a === 'transform') a = 'patternTransform' + return SVG.Container.prototype.attr.call(this, a, b, c) + } + + }, + + // Add parent method + construct: { + // Create pattern element in defs + pattern: function (width, height, block) { + return this.defs().pattern(width, height, block) + } + } +}) + +SVG.extend(SVG.Defs, { + // Define gradient + pattern: function (width, height, block) { + return this.put(new SVG.Pattern()).update(block).attr({ + x: 0, + y: 0, + width: width, + height: height, + patternUnits: 'userSpaceOnUse' + }) + } + +}) diff --git a/src/Point.js b/src/Point.js new file mode 100644 index 0000000..6c64ed6 --- /dev/null +++ b/src/Point.js @@ -0,0 +1,74 @@ + +SVG.Point = SVG.invent({ + // Initialize + create: function (x, y, base) { + var source + base = base || {x: 0, y: 0} + + // ensure source as object + source = Array.isArray(x) ? {x: x[0], y: x[1]} + : typeof x === 'object' ? {x: x.x, y: x.y} + : {x: x, y: y} + + // merge source + this.x = source.x == null ? base.x : source.x + this.y = source.y == null ? base.y : source.y + }, + + // Add methods + extend: { + // Clone point + clone: function () { + return new SVG.Point(this) + }, + + // Morph one point into another + morph: function (x, y) { + // store new destination + this.destination = new SVG.Point(x, y) + return this + }, + + // Get morphed point at a given position + at: function (pos) { + // make sure a destination is defined + if (!this.destination) return this + + // calculate morphed matrix at a given position + var point = new SVG.Point({ + x: this.x + (this.destination.x - this.x) * pos, + y: this.y + (this.destination.y - this.y) * pos + }) + return point + }, + + // Convert to native SVGPoint + native: function () { + // create new point + var point = SVG.parser.nodes.svg.node.createSVGPoint() + + // update with current values + point.x = this.x + point.y = this.y + return point + }, + + // transform point with matrix + transform: function (m) { + // Perform the matrix multiplication + var x = m.a * this.x + m.c * this.y + m.e + var y = m.b * this.x + m.d * this.y + m.f + + // Return the required point + return new SVG.Point(x, y) + } + } +}) + +SVG.extend(SVG.Element, { + + // Get point + point: function (x, y) { + return new SVG.Point(x, y).transform(this.screenCTM().inverse()) + } +}) diff --git a/src/PointArray.js b/src/PointArray.js new file mode 100644 index 0000000..aa5f84a --- /dev/null +++ b/src/PointArray.js @@ -0,0 +1,128 @@ + +// Poly points array +SVG.PointArray = function (array, fallback) { + SVG.Array.call(this, array, fallback || [[0, 0]]) +} + +// Inherit from SVG.Array +SVG.PointArray.prototype = new SVG.Array() +SVG.PointArray.prototype.constructor = SVG.PointArray + +SVG.extend(SVG.PointArray, { + // Convert array to string + toString: function () { + // convert to a poly point string + for (var i = 0, il = this.value.length, array = []; i < il; i++) { + array.push(this.value[i].join(',')) + } + + return array.join(' ') + }, + + toArray: function () { + return this.value.reduce(function (prev, curr) { + return [].concat.call(prev, curr) + }, []) + }, + + // Convert array to line object + toLine: function () { + return { + x1: this.value[0][0], + y1: this.value[0][1], + x2: this.value[1][0], + y2: this.value[1][1] + } + }, + + // Get morphed array at given position + at: function (pos) { + // make sure a destination is defined + if (!this.destination) return this + + // generate morphed point string + for (var i = 0, il = this.value.length, array = []; i < il; i++) { + array.push([ + this.value[i][0] + (this.destination[i][0] - this.value[i][0]) * pos, + this.value[i][1] + (this.destination[i][1] - this.value[i][1]) * pos + ]) + } + + return new SVG.PointArray(array) + }, + + // Parse point string and flat array + parse: function (array) { + var points = [] + + array = array.valueOf() + + // if it is an array + if (Array.isArray(array)) { + // and it is not flat, there is no need to parse it + if (Array.isArray(array[0])) { + return array + } + } else { // Else, it is considered as a string + // parse points + array = array.trim().split(SVG.regex.delimiter).map(parseFloat) + } + + // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints + // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. + if (array.length % 2 !== 0) array.pop() + + // wrap points in two-tuples and parse points as floats + for (var i = 0, len = array.length; i < len; i = i + 2) { + points.push([ array[i], array[i + 1] ]) + } + + return points + }, + + // Move point string + move: function (x, y) { + var box = this.bbox() + + // get relative offset + x -= box.x + y -= box.y + + // move every point + if (!isNaN(x) && !isNaN(y)) { + for (var i = this.value.length - 1; i >= 0; i--) { + this.value[i] = [this.value[i][0] + x, this.value[i][1] + y] + } + } + + return this + }, + // Resize poly string + size: function (width, height) { + var i + var box = this.bbox() + + // recalculate position of all points according to new size + for (i = this.value.length - 1; i >= 0; i--) { + if (box.width) this.value[i][0] = ((this.value[i][0] - box.x) * width) / box.width + box.x + if (box.height) this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y + } + + return this + }, + + // Get bounding box of points + bbox: function () { + var maxX = -Infinity + var maxY = -Infinity + var minX = Infinity + var minY = Infinity + this.value.forEach(function (el) { + maxX = Math.max(el[0], maxX) + maxY = Math.max(el[1], maxY) + minX = Math.min(el[0], minX) + minY = Math.min(el[1], minY) + }) + return {x: minX, y: minY, width: maxX - minX, height: maxY - minY} + } +}) diff --git a/src/Polygon.js b/src/Polygon.js new file mode 100644 index 0000000..9625776 --- /dev/null +++ b/src/Polygon.js @@ -0,0 +1,67 @@ +/* global proportionalSize */ + +SVG.Polyline = SVG.invent({ + // Initialize node + create: 'polyline', + + // Inherit from + inherit: SVG.Shape, + + // Add parent method + construct: { + // Create a wrapped polyline element + polyline: function (p) { + // make sure plot is called as a setter + return this.put(new SVG.Polyline()).plot(p || new SVG.PointArray()) + } + } +}) + +SVG.Polygon = SVG.invent({ + // Initialize node + create: 'polygon', + + // Inherit from + inherit: SVG.Shape, + + // Add parent method + construct: { + // Create a wrapped polygon element + polygon: function (p) { + // make sure plot is called as a setter + return this.put(new SVG.Polygon()).plot(p || new SVG.PointArray()) + } + } +}) + +// Add polygon-specific functions +SVG.extend([SVG.Polyline, SVG.Polygon], { + // Get array + array: function () { + return this._array || (this._array = new SVG.PointArray(this.attr('points'))) + }, + + // Plot new path + plot: function (p) { + return (p == null) ? this.array() + : this.clear().attr('points', typeof p === 'string' ? p + : (this._array = new SVG.PointArray(p))) + }, + + // Clear array cache + clear: function () { + delete this._array + return this + }, + + // Move by left top corner + move: function (x, y) { + return this.attr('points', this.array().move(x, y)) + }, + + // Set element size to given width and height + size: function (width, height) { + var p = proportionalSize(this, width, height) + return this.attr('points', this.array().size(p.width, p.height)) + } +}) diff --git a/src/Queue.js b/src/Queue.js new file mode 100644 index 0000000..621c887 --- /dev/null +++ b/src/Queue.js @@ -0,0 +1,61 @@ +SVG.Queue = SVG.invent({ + create: function () { + this._first = null + this._last = null + }, + + extend: { + push: function (value) { + // An item stores an id and the provided value + var item = value.next ? value : { value: value, next: null, prev: null } + + // Deal with the queue being empty or populated + if (this._last) { + item.prev = this._last + this._last.next = item + this._last = item + } else { + this._last = item + this._first = item + } + + // Update the length and return the current item + return item + }, + + shift: function () { + // Check if we have a value + var remove = this._first + if (!remove) return null + + // If we do, remove it and relink things + this._first = remove.next + if (this._first) this._first.prev = null + this._last = this._first ? this._last : null + return remove.value + }, + + // Shows us the first item in the list + first: function () { + return this._first && this._first.value + }, + + // Shows us the last item in the list + last: function () { + return this._last && this._last.value + }, + + // Removes the item that was returned from the push + remove: function (item) { + // Relink the previous item + if (item.prev) item.prev.next = item.next + if (item.next) item.next.prev = item.prev + if (item === this._last) this._last = item.prev + if (item === this._first) this._first = item.next + + // Invalidate item + item.prev = null + item.next = null + } + } +}) diff --git a/src/Rect.js b/src/Rect.js new file mode 100644 index 0000000..35a3678 --- /dev/null +++ b/src/Rect.js @@ -0,0 +1,16 @@ + +SVG.Rect = SVG.invent({ + // Initialize node + create: 'rect', + + // Inherit from + inherit: SVG.Shape, + + // Add parent method + construct: { + // Create a rect element + rect: function (width, height) { + return this.put(new SVG.Rect()).size(width, height) + } + } +}) diff --git a/src/Runner.js b/src/Runner.js new file mode 100644 index 0000000..97e04e2 --- /dev/null +++ b/src/Runner.js @@ -0,0 +1,928 @@ +/* global isMatrixLike getOrigin */ + +SVG.easing = { + '-': function (pos) { return pos }, + '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, + '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, + '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } +} + +SVG.Runner = SVG.invent({ + parent: SVG.Element, + + create: function (options) { + // Store a unique id on the runner, so that we can identify it later + this.id = SVG.Runner.id++ + + // Ensure a default value + options = options == null + ? SVG.defaults.timeline.duration + : options + + // Ensure that we get a controller + options = typeof options === 'function' + ? new SVG.Controller(options) + : options + + // Declare all of the variables + this._element = null + this._timeline = null + this.done = false + this._queue = [] + + // Work out the stepper and the duration + this._duration = typeof options === 'number' && options + this._isDeclarative = options instanceof SVG.Controller + this._stepper = this._isDeclarative ? options : new SVG.Ease() + + // We copy the current values from the timeline because they can change + this._history = {} + + // Store the state of the runner + this.enabled = true + this._time = 0 + this._last = 0 + + // Save transforms applied to this runner + this.transforms = new SVG.Matrix() + this.transformId = 1 + + // Looping variables + this._haveReversed = false + this._reverse = false + this._loopsDone = 0 + this._swing = false + this._wait = 0 + this._times = 1 + }, + + construct: { + + animate: function (duration, delay, when) { + var o = SVG.Runner.sanitise(duration, delay, when) + var timeline = this.timeline() + return new SVG.Runner(o.duration) + .loop(o) + .element(this) + .timeline(timeline) + .schedule(delay, when) + }, + + delay: function (by, when) { + return this.animate(0, by, when) + } + }, + + extend: { + + /* + Runner Definitions + ================== + These methods help us define the runtime behaviour of the Runner or they + help us make new runners from the current runner + */ + + element: function (element) { + if (element == null) return this._element + this._element = element + element._prepareRunner() + return this + }, + + timeline: function (timeline) { + // check explicitly for undefined so we can set the timeline to null + if (typeof timeline === 'undefined') return this._timeline + this._timeline = timeline + return this + }, + + animate: function (duration, delay, when) { + var o = SVG.Runner.sanitise(duration, delay, when) + var runner = new SVG.Runner(o.duration) + if (this._timeline) runner.timeline(this._timeline) + if (this._element) runner.element(this._element) + return runner.loop(o).schedule(delay, when) + }, + + schedule: function (timeline, delay, when) { + // The user doesn't need to pass a timeline if we already have one + if (!(timeline instanceof SVG.Timeline)) { + when = delay + delay = timeline + timeline = this.timeline() + } + + // If there is no timeline, yell at the user... + if (!timeline) { + throw Error('Runner cannot be scheduled without timeline') + } + + // Schedule the runner on the timeline provided + timeline.schedule(this, delay, when) + return this + }, + + unschedule: function () { + var timeline = this.timeline() + timeline && timeline.unschedule(this) + return this + }, + + loop: function (times, swing, wait) { + // Deal with the user passing in an object + if (typeof times === 'object') { + swing = times.swing + wait = times.wait + times = times.times + } + + // Sanitise the values and store them + this._times = times || Infinity + this._swing = swing || false + this._wait = wait || 0 + return this + }, + + delay: function (delay) { + return this.animate(0, delay) + }, + + /* + Basic Functionality + =================== + These methods allow us to attach basic functions to the runner directly + */ + + queue: function (initFn, runFn, isTransform) { + this._queue.push({ + initialiser: initFn || SVG.void, + runner: runFn || SVG.void, + isTransform: isTransform, + initialised: false, + finished: false + }) + var timeline = this.timeline() + timeline && this.timeline()._continue() + return this + }, + + during: function (fn) { + return this.queue(null, fn) + }, + + after (fn) { + return this.on('finish', fn) + }, + + /* + Runner animation methods + ======================== + Control how the animation plays + */ + + time: function (time) { + if (time == null) { + return this._time + } + let dt = time - this._time + this.step(dt) + return this + }, + + duration: function () { + return this._times * (this._wait + this._duration) - this._wait + }, + + loops: function (p) { + var loopDuration = this._duration + this._wait + if (p == null) { + var loopsDone = Math.floor(this._time / loopDuration) + var relativeTime = (this._time - loopsDone * loopDuration) + var position = relativeTime / this._duration + return Math.min(loopsDone + position, this._times) + } + var whole = Math.floor(p) + var partial = p % 1 + var time = loopDuration * whole + this._duration * partial + return this.time(time) + }, + + position: function (p) { + // Get all of the variables we need + var x = this._time + var d = this._duration + var w = this._wait + var t = this._times + var s = this._swing + var r = this._reverse + var position + + if (p == null) { + /* + This function converts a time to a position in the range [0, 1] + The full explanation can be found in this desmos demonstration + https://www.desmos.com/calculator/u4fbavgche + The logic is slightly simplified here because we can use booleans + */ + + // Figure out the value without thinking about the start or end time + const f = function (x) { + var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)) + var backwards = (swinging && !r) || (!swinging && r) + var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards + var clipped = Math.max(Math.min(uncliped, 1), 0) + return clipped + } + + // Figure out the value by incorporating the start time + var endTime = t * (w + d) - w + position = x <= 0 ? Math.round(f(1e-5)) + : x < endTime ? f(x) + : Math.round(f(endTime - 1e-5)) + return position + } + + // Work out the loops done and add the position to the loops done + var loopsDone = Math.floor(this.loops()) + var swingForward = s && (loopsDone % 2 === 0) + var forwards = (swingForward && !r) || (r && swingForward) + position = loopsDone + (forwards ? p : 1 - p) + return this.loops(position) + }, + + progress: function (p) { + if (p == null) { + return Math.min(1, this._time / this.duration()) + } + return this.time(p * this.duration()) + }, + + step: function (dt) { + // If we are inactive, this stepper just gets skipped + if (!this.enabled) return this + + // Update the time and get the new position + dt = dt == null ? 16 : dt + this._time += dt + var position = this.position() + + // Figure out if we need to run the stepper in this frame + var running = this._lastPosition !== position && this._time >= 0 + this._lastPosition = position + + // Figure out if we just started + var duration = this.duration() + var justStarted = this._lastTime < 0 && this._time > 0 + var justFinished = this._lastTime < this._time && this.time > duration + this._lastTime = this._time + if (justStarted) { + // this.fire('start', this) + } + + // Work out if the runner is finished set the done flag here so animations + // know, that they are running in the last step (this is good for + // transformations which can be merged) + var declarative = this._isDeclarative + this.done = !declarative && !justFinished && this._time >= duration + + // Call initialise and the run function + if (running || declarative) { + this._initialise(running) + + // clear the transforms on this runner so they dont get added again and again + this.transforms = new SVG.Matrix() + var converged = this._run(declarative ? dt : position) + // this.fire('step', this) + } + // correct the done flag here + // declaritive animations itself know when they converged + this.done = this.done || (converged && declarative) + // if (this.done) { + // this.fire('finish', this) + // } + return this + }, + + finish: function () { + return this.step(Infinity) + }, + + reverse: function (reverse) { + this._reverse = reverse == null ? !this._reverse : reverse + return this + }, + + ease: function (fn) { + this._stepper = new SVG.Ease(fn) + return this + }, + + active: function (enabled) { + if (enabled == null) return this.enabled + this.enabled = enabled + return this + }, + + /* + Private Methods + =============== + Methods that shouldn't be used externally + */ + + // Save a morpher to the morpher list so that we can retarget it later + _rememberMorpher: function (method, morpher) { + this._history[method] = { + morpher: morpher, + caller: this._queue[this._queue.length - 1] + } + }, + + // Try to set the target for a morpher if the morpher exists, otherwise + // do nothing and return false + _tryRetarget: function (method, target) { + if (this._history[method]) { + // if the last method wasnt even initialised, throw it away + if (!this._history[method].caller.initialised) { + let index = this._queue.indexOf(this._history[method].caller) + this._queue.splice(index, 1) + return false + } + + // for the case of transformations, we use the special retarget function + // which has access to the outer scope + if (this._history[method].caller.isTransform) { + this._history[method].caller.isTransform(target) + // for everything else a simple morpher change is sufficient + } else { + this._history[method].morpher.to(target) + } + + this._history[method].caller.finished = false + var timeline = this.timeline() + timeline && timeline._continue() + return true + } + return false + }, + + // Run each initialise function in the runner if required + _initialise: function (running) { + // If we aren't running, we shouldn't initialise when not declarative + if (!running && !this._isDeclarative) return + + // Loop through all of the initialisers + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current initialiser + var current = this._queue[i] + + // Determine whether we need to initialise + var needsIt = this._isDeclarative || (!current.initialised && running) + running = !current.finished + + // Call the initialiser if we need to + if (needsIt && running) { + current.initialiser.call(this) + current.initialised = true + } + } + }, + + // Run each run function for the position or dt given + _run: function (positionOrDt) { + // Run all of the _queue directly + var allfinished = true + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current function to run + var current = this._queue[i] + + // Run the function if its not finished, we keep track of the finished + // flag for the sake of declarative _queue + var converged = current.runner.call(this, positionOrDt) + current.finished = current.finished || (converged === true) + allfinished = allfinished && current.finished + } + + // We report when all of the constructors are finished + return allfinished + }, + + addTransform: function (transform, index) { + this.transforms.lmultiplyO(transform) + return this + }, + + clearTransform: function () { + this.transforms = new SVG.Matrix() + return this + } + } +}) + +SVG.Runner.id = 0 + +SVG.Runner.sanitise = function (duration, delay, when) { + // Initialise the default parameters + var times = 1 + var swing = false + var wait = 0 + duration = duration || SVG.defaults.timeline.duration + delay = delay || SVG.defaults.timeline.delay + when = when || 'last' + + // If we have an object, unpack the values + if (typeof duration === 'object' && !(duration instanceof SVG.Stepper)) { + delay = duration.delay || delay + when = duration.when || when + swing = duration.swing || swing + times = duration.times || times + wait = duration.wait || wait + duration = duration.duration || SVG.defaults.timeline.duration + } + + return { + duration: duration, + delay: delay, + swing: swing, + times: times, + wait: wait, + when: when + } +} + +SVG.FakeRunner = class { + constructor (transforms = new SVG.Matrix(), id = -1, done = true) { + this.transforms = transforms + this.id = id + this.done = done + } +} + +SVG.extend([SVG.Runner, SVG.FakeRunner], { + mergeWith (runner) { + return new SVG.FakeRunner( + runner.transforms.lmultiply(this.transforms), + runner.id + ) + } +}) + +// SVG.FakeRunner.emptyRunner = new SVG.FakeRunner() + +const lmultiply = (last, curr) => last.lmultiplyO(curr) +const getRunnerTransform = (runner) => runner.transforms + +function mergeTransforms () { + // Find the matrix to apply to the element and apply it + let runners = this._transformationRunners.runners + let netTransform = runners + .map(getRunnerTransform) + .reduce(lmultiply, new SVG.Matrix()) + + this.transform(netTransform) + + this._transformationRunners.merge() + + if (this._transformationRunners.length() === 1) { + this._frameId = null + } +} + +class RunnerArray { + constructor () { + this.runners = [] + this.ids = [] + } + + add (runner) { + if (this.runners.includes(runner)) return + + let id = runner.id + 1 + + let leftSibling = this.ids.reduce((last, curr) => { + if (curr > last && curr < id) return curr + return last + }, 0) + + let index = this.ids.indexOf(leftSibling) + 1 + + this.ids.splice(index, 0, id) + this.runners.splice(index, 0, runner) + + return this + } + + getByID (id) { + return this.runners[this.ids.indexOf(id + 1)] + } + + remove (id) { + let index = this.ids.indexOf(id + 1) + this.ids.splice(index, 1) + this.runners.splice(index, 1) + return this + } + + merge () { + let lastRunner = null + this.runners.forEach((runner, i) => { + if (lastRunner && runner.done && lastRunner.done) { + this.remove(runner.id) + this.edit(lastRunner.id, runner.mergeWith(lastRunner)) + } + + lastRunner = runner + }) + + return this + } + + edit (id, newRunner) { + let index = this.ids.indexOf(id + 1) + this.ids.splice(index, 1, id) + this.runners.splice(index, 1, newRunner) + return this + } + + length () { + return this.ids.length + } + + clearBefore (id) { + let deleteCnt = this.ids.indexOf(id + 1) || 1 + this.ids.splice(0, deleteCnt, 0) + this.runners.splice(0, deleteCnt, new SVG.FakeRunner()) + return this + } +} + +SVG.extend(SVG.Element, { + // this function searches for all runners on the element and deletes the ones + // which run before the current one. This is because absolute transformations + // overwfrite anything anyway so there is no need to waste time computing + // other runners + _clearTransformRunnersBefore: function (currentRunner) { + this._transformationRunners.clearBefore(currentRunner.id) + }, + + _currentTransform (current) { + return this._transformationRunners.runners + // we need the equal sign here to make sure, that also transformations + // on the same runner which execute before the current transformation are + // taken into account + .filter((runner) => runner.id <= current.id) + .map(getRunnerTransform) + .reduce(lmultiply, new SVG.Matrix()) + }, + + addRunner: function (runner) { + this._transformationRunners.add(runner) + + SVG.Animator.transform_frame( + mergeTransforms.bind(this), this._frameId + ) + }, + + _prepareRunner: function () { + if (this._frameId == null) { + this._transformationRunners = new RunnerArray() + .add(new SVG.FakeRunner(new SVG.Matrix(this))) + + this._frameId = SVG.Element.frameId++ + } + } +}) + +SVG.Element.frameId = 0 + +SVG.extend(SVG.Runner, { + attr: function (a, v) { + return this.styleAttr('attr', a, v) + }, + + // Add animatable styles + css: function (s, v) { + return this.styleAttr('css', s, v) + }, + + styleAttr (type, name, val) { + // apply attributes individually + if (typeof name === 'object') { + for (var key in val) { + this.styleAttr(type, key, val[key]) + } + } + + var morpher = new SVG.Morphable(this._stepper).to(val) + + this.queue(function () { + morpher = morpher.from(this.element()[type](name)) + }, function (pos) { + this.element()[type](name, morpher.at(pos)) + return morpher.done() + }) + + return this + }, + + zoom: function (level, point) { + var morpher = new SVG.Morphable(this._stepper).to(new SVG.Number(level)) + + this.queue(function () { + morpher = morpher.from(this.zoom()) + }, function (pos) { + this.element().zoom(morpher.at(pos), point) + return morpher.done() + }) + + return this + }, + + /** + ** absolute transformations + **/ + + // + // M v -----|-----(D M v = F v)------|-----> T v + // + // 1. define the final state (T) and decompose it (once) + // t = [tx, ty, the, lam, sy, sx] + // 2. on every frame: pull the current state of all previous transforms + // (M - m can change) + // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] + // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) + // - Note F(0) = M + // - Note F(1) = T + // 4. Now you get the delta matrix as a result: D = F * inv(M) + + transform: function (transforms, relative, affine) { + // If we have a declarative function, we should retarget it if possible + relative = transforms.relative || relative + if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { + return this + } + + // Parse the parameters + var isMatrix = isMatrixLike(transforms) + affine = transforms.affine != null + ? transforms.affine + : (affine != null ? affine : !isMatrix) + + // Create a morepher and set its type + const morpher = new SVG.Morphable() + .type(affine ? SVG.Morphable.TransformBag : SVG.Matrix) + .stepper(this._stepper) + + let origin + let element + let current + let currentAngle + let startTransform + + function setup () { + // make sure element and origin is defined + element = element || this.element() + origin = origin || getOrigin(transforms, element) + + startTransform = new SVG.Matrix(relative ? undefined : element) + + // add the runner to the element so it can merge transformations + element.addRunner(this) + + // Deactivate all transforms that have run so far if we are absolute + if (!relative) { + element._clearTransformRunnersBefore(this) + } + } + + function run (pos) { + // clear all other transforms before this in case something is saved + // on this runner. We are absolute. We dont need these! + if (!relative) this.clearTransform() + + let {x, y} = new SVG.Point(origin).transform(element._currentTransform(this)) + + let target = new SVG.Matrix({...transforms, origin: [x, y]}) + let start = this._isDeclarative && current + ? current + : startTransform + + if (affine) { + target = target.decompose(x, y) + start = start.decompose(x, y) + + // Get the current and target angle as it was set + const rTarget = target.rotate + const rCurrent = start.rotate + + // Figure out the shortest path to rotate directly + const possibilities = [rTarget - 360, rTarget, rTarget + 360] + const distances = possibilities.map(a => Math.abs(a - rCurrent)) + const shortest = Math.min(...distances) + const index = distances.indexOf(shortest) + target.rotate = possibilities[index] + } + + if (relative) { + // we have to be careful here not to overwrite the rotation + // with the rotate method of SVG.Matrix + if (!isMatrix) { + target.rotate = transforms.rotate || 0 + } + if (this._isDeclarative && currentAngle) { + start.rotate = currentAngle + } + } + + morpher.from(start) + morpher.to(target) + + let affineParameters = morpher.at(pos) + currentAngle = affineParameters.rotate + current = new SVG.Matrix(affineParameters) + + this.addTransform(current) + return morpher.done() + } + + function retarget (newTransforms) { + // only get a new origin if it changed since the last call + if ( + (newTransforms.origin || 'center').toString() !== + (transforms.origin || 'center').toString() + ) { + origin = getOrigin(transforms, element) + } + + // overwrite the old transformations with the new ones + transforms = {...newTransforms, origin} + } + + this.queue(setup, run, retarget) + this._isDeclarative && this._rememberMorpher('transform', morpher) + return this + }, + + // Animatable x-axis + x: function (x, relative) { + return this._queueNumber('x', x) + }, + + // Animatable y-axis + y: function (y) { + return this._queueNumber('y', y) + }, + + dx: function (x) { + return this._queueNumberDelta('dx', x) + }, + + dy: function (y) { + return this._queueNumberDelta('dy', y) + }, + + _queueNumberDelta: function (method, to) { + to = new SVG.Number(to) + + // Try to change the target if we have this method already registerd + if (this._tryRetargetDelta(method, to)) return this + + // Make a morpher and queue the animation + var morpher = new SVG.Morphable(this._stepper).to(to) + this.queue(function () { + var from = this.element()[method]() + morpher.from(from) + morpher.to(from + to) + }, function (pos) { + this.element()[method](morpher.at(pos)) + return morpher.done() + }) + + // Register the morpher so that if it is changed again, we can retarget it + this._rememberMorpher(method, morpher) + return this + }, + + _queueObject: function (method, to) { + // Try to change the target if we have this method already registerd + if (this._tryRetarget(method, to)) return this + + // Make a morpher and queue the animation + var morpher = new SVG.Morphable(this._stepper).to(to) + this.queue(function () { + morpher.from(this.element()[method]()) + }, function (pos) { + this.element()[method](morpher.at(pos)) + return morpher.done() + }) + + // Register the morpher so that if it is changed again, we can retarget it + this._rememberMorpher(method, morpher) + return this + }, + + _queueNumber: function (method, value) { + return this._queueObject(method, new SVG.Number(value)) + }, + + // Animatable center x-axis + cx: function (x) { + return this._queueNumber('cx', x) + }, + + // Animatable center y-axis + cy: function (y) { + return this._queueNumber('cy', y) + }, + + // Add animatable move + move: function (x, y) { + return this.x(x).y(y) + }, + + // Add animatable center + center: function (x, y) { + return this.cx(x).cy(y) + }, + + // Add animatable size + size: function (width, height) { + // animate bbox based size for all other elements + var box + + if (!width || !height) { + box = this._element.bbox() + } + + if (!width) { + width = box.width / box.height * height + } + + if (!height) { + height = box.height / box.width * width + } + + return this + .width(width) + .height(height) + }, + + // Add animatable width + width: function (width) { + return this._queueNumber('width', width) + }, + + // Add animatable height + height: function (height) { + return this._queueNumber('height', height) + }, + + // Add animatable plot + plot: function (a, b, c, d) { + // Lines can be plotted with 4 arguments + if (arguments.length === 4) { + return this.plot([a, b, c, d]) + } + + // FIXME: this needs to be rewritten such that the element is only accesed + // in the init function + return this._queueObject('plot', new this._element.MorphArray(a)) + + /* + var morpher = this._element.morphArray().to(a) + + this.queue(function () { + morpher.from(this._element.array()) + }, function (pos) { + this._element.plot(morpher.at(pos)) + }) + + return this + */ + }, + + // Add leading method + leading: function (value) { + return this._queueNumber('leading', value) + }, + + // Add animatable viewbox + viewbox: function (x, y, width, height) { + return this._queueObject('viewbox', new SVG.Box(x, y, width, height)) + }, + + update: function (o) { + if (typeof o !== 'object') { + return this.update({ + offset: arguments[0], + color: arguments[1], + opacity: arguments[2] + }) + } + + 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', o.offset) + + return this + } +}) diff --git a/src/SVGArray.js b/src/SVGArray.js new file mode 100644 index 0000000..aa43d5c --- /dev/null +++ b/src/SVGArray.js @@ -0,0 +1,92 @@ +/* global arrayClone */ + +// Module for array conversion +SVG.Array = function (array, fallback) { + array = (array || []).valueOf() + + // if array is empty and fallback is provided, use fallback + if (array.length === 0 && fallback) { + array = fallback.valueOf() + } + + // parse array + this.value = this.parse(array) +} + +SVG.extend(SVG.Array, { + // Make array morphable + morph: function (array) { + this.destination = this.parse(array) + + // normalize length of arrays + if (this.value.length !== this.destination.length) { + var lastValue = this.value[this.value.length - 1] + var lastDestination = this.destination[this.destination.length - 1] + + while (this.value.length > this.destination.length) { + this.destination.push(lastDestination) + } + while (this.value.length < this.destination.length) { + this.value.push(lastValue) + } + } + + return this + }, + // Clean up any duplicate points + settle: function () { + // find all unique values + for (var i = 0, il = this.value.length, seen = []; i < il; i++) { + if (seen.indexOf(this.value[i]) === -1) { + seen.push(this.value[i]) + } + } + + // set new value + this.value = seen + return seen + }, + // Get morphed array at given position + at: function (pos) { + // make sure a destination is defined + if (!this.destination) return this + + // generate morphed array + for (var i = 0, il = this.value.length, array = []; i < il; i++) { + array.push(this.value[i] + (this.destination[i] - this.value[i]) * pos) + } + + return new SVG.Array(array) + }, + toArray: function () { + return this.value + }, + // Convert array to string + toString: function () { + return this.value.join(' ') + }, + // Real value + valueOf: function () { + return this.value + }, + // Parse whitespace separated string + parse: function (array) { + array = array.valueOf() + + // if already is an array, no need to parse it + if (Array.isArray(array)) return array + + return array.trim().split(SVG.regex.delimiter).map(parseFloat) + }, + // Reverse array + reverse: function () { + this.value.reverse() + + return this + }, + clone: function () { + var clone = new this.constructor() + clone.value = arrayClone(this.value) + return clone + } +}) diff --git a/src/SVGNumber.js b/src/SVGNumber.js new file mode 100644 index 0000000..2135b61 --- /dev/null +++ b/src/SVGNumber.js @@ -0,0 +1,99 @@ + +// Module for unit convertions +SVG.Number = SVG.invent({ + // Initialize + create: function (value, unit) { + unit = Array.isArray(value) ? value[1] : unit + value = Array.isArray(value) ? value[0] : value + + // initialize defaults + this.value = 0 + this.unit = unit || '' + + // parse value + if (typeof value === 'number') { + // ensure a valid numeric value + this.value = isNaN(value) ? 0 : !isFinite(value) ? (value < 0 ? -3.4e+38 : +3.4e+38) : value + } else if (typeof value === 'string') { + unit = value.match(SVG.regex.numberAndUnit) + + if (unit) { + // make value numeric + this.value = parseFloat(unit[1]) + + // normalize + if (unit[5] === '%') { this.value /= 100 } else if (unit[5] === 's') { + this.value *= 1000 + } + + // store unit + this.unit = unit[5] + } + } else { + if (value instanceof SVG.Number) { + this.value = value.valueOf() + this.unit = value.unit + } + } + }, + // Add methods + extend: { + // Stringalize + toString: function () { + return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 + : this.unit === 's' ? this.value / 1e3 + : this.value + ) + this.unit + }, + toJSON: function () { + return this.toString() + }, // Convert to primitive + toArray: function () { + return [this.value, this.unit] + }, + valueOf: function () { + return this.value + }, + // Add number + plus: function (number) { + number = new SVG.Number(number) + return new SVG.Number(this + number, this.unit || number.unit) + }, + // Subtract number + minus: function (number) { + number = new SVG.Number(number) + return new SVG.Number(this - number, this.unit || number.unit) + }, + // Multiply number + times: function (number) { + number = new SVG.Number(number) + return new SVG.Number(this * number, this.unit || number.unit) + }, + // Divide number + divide: function (number) { + number = new SVG.Number(number) + return new SVG.Number(this / number, this.unit || number.unit) + }, + // Make number morphable + morph: function (number) { + this.destination = new SVG.Number(number) + + if (number.relative) { + this.destination.value += this.value + } + + return this + }, + // Get morphed number at given position + at: function (pos) { + // Make sure a destination is defined + if (!this.destination) return this + + // Generate new morphed number + return new SVG.Number(this.destination) + .minus(this) + .times(pos) + .plus(this) + } + } +}) diff --git a/src/Shape.js b/src/Shape.js new file mode 100644 index 0000000..cb15098 --- /dev/null +++ b/src/Shape.js @@ -0,0 +1,10 @@ + +SVG.Shape = SVG.invent({ + // Initialize node + create: function (node) { + SVG.Element.call(this, node) + }, + + // Inherit from + inherit: SVG.Element +}) diff --git a/src/Symbol.js b/src/Symbol.js new file mode 100644 index 0000000..ca67607 --- /dev/null +++ b/src/Symbol.js @@ -0,0 +1,15 @@ + +SVG.Symbol = SVG.invent({ + // Initialize node + create: 'symbol', + + // Inherit from + inherit: SVG.Container, + + construct: { + // create symbol + symbol: function () { + return this.put(new SVG.Symbol()) + } + } +}) diff --git a/src/Text.js b/src/Text.js new file mode 100644 index 0000000..8a50df9 --- /dev/null +++ b/src/Text.js @@ -0,0 +1,234 @@ +SVG.Text = SVG.invent({ + // Initialize node + create: function (node) { + SVG.Element.call(this, node || SVG.create('text')) + this.dom.leading = new SVG.Number(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', SVG.defaults.attrs['font-family']) + }, + + // Inherit from + inherit: SVG.Parent, + + // Add class methods + extend: { + // Move over x-axis + x: function (x) { + // act as getter + if (x == null) { + return this.attr('x') + } + + return this.attr('x', x) + }, + // Move over y-axis + y: function (y) { + var oy = this.attr('y') + var o = typeof oy === 'number' ? oy - this.bbox().y : 0 + + // act as getter + if (y == null) { + return typeof oy === 'number' ? oy - o : oy + } + + return this.attr('y', typeof y === 'number' ? y + o : y) + }, + // Move center over x-axis + cx: function (x) { + return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2) + }, + // Move center over y-axis + cy: function (y) { + return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2) + }, + // Set the text content + text: function (text) { + // act as getter + if (text === undefined) { + var children = this.node.childNodes + var firstLine = 0 + text = '' + + 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 + continue + } + + // add newline if its not the first child and newLined is set to true + if (i !== firstLine && children[i].nodeType !== 3 && SVG.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) + + if (typeof text === 'function') { + // call block + text.call(this, this) + } else { + // store text and make sure text is not blank + text = text.split('\n') + + // build new lines + 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() + }, + // Set / get leading + leading: function (value) { + // act as getter + if (value == null) { + return this.dom.leading + } + + // act as setter + this.dom.leading = new SVG.Number(value) + + return this.rebuild() + }, + // Rebuild appearance type + rebuild: function (rebuild) { + // store new rebuild flag if given + if (typeof rebuild === 'boolean') { + this._rebuild = rebuild + } + + // define position of all lines + if (this._rebuild) { + var self = this + var blankLineOffset = 0 + var dy = this.dom.leading * new SVG.Number(this.attr('font-size')) + + this.each(function () { + if (this.dom.newLined) { + this.attr('x', self.attr('x')) + + if (this.text() === '\n') { + blankLineOffset += dy + } else { + this.attr('dy', dy + blankLineOffset) + blankLineOffset = 0 + } + } + }) + + this.fire('rebuild') + } + + return this + }, + // Enable / disable build mode + build: function (build) { + this._build = !!build + return this + }, + // overwrite method from parent to set data properly + setData: function (o) { + this.dom = o + this.dom.leading = new SVG.Number(o.leading || 1.3) + return this + } + }, + + // Add parent method + construct: { + // Create text element + text: function (text) { + return this.put(new SVG.Text()).text(text) + }, + // Create plain text element + plain: function (text) { + return this.put(new SVG.Text()).plain(text) + } + } + +}) + +SVG.Tspan = SVG.invent({ + // Initialize node + create: 'tspan', + + // Inherit from + inherit: SVG.Parent, + + // Add class methods + extend: { + // Set text content + text: function (text) { + if (text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '') + + typeof text === 'function' ? text.call(this, this) : this.plain(text) + + return this + }, + // Shortcut dx + dx: function (dx) { + return this.attr('dx', dx) + }, + // Shortcut dy + dy: function (dy) { + return this.attr('dy', dy) + }, + // Create new line + newLine: function () { + // fetch text parent + var t = this.parent(SVG.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()) + } + } +}) + +SVG.extend([SVG.Text, SVG.Tspan], { + // Create plain text node + plain: function (text) { + // clear if build mode is disabled + if (this._build === false) { + this.clear() + } + + // create text node + this.node.appendChild(document.createTextNode(text)) + + return this + }, + // Create a tspan + tspan: function (text) { + var tspan = new SVG.Tspan() + + // clear if build mode is disabled + if (!this._build) { + this.clear() + } + + // add new tspan + this.node.appendChild(tspan.node) + + return tspan.text(text) + }, + // FIXME: Does this also work for textpath? + // Get length of text element + length: function () { + return this.node.getComputedTextLength() + } +}) diff --git a/src/TextPath.js b/src/TextPath.js new file mode 100644 index 0000000..561f147 --- /dev/null +++ b/src/TextPath.js @@ -0,0 +1,77 @@ +SVG.TextPath = SVG.invent({ + // Initialize node + create: 'textPath', + + // Inherit from + inherit: SVG.Text, + + // Define parent class + parent: SVG.Parent, + + // Add parent method + extend: { + MorphArray: SVG.PathArray, + // return the array of the path track element + array: function () { + var track = this.track() + + return track ? track.array() : null + }, + // Plot path if any + plot: function (d) { + var track = this.track() + var pathArray = null + + if (track) { + pathArray = track.plot(d) + } + + return (d == null) ? pathArray : this + }, + // Get the path element + track: function () { + return this.reference('href') + } + }, + construct: { + textPath: function (text, path) { + return this.defs().path(path).text(text).addTo(this) + } + } +}) + +SVG.extend([SVG.Text], { + // Create path for text to run on + path: function (track) { + var path = new SVG.TextPath() + + // if d is a path, reuse it + if (!(track instanceof SVG.Path)) { + // create path element + track = this.doc().defs().path(track) + } + + // link textPath to path and add content + path.attr('href', '#' + track, SVG.xlink) + + // add textPath element as child node and return textPath + return this.put(path) + }, + // Todo: make this plural? + // Get the textPath children + textPath: function () { + return this.select('textPath') + } +}) + +SVG.extend([SVG.Path], { + // creates a textPath from this path + text: function (text) { + if (text instanceof SVG.Text) { + var txt = text.text() + return text.clear().path(this).text(txt) + } + return this.parent().put(new SVG.Text()).path(this).text(text) + } + // TODO: Maybe add `targets` to get all textPaths associated with this path +}) diff --git a/src/Timeline.js b/src/Timeline.js new file mode 100644 index 0000000..0bf8ac5 --- /dev/null +++ b/src/Timeline.js @@ -0,0 +1,282 @@ + +// Must Change .... +SVG.easing = { + '-': function (pos) { return pos }, + '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, + '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, + '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } +} + +var time = window.performance || Date + +var makeSchedule = function (runnerInfo) { + var start = runnerInfo.start + var duration = runnerInfo.runner.duration() + var end = start + duration + return {start: start, duration: duration, end: end, runner: runnerInfo.runner} +} + +SVG.Timeline = SVG.invent({ + inherit: SVG.EventTarget, + + // Construct a new timeline on the given element + create: function () { + this._timeSource = function () { + return time.now() + } + + this._dispatcher = document.createElement('div') + + // Store the timing variables + this._startTime = 0 + this._speed = 1.0 + + // Play control variables control how the animation proceeds + this._reverse = false + this._persist = 0 + + // Keep track of the running animations and their starting parameters + this._nextFrame = null + this._paused = false + this._runners = [] + this._order = [] + this._time = 0 + this._lastSourceTime = 0 + this._lastStepTime = 0 + }, + + extend: { + + getEventTarget () { + return this._dispatcher + }, + + /** + * + */ + + // schedules a runner on the timeline + schedule (runner, delay, when) { + if (runner == null) { + return this._runners.map(makeSchedule).sort(function (a, b) { + return (a.start - b.start) || (a.duration - b.duration) + }) + } + + if (!this.active()) { + this._step() + if (when == null) { + when = 'now' + } + } + + // The start time for the next animation can either be given explicitly, + // derived from the current timeline time or it can be relative to the + // last start time to chain animations direclty + var absoluteStartTime = 0 + delay = delay || 0 + + // Work out when to start the animation + if (when == null || when === 'last' || when === 'after') { + // Take the last time and increment + absoluteStartTime = this._startTime + } else if (when === 'absolute' || when === 'start') { + absoluteStartTime = delay + delay = 0 + } else if (when === 'now') { + absoluteStartTime = this._time + } else if (when === 'relative') { + let runnerInfo = this._runners[runner.id] + if (runnerInfo) { + absoluteStartTime = runnerInfo.start + delay + delay = 0 + } + } else { + throw new Error('Invalid value for the "when" parameter') + } + + // Manage runner + runner.unschedule() + runner.timeline(this) + runner.time(-delay) + + // Save startTime for next runner + this._startTime = absoluteStartTime + runner.duration() + delay + + // Save runnerInfo + this._runners[runner.id] = { + persist: this.persist(), + runner: runner, + start: absoluteStartTime + } + + // Save order and continue + this._order.push(runner.id) + this._continue() + return this + }, + + // Remove the runner from this timeline + unschedule (runner) { + var index = this._order.indexOf(runner.id) + if (index < 0) return this + + delete this._runners[runner.id] + this._order.splice(index, 1) + runner.timeline(null) + return this + }, + + play () { + // Now make sure we are not paused and continue the animation + this._paused = false + return this._continue() + }, + + pause () { + // Cancel the next animation frame and pause + this._nextFrame = null + this._paused = true + return this + }, + + stop () { + // Cancel the next animation frame and go to start + this.seek(-this._time) + return this.pause() + }, + + finish () { + this.seek(Infinity) + return this.pause() + }, + + speed (speed) { + if (speed == null) return this._speed + this._speed = speed + return this + }, + + reverse (yes) { + var currentSpeed = this.speed() + if (yes == null) return this.speed(-currentSpeed) + + var positive = Math.abs(currentSpeed) + return this.speed(yes ? positive : -positive) + }, + + seek (dt) { + this._time += dt + return this._continue() + }, + + time (time) { + if (time == null) return this._time + this._time = time + return this + }, + + persist (dtOrForever) { + if (dtOrForever == null) return this._persist + this._persist = dtOrForever + return this + }, + + source (fn) { + if (fn == null) return this._timeSource + this._timeSource = fn + return this + }, + + _step () { + // If the timeline is paused, just do nothing + if (this._paused) return + + // Get the time delta from the last time and update the time + // TODO: Deal with window.blur window.focus to pause animations + var time = this._timeSource() + var dtSource = time - this._lastSourceTime + var dtTime = this._speed * dtSource + (this._time - this._lastStepTime) + this._lastSourceTime = time + + // Update the time + this._time += dtTime + this._lastStepTime = this._time + // this.fire('time', this._time) + + // Run all of the runners directly + var runnersLeft = false + for (var i = 0, len = this._order.length; i < len; i++) { + // Get and run the current runner and ignore it if its inactive + var runnerInfo = this._runners[this._order[i]] + var runner = runnerInfo.runner + let dt = dtTime + + // Make sure that we give the actual difference + // between runner start time and now + let dtToStart = this._time - runnerInfo.start + + // Dont run runner if not started yet + if (dtToStart < 0) { + runnersLeft = true + continue + } else if (dtToStart < dt) { + // Adjust dt to make sure that animation is on point + dt = dtToStart + } + + if (!runner.active()) continue + + // If this runner is still going, signal that we need another animation + // frame, otherwise, remove the completed runner + var finished = runner.step(dt).done + if (!finished) { + runnersLeft = true + // continue + } else if (runnerInfo.persist !== true) { + // runner is finished. And runner might get removed + + // TODO: Figure out end time of runner + var endTime = runner.duration() - runner.time() + this._time + + if (endTime + this._persist < this._time) { + // Delete runner and correct index + delete this._runners[this._order[i]] + this._order.splice(i--, 1) && --len + runner.timeline(null) + } + } + } + + // Get the next animation frame to keep the simulation going + if (runnersLeft) { + this._nextFrame = SVG.Animator.frame(this._step.bind(this)) + } else { + this._nextFrame = null + } + return this + }, + + // Checks if we are running and continues the animation + _continue () { + if (this._paused) return this + if (!this._nextFrame) { + this._nextFrame = SVG.Animator.frame(this._step.bind(this)) + } + return this + }, + + active () { + return !!this._nextFrame + } + }, + + // These methods will be added to all SVG.Element objects + parent: SVG.Element, + construct: { + timeline: function () { + this._timeline = (this._timeline || new SVG.Timeline()) + return this._timeline + } + } +}) diff --git a/src/animator.js b/src/animator.js deleted file mode 100644 index eb8ca72..0000000 --- a/src/animator.js +++ /dev/null @@ -1,83 +0,0 @@ -/* global requestAnimationFrame */ - -SVG.Animator = { - nextDraw: null, - frames: new SVG.Queue(), - timeouts: new SVG.Queue(), - timer: window.performance || window.Date, - transforms: [], - - frame: function (fn) { - // Store the node - var node = SVG.Animator.frames.push({ run: fn }) - - // Request an animation frame if we don't have one - if (SVG.Animator.nextDraw === null) { - SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw) - } - - // Return the node so we can remove it easily - return node - }, - - transform_frame: function (fn, id) { - SVG.Animator.transforms[id] = fn - }, - - timeout: function (fn, delay) { - delay = delay || 0 - - // Work out when the event should fire - var time = SVG.Animator.timer.now() + delay - - // Add the timeout to the end of the queue - var node = SVG.Animator.timeouts.push({ run: fn, time: time }) - - // Request another animation frame if we need one - if (SVG.Animator.nextDraw === null) { - SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw) - } - - return node - }, - - cancelFrame: function (node) { - SVG.Animator.frames.remove(node) - }, - - clearTimeout: function (node) { - SVG.Animator.timeouts.remove(node) - }, - - _draw: function (now) { - // Run all the timeouts we can run, if they are not ready yet, add them - // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) - var nextTimeout = null - var lastTimeout = SVG.Animator.timeouts.last() - while ((nextTimeout = SVG.Animator.timeouts.shift())) { - // Run the timeout if its time, or push it to the end - if (now >= nextTimeout.time) { - nextTimeout.run() - } else { - SVG.Animator.timeouts.push(nextTimeout) - } - - // If we hit the last item, we should stop shifting out more items - if (nextTimeout === lastTimeout) break - } - - // Run all of the animation frames - var nextFrame = null - var lastFrame = SVG.Animator.frames.last() - while ((nextFrame !== lastFrame) && (nextFrame = SVG.Animator.frames.shift())) { - nextFrame.run() - } - - SVG.Animator.transforms.forEach(function (el) { el() }) - - // If we have remaining timeouts or frames, draw until we don't anymore - SVG.Animator.nextDraw = SVG.Animator.timeouts.first() || SVG.Animator.frames.first() - ? requestAnimationFrame(SVG.Animator._draw) - : null - } -} diff --git a/src/array.js b/src/array.js deleted file mode 100644 index aa43d5c..0000000 --- a/src/array.js +++ /dev/null @@ -1,92 +0,0 @@ -/* global arrayClone */ - -// Module for array conversion -SVG.Array = function (array, fallback) { - array = (array || []).valueOf() - - // if array is empty and fallback is provided, use fallback - if (array.length === 0 && fallback) { - array = fallback.valueOf() - } - - // parse array - this.value = this.parse(array) -} - -SVG.extend(SVG.Array, { - // Make array morphable - morph: function (array) { - this.destination = this.parse(array) - - // normalize length of arrays - if (this.value.length !== this.destination.length) { - var lastValue = this.value[this.value.length - 1] - var lastDestination = this.destination[this.destination.length - 1] - - while (this.value.length > this.destination.length) { - this.destination.push(lastDestination) - } - while (this.value.length < this.destination.length) { - this.value.push(lastValue) - } - } - - return this - }, - // Clean up any duplicate points - settle: function () { - // find all unique values - for (var i = 0, il = this.value.length, seen = []; i < il; i++) { - if (seen.indexOf(this.value[i]) === -1) { - seen.push(this.value[i]) - } - } - - // set new value - this.value = seen - return seen - }, - // Get morphed array at given position - at: function (pos) { - // make sure a destination is defined - if (!this.destination) return this - - // generate morphed array - for (var i = 0, il = this.value.length, array = []; i < il; i++) { - array.push(this.value[i] + (this.destination[i] - this.value[i]) * pos) - } - - return new SVG.Array(array) - }, - toArray: function () { - return this.value - }, - // Convert array to string - toString: function () { - return this.value.join(' ') - }, - // Real value - valueOf: function () { - return this.value - }, - // Parse whitespace separated string - parse: function (array) { - array = array.valueOf() - - // if already is an array, no need to parse it - if (Array.isArray(array)) return array - - return array.trim().split(SVG.regex.delimiter).map(parseFloat) - }, - // Reverse array - reverse: function () { - this.value.reverse() - - return this - }, - clone: function () { - var clone = new this.constructor() - clone.value = arrayClone(this.value) - return clone - } -}) diff --git a/src/bare.js b/src/bare.js deleted file mode 100644 index 393ce6e..0000000 --- a/src/bare.js +++ /dev/null @@ -1,43 +0,0 @@ - -SVG.Bare = SVG.invent({ - // Initialize - create: function (element, inherit) { - // construct element - SVG.Element.call(this, SVG.create(element)) - - // inherit custom methods - if (inherit) { - for (var method in inherit.prototype) { - if (typeof inherit.prototype[method] === 'function') { - this[method] = inherit.prototype[method] - } - } - } - }, - - // Inherit from - inherit: SVG.Element, - - // Add methods - extend: { - // Insert some plain text - words: function (text) { - // remove contents - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) - } - - // create text node - this.node.appendChild(document.createTextNode(text)) - - return this - } - } -}) - -SVG.extend(SVG.Parent, { - // Create an element that is not described by SVG.js - element: function (element, inherit) { - return this.put(new SVG.Bare(element, inherit)) - } -}) diff --git a/src/boxes.js b/src/boxes.js deleted file mode 100644 index a9247ef..0000000 --- a/src/boxes.js +++ /dev/null @@ -1,141 +0,0 @@ -/* globals fullBox, domContains, isNulledBox, Exception */ - -SVG.Box = SVG.invent({ - create: function (source) { - var base = [0, 0, 0, 0] - source = typeof source === 'string' ? source.split(SVG.regex.delimiter).map(parseFloat) - : Array.isArray(source) ? source - : typeof source === 'object' ? [source.left != null ? source.left - : source.x, source.top != null ? source.top : source.y, source.width, source.height] - : arguments.length === 4 ? [].slice.call(arguments) - : base - - this.x = source[0] - this.y = source[1] - this.width = source[2] - this.height = source[3] - - // add center, right, bottom... - fullBox(this) - }, - extend: { - // Merge rect box with another, return a new instance - merge: function (box) { - var x = Math.min(this.x, box.x) - var y = Math.min(this.y, box.y) - - return new SVG.Box( - x, y, - Math.max(this.x + this.width, box.x + box.width) - x, - Math.max(this.y + this.height, box.y + box.height) - y - ) - }, - - transform: function (m) { - var xMin = Infinity - var xMax = -Infinity - var yMin = Infinity - var yMax = -Infinity - - var pts = [ - new SVG.Point(this.x, this.y), - new SVG.Point(this.x2, this.y), - new SVG.Point(this.x, this.y2), - new SVG.Point(this.x2, this.y2) - ] - - pts.forEach(function (p) { - p = p.transform(m) - xMin = Math.min(xMin, p.x) - xMax = Math.max(xMax, p.x) - yMin = Math.min(yMin, p.y) - yMax = Math.max(yMax, p.y) - }) - - return new SVG.Box( - xMin, yMin, - xMax - xMin, - yMax - yMin - ) - }, - - addOffset: function () { - // offset by window scroll position, because getBoundingClientRect changes when window is scrolled - this.x += window.pageXOffset - this.y += window.pageYOffset - return this - }, - toString: function () { - return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height - }, - toArray: function () { - return [this.x, this.y, this.width, this.height] - }, - morph: function (x, y, width, height) { - this.destination = new SVG.Box(x, y, width, height) - return this - }, - - at: function (pos) { - if (!this.destination) return this - - return new SVG.Box( - this.x + (this.destination.x - this.x) * pos - , this.y + (this.destination.y - this.y) * pos - , this.width + (this.destination.width - this.width) * pos - , this.height + (this.destination.height - this.height) * pos - ) - } - }, - - // Define Parent - parent: SVG.Element, - - // Constructor - construct: { - // Get bounding box - bbox: function () { - var box - - try { - // find native bbox - box = this.node.getBBox() - - if (isNulledBox(box) && !domContains(this.node)) { - throw new Exception('Element not in the dom') - } - } catch (e) { - try { - var clone = this.clone(SVG.parser().svg).show() - box = clone.node.getBBox() - clone.remove() - } catch (e) { - console.warn('Getting a bounding box of this element is not possible') - } - } - - return new SVG.Box(box) - }, - - rbox: function (el) { - // IE11 throws an error when element not in dom - try { - var box = new SVG.Box(this.node.getBoundingClientRect()) - if (el) return box.transform(el.screenCTM().inverse()) - return box.addOffset() - } catch (e) { - return new SVG.Box() - } - } - } -}) - -SVG.extend([SVG.Doc, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View], { - viewbox: function (x, y, width, height) { - // act as getter - if (x == null) return new SVG.Box(this.attr('viewBox')) - - // act as setter - return this.attr('viewBox', new SVG.Box(x, y, width, height)) - } -}) diff --git a/src/clip.js b/src/clip.js deleted file mode 100644 index 63fff74..0000000 --- a/src/clip.js +++ /dev/null @@ -1,53 +0,0 @@ -SVG.ClipPath = SVG.invent({ - // Initialize node - create: 'clipPath', - - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - // Unclip all clipped elements and remove itself - remove: function () { - // unclip all targets - this.targets().forEach(function (el) { - el.unclip() - }) - - // remove clipPath from parent - return SVG.Element.prototype.remove.call(this) - }, - - targets: function () { - return SVG.select('svg [clip-path*="' + this.id() + '"]') - } - }, - - // Add parent method - construct: { - // Create clipping element - clip: function () { - return this.defs().put(new SVG.ClipPath()) - } - } -}) - -// -SVG.extend(SVG.Element, { - // Distribute clipPath to svg element - clipWith: function (element) { - // use given clip or create a new one - var clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element) - - // apply mask - return this.attr('clip-path', 'url("#' + clipper.id() + '")') - }, - // Unclip element - unclip: function () { - return this.attr('clip-path', null) - }, - clipper: function () { - return this.reference('clip-path') - } - -}) diff --git a/src/color.js b/src/color.js deleted file mode 100644 index 43bafcb..0000000 --- a/src/color.js +++ /dev/null @@ -1,148 +0,0 @@ -/* globals fullHex, compToHex */ - -/* - -Color { - constructor (a, b, c, space) { - space: 'hsl' - a: 30 - b: 20 - c: 10 - }, - - toRgb () { return new Color in rgb space } - toHsl () { return new Color in hsl space } - toLab () { return new Color in lab space } - - toArray () { [space, a, b, c] } - fromArray () { convert it back } -} - -// Conversions aren't always exact because of monitor profiles etc... -new Color(h, s, l, 'hsl') !== new Color(r, g, b).hsl() -new Color(100, 100, 100, [space]) -new Color('hsl(30, 20, 10)') - -// Sugar -SVG.rgb(30, 20, 50).lab() -SVG.hsl() -SVG.lab('rgb(100, 100, 100)') -*/ - -// Module for color convertions -SVG.Color = function (color, g, b) { - var match - - // initialize defaults - this.r = 0 - this.g = 0 - this.b = 0 - - if (!color) return - - // parse color - if (typeof color === 'string') { - if (SVG.regex.isRgb.test(color)) { - // get rgb values - match = SVG.regex.rgb.exec(color.replace(SVG.regex.whitespace, '')) - - // parse numeric values - this.r = parseInt(match[1]) - this.g = parseInt(match[2]) - this.b = parseInt(match[3]) - } else if (SVG.regex.isHex.test(color)) { - // get hex values - match = SVG.regex.hex.exec(fullHex(color)) - - // parse numeric values - this.r = parseInt(match[1], 16) - this.g = parseInt(match[2], 16) - this.b = parseInt(match[3], 16) - } - } else if (Array.isArray(color)) { - this.r = color[0] - this.g = color[1] - this.b = color[2] - } else if (typeof color === 'object') { - this.r = color.r - this.g = color.g - this.b = color.b - } else if (arguments.length === 3) { - this.r = color - this.g = g - this.b = b - } -} - -SVG.extend(SVG.Color, { - // Default to hex conversion - toString: function () { - return this.toHex() - }, - toArray: function () { - return [this.r, this.g, this.b] - }, - fromArray: function (a) { - return new SVG.Color(a) - }, - // Build hex value - toHex: function () { - return '#' + - compToHex(Math.round(this.r)) + - compToHex(Math.round(this.g)) + - compToHex(Math.round(this.b)) - }, - // Build rgb value - toRgb: function () { - return 'rgb(' + [this.r, this.g, this.b].join() + ')' - }, - // Calculate true brightness - brightness: function () { - return (this.r / 255 * 0.30) + - (this.g / 255 * 0.59) + - (this.b / 255 * 0.11) - }, - // Make color morphable - morph: function (color) { - this.destination = new SVG.Color(color) - - return this - }, - // Get morphed color at given position - at: function (pos) { - // make sure a destination is defined - if (!this.destination) return this - - // normalise pos - pos = pos < 0 ? 0 : pos > 1 ? 1 : pos - - // generate morphed color - return new SVG.Color({ - r: ~~(this.r + (this.destination.r - this.r) * pos), - g: ~~(this.g + (this.destination.g - this.g) * pos), - b: ~~(this.b + (this.destination.b - this.b) * pos) - }) - } - -}) - -// Testers - -// Test if given value is a color string -SVG.Color.test = function (color) { - color += '' - return SVG.regex.isHex.test(color) || - SVG.regex.isRgb.test(color) -} - -// Test if given value is a rgb object -SVG.Color.isRgb = function (color) { - return color && typeof color.r === 'number' && - typeof color.g === 'number' && - typeof color.b === 'number' -} - -// Test if given value is a color -SVG.Color.isColor = function (color) { - return SVG.Color.isRgb(color) || SVG.Color.test(color) -} diff --git a/src/container.js b/src/container.js deleted file mode 100644 index 8b324bd..0000000 --- a/src/container.js +++ /dev/null @@ -1,9 +0,0 @@ -SVG.Container = SVG.invent({ - // Initialize node - create: function (node) { - SVG.Element.call(this, node) - }, - - // Inherit from - inherit: SVG.Parent -}) diff --git a/src/controller.js b/src/controller.js deleted file mode 100644 index 842c772..0000000 --- a/src/controller.js +++ /dev/null @@ -1,193 +0,0 @@ - -// c = { -// finished: Whether or not we are finished -// } - -/*** -Base Class -========== -The base stepper class that will be -***/ - -function makeSetterGetter (k, f) { - return function (v) { - if (v == null) return this[v] - this[k] = v - if (f) f.call(this) - return this - } -} - -SVG.Stepper = SVG.invent({ - create: function () {} -}) - -/*** -Easing Functions -================ -***/ - -SVG.Ease = SVG.invent({ - inherit: SVG.Stepper, - - create: function (fn) { - SVG.Stepper.call(this, fn) - - this.ease = SVG.easing[fn || SVG.defaults.timeline.ease] || fn - }, - - extend: { - - step: function (from, to, pos) { - if (typeof from !== 'number') { - return pos < 1 ? from : to - } - return from + (to - from) * this.ease(pos) - }, - - done: function (dt, c) { - return false - } - } -}) - -SVG.easing = { - '-': function (pos) { return pos }, - '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, - '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, - '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }, - bezier: function (t0, x0, t1, x1) { - return function (t) { - // TODO: FINISH - } - } -} - -/*** -Controller Types -================ -***/ - -SVG.Controller = SVG.invent({ - inherit: SVG.Stepper, - - create: function (fn) { - SVG.Stepper.call(this, fn) - this.stepper = fn - }, - - extend: { - - step: function (current, target, dt, c) { - return this.stepper(current, target, dt, c) - }, - - done: function (c) { - return c.done - } - } -}) - -function recalculate () { - // Apply the default parameters - var duration = (this._duration || 500) / 1000 - var overshoot = this._overshoot || 0 - - // Calculate the PID natural response - var eps = 1e-10 - var pi = Math.PI - var os = Math.log(overshoot / 100 + eps) - var zeta = -os / Math.sqrt(pi * pi + os * os) - var wn = 3.9 / (zeta * duration) - - // Calculate the Spring values - this.d = 2 * zeta * wn - this.k = wn * wn -} - -SVG.Spring = SVG.invent({ - inherit: SVG.Controller, - - create: function (duration, overshoot) { - this.duration(duration || 500) - .overshoot(overshoot || 0) - }, - - extend: { - step: function (current, target, dt, c) { - if (typeof current === 'string') return current - c.done = dt === Infinity - if (dt === Infinity) return target - if (dt === 0) return current - - if (dt > 100) dt = 16 - - dt /= 1000 - - // Get the previous velocity - var velocity = c.velocity || 0 - - // Apply the control to get the new position and store it - var acceleration = -this.d * velocity - this.k * (current - target) - var newPosition = current + - velocity * dt + - acceleration * dt * dt / 2 - - // Store the velocity - c.velocity = velocity + acceleration * dt - - // Figure out if we have converged, and if so, pass the value - c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002 - return c.done ? target : newPosition - }, - - duration: makeSetterGetter('_duration', recalculate), - overshoot: makeSetterGetter('_overshoot', recalculate) - } -}) - -SVG.PID = SVG.invent({ - inherit: SVG.Controller, - - create: function (p, i, d, windup) { - SVG.Controller.call(this) - - p = p == null ? 0.1 : p - i = i == null ? 0.01 : i - d = d == null ? 0 : d - windup = windup == null ? 1000 : windup - this.p(p).i(i).d(d).windup(windup) - }, - - extend: { - step: function (current, target, dt, c) { - if (typeof current === 'string') return current - c.done = dt === Infinity - - if (dt === Infinity) return target - if (dt === 0) return current - - var p = target - current - var i = (c.integral || 0) + p * dt - var d = (p - (c.error || 0)) / dt - var windup = this.windup - - // antiwindup - if (windup !== false) { - i = Math.max(-windup, Math.min(i, windup)) - } - - c.error = p - c.integral = i - - c.done = Math.abs(p) < 0.001 - - return c.done ? target : current + (this.P * p + this.I * i + this.D * d) - }, - - windup: makeSetterGetter('windup'), - p: makeSetterGetter('P'), - i: makeSetterGetter('I'), - d: makeSetterGetter('D') - } -}) diff --git a/src/defs.js b/src/defs.js deleted file mode 100644 index 3d6ebb9..0000000 --- a/src/defs.js +++ /dev/null @@ -1,7 +0,0 @@ -SVG.Defs = SVG.invent({ - // Initialize node - create: 'defs', - - // Inherit from - inherit: SVG.Container -}) diff --git a/src/doc.js b/src/doc.js deleted file mode 100644 index 423204f..0000000 --- a/src/doc.js +++ /dev/null @@ -1,70 +0,0 @@ -SVG.Doc = SVG.invent({ - // Initialize node - create: function (node) { - SVG.Element.call(this, node || SVG.create('svg')) - - // set svg element attributes and ensure defs node - this.namespace() - }, - - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - isRoot: function () { - return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document' - }, - // Check if this is a root svg. If not, call docs from this element - doc: function () { - if (this.isRoot()) return this - return SVG.Element.prototype.doc.call(this) - }, - // Add namespaces - namespace: function () { - if (!this.isRoot()) return this.doc().namespace() - return this - .attr({ xmlns: SVG.ns, version: '1.1' }) - .attr('xmlns:xlink', SVG.xlink, SVG.xmlns) - .attr('xmlns:svgjs', SVG.svgjs, SVG.xmlns) - }, - // Creates and returns defs element - defs: function () { - if (!this.isRoot()) return this.doc().defs() - return SVG.adopt(this.node.getElementsByTagName('defs')[0]) || this.put(new SVG.Defs()) - }, - // custom parent method - parent: function (type) { - if (this.isRoot()) { - return this.node.parentNode.nodeName === '#document' ? null : this.node.parentNode - } - - return SVG.Element.prototype.parent.call(this, type) - }, - // Removes the doc from the DOM - remove: function () { - if (!this.isRoot()) { - return SVG.Element.prototype.remove.call(this) - } - - if (this.parent()) { - this.parent().removeChild(this.node) - } - - return this - }, - clear: function () { - // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) - } - return this - } - }, - construct: { - // Create nested svg document - nested: function () { - return this.put(new SVG.Doc()) - } - } -}) diff --git a/src/element.js b/src/element.js deleted file mode 100644 index f0d9e8e..0000000 --- a/src/element.js +++ /dev/null @@ -1,316 +0,0 @@ -/* global proportionalSize, assignNewId, createElement, matches, is */ - -SVG.Element = SVG.invent({ - inherit: SVG.EventTarget, - - // Initialize node - create: function (node) { - // event listener - this.events = {} - - // initialize data object - this.dom = {} - - // create circular reference - this.node = node - if (this.node) { - this.type = node.nodeName - this.node.instance = this - this.events = node.events || {} - - 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')) || {}) - } - } - }, - - // 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) { - // write dom data to the dom so the clone can pickup the data - this.writeDataToDom() - - // 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 createElement(parent).put(this) - }, - - // Add element to given container and return container - putIn: function (parent) { - return createElement(parent).add(this) - }, - - // Get / set id - id: function (id) { - // generate new id if no id set - if (typeof id === 'undefined' && !this.node.id) { - this.node.id = SVG.eid(this.type) - } - - // dont't set directly width this.node.id to make `null` work correctly - 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.css('display', '') - }, - - // Hide element - hide: function () { - return this.css('display', 'none') - }, - - // Is element visible? - visible: function () { - return this.css('display') !== 'none' - }, - - // Return id on string conversion - toString: function () { - return this.id() - }, - - // Return array of classes on the node - classes: function () { - var attr = this.attr('class') - return attr == null ? [] : attr.trim().split(SVG.regex.delimiter) - }, - - // 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 window.SVGElement) { - if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent - parent = SVG.adopt(parent.node.parentNode) - } - }, - - // Get parent document - doc: function () { - var p = this.parent(SVG.Doc) - return p && p.doc() - }, - - // Get defs - defs: function () { - return this.doc().defs() - }, - - // return array of all ancestors of given type up to the root svg - parents: function (type) { - var parents = [] - var 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) { - var well, len - - // act as a setter if svg is given - if (svg && this instanceof SVG.Parent) { - // create temporary holder - well = document.createElementNS(SVG.ns, 'svg') - // dump raw svg - well.innerHTML = svg - - // transplant nodes - for (len = well.children.length; len--;) { - this.node.appendChild(well.firstElementChild) - } - - // otherwise act as a getter - } else { - // write svgjs data to the dom - this.writeDataToDom() - - return this.node.outerHTML - } - - return this - }, - - // write svgjs data to the dom - writeDataToDom: function () { - // dump variables recursively - if (this.is(SVG.Parent)) { - this.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) - }, - getEventTarget: function () { - return this.node - } - } -}) diff --git a/src/ellipse.js b/src/ellipse.js deleted file mode 100644 index 8a8f027..0000000 --- a/src/ellipse.js +++ /dev/null @@ -1,91 +0,0 @@ -/* global proportionalSize */ - -SVG.Circle = SVG.invent({ - // Initialize node - create: 'circle', - - // Inherit from - inherit: SVG.Shape, - - // Add parent method - construct: { - // Create circle element, based on ellipse - circle: function (size) { - return this.put(new SVG.Circle()).rx(new SVG.Number(size).divide(2)).move(0, 0) - } - } -}) - -SVG.extend([SVG.Circle, SVG.Timeline], { - // Radius x value - rx: function (rx) { - return this.attr('r', rx) - }, - // Alias radius x value - ry: function (ry) { - return this.rx(ry) - } -}) - -SVG.Ellipse = SVG.invent({ - // Initialize node - create: 'ellipse', - - // Inherit from - inherit: SVG.Shape, - - // Add parent method - construct: { - // Create an ellipse - ellipse: function (width, height) { - return this.put(new SVG.Ellipse()).size(width, height).move(0, 0) - } - } -}) - -SVG.extend([SVG.Ellipse, SVG.Rect, SVG.Timeline], { - // Radius x value - rx: function (rx) { - return this.attr('rx', rx) - }, - // Radius y value - ry: function (ry) { - return this.attr('ry', ry) - } -}) - -// Add common method -SVG.extend([SVG.Circle, SVG.Ellipse], { - // Move over x-axis - x: function (x) { - return x == null ? this.cx() - this.rx() : this.cx(x + this.rx()) - }, - // Move over y-axis - y: function (y) { - return y == null ? this.cy() - this.ry() : this.cy(y + this.ry()) - }, - // Move by center over x-axis - cx: function (x) { - return x == null ? this.attr('cx') : this.attr('cx', x) - }, - // Move by center over y-axis - cy: function (y) { - return y == null ? this.attr('cy') : this.attr('cy', y) - }, - // Set width of element - width: function (width) { - return width == null ? this.rx() * 2 : this.rx(new SVG.Number(width).divide(2)) - }, - // Set height of element - height: function (height) { - return height == null ? this.ry() * 2 : this.ry(new SVG.Number(height).divide(2)) - }, - // Custom size function - size: function (width, height) { - var p = proportionalSize(this, width, height) - - return this - .rx(new SVG.Number(p.width).divide(2)) - .ry(new SVG.Number(p.height).divide(2)) - } -}) diff --git a/src/eventtarget.js b/src/eventtarget.js deleted file mode 100644 index fbe4781..0000000 --- a/src/eventtarget.js +++ /dev/null @@ -1,23 +0,0 @@ -SVG.EventTarget = SVG.invent({ - create: function () {}, - extend: { - // Bind given event to listener - on: function (event, listener, binding, options) { - SVG.on(this, event, listener, binding, options) - return this - }, - // Unbind event from listener - off: function (event, listener) { - SVG.off(this, event, listener) - return this - }, - dispatch: function (event, data) { - return SVG.dispatch(this, event, data) - }, - // Fire given event - fire: function (event, data) { - this.dispatch(event, data) - return this - } - } -}) diff --git a/src/gradient.js b/src/gradient.js deleted file mode 100644 index 45a4e08..0000000 --- a/src/gradient.js +++ /dev/null @@ -1,104 +0,0 @@ -SVG.Gradient = SVG.invent({ - // Initialize node - create: function (type) { - SVG.Element.call(this, typeof type === 'object' ? type : SVG.create(type + 'Gradient')) - }, - - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - // Add a color stop - stop: function (offset, color, opacity) { - return this.put(new SVG.Stop()).update(offset, color, opacity) - }, - // Update gradient - update: function (block) { - // remove all stops - this.clear() - - // invoke passed block - if (typeof block === 'function') { - block.call(this, this) - } - - return this - }, - // Return the fill id - url: function () { - return 'url(#' + this.id() + ')' - }, - // Alias string convertion to fill - toString: function () { - return this.url() - }, - // custom attr to handle transform - attr: function (a, b, c) { - if (a === 'transform') a = 'gradientTransform' - return SVG.Container.prototype.attr.call(this, a, b, c) - } - }, - - // Add parent method - construct: { - // Create gradient element in defs - gradient: function (type, block) { - return this.defs().gradient(type, block) - } - } -}) - -// Add animatable methods to both gradient and fx module -SVG.extend([SVG.Gradient, SVG.Timeline], { - // From position - from: function (x, y) { - return (this._target || this).type === 'radialGradient' - ? this.attr({ fx: new SVG.Number(x), fy: new SVG.Number(y) }) - : this.attr({ x1: new SVG.Number(x), y1: new SVG.Number(y) }) - }, - // To position - to: function (x, y) { - return (this._target || this).type === 'radialGradient' - ? this.attr({ cx: new SVG.Number(x), cy: new SVG.Number(y) }) - : this.attr({ x2: new SVG.Number(x), y2: new SVG.Number(y) }) - } -}) - -// Base gradient generation -SVG.extend(SVG.Defs, { - // define gradient - gradient: function (type, block) { - return this.put(new SVG.Gradient(type)).update(block) - } - -}) - -SVG.Stop = SVG.invent({ - // Initialize node - create: 'stop', - - // Inherit from - inherit: SVG.Element, - - // Add class methods - extend: { - // add color stops - update: function (o) { - if (typeof o === 'number' || o instanceof SVG.Number) { - 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 SVG.Number(o.offset)) - - return this - } - } -}) diff --git a/src/group.js b/src/group.js deleted file mode 100644 index 0088a1c..0000000 --- a/src/group.js +++ /dev/null @@ -1,19 +0,0 @@ -SVG.G = SVG.invent({ - // Initialize node - create: 'g', - - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - }, - - // Add parent method - construct: { - // Create a group element - group: function () { - return this.put(new SVG.G()) - } - } -}) diff --git a/src/hyperlink.js b/src/hyperlink.js deleted file mode 100644 index cb0a341..0000000 --- a/src/hyperlink.js +++ /dev/null @@ -1,41 +0,0 @@ -SVG.A = SVG.invent({ - // Initialize node - create: 'a', - - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - // Link url - to: function (url) { - return this.attr('href', url, SVG.xlink) - }, - // Link target attribute - target: function (target) { - return this.attr('target', target) - } - }, - - // Add parent method - construct: { - // Create a hyperlink element - link: function (url) { - return this.put(new SVG.A()).to(url) - } - } -}) - -SVG.extend(SVG.Element, { - // Create a hyperlink element - linkTo: function (url) { - var link = new SVG.A() - - if (typeof url === 'function') { url.call(link, link) } else { - link.to(url) - } - - return this.parent().put(link).put(this) - } - -}) diff --git a/src/image.js b/src/image.js deleted file mode 100644 index f9395eb..0000000 --- a/src/image.js +++ /dev/null @@ -1,57 +0,0 @@ -SVG.Image = SVG.invent({ - // Initialize node - create: 'image', - - // Inherit from - inherit: SVG.Shape, - - // Add class methods - extend: { - // (re)load image - load: function (url, callback) { - if (!url) return this - - var img = new window.Image() - - SVG.on(img, 'load', function (e) { - var p = this.parent(SVG.Pattern) - - // ensure image size - if (this.width() === 0 && this.height() === 0) { - this.size(img.width, img.height) - } - - if (p instanceof SVG.Pattern) { - // ensure pattern size if not set - if (p.width() === 0 && p.height() === 0) { - p.size(this.width(), this.height()) - } - } - - if (typeof callback === 'function') { - callback.call(this, { - width: img.width, - height: img.height, - ratio: img.width / img.height, - url: url - }) - } - }, this) - - SVG.on(img, 'load error', function () { - // dont forget to unbind memory leaking events - SVG.off(img) - }) - - return this.attr('href', (img.src = url), SVG.xlink) - } - }, - - // Add parent method - construct: { - // create image element, load image and set its size - image: function (source, callback) { - return this.put(new SVG.Image()).size(0, 0).load(source, callback) - } - } -}) diff --git a/src/line.js b/src/line.js deleted file mode 100644 index da0c0ca..0000000 --- a/src/line.js +++ /dev/null @@ -1,57 +0,0 @@ -/* global proportionalSize */ - -SVG.Line = SVG.invent({ - // Initialize node - create: 'line', - - // Inherit from - inherit: SVG.Shape, - - // Add class methods - extend: { - // Get array - array: function () { - return new SVG.PointArray([ - [ this.attr('x1'), this.attr('y1') ], - [ this.attr('x2'), this.attr('y2') ] - ]) - }, - - // Overwrite native plot() method - plot: function (x1, y1, x2, y2) { - if (x1 == null) { - return this.array() - } else if (typeof y1 !== 'undefined') { - x1 = { x1: x1, y1: y1, x2: x2, y2: y2 } - } else { - x1 = new SVG.PointArray(x1).toLine() - } - - return this.attr(x1) - }, - - // Move by left top corner - move: function (x, y) { - return this.attr(this.array().move(x, y).toLine()) - }, - - // Set element size to given width and height - size: function (width, height) { - var p = proportionalSize(this, width, height) - return this.attr(this.array().size(p.width, p.height).toLine()) - } - }, - - // Add parent method - construct: { - // Create a line element - line: function (x1, y1, x2, y2) { - // make sure plot is called as a setter - // x1 is not necessarily a number, it can also be an array, a string and a SVG.PointArray - return SVG.Line.prototype.plot.apply( - this.put(new SVG.Line()) - , x1 != null ? [x1, y1, x2, y2] : [0, 0, 0, 0] - ) - } - } -}) diff --git a/src/marker.js b/src/marker.js deleted file mode 100644 index 32f8e4e..0000000 --- a/src/marker.js +++ /dev/null @@ -1,78 +0,0 @@ -SVG.Marker = SVG.invent({ - // Initialize node - create: 'marker', - - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - // Set width of element - width: function (width) { - return this.attr('markerWidth', width) - }, - // Set height of element - height: function (height) { - return this.attr('markerHeight', height) - }, - // Set marker refX and refY - ref: function (x, y) { - return this.attr('refX', x).attr('refY', y) - }, - // Update marker - update: function (block) { - // remove all content - this.clear() - - // invoke passed block - if (typeof block === 'function') { block.call(this, this) } - - return this - }, - // Return the fill id - toString: function () { - return 'url(#' + this.id() + ')' - } - }, - - // Add parent method - construct: { - marker: function (width, height, block) { - // Create marker element in defs - return this.defs().marker(width, height, block) - } - } - -}) - -SVG.extend(SVG.Defs, { - // Create marker - marker: 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 SVG.Marker()) - .size(width, height) - .ref(width / 2, height / 2) - .viewbox(0, 0, width, height) - .attr('orient', 'auto') - .update(block) - } - -}) - -SVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon, SVG.Path], { - // Create and attach markers - marker: function (marker, width, height, block) { - var attr = ['marker'] - - // Build attribute name - if (marker !== 'all') attr.push(marker) - attr = attr.join('-') - - // Set marker attribute - marker = arguments[1] instanceof SVG.Marker - ? arguments[1] - : this.doc().marker(width, height, block) - - return this.attr(attr, marker) - } -}) diff --git a/src/mask.js b/src/mask.js deleted file mode 100644 index e40d80f..0000000 --- a/src/mask.js +++ /dev/null @@ -1,51 +0,0 @@ -SVG.Mask = SVG.invent({ - // Initialize node - create: 'mask', - - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - // Unmask all masked elements and remove itself - remove: function () { - // unmask all targets - this.targets().forEach(function (el) { - el.unmask() - }) - - // remove mask from parent - return SVG.Element.prototype.remove.call(this) - }, - - targets: function () { - return SVG.select('svg [mask*="' + this.id() + '"]') - } - }, - - // Add parent method - construct: { - // Create masking element - mask: function () { - return this.defs().put(new SVG.Mask()) - } - } -}) - -SVG.extend(SVG.Element, { - // Distribute mask to svg element - maskWith: function (element) { - // use given mask or create a new one - var masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element) - - // apply mask - return this.attr('mask', 'url("#' + masker.id() + '")') - }, - // Unmask element - unmask: function () { - return this.attr('mask', null) - }, - masker: function () { - return this.reference('mask') - } -}) diff --git a/src/matrix.js b/src/matrix.js deleted file mode 100644 index 666b898..0000000 --- a/src/matrix.js +++ /dev/null @@ -1,472 +0,0 @@ -/* global abcdef arrayToMatrix closeEnough formatTransforms isMatrixLike matrixMultiply */ - -SVG.Matrix = SVG.invent({ - // Initialize - create: function (source) { - var base = arrayToMatrix([1, 0, 0, 1, 0, 0]) - - // ensure source as object - source = source instanceof SVG.Element ? source.matrixify() - : typeof source === 'string' ? arrayToMatrix(source.split(SVG.regex.delimiter).map(parseFloat)) - : Array.isArray(source) ? arrayToMatrix(source) - : (typeof source === 'object' && isMatrixLike(source)) ? source - : (typeof source === 'object') ? new SVG.Matrix().transform(source) - : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) - : base - - // Merge the source matrix with the base matrix - this.a = source.a != null ? source.a : base.a - this.b = source.b != null ? source.b : base.b - this.c = source.c != null ? source.c : base.c - this.d = source.d != null ? source.d : base.d - this.e = source.e != null ? source.e : base.e - this.f = source.f != null ? source.f : base.f - }, - - // Add methods - extend: { - - // Clones this matrix - clone: function () { - return new SVG.Matrix(this) - }, - - // Transform a matrix into another matrix by manipulating the space - transform: function (o) { - // Check if o is a matrix and then left multiply it directly - if (isMatrixLike(o)) { - var matrix = new SVG.Matrix(o) - return matrix.multiplyO(this) - } - - // Get the proposed transformations and the current transformations - var t = formatTransforms(o) - var current = this - let { x: ox, y: oy } = new SVG.Point(t.ox, t.oy).transform(current) - - // Construct the resulting matrix - var transformer = new SVG.Matrix() - .translateO(t.rx, t.ry) - .lmultiplyO(current) - .translateO(-ox, -oy) - .scaleO(t.scaleX, t.scaleY) - .skewO(t.skewX, t.skewY) - .shearO(t.shear) - .rotateO(t.theta) - .translateO(ox, oy) - - // If we want the origin at a particular place, we force it there - if (isFinite(t.px) || isFinite(t.py)) { - const origin = new SVG.Point(ox, oy).transform(transformer) - // TODO: Replace t.px with isFinite(t.px) - const dx = t.px ? t.px - origin.x : 0 - const dy = t.py ? t.py - origin.y : 0 - transformer.translateO(dx, dy) - } - - // Translate now after positioning - transformer.translateO(t.tx, t.ty) - return transformer - }, - - // Applies a matrix defined by its affine parameters - compose: function (o) { - if (o.origin) { - o.originX = o.origin[0] - o.originY = o.origin[1] - } - // Get the parameters - var ox = o.originX || 0 - var oy = o.originY || 0 - var sx = o.scaleX || 1 - var sy = o.scaleY || 1 - var lam = o.shear || 0 - var theta = o.rotate || 0 - var tx = o.translateX || 0 - var ty = o.translateY || 0 - - // Apply the standard matrix - var result = new SVG.Matrix() - .translateO(-ox, -oy) - .scaleO(sx, sy) - .shearO(lam) - .rotateO(theta) - .translateO(tx, ty) - .lmultiplyO(this) - .translateO(ox, oy) - return result - }, - - // Decomposes this matrix into its affine parameters - decompose: function (cx = 0, cy = 0) { - // Get the parameters from the matrix - var a = this.a - var b = this.b - var c = this.c - var d = this.d - var e = this.e - var f = this.f - - // Figure out if the winding direction is clockwise or counterclockwise - var determinant = a * d - b * c - var ccw = determinant > 0 ? 1 : -1 - - // Since we only shear in x, we can use the x basis to get the x scale - // and the rotation of the resulting matrix - var sx = ccw * Math.sqrt(a * a + b * b) - var thetaRad = Math.atan2(ccw * b, ccw * a) - var theta = 180 / Math.PI * thetaRad - var ct = Math.cos(thetaRad) - var st = Math.sin(thetaRad) - - // We can then solve the y basis vector simultaneously to get the other - // two affine parameters directly from these parameters - var lam = (a * c + b * d) / determinant - var sy = ((c * sx) / (lam * a - b)) || ((d * sx) / (lam * b + a)) - - // Use the translations - let tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy) - let ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy) - - // Construct the decomposition and return it - return { - // Return the affine parameters - scaleX: sx, - scaleY: sy, - shear: lam, - rotate: theta, - translateX: tx, - translateY: ty, - originX: cx, - originY: cy, - - // Return the matrix parameters - a: this.a, - b: this.b, - c: this.c, - d: this.d, - e: this.e, - f: this.f - } - }, - - // Morph one matrix into another - morph: function (matrix) { - // Store new destination - this.destination = new SVG.Matrix(matrix) - return this - }, - - // Get morphed matrix at a given position - at: function (pos) { - // Make sure a destination is defined - if (!this.destination) return this - - // Calculate morphed matrix at a given position - var matrix = new SVG.Matrix({ - a: this.a + (this.destination.a - this.a) * pos, - b: this.b + (this.destination.b - this.b) * pos, - c: this.c + (this.destination.c - this.c) * pos, - d: this.d + (this.destination.d - this.d) * pos, - e: this.e + (this.destination.e - this.e) * pos, - f: this.f + (this.destination.f - this.f) * pos - }) - - return matrix - }, - - // Left multiplies by the given matrix - multiply: function (matrix) { - return this.clone().multiplyO(matrix) - }, - - multiplyO: function (matrix) { - // Get the matrices - var l = this - var r = matrix instanceof SVG.Matrix - ? matrix - : new SVG.Matrix(matrix) - - return matrixMultiply(l, r, this) - }, - - lmultiply: function (matrix) { - return this.clone().lmultiplyO(matrix) - }, - - lmultiplyO: function (matrix) { - var r = this - var l = matrix instanceof SVG.Matrix - ? matrix - : new SVG.Matrix(matrix) - - return matrixMultiply(l, r, this) - }, - - // Inverses matrix - inverseO: function () { - // Get the current parameters out of the matrix - var a = this.a - var b = this.b - var c = this.c - var d = this.d - var e = this.e - var f = this.f - - // Invert the 2x2 matrix in the top left - var det = a * d - b * c - if (!det) throw new Error('Cannot invert ' + this) - - // Calculate the top 2x2 matrix - var na = d / det - var nb = -b / det - var nc = -c / det - var nd = a / det - - // Apply the inverted matrix to the top right - var ne = -(na * e + nc * f) - var nf = -(nb * e + nd * f) - - // Construct the inverted matrix - this.a = na - this.b = nb - this.c = nc - this.d = nd - this.e = ne - this.f = nf - - return this - }, - - inverse: function () { - return this.clone().inverseO() - }, - - // Translate matrix - translate: function (x, y) { - return this.clone().translateO(x, y) - }, - - translateO: function (x, y) { - this.e += x || 0 - this.f += y || 0 - return this - }, - - // Scale matrix - scale: function (x, y, cx, cy) { - return this.clone().scaleO(...arguments) - }, - - scaleO: function (x, y = x, cx = 0, cy = 0) { - // Support uniform scaling - if (arguments.length === 3) { - cy = cx - cx = y - y = x - } - - let {a, b, c, d, e, f} = this - - this.a = a * x - this.b = b * y - this.c = c * x - this.d = d * y - this.e = e * x - cx * x + cx - this.f = f * y - cy * y + cy - - return this - }, - - // Rotate matrix - rotate: function (r, cx, cy) { - return this.clone().rotateO(r, cx, cy) - }, - - rotateO: function (r, cx = 0, cy = 0) { - // Convert degrees to radians - r = SVG.utils.radians(r) - - let cos = Math.cos(r) - let sin = Math.sin(r) - - let {a, b, c, d, e, f} = this - - this.a = a * cos - b * sin - this.b = b * cos + a * sin - this.c = c * cos - d * sin - this.d = d * cos + c * sin - this.e = e * cos - f * sin + cy * sin - cx * cos + cx - this.f = f * cos + e * sin - cx * sin - cy * cos + cy - - return this - }, - - // Flip matrix on x or y, at a given offset - flip: function (axis, around) { - return this.clone().flipO(axis, around) - }, - - flipO: function (axis, around) { - return axis === 'x' ? this.scaleO(-1, 1, around, 0) - : axis === 'y' ? this.scaleO(1, -1, 0, around) - : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point - }, - - // Shear matrix - shear: function (a, cx, cy) { - return this.clone().shearO(a, cx, cy) - }, - - shearO: function (lx, cx = 0, cy = 0) { - let {a, b, c, d, e, f} = this - - this.a = a + b * lx - this.c = c + d * lx - this.e = e + f * lx - cy * lx - - return this - }, - - // Skew Matrix - skew: function (x, y, cx, cy) { - return this.clone().skewO(...arguments) - }, - - skewO: function (x, y = x, cx = 0, cy = 0) { - // support uniformal skew - if (arguments.length === 3) { - cy = cx - cx = y - y = x - } - - // Convert degrees to radians - x = SVG.utils.radians(x) - y = SVG.utils.radians(y) - - let lx = Math.tan(x) - let ly = Math.tan(y) - - let {a, b, c, d, e, f} = this - - this.a = a + b * lx - this.b = b + a * ly - this.c = c + d * lx - this.d = d + c * ly - this.e = e + f * lx - cy * lx - this.f = f + e * ly - cx * ly - - return this - }, - - // SkewX - skewX: function (x, cx, cy) { - return this.skew(x, 0, cx, cy) - }, - - skewXO: function (x, cx, cy) { - return this.skewO(x, 0, cx, cy) - }, - - // SkewY - skewY: function (y, cx, cy) { - return this.skew(0, y, cx, cy) - }, - - skewYO: function (y, cx, cy) { - return this.skewO(0, y, cx, cy) - }, - - // Transform around a center point - aroundO: function (cx, cy, matrix) { - var dx = cx || 0 - var dy = cy || 0 - return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy) - }, - - around: function (cx, cy, matrix) { - return this.clone().aroundO(cx, cy, matrix) - }, - - // Convert to native SVGMatrix - native: function () { - // create new matrix - var matrix = SVG.parser.nodes.svg.node.createSVGMatrix() - - // update with current values - for (var i = abcdef.length - 1; i >= 0; i--) { - matrix[abcdef[i]] = this[abcdef[i]] - } - - return matrix - }, - - // Check if two matrices are equal - equals: function (other) { - var comp = new SVG.Matrix(other) - return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && - closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && - closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f) - }, - - // Convert matrix to string - toString: function () { - return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')' - }, - - toArray: function () { - return [this.a, this.b, this.c, this.d, this.e, this.f] - }, - - valueOf: function () { - return { - a: this.a, - b: this.b, - c: this.c, - d: this.d, - e: this.e, - f: this.f - } - } - }, - - // Define parent - parent: SVG.Element, - - // Add parent method - construct: { - // Get current matrix - ctm: function () { - return new SVG.Matrix(this.node.getCTM()) - }, - // Get current screen matrix - screenCTM: function () { - /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 - This is needed because FF does not return the transformation matrix - for the inner coordinate system when getScreenCTM() is called on nested svgs. - However all other Browsers do that */ - if (this instanceof SVG.Doc && !this.isRoot()) { - var rect = this.rect(1, 1) - var m = rect.node.getScreenCTM() - rect.remove() - return new SVG.Matrix(m) - } - return new SVG.Matrix(this.node.getScreenCTM()) - } - } -}) - -// let extensions = {} -// ['rotate'].forEach((method) => { -// let methodO = method + 'O' -// extensions[method] = function (...args) { -// return new SVG.Matrix(this)[methodO](...args) -// } -// }) -// -// SVG.extend(SVG.Matrix, extensions) - -// function matrixMultiplyParams (matrix, a, b, c, d, e, f) { -// return matrixMultiply({a, b, c, d, e, f}, matrix, matrix) -// } diff --git a/src/morph.js b/src/morph.js deleted file mode 100644 index acb9e21..0000000 --- a/src/morph.js +++ /dev/null @@ -1,231 +0,0 @@ - -SVG.Morphable = SVG.invent({ - create: function (stepper) { - // FIXME: the default stepper does not know about easing - this._stepper = stepper || new SVG.Ease('-') - - this._from = null - this._to = null - this._type = null - this._context = null - this._morphObj = null - }, - - extend: { - - from: function (val) { - if (val == null) { - return this._from - } - - this._from = this._set(val) - return this - }, - - to: function (val) { - if (val == null) { - return this._to - } - - this._to = this._set(val) - return this - }, - - type: function (type) { - // getter - if (type == null) { - return this._type - } - - // setter - this._type = type - return this - }, - - _set: function (value) { - if (!this._type) { - var type = typeof value - - if (type === 'number') { - this.type(SVG.Number) - } else if (type === 'string') { - if (SVG.Color.isColor(value)) { - this.type(SVG.Color) - } else if (SVG.regex.delimiter.test(value)) { - this.type(SVG.regex.pathLetters.test(value) - ? SVG.PathArray - : SVG.Array - ) - } else if (SVG.regex.numberAndUnit.test(value)) { - this.type(SVG.Number) - } else { - this.type(SVG.Morphable.NonMorphable) - } - } else if (SVG.MorphableTypes.indexOf(value.constructor) > -1) { - this.type(value.constructor) - } else if (Array.isArray(value)) { - this.type(SVG.Array) - } else if (type === 'object') { - this.type(SVG.Morphable.ObjectBag) - } else { - this.type(SVG.Morphable.NonMorphable) - } - } - - var result = (new this._type(value)).toArray() - this._morphObj = this._morphObj || new this._type() - this._context = this._context || - Array.apply(null, Array(result.length)).map(Object) - return result - }, - - stepper: function (stepper) { - if (stepper == null) return this._stepper - this._stepper = stepper - return this - }, - - done: function () { - var complete = this._context - .map(this._stepper.done) - .reduce(function (last, curr) { - return last && curr - }, true) - return complete - }, - - at: function (pos) { - var _this = this - - return this._morphObj.fromArray( - this._from.map(function (i, index) { - return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context) - }) - ) - } - } -}) - -SVG.Morphable.NonMorphable = SVG.invent({ - create: function (val) { - val = Array.isArray(val) ? val[0] : val - this.value = val - }, - - extend: { - valueOf: function () { - return this.value - }, - - toArray: function () { - return [this.value] - } - } -}) - -SVG.Morphable.TransformBag = SVG.invent({ - create: function (obj) { - if (Array.isArray(obj)) { - obj = { - scaleX: obj[0], - scaleY: obj[1], - shear: obj[2], - rotate: obj[3], - translateX: obj[4], - translateY: obj[5], - originX: obj[6], - originY: obj[7] - } - } - - Object.assign(this, SVG.Morphable.TransformBag.defaults, obj) - }, - - extend: { - toArray: function () { - var v = this - - return [ - v.scaleX, - v.scaleY, - v.shear, - v.rotate, - v.translateX, - v.translateY, - v.originX, - v.originY - ] - } - } -}) - -SVG.Morphable.TransformBag.defaults = { - scaleX: 1, - scaleY: 1, - shear: 0, - rotate: 0, - translateX: 0, - translateY: 0, - originX: 0, - originY: 0 -} - -SVG.Morphable.ObjectBag = SVG.invent({ - create: function (objOrArr) { - this.values = [] - - if (Array.isArray(objOrArr)) { - this.values = objOrArr - return - } - - var entries = Object.entries(objOrArr || {}).sort((a, b) => { - return a[0] - b[0] - }) - - this.values = entries.reduce((last, curr) => last.concat(curr), []) - }, - - extend: { - valueOf: function () { - var obj = {} - var arr = this.values - - for (var i = 0, len = arr.length; i < len; i += 2) { - obj[arr[i]] = arr[i + 1] - } - - return obj - }, - - toArray: function () { - return this.values - } - } -}) - -SVG.MorphableTypes = [ - SVG.Number, - SVG.Color, - SVG.Box, - SVG.Matrix, - SVG.Array, - SVG.PointArray, - SVG.PathArray, - SVG.Morphable.NonMorphable, - SVG.Morphable.TransformBag, - SVG.Morphable.ObjectBag -] - -SVG.extend(SVG.MorphableTypes, { - to: function (val, args) { - return new SVG.Morphable() - .type(this.constructor) - .from(this.valueOf()) - .to(val, args) - }, - fromArray: function (arr) { - this.constructor(arr) - return this - } -}) diff --git a/src/number.js b/src/number.js deleted file mode 100644 index 2135b61..0000000 --- a/src/number.js +++ /dev/null @@ -1,99 +0,0 @@ - -// Module for unit convertions -SVG.Number = SVG.invent({ - // Initialize - create: function (value, unit) { - unit = Array.isArray(value) ? value[1] : unit - value = Array.isArray(value) ? value[0] : value - - // initialize defaults - this.value = 0 - this.unit = unit || '' - - // parse value - if (typeof value === 'number') { - // ensure a valid numeric value - this.value = isNaN(value) ? 0 : !isFinite(value) ? (value < 0 ? -3.4e+38 : +3.4e+38) : value - } else if (typeof value === 'string') { - unit = value.match(SVG.regex.numberAndUnit) - - if (unit) { - // make value numeric - this.value = parseFloat(unit[1]) - - // normalize - if (unit[5] === '%') { this.value /= 100 } else if (unit[5] === 's') { - this.value *= 1000 - } - - // store unit - this.unit = unit[5] - } - } else { - if (value instanceof SVG.Number) { - this.value = value.valueOf() - this.unit = value.unit - } - } - }, - // Add methods - extend: { - // Stringalize - toString: function () { - return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 - : this.unit === 's' ? this.value / 1e3 - : this.value - ) + this.unit - }, - toJSON: function () { - return this.toString() - }, // Convert to primitive - toArray: function () { - return [this.value, this.unit] - }, - valueOf: function () { - return this.value - }, - // Add number - plus: function (number) { - number = new SVG.Number(number) - return new SVG.Number(this + number, this.unit || number.unit) - }, - // Subtract number - minus: function (number) { - number = new SVG.Number(number) - return new SVG.Number(this - number, this.unit || number.unit) - }, - // Multiply number - times: function (number) { - number = new SVG.Number(number) - return new SVG.Number(this * number, this.unit || number.unit) - }, - // Divide number - divide: function (number) { - number = new SVG.Number(number) - return new SVG.Number(this / number, this.unit || number.unit) - }, - // Make number morphable - morph: function (number) { - this.destination = new SVG.Number(number) - - if (number.relative) { - this.destination.value += this.value - } - - return this - }, - // Get morphed number at given position - at: function (pos) { - // Make sure a destination is defined - if (!this.destination) return this - - // Generate new morphed number - return new SVG.Number(this.destination) - .minus(this) - .times(pos) - .plus(this) - } - } -}) diff --git a/src/parent.js b/src/parent.js deleted file mode 100644 index 6bdad58..0000000 --- a/src/parent.js +++ /dev/null @@ -1,92 +0,0 @@ -/* global createElement */ - -SVG.Parent = SVG.invent({ - // Initialize node - create: function (node) { - SVG.Element.call(this, node) - }, - - // Inherit from - inherit: SVG.Element, - - // Add class methods - extend: { - // Returns all child elements - children: function () { - return SVG.utils.map(this.node.children, function (node) { - return SVG.adopt(node) - }) - }, - // Add given element at a position - add: function (element, i) { - element = createElement(element) - - if (element.node !== this.node.children[i]) { - this.node.insertBefore(element.node, this.node.children[i] || null) - } - - return this - }, - // Basically does the same as `add()` but returns the added element instead - put: function (element, i) { - this.add(element, i) - return element.instance || element - }, - // Checks if the given element is a child - has: function (element) { - return this.index(element) >= 0 - }, - // Gets index of given element - index: function (element) { - return [].slice.call(this.node.children).indexOf(element.node) - }, - // Get a element at the given index - get: function (i) { - return SVG.adopt(this.node.children[i]) - }, - // Get first child - first: function () { - return this.get(0) - }, - // Get the last child - last: function () { - return this.get(this.node.children.length - 1) - }, - // Iterates over all children and invokes a given block - each: function (block, deep) { - var children = this.children() - var i, il - - for (i = 0, il = children.length; i < il; i++) { - if (children[i] instanceof SVG.Element) { - block.apply(children[i], [i, children]) - } - - if (deep && (children[i] instanceof SVG.Parent)) { - children[i].each(block, deep) - } - } - - return this - }, - // Remove a given child - removeElement: function (element) { - this.node.removeChild(element.node) - - return this - }, - // Remove all elements in this container - clear: function () { - // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) - } - - // remove defs reference - delete this._defs - - return this - } - } - -}) diff --git a/src/path.js b/src/path.js deleted file mode 100644 index db3929b..0000000 --- a/src/path.js +++ /dev/null @@ -1,63 +0,0 @@ -/* global proportionalSize */ - -SVG.Path = SVG.invent({ - // Initialize node - create: 'path', - - // Inherit from - inherit: SVG.Shape, - - // Add class methods - extend: { - // Define morphable array - MorphArray: SVG.PathArray, - // Get array - array: function () { - return this._array || (this._array = new SVG.PathArray(this.attr('d'))) - }, - // Plot new path - plot: function (d) { - return (d == null) ? this.array() - : this.clear().attr('d', typeof d === 'string' ? d : (this._array = new SVG.PathArray(d))) - }, - // Clear array cache - clear: function () { - delete this._array - return this - }, - // Move by left top corner - move: function (x, y) { - return this.attr('d', this.array().move(x, y)) - }, - // Move by left top corner over x-axis - x: function (x) { - return x == null ? this.bbox().x : this.move(x, this.bbox().y) - }, - // Move by left top corner over y-axis - y: function (y) { - return y == null ? this.bbox().y : this.move(this.bbox().x, y) - }, - // Set element size to given width and height - size: function (width, height) { - var p = proportionalSize(this, width, height) - return this.attr('d', this.array().size(p.width, p.height)) - }, - // Set width of element - width: function (width) { - return width == null ? this.bbox().width : this.size(width, this.bbox().height) - }, - // Set height of element - height: function (height) { - return height == null ? this.bbox().height : this.size(this.bbox().width, height) - } - }, - - // Add parent method - construct: { - // Create a wrapped path element - path: function (d) { - // make sure plot is called as a setter - return this.put(new SVG.Path()).plot(d || new SVG.PathArray()) - } - } -}) diff --git a/src/patharray.js b/src/patharray.js deleted file mode 100644 index 4432df3..0000000 --- a/src/patharray.js +++ /dev/null @@ -1,289 +0,0 @@ -/* globals arrayToString, pathRegReplace */ - -var pathHandlers = { - M: function (c, p, p0) { - p.x = p0.x = c[0] - p.y = p0.y = c[1] - - return ['M', p.x, p.y] - }, - L: function (c, p) { - p.x = c[0] - p.y = c[1] - return ['L', c[0], c[1]] - }, - H: function (c, p) { - p.x = c[0] - return ['H', c[0]] - }, - V: function (c, p) { - p.y = c[0] - return ['V', c[0]] - }, - C: function (c, p) { - p.x = c[4] - p.y = c[5] - return ['C', c[0], c[1], c[2], c[3], c[4], c[5]] - }, - S: function (c, p) { - p.x = c[2] - p.y = c[3] - return ['S', c[0], c[1], c[2], c[3]] - }, - Q: function (c, p) { - p.x = c[2] - p.y = c[3] - return ['Q', c[0], c[1], c[2], c[3]] - }, - T: function (c, p) { - p.x = c[0] - p.y = c[1] - return ['T', c[0], c[1]] - }, - Z: function (c, p, p0) { - p.x = p0.x - p.y = p0.y - return ['Z'] - }, - A: function (c, p) { - p.x = c[5] - p.y = c[6] - return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]] - } -} - -var mlhvqtcsaz = 'mlhvqtcsaz'.split('') - -for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { - pathHandlers[mlhvqtcsaz[i]] = (function (i) { - return function (c, p, p0) { - if (i === 'H') c[0] = c[0] + p.x - else if (i === 'V') c[0] = c[0] + p.y - else if (i === 'A') { - c[5] = c[5] + p.x - c[6] = c[6] + p.y - } else { - for (var j = 0, jl = c.length; j < jl; ++j) { - c[j] = c[j] + (j % 2 ? p.y : p.x) - } - } - - return pathHandlers[i](c, p, p0) - } - })(mlhvqtcsaz[i].toUpperCase()) -} - -// Path points array -SVG.PathArray = function (array, fallback) { - SVG.Array.call(this, array, fallback || [['M', 0, 0]]) -} - -// Inherit from SVG.Array -SVG.PathArray.prototype = new SVG.Array() -SVG.PathArray.prototype.constructor = SVG.PathArray - -SVG.extend(SVG.PathArray, { - // Convert array to string - toString: function () { - return arrayToString(this.value) - }, - toArray: function () { - return this.value.reduce(function (prev, curr) { - return [].concat.call(prev, curr) - }, []) - }, - // Move path string - move: function (x, y) { - // get bounding box of current situation - var box = this.bbox() - - // get relative offset - x -= box.x - y -= box.y - - if (!isNaN(x) && !isNaN(y)) { - // move every point - for (var l, i = this.value.length - 1; i >= 0; i--) { - l = this.value[i][0] - - if (l === 'M' || l === 'L' || l === 'T') { - this.value[i][1] += x - this.value[i][2] += y - } else if (l === 'H') { - this.value[i][1] += x - } else if (l === 'V') { - this.value[i][1] += y - } else if (l === 'C' || l === 'S' || l === 'Q') { - this.value[i][1] += x - this.value[i][2] += y - this.value[i][3] += x - this.value[i][4] += y - - if (l === 'C') { - this.value[i][5] += x - this.value[i][6] += y - } - } else if (l === 'A') { - this.value[i][6] += x - this.value[i][7] += y - } - } - } - - return this - }, - // Resize path string - size: function (width, height) { - // get bounding box of current situation - var box = this.bbox() - var i, l - - // recalculate position of all points according to new size - for (i = this.value.length - 1; i >= 0; i--) { - l = this.value[i][0] - - if (l === 'M' || l === 'L' || l === 'T') { - this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x - this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y - } else if (l === 'H') { - this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x - } else if (l === 'V') { - this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y - } else if (l === 'C' || l === 'S' || l === 'Q') { - this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x - this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y - this.value[i][3] = ((this.value[i][3] - box.x) * width) / box.width + box.x - this.value[i][4] = ((this.value[i][4] - box.y) * height) / box.height + box.y - - if (l === 'C') { - this.value[i][5] = ((this.value[i][5] - box.x) * width) / box.width + box.x - this.value[i][6] = ((this.value[i][6] - box.y) * height) / box.height + box.y - } - } else if (l === 'A') { - // resize radii - this.value[i][1] = (this.value[i][1] * width) / box.width - this.value[i][2] = (this.value[i][2] * height) / box.height - - // move position values - this.value[i][6] = ((this.value[i][6] - box.x) * width) / box.width + box.x - this.value[i][7] = ((this.value[i][7] - box.y) * height) / box.height + box.y - } - } - - return this - }, - // Test if the passed path array use the same path data commands as this path array - equalCommands: function (pathArray) { - var i, il, equalCommands - - pathArray = new SVG.PathArray(pathArray) - - equalCommands = this.value.length === pathArray.value.length - for (i = 0, il = this.value.length; equalCommands && i < il; i++) { - equalCommands = this.value[i][0] === pathArray.value[i][0] - } - - return equalCommands - }, - // Make path array morphable - morph: function (pathArray) { - pathArray = new SVG.PathArray(pathArray) - - if (this.equalCommands(pathArray)) { - this.destination = pathArray - } else { - this.destination = null - } - - return this - }, - // Get morphed path array at given position - at: function (pos) { - // make sure a destination is defined - if (!this.destination) return this - - var sourceArray = this.value - var destinationArray = this.destination.value - var array = [] - var pathArray = new SVG.PathArray() - var i, il, j, jl - - // Animate has specified in the SVG spec - // See: https://www.w3.org/TR/SVG11/paths.html#PathElement - for (i = 0, il = sourceArray.length; i < il; i++) { - array[i] = [sourceArray[i][0]] - for (j = 1, jl = sourceArray[i].length; j < jl; j++) { - array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos - } - // For the two flags of the elliptical arc command, the SVG spec say: - // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true - // Elliptical arc command as an array followed by corresponding indexes: - // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] - // 0 1 2 3 4 5 6 7 - if (array[i][0] === 'A') { - array[i][4] = +(array[i][4] !== 0) - array[i][5] = +(array[i][5] !== 0) - } - } - - // Directly modify the value of a path array, this is done this way for performance - pathArray.value = array - return pathArray - }, - // Absolutize and parse path to array - parse: function (array) { - // if it's already a patharray, no need to parse it - if (array instanceof SVG.PathArray) return array.valueOf() - - // prepare for parsing - var s - var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 } - - if (typeof array === 'string') { - array = array - .replace(SVG.regex.numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 - .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers - .replace(SVG.regex.hyphen, '$1 -') // add space before hyphen - .trim() // trim - .split(SVG.regex.delimiter) // split into array - } else { - array = array.reduce(function (prev, curr) { - return [].concat.call(prev, curr) - }, []) - } - - // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] - var result = [] - var p = new SVG.Point() - var p0 = new SVG.Point() - var index = 0 - var len = array.length - - do { - // Test if we have a path letter - if (SVG.regex.isPathLetter.test(array[index])) { - s = array[index] - ++index - // If last letter was a move command and we got no new, it defaults to [L]ine - } else if (s === 'M') { - s = 'L' - } else if (s === 'm') { - s = 'l' - } - - result.push(pathHandlers[s].call(null, - array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), - p, p0 - ) - ) - } while (len > index) - - return result - }, - // Get bounding box of path - bbox: function () { - SVG.parser().path.setAttribute('d', this.toString()) - return SVG.parser.nodes.path.getBBox() - } - -}) diff --git a/src/pattern.js b/src/pattern.js deleted file mode 100644 index d4c4116..0000000 --- a/src/pattern.js +++ /dev/null @@ -1,59 +0,0 @@ -SVG.Pattern = SVG.invent({ - // Initialize node - create: 'pattern', - - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - // Return the fill id - url: function () { - return 'url(#' + this.id() + ')' - }, - // Update pattern by rebuilding - update: function (block) { - // remove content - this.clear() - - // invoke passed block - if (typeof block === 'function') { - block.call(this, this) - } - - return this - }, - // Alias string convertion to fill - toString: function () { - return this.url() - }, - // custom attr to handle transform - attr: function (a, b, c) { - if (a === 'transform') a = 'patternTransform' - return SVG.Container.prototype.attr.call(this, a, b, c) - } - - }, - - // Add parent method - construct: { - // Create pattern element in defs - pattern: function (width, height, block) { - return this.defs().pattern(width, height, block) - } - } -}) - -SVG.extend(SVG.Defs, { - // Define gradient - pattern: function (width, height, block) { - return this.put(new SVG.Pattern()).update(block).attr({ - x: 0, - y: 0, - width: width, - height: height, - patternUnits: 'userSpaceOnUse' - }) - } - -}) diff --git a/src/point.js b/src/point.js deleted file mode 100644 index 6c64ed6..0000000 --- a/src/point.js +++ /dev/null @@ -1,74 +0,0 @@ - -SVG.Point = SVG.invent({ - // Initialize - create: function (x, y, base) { - var source - base = base || {x: 0, y: 0} - - // ensure source as object - source = Array.isArray(x) ? {x: x[0], y: x[1]} - : typeof x === 'object' ? {x: x.x, y: x.y} - : {x: x, y: y} - - // merge source - this.x = source.x == null ? base.x : source.x - this.y = source.y == null ? base.y : source.y - }, - - // Add methods - extend: { - // Clone point - clone: function () { - return new SVG.Point(this) - }, - - // Morph one point into another - morph: function (x, y) { - // store new destination - this.destination = new SVG.Point(x, y) - return this - }, - - // Get morphed point at a given position - at: function (pos) { - // make sure a destination is defined - if (!this.destination) return this - - // calculate morphed matrix at a given position - var point = new SVG.Point({ - x: this.x + (this.destination.x - this.x) * pos, - y: this.y + (this.destination.y - this.y) * pos - }) - return point - }, - - // Convert to native SVGPoint - native: function () { - // create new point - var point = SVG.parser.nodes.svg.node.createSVGPoint() - - // update with current values - point.x = this.x - point.y = this.y - return point - }, - - // transform point with matrix - transform: function (m) { - // Perform the matrix multiplication - var x = m.a * this.x + m.c * this.y + m.e - var y = m.b * this.x + m.d * this.y + m.f - - // Return the required point - return new SVG.Point(x, y) - } - } -}) - -SVG.extend(SVG.Element, { - - // Get point - point: function (x, y) { - return new SVG.Point(x, y).transform(this.screenCTM().inverse()) - } -}) diff --git a/src/pointarray.js b/src/pointarray.js deleted file mode 100644 index aa5f84a..0000000 --- a/src/pointarray.js +++ /dev/null @@ -1,128 +0,0 @@ - -// Poly points array -SVG.PointArray = function (array, fallback) { - SVG.Array.call(this, array, fallback || [[0, 0]]) -} - -// Inherit from SVG.Array -SVG.PointArray.prototype = new SVG.Array() -SVG.PointArray.prototype.constructor = SVG.PointArray - -SVG.extend(SVG.PointArray, { - // Convert array to string - toString: function () { - // convert to a poly point string - for (var i = 0, il = this.value.length, array = []; i < il; i++) { - array.push(this.value[i].join(',')) - } - - return array.join(' ') - }, - - toArray: function () { - return this.value.reduce(function (prev, curr) { - return [].concat.call(prev, curr) - }, []) - }, - - // Convert array to line object - toLine: function () { - return { - x1: this.value[0][0], - y1: this.value[0][1], - x2: this.value[1][0], - y2: this.value[1][1] - } - }, - - // Get morphed array at given position - at: function (pos) { - // make sure a destination is defined - if (!this.destination) return this - - // generate morphed point string - for (var i = 0, il = this.value.length, array = []; i < il; i++) { - array.push([ - this.value[i][0] + (this.destination[i][0] - this.value[i][0]) * pos, - this.value[i][1] + (this.destination[i][1] - this.value[i][1]) * pos - ]) - } - - return new SVG.PointArray(array) - }, - - // Parse point string and flat array - parse: function (array) { - var points = [] - - array = array.valueOf() - - // if it is an array - if (Array.isArray(array)) { - // and it is not flat, there is no need to parse it - if (Array.isArray(array[0])) { - return array - } - } else { // Else, it is considered as a string - // parse points - array = array.trim().split(SVG.regex.delimiter).map(parseFloat) - } - - // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints - // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. - if (array.length % 2 !== 0) array.pop() - - // wrap points in two-tuples and parse points as floats - for (var i = 0, len = array.length; i < len; i = i + 2) { - points.push([ array[i], array[i + 1] ]) - } - - return points - }, - - // Move point string - move: function (x, y) { - var box = this.bbox() - - // get relative offset - x -= box.x - y -= box.y - - // move every point - if (!isNaN(x) && !isNaN(y)) { - for (var i = this.value.length - 1; i >= 0; i--) { - this.value[i] = [this.value[i][0] + x, this.value[i][1] + y] - } - } - - return this - }, - // Resize poly string - size: function (width, height) { - var i - var box = this.bbox() - - // recalculate position of all points according to new size - for (i = this.value.length - 1; i >= 0; i--) { - if (box.width) this.value[i][0] = ((this.value[i][0] - box.x) * width) / box.width + box.x - if (box.height) this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y - } - - return this - }, - - // Get bounding box of points - bbox: function () { - var maxX = -Infinity - var maxY = -Infinity - var minX = Infinity - var minY = Infinity - this.value.forEach(function (el) { - maxX = Math.max(el[0], maxX) - maxY = Math.max(el[1], maxY) - minX = Math.min(el[0], minX) - minY = Math.min(el[1], minY) - }) - return {x: minX, y: minY, width: maxX - minX, height: maxY - minY} - } -}) diff --git a/src/poly.js b/src/poly.js deleted file mode 100644 index 9625776..0000000 --- a/src/poly.js +++ /dev/null @@ -1,67 +0,0 @@ -/* global proportionalSize */ - -SVG.Polyline = SVG.invent({ - // Initialize node - create: 'polyline', - - // Inherit from - inherit: SVG.Shape, - - // Add parent method - construct: { - // Create a wrapped polyline element - polyline: function (p) { - // make sure plot is called as a setter - return this.put(new SVG.Polyline()).plot(p || new SVG.PointArray()) - } - } -}) - -SVG.Polygon = SVG.invent({ - // Initialize node - create: 'polygon', - - // Inherit from - inherit: SVG.Shape, - - // Add parent method - construct: { - // Create a wrapped polygon element - polygon: function (p) { - // make sure plot is called as a setter - return this.put(new SVG.Polygon()).plot(p || new SVG.PointArray()) - } - } -}) - -// Add polygon-specific functions -SVG.extend([SVG.Polyline, SVG.Polygon], { - // Get array - array: function () { - return this._array || (this._array = new SVG.PointArray(this.attr('points'))) - }, - - // Plot new path - plot: function (p) { - return (p == null) ? this.array() - : this.clear().attr('points', typeof p === 'string' ? p - : (this._array = new SVG.PointArray(p))) - }, - - // Clear array cache - clear: function () { - delete this._array - return this - }, - - // Move by left top corner - move: function (x, y) { - return this.attr('points', this.array().move(x, y)) - }, - - // Set element size to given width and height - size: function (width, height) { - var p = proportionalSize(this, width, height) - return this.attr('points', this.array().size(p.width, p.height)) - } -}) diff --git a/src/queue.js b/src/queue.js deleted file mode 100644 index 621c887..0000000 --- a/src/queue.js +++ /dev/null @@ -1,61 +0,0 @@ -SVG.Queue = SVG.invent({ - create: function () { - this._first = null - this._last = null - }, - - extend: { - push: function (value) { - // An item stores an id and the provided value - var item = value.next ? value : { value: value, next: null, prev: null } - - // Deal with the queue being empty or populated - if (this._last) { - item.prev = this._last - this._last.next = item - this._last = item - } else { - this._last = item - this._first = item - } - - // Update the length and return the current item - return item - }, - - shift: function () { - // Check if we have a value - var remove = this._first - if (!remove) return null - - // If we do, remove it and relink things - this._first = remove.next - if (this._first) this._first.prev = null - this._last = this._first ? this._last : null - return remove.value - }, - - // Shows us the first item in the list - first: function () { - return this._first && this._first.value - }, - - // Shows us the last item in the list - last: function () { - return this._last && this._last.value - }, - - // Removes the item that was returned from the push - remove: function (item) { - // Relink the previous item - if (item.prev) item.prev.next = item.next - if (item.next) item.next.prev = item.prev - if (item === this._last) this._last = item.prev - if (item === this._first) this._first = item.next - - // Invalidate item - item.prev = null - item.next = null - } - } -}) diff --git a/src/rect.js b/src/rect.js deleted file mode 100644 index 35a3678..0000000 --- a/src/rect.js +++ /dev/null @@ -1,16 +0,0 @@ - -SVG.Rect = SVG.invent({ - // Initialize node - create: 'rect', - - // Inherit from - inherit: SVG.Shape, - - // Add parent method - construct: { - // Create a rect element - rect: function (width, height) { - return this.put(new SVG.Rect()).size(width, height) - } - } -}) diff --git a/src/runner.js b/src/runner.js deleted file mode 100644 index 97e04e2..0000000 --- a/src/runner.js +++ /dev/null @@ -1,928 +0,0 @@ -/* global isMatrixLike getOrigin */ - -SVG.easing = { - '-': function (pos) { return pos }, - '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, - '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, - '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } -} - -SVG.Runner = SVG.invent({ - parent: SVG.Element, - - create: function (options) { - // Store a unique id on the runner, so that we can identify it later - this.id = SVG.Runner.id++ - - // Ensure a default value - options = options == null - ? SVG.defaults.timeline.duration - : options - - // Ensure that we get a controller - options = typeof options === 'function' - ? new SVG.Controller(options) - : options - - // Declare all of the variables - this._element = null - this._timeline = null - this.done = false - this._queue = [] - - // Work out the stepper and the duration - this._duration = typeof options === 'number' && options - this._isDeclarative = options instanceof SVG.Controller - this._stepper = this._isDeclarative ? options : new SVG.Ease() - - // We copy the current values from the timeline because they can change - this._history = {} - - // Store the state of the runner - this.enabled = true - this._time = 0 - this._last = 0 - - // Save transforms applied to this runner - this.transforms = new SVG.Matrix() - this.transformId = 1 - - // Looping variables - this._haveReversed = false - this._reverse = false - this._loopsDone = 0 - this._swing = false - this._wait = 0 - this._times = 1 - }, - - construct: { - - animate: function (duration, delay, when) { - var o = SVG.Runner.sanitise(duration, delay, when) - var timeline = this.timeline() - return new SVG.Runner(o.duration) - .loop(o) - .element(this) - .timeline(timeline) - .schedule(delay, when) - }, - - delay: function (by, when) { - return this.animate(0, by, when) - } - }, - - extend: { - - /* - Runner Definitions - ================== - These methods help us define the runtime behaviour of the Runner or they - help us make new runners from the current runner - */ - - element: function (element) { - if (element == null) return this._element - this._element = element - element._prepareRunner() - return this - }, - - timeline: function (timeline) { - // check explicitly for undefined so we can set the timeline to null - if (typeof timeline === 'undefined') return this._timeline - this._timeline = timeline - return this - }, - - animate: function (duration, delay, when) { - var o = SVG.Runner.sanitise(duration, delay, when) - var runner = new SVG.Runner(o.duration) - if (this._timeline) runner.timeline(this._timeline) - if (this._element) runner.element(this._element) - return runner.loop(o).schedule(delay, when) - }, - - schedule: function (timeline, delay, when) { - // The user doesn't need to pass a timeline if we already have one - if (!(timeline instanceof SVG.Timeline)) { - when = delay - delay = timeline - timeline = this.timeline() - } - - // If there is no timeline, yell at the user... - if (!timeline) { - throw Error('Runner cannot be scheduled without timeline') - } - - // Schedule the runner on the timeline provided - timeline.schedule(this, delay, when) - return this - }, - - unschedule: function () { - var timeline = this.timeline() - timeline && timeline.unschedule(this) - return this - }, - - loop: function (times, swing, wait) { - // Deal with the user passing in an object - if (typeof times === 'object') { - swing = times.swing - wait = times.wait - times = times.times - } - - // Sanitise the values and store them - this._times = times || Infinity - this._swing = swing || false - this._wait = wait || 0 - return this - }, - - delay: function (delay) { - return this.animate(0, delay) - }, - - /* - Basic Functionality - =================== - These methods allow us to attach basic functions to the runner directly - */ - - queue: function (initFn, runFn, isTransform) { - this._queue.push({ - initialiser: initFn || SVG.void, - runner: runFn || SVG.void, - isTransform: isTransform, - initialised: false, - finished: false - }) - var timeline = this.timeline() - timeline && this.timeline()._continue() - return this - }, - - during: function (fn) { - return this.queue(null, fn) - }, - - after (fn) { - return this.on('finish', fn) - }, - - /* - Runner animation methods - ======================== - Control how the animation plays - */ - - time: function (time) { - if (time == null) { - return this._time - } - let dt = time - this._time - this.step(dt) - return this - }, - - duration: function () { - return this._times * (this._wait + this._duration) - this._wait - }, - - loops: function (p) { - var loopDuration = this._duration + this._wait - if (p == null) { - var loopsDone = Math.floor(this._time / loopDuration) - var relativeTime = (this._time - loopsDone * loopDuration) - var position = relativeTime / this._duration - return Math.min(loopsDone + position, this._times) - } - var whole = Math.floor(p) - var partial = p % 1 - var time = loopDuration * whole + this._duration * partial - return this.time(time) - }, - - position: function (p) { - // Get all of the variables we need - var x = this._time - var d = this._duration - var w = this._wait - var t = this._times - var s = this._swing - var r = this._reverse - var position - - if (p == null) { - /* - This function converts a time to a position in the range [0, 1] - The full explanation can be found in this desmos demonstration - https://www.desmos.com/calculator/u4fbavgche - The logic is slightly simplified here because we can use booleans - */ - - // Figure out the value without thinking about the start or end time - const f = function (x) { - var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)) - var backwards = (swinging && !r) || (!swinging && r) - var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards - var clipped = Math.max(Math.min(uncliped, 1), 0) - return clipped - } - - // Figure out the value by incorporating the start time - var endTime = t * (w + d) - w - position = x <= 0 ? Math.round(f(1e-5)) - : x < endTime ? f(x) - : Math.round(f(endTime - 1e-5)) - return position - } - - // Work out the loops done and add the position to the loops done - var loopsDone = Math.floor(this.loops()) - var swingForward = s && (loopsDone % 2 === 0) - var forwards = (swingForward && !r) || (r && swingForward) - position = loopsDone + (forwards ? p : 1 - p) - return this.loops(position) - }, - - progress: function (p) { - if (p == null) { - return Math.min(1, this._time / this.duration()) - } - return this.time(p * this.duration()) - }, - - step: function (dt) { - // If we are inactive, this stepper just gets skipped - if (!this.enabled) return this - - // Update the time and get the new position - dt = dt == null ? 16 : dt - this._time += dt - var position = this.position() - - // Figure out if we need to run the stepper in this frame - var running = this._lastPosition !== position && this._time >= 0 - this._lastPosition = position - - // Figure out if we just started - var duration = this.duration() - var justStarted = this._lastTime < 0 && this._time > 0 - var justFinished = this._lastTime < this._time && this.time > duration - this._lastTime = this._time - if (justStarted) { - // this.fire('start', this) - } - - // Work out if the runner is finished set the done flag here so animations - // know, that they are running in the last step (this is good for - // transformations which can be merged) - var declarative = this._isDeclarative - this.done = !declarative && !justFinished && this._time >= duration - - // Call initialise and the run function - if (running || declarative) { - this._initialise(running) - - // clear the transforms on this runner so they dont get added again and again - this.transforms = new SVG.Matrix() - var converged = this._run(declarative ? dt : position) - // this.fire('step', this) - } - // correct the done flag here - // declaritive animations itself know when they converged - this.done = this.done || (converged && declarative) - // if (this.done) { - // this.fire('finish', this) - // } - return this - }, - - finish: function () { - return this.step(Infinity) - }, - - reverse: function (reverse) { - this._reverse = reverse == null ? !this._reverse : reverse - return this - }, - - ease: function (fn) { - this._stepper = new SVG.Ease(fn) - return this - }, - - active: function (enabled) { - if (enabled == null) return this.enabled - this.enabled = enabled - return this - }, - - /* - Private Methods - =============== - Methods that shouldn't be used externally - */ - - // Save a morpher to the morpher list so that we can retarget it later - _rememberMorpher: function (method, morpher) { - this._history[method] = { - morpher: morpher, - caller: this._queue[this._queue.length - 1] - } - }, - - // Try to set the target for a morpher if the morpher exists, otherwise - // do nothing and return false - _tryRetarget: function (method, target) { - if (this._history[method]) { - // if the last method wasnt even initialised, throw it away - if (!this._history[method].caller.initialised) { - let index = this._queue.indexOf(this._history[method].caller) - this._queue.splice(index, 1) - return false - } - - // for the case of transformations, we use the special retarget function - // which has access to the outer scope - if (this._history[method].caller.isTransform) { - this._history[method].caller.isTransform(target) - // for everything else a simple morpher change is sufficient - } else { - this._history[method].morpher.to(target) - } - - this._history[method].caller.finished = false - var timeline = this.timeline() - timeline && timeline._continue() - return true - } - return false - }, - - // Run each initialise function in the runner if required - _initialise: function (running) { - // If we aren't running, we shouldn't initialise when not declarative - if (!running && !this._isDeclarative) return - - // Loop through all of the initialisers - for (var i = 0, len = this._queue.length; i < len; ++i) { - // Get the current initialiser - var current = this._queue[i] - - // Determine whether we need to initialise - var needsIt = this._isDeclarative || (!current.initialised && running) - running = !current.finished - - // Call the initialiser if we need to - if (needsIt && running) { - current.initialiser.call(this) - current.initialised = true - } - } - }, - - // Run each run function for the position or dt given - _run: function (positionOrDt) { - // Run all of the _queue directly - var allfinished = true - for (var i = 0, len = this._queue.length; i < len; ++i) { - // Get the current function to run - var current = this._queue[i] - - // Run the function if its not finished, we keep track of the finished - // flag for the sake of declarative _queue - var converged = current.runner.call(this, positionOrDt) - current.finished = current.finished || (converged === true) - allfinished = allfinished && current.finished - } - - // We report when all of the constructors are finished - return allfinished - }, - - addTransform: function (transform, index) { - this.transforms.lmultiplyO(transform) - return this - }, - - clearTransform: function () { - this.transforms = new SVG.Matrix() - return this - } - } -}) - -SVG.Runner.id = 0 - -SVG.Runner.sanitise = function (duration, delay, when) { - // Initialise the default parameters - var times = 1 - var swing = false - var wait = 0 - duration = duration || SVG.defaults.timeline.duration - delay = delay || SVG.defaults.timeline.delay - when = when || 'last' - - // If we have an object, unpack the values - if (typeof duration === 'object' && !(duration instanceof SVG.Stepper)) { - delay = duration.delay || delay - when = duration.when || when - swing = duration.swing || swing - times = duration.times || times - wait = duration.wait || wait - duration = duration.duration || SVG.defaults.timeline.duration - } - - return { - duration: duration, - delay: delay, - swing: swing, - times: times, - wait: wait, - when: when - } -} - -SVG.FakeRunner = class { - constructor (transforms = new SVG.Matrix(), id = -1, done = true) { - this.transforms = transforms - this.id = id - this.done = done - } -} - -SVG.extend([SVG.Runner, SVG.FakeRunner], { - mergeWith (runner) { - return new SVG.FakeRunner( - runner.transforms.lmultiply(this.transforms), - runner.id - ) - } -}) - -// SVG.FakeRunner.emptyRunner = new SVG.FakeRunner() - -const lmultiply = (last, curr) => last.lmultiplyO(curr) -const getRunnerTransform = (runner) => runner.transforms - -function mergeTransforms () { - // Find the matrix to apply to the element and apply it - let runners = this._transformationRunners.runners - let netTransform = runners - .map(getRunnerTransform) - .reduce(lmultiply, new SVG.Matrix()) - - this.transform(netTransform) - - this._transformationRunners.merge() - - if (this._transformationRunners.length() === 1) { - this._frameId = null - } -} - -class RunnerArray { - constructor () { - this.runners = [] - this.ids = [] - } - - add (runner) { - if (this.runners.includes(runner)) return - - let id = runner.id + 1 - - let leftSibling = this.ids.reduce((last, curr) => { - if (curr > last && curr < id) return curr - return last - }, 0) - - let index = this.ids.indexOf(leftSibling) + 1 - - this.ids.splice(index, 0, id) - this.runners.splice(index, 0, runner) - - return this - } - - getByID (id) { - return this.runners[this.ids.indexOf(id + 1)] - } - - remove (id) { - let index = this.ids.indexOf(id + 1) - this.ids.splice(index, 1) - this.runners.splice(index, 1) - return this - } - - merge () { - let lastRunner = null - this.runners.forEach((runner, i) => { - if (lastRunner && runner.done && lastRunner.done) { - this.remove(runner.id) - this.edit(lastRunner.id, runner.mergeWith(lastRunner)) - } - - lastRunner = runner - }) - - return this - } - - edit (id, newRunner) { - let index = this.ids.indexOf(id + 1) - this.ids.splice(index, 1, id) - this.runners.splice(index, 1, newRunner) - return this - } - - length () { - return this.ids.length - } - - clearBefore (id) { - let deleteCnt = this.ids.indexOf(id + 1) || 1 - this.ids.splice(0, deleteCnt, 0) - this.runners.splice(0, deleteCnt, new SVG.FakeRunner()) - return this - } -} - -SVG.extend(SVG.Element, { - // this function searches for all runners on the element and deletes the ones - // which run before the current one. This is because absolute transformations - // overwfrite anything anyway so there is no need to waste time computing - // other runners - _clearTransformRunnersBefore: function (currentRunner) { - this._transformationRunners.clearBefore(currentRunner.id) - }, - - _currentTransform (current) { - return this._transformationRunners.runners - // we need the equal sign here to make sure, that also transformations - // on the same runner which execute before the current transformation are - // taken into account - .filter((runner) => runner.id <= current.id) - .map(getRunnerTransform) - .reduce(lmultiply, new SVG.Matrix()) - }, - - addRunner: function (runner) { - this._transformationRunners.add(runner) - - SVG.Animator.transform_frame( - mergeTransforms.bind(this), this._frameId - ) - }, - - _prepareRunner: function () { - if (this._frameId == null) { - this._transformationRunners = new RunnerArray() - .add(new SVG.FakeRunner(new SVG.Matrix(this))) - - this._frameId = SVG.Element.frameId++ - } - } -}) - -SVG.Element.frameId = 0 - -SVG.extend(SVG.Runner, { - attr: function (a, v) { - return this.styleAttr('attr', a, v) - }, - - // Add animatable styles - css: function (s, v) { - return this.styleAttr('css', s, v) - }, - - styleAttr (type, name, val) { - // apply attributes individually - if (typeof name === 'object') { - for (var key in val) { - this.styleAttr(type, key, val[key]) - } - } - - var morpher = new SVG.Morphable(this._stepper).to(val) - - this.queue(function () { - morpher = morpher.from(this.element()[type](name)) - }, function (pos) { - this.element()[type](name, morpher.at(pos)) - return morpher.done() - }) - - return this - }, - - zoom: function (level, point) { - var morpher = new SVG.Morphable(this._stepper).to(new SVG.Number(level)) - - this.queue(function () { - morpher = morpher.from(this.zoom()) - }, function (pos) { - this.element().zoom(morpher.at(pos), point) - return morpher.done() - }) - - return this - }, - - /** - ** absolute transformations - **/ - - // - // M v -----|-----(D M v = F v)------|-----> T v - // - // 1. define the final state (T) and decompose it (once) - // t = [tx, ty, the, lam, sy, sx] - // 2. on every frame: pull the current state of all previous transforms - // (M - m can change) - // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] - // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) - // - Note F(0) = M - // - Note F(1) = T - // 4. Now you get the delta matrix as a result: D = F * inv(M) - - transform: function (transforms, relative, affine) { - // If we have a declarative function, we should retarget it if possible - relative = transforms.relative || relative - if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { - return this - } - - // Parse the parameters - var isMatrix = isMatrixLike(transforms) - affine = transforms.affine != null - ? transforms.affine - : (affine != null ? affine : !isMatrix) - - // Create a morepher and set its type - const morpher = new SVG.Morphable() - .type(affine ? SVG.Morphable.TransformBag : SVG.Matrix) - .stepper(this._stepper) - - let origin - let element - let current - let currentAngle - let startTransform - - function setup () { - // make sure element and origin is defined - element = element || this.element() - origin = origin || getOrigin(transforms, element) - - startTransform = new SVG.Matrix(relative ? undefined : element) - - // add the runner to the element so it can merge transformations - element.addRunner(this) - - // Deactivate all transforms that have run so far if we are absolute - if (!relative) { - element._clearTransformRunnersBefore(this) - } - } - - function run (pos) { - // clear all other transforms before this in case something is saved - // on this runner. We are absolute. We dont need these! - if (!relative) this.clearTransform() - - let {x, y} = new SVG.Point(origin).transform(element._currentTransform(this)) - - let target = new SVG.Matrix({...transforms, origin: [x, y]}) - let start = this._isDeclarative && current - ? current - : startTransform - - if (affine) { - target = target.decompose(x, y) - start = start.decompose(x, y) - - // Get the current and target angle as it was set - const rTarget = target.rotate - const rCurrent = start.rotate - - // Figure out the shortest path to rotate directly - const possibilities = [rTarget - 360, rTarget, rTarget + 360] - const distances = possibilities.map(a => Math.abs(a - rCurrent)) - const shortest = Math.min(...distances) - const index = distances.indexOf(shortest) - target.rotate = possibilities[index] - } - - if (relative) { - // we have to be careful here not to overwrite the rotation - // with the rotate method of SVG.Matrix - if (!isMatrix) { - target.rotate = transforms.rotate || 0 - } - if (this._isDeclarative && currentAngle) { - start.rotate = currentAngle - } - } - - morpher.from(start) - morpher.to(target) - - let affineParameters = morpher.at(pos) - currentAngle = affineParameters.rotate - current = new SVG.Matrix(affineParameters) - - this.addTransform(current) - return morpher.done() - } - - function retarget (newTransforms) { - // only get a new origin if it changed since the last call - if ( - (newTransforms.origin || 'center').toString() !== - (transforms.origin || 'center').toString() - ) { - origin = getOrigin(transforms, element) - } - - // overwrite the old transformations with the new ones - transforms = {...newTransforms, origin} - } - - this.queue(setup, run, retarget) - this._isDeclarative && this._rememberMorpher('transform', morpher) - return this - }, - - // Animatable x-axis - x: function (x, relative) { - return this._queueNumber('x', x) - }, - - // Animatable y-axis - y: function (y) { - return this._queueNumber('y', y) - }, - - dx: function (x) { - return this._queueNumberDelta('dx', x) - }, - - dy: function (y) { - return this._queueNumberDelta('dy', y) - }, - - _queueNumberDelta: function (method, to) { - to = new SVG.Number(to) - - // Try to change the target if we have this method already registerd - if (this._tryRetargetDelta(method, to)) return this - - // Make a morpher and queue the animation - var morpher = new SVG.Morphable(this._stepper).to(to) - this.queue(function () { - var from = this.element()[method]() - morpher.from(from) - morpher.to(from + to) - }, function (pos) { - this.element()[method](morpher.at(pos)) - return morpher.done() - }) - - // Register the morpher so that if it is changed again, we can retarget it - this._rememberMorpher(method, morpher) - return this - }, - - _queueObject: function (method, to) { - // Try to change the target if we have this method already registerd - if (this._tryRetarget(method, to)) return this - - // Make a morpher and queue the animation - var morpher = new SVG.Morphable(this._stepper).to(to) - this.queue(function () { - morpher.from(this.element()[method]()) - }, function (pos) { - this.element()[method](morpher.at(pos)) - return morpher.done() - }) - - // Register the morpher so that if it is changed again, we can retarget it - this._rememberMorpher(method, morpher) - return this - }, - - _queueNumber: function (method, value) { - return this._queueObject(method, new SVG.Number(value)) - }, - - // Animatable center x-axis - cx: function (x) { - return this._queueNumber('cx', x) - }, - - // Animatable center y-axis - cy: function (y) { - return this._queueNumber('cy', y) - }, - - // Add animatable move - move: function (x, y) { - return this.x(x).y(y) - }, - - // Add animatable center - center: function (x, y) { - return this.cx(x).cy(y) - }, - - // Add animatable size - size: function (width, height) { - // animate bbox based size for all other elements - var box - - if (!width || !height) { - box = this._element.bbox() - } - - if (!width) { - width = box.width / box.height * height - } - - if (!height) { - height = box.height / box.width * width - } - - return this - .width(width) - .height(height) - }, - - // Add animatable width - width: function (width) { - return this._queueNumber('width', width) - }, - - // Add animatable height - height: function (height) { - return this._queueNumber('height', height) - }, - - // Add animatable plot - plot: function (a, b, c, d) { - // Lines can be plotted with 4 arguments - if (arguments.length === 4) { - return this.plot([a, b, c, d]) - } - - // FIXME: this needs to be rewritten such that the element is only accesed - // in the init function - return this._queueObject('plot', new this._element.MorphArray(a)) - - /* - var morpher = this._element.morphArray().to(a) - - this.queue(function () { - morpher.from(this._element.array()) - }, function (pos) { - this._element.plot(morpher.at(pos)) - }) - - return this - */ - }, - - // Add leading method - leading: function (value) { - return this._queueNumber('leading', value) - }, - - // Add animatable viewbox - viewbox: function (x, y, width, height) { - return this._queueObject('viewbox', new SVG.Box(x, y, width, height)) - }, - - update: function (o) { - if (typeof o !== 'object') { - return this.update({ - offset: arguments[0], - color: arguments[1], - opacity: arguments[2] - }) - } - - 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', o.offset) - - return this - } -}) diff --git a/src/shape.js b/src/shape.js deleted file mode 100644 index cb15098..0000000 --- a/src/shape.js +++ /dev/null @@ -1,10 +0,0 @@ - -SVG.Shape = SVG.invent({ - // Initialize node - create: function (node) { - SVG.Element.call(this, node) - }, - - // Inherit from - inherit: SVG.Element -}) diff --git a/src/symbol.js b/src/symbol.js deleted file mode 100644 index ca67607..0000000 --- a/src/symbol.js +++ /dev/null @@ -1,15 +0,0 @@ - -SVG.Symbol = SVG.invent({ - // Initialize node - create: 'symbol', - - // Inherit from - inherit: SVG.Container, - - construct: { - // create symbol - symbol: function () { - return this.put(new SVG.Symbol()) - } - } -}) diff --git a/src/text.js b/src/text.js deleted file mode 100644 index 8a50df9..0000000 --- a/src/text.js +++ /dev/null @@ -1,234 +0,0 @@ -SVG.Text = SVG.invent({ - // Initialize node - create: function (node) { - SVG.Element.call(this, node || SVG.create('text')) - this.dom.leading = new SVG.Number(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', SVG.defaults.attrs['font-family']) - }, - - // Inherit from - inherit: SVG.Parent, - - // Add class methods - extend: { - // Move over x-axis - x: function (x) { - // act as getter - if (x == null) { - return this.attr('x') - } - - return this.attr('x', x) - }, - // Move over y-axis - y: function (y) { - var oy = this.attr('y') - var o = typeof oy === 'number' ? oy - this.bbox().y : 0 - - // act as getter - if (y == null) { - return typeof oy === 'number' ? oy - o : oy - } - - return this.attr('y', typeof y === 'number' ? y + o : y) - }, - // Move center over x-axis - cx: function (x) { - return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2) - }, - // Move center over y-axis - cy: function (y) { - return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2) - }, - // Set the text content - text: function (text) { - // act as getter - if (text === undefined) { - var children = this.node.childNodes - var firstLine = 0 - text = '' - - 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 - continue - } - - // add newline if its not the first child and newLined is set to true - if (i !== firstLine && children[i].nodeType !== 3 && SVG.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) - - if (typeof text === 'function') { - // call block - text.call(this, this) - } else { - // store text and make sure text is not blank - text = text.split('\n') - - // build new lines - 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() - }, - // Set / get leading - leading: function (value) { - // act as getter - if (value == null) { - return this.dom.leading - } - - // act as setter - this.dom.leading = new SVG.Number(value) - - return this.rebuild() - }, - // Rebuild appearance type - rebuild: function (rebuild) { - // store new rebuild flag if given - if (typeof rebuild === 'boolean') { - this._rebuild = rebuild - } - - // define position of all lines - if (this._rebuild) { - var self = this - var blankLineOffset = 0 - var dy = this.dom.leading * new SVG.Number(this.attr('font-size')) - - this.each(function () { - if (this.dom.newLined) { - this.attr('x', self.attr('x')) - - if (this.text() === '\n') { - blankLineOffset += dy - } else { - this.attr('dy', dy + blankLineOffset) - blankLineOffset = 0 - } - } - }) - - this.fire('rebuild') - } - - return this - }, - // Enable / disable build mode - build: function (build) { - this._build = !!build - return this - }, - // overwrite method from parent to set data properly - setData: function (o) { - this.dom = o - this.dom.leading = new SVG.Number(o.leading || 1.3) - return this - } - }, - - // Add parent method - construct: { - // Create text element - text: function (text) { - return this.put(new SVG.Text()).text(text) - }, - // Create plain text element - plain: function (text) { - return this.put(new SVG.Text()).plain(text) - } - } - -}) - -SVG.Tspan = SVG.invent({ - // Initialize node - create: 'tspan', - - // Inherit from - inherit: SVG.Parent, - - // Add class methods - extend: { - // Set text content - text: function (text) { - if (text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '') - - typeof text === 'function' ? text.call(this, this) : this.plain(text) - - return this - }, - // Shortcut dx - dx: function (dx) { - return this.attr('dx', dx) - }, - // Shortcut dy - dy: function (dy) { - return this.attr('dy', dy) - }, - // Create new line - newLine: function () { - // fetch text parent - var t = this.parent(SVG.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()) - } - } -}) - -SVG.extend([SVG.Text, SVG.Tspan], { - // Create plain text node - plain: function (text) { - // clear if build mode is disabled - if (this._build === false) { - this.clear() - } - - // create text node - this.node.appendChild(document.createTextNode(text)) - - return this - }, - // Create a tspan - tspan: function (text) { - var tspan = new SVG.Tspan() - - // clear if build mode is disabled - if (!this._build) { - this.clear() - } - - // add new tspan - this.node.appendChild(tspan.node) - - return tspan.text(text) - }, - // FIXME: Does this also work for textpath? - // Get length of text element - length: function () { - return this.node.getComputedTextLength() - } -}) diff --git a/src/textpath.js b/src/textpath.js deleted file mode 100644 index 561f147..0000000 --- a/src/textpath.js +++ /dev/null @@ -1,77 +0,0 @@ -SVG.TextPath = SVG.invent({ - // Initialize node - create: 'textPath', - - // Inherit from - inherit: SVG.Text, - - // Define parent class - parent: SVG.Parent, - - // Add parent method - extend: { - MorphArray: SVG.PathArray, - // return the array of the path track element - array: function () { - var track = this.track() - - return track ? track.array() : null - }, - // Plot path if any - plot: function (d) { - var track = this.track() - var pathArray = null - - if (track) { - pathArray = track.plot(d) - } - - return (d == null) ? pathArray : this - }, - // Get the path element - track: function () { - return this.reference('href') - } - }, - construct: { - textPath: function (text, path) { - return this.defs().path(path).text(text).addTo(this) - } - } -}) - -SVG.extend([SVG.Text], { - // Create path for text to run on - path: function (track) { - var path = new SVG.TextPath() - - // if d is a path, reuse it - if (!(track instanceof SVG.Path)) { - // create path element - track = this.doc().defs().path(track) - } - - // link textPath to path and add content - path.attr('href', '#' + track, SVG.xlink) - - // add textPath element as child node and return textPath - return this.put(path) - }, - // Todo: make this plural? - // Get the textPath children - textPath: function () { - return this.select('textPath') - } -}) - -SVG.extend([SVG.Path], { - // creates a textPath from this path - text: function (text) { - if (text instanceof SVG.Text) { - var txt = text.text() - return text.clear().path(this).text(txt) - } - return this.parent().put(new SVG.Text()).path(this).text(text) - } - // TODO: Maybe add `targets` to get all textPaths associated with this path -}) diff --git a/src/timeline.js b/src/timeline.js deleted file mode 100644 index 0bf8ac5..0000000 --- a/src/timeline.js +++ /dev/null @@ -1,282 +0,0 @@ - -// Must Change .... -SVG.easing = { - '-': function (pos) { return pos }, - '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, - '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, - '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } -} - -var time = window.performance || Date - -var makeSchedule = function (runnerInfo) { - var start = runnerInfo.start - var duration = runnerInfo.runner.duration() - var end = start + duration - return {start: start, duration: duration, end: end, runner: runnerInfo.runner} -} - -SVG.Timeline = SVG.invent({ - inherit: SVG.EventTarget, - - // Construct a new timeline on the given element - create: function () { - this._timeSource = function () { - return time.now() - } - - this._dispatcher = document.createElement('div') - - // Store the timing variables - this._startTime = 0 - this._speed = 1.0 - - // Play control variables control how the animation proceeds - this._reverse = false - this._persist = 0 - - // Keep track of the running animations and their starting parameters - this._nextFrame = null - this._paused = false - this._runners = [] - this._order = [] - this._time = 0 - this._lastSourceTime = 0 - this._lastStepTime = 0 - }, - - extend: { - - getEventTarget () { - return this._dispatcher - }, - - /** - * - */ - - // schedules a runner on the timeline - schedule (runner, delay, when) { - if (runner == null) { - return this._runners.map(makeSchedule).sort(function (a, b) { - return (a.start - b.start) || (a.duration - b.duration) - }) - } - - if (!this.active()) { - this._step() - if (when == null) { - when = 'now' - } - } - - // The start time for the next animation can either be given explicitly, - // derived from the current timeline time or it can be relative to the - // last start time to chain animations direclty - var absoluteStartTime = 0 - delay = delay || 0 - - // Work out when to start the animation - if (when == null || when === 'last' || when === 'after') { - // Take the last time and increment - absoluteStartTime = this._startTime - } else if (when === 'absolute' || when === 'start') { - absoluteStartTime = delay - delay = 0 - } else if (when === 'now') { - absoluteStartTime = this._time - } else if (when === 'relative') { - let runnerInfo = this._runners[runner.id] - if (runnerInfo) { - absoluteStartTime = runnerInfo.start + delay - delay = 0 - } - } else { - throw new Error('Invalid value for the "when" parameter') - } - - // Manage runner - runner.unschedule() - runner.timeline(this) - runner.time(-delay) - - // Save startTime for next runner - this._startTime = absoluteStartTime + runner.duration() + delay - - // Save runnerInfo - this._runners[runner.id] = { - persist: this.persist(), - runner: runner, - start: absoluteStartTime - } - - // Save order and continue - this._order.push(runner.id) - this._continue() - return this - }, - - // Remove the runner from this timeline - unschedule (runner) { - var index = this._order.indexOf(runner.id) - if (index < 0) return this - - delete this._runners[runner.id] - this._order.splice(index, 1) - runner.timeline(null) - return this - }, - - play () { - // Now make sure we are not paused and continue the animation - this._paused = false - return this._continue() - }, - - pause () { - // Cancel the next animation frame and pause - this._nextFrame = null - this._paused = true - return this - }, - - stop () { - // Cancel the next animation frame and go to start - this.seek(-this._time) - return this.pause() - }, - - finish () { - this.seek(Infinity) - return this.pause() - }, - - speed (speed) { - if (speed == null) return this._speed - this._speed = speed - return this - }, - - reverse (yes) { - var currentSpeed = this.speed() - if (yes == null) return this.speed(-currentSpeed) - - var positive = Math.abs(currentSpeed) - return this.speed(yes ? positive : -positive) - }, - - seek (dt) { - this._time += dt - return this._continue() - }, - - time (time) { - if (time == null) return this._time - this._time = time - return this - }, - - persist (dtOrForever) { - if (dtOrForever == null) return this._persist - this._persist = dtOrForever - return this - }, - - source (fn) { - if (fn == null) return this._timeSource - this._timeSource = fn - return this - }, - - _step () { - // If the timeline is paused, just do nothing - if (this._paused) return - - // Get the time delta from the last time and update the time - // TODO: Deal with window.blur window.focus to pause animations - var time = this._timeSource() - var dtSource = time - this._lastSourceTime - var dtTime = this._speed * dtSource + (this._time - this._lastStepTime) - this._lastSourceTime = time - - // Update the time - this._time += dtTime - this._lastStepTime = this._time - // this.fire('time', this._time) - - // Run all of the runners directly - var runnersLeft = false - for (var i = 0, len = this._order.length; i < len; i++) { - // Get and run the current runner and ignore it if its inactive - var runnerInfo = this._runners[this._order[i]] - var runner = runnerInfo.runner - let dt = dtTime - - // Make sure that we give the actual difference - // between runner start time and now - let dtToStart = this._time - runnerInfo.start - - // Dont run runner if not started yet - if (dtToStart < 0) { - runnersLeft = true - continue - } else if (dtToStart < dt) { - // Adjust dt to make sure that animation is on point - dt = dtToStart - } - - if (!runner.active()) continue - - // If this runner is still going, signal that we need another animation - // frame, otherwise, remove the completed runner - var finished = runner.step(dt).done - if (!finished) { - runnersLeft = true - // continue - } else if (runnerInfo.persist !== true) { - // runner is finished. And runner might get removed - - // TODO: Figure out end time of runner - var endTime = runner.duration() - runner.time() + this._time - - if (endTime + this._persist < this._time) { - // Delete runner and correct index - delete this._runners[this._order[i]] - this._order.splice(i--, 1) && --len - runner.timeline(null) - } - } - } - - // Get the next animation frame to keep the simulation going - if (runnersLeft) { - this._nextFrame = SVG.Animator.frame(this._step.bind(this)) - } else { - this._nextFrame = null - } - return this - }, - - // Checks if we are running and continues the animation - _continue () { - if (this._paused) return this - if (!this._nextFrame) { - this._nextFrame = SVG.Animator.frame(this._step.bind(this)) - } - return this - }, - - active () { - return !!this._nextFrame - } - }, - - // These methods will be added to all SVG.Element objects - parent: SVG.Element, - construct: { - timeline: function () { - this._timeline = (this._timeline || new SVG.Timeline()) - return this._timeline - } - } -}) -- cgit v1.2.3 From cfdfcc529dedff770dc54e78d2900d9a790f5766 Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Thu, 25 Oct 2018 23:28:12 +0200 Subject: convert everything to es6 classes and imports --- src/A.js | 48 ++- src/Animator.js | 56 ++-- src/ArrayPolyfill.js | 1 + src/Bare.js | 45 ++- src/Box.js | 215 ++++++------- src/Circle.js | 34 ++ src/ClipPath.js | 75 ++--- src/Color.js | 167 +++++----- src/Container.js | 11 +- src/Controller.js | 202 ++++++------ src/Defs.js | 13 +- src/Doc.js | 129 ++++---- src/Element.js | 524 +++++++++++++++---------------- src/Ellipse.js | 96 +----- src/EventTarget.js | 46 +-- src/G.js | 26 +- src/Gradient.js | 130 +++----- src/HtmlNode.js | 40 ++- src/Image.js | 97 +++--- src/Line.js | 102 +++--- src/Marker.js | 92 +++--- src/Mask.js | 72 +++-- src/Matrix.js | 847 +++++++++++++++++++++++++------------------------- src/Morphable.js | 293 +++++++++--------- src/Parent.js | 169 +++++----- src/Path.js | 122 ++++---- src/PathArray.js | 93 +++--- src/Pattern.js | 79 +++-- src/Point.js | 80 ++--- src/PointArray.js | 52 ++-- src/Polygon.js | 106 +++---- src/Polyline.js | 19 ++ src/Queue.js | 112 ++++--- src/Rect.js | 22 +- src/Runner.js | 852 ++++++++++++++++++++++++++------------------------- src/SVGArray.js | 107 ++----- src/SVGNumber.js | 109 +++---- src/Shape.js | 11 +- src/Symbol.js | 21 +- src/Text.js | 348 +++++++++++---------- src/TextPath.js | 95 +++--- src/Timeline.js | 445 +++++++++++++-------------- src/arrange.js | 153 +++++---- src/attr.js | 130 ++++---- src/circled.js | 64 ++++ src/classes.js | 87 ++++++ src/css.js | 55 +++- src/data.js | 6 +- src/defaults.js | 48 +++ src/event.js | 84 ++--- src/flatten.js | 62 ++-- src/gradiented.js | 14 + src/helpers.js | 83 +++-- src/memory.js | 11 +- src/namespaces.js | 5 + src/parser.js | 21 +- src/pointed.js | 46 +-- src/regex.js | 81 +++-- src/selector.js | 61 ++-- src/stop.js | 27 ++ src/sugar.js | 26 +- src/svg.js | 105 +------ src/tools.js | 94 ++++++ src/transform.js | 117 ++++--- src/use.js | 36 +-- src/utils.js | 40 +++ 66 files changed, 3863 insertions(+), 3796 deletions(-) create mode 100644 src/ArrayPolyfill.js create mode 100644 src/Circle.js create mode 100644 src/Polyline.js create mode 100644 src/circled.js create mode 100644 src/classes.js create mode 100644 src/defaults.js create mode 100644 src/gradiented.js create mode 100644 src/namespaces.js create mode 100644 src/stop.js create mode 100644 src/tools.js create mode 100644 src/utils.js (limited to 'src') diff --git a/src/A.js b/src/A.js index cb0a341..72e13e4 100644 --- a/src/A.js +++ b/src/A.js @@ -1,35 +1,34 @@ -SVG.A = SVG.invent({ - // Initialize node - create: 'a', +import {Container, Element} from './classes.js' +import {nodeOrNew, addFactory} from './tools.js' +import {xlink} from './namespaces.js' - // Inherit from - inherit: SVG.Container, +export default class A extends Container { + constructor (node) { + super(nodeOrNew('a', node)) + } - // Add class methods - extend: { - // Link url - to: function (url) { - return this.attr('href', url, SVG.xlink) - }, - // Link target attribute - target: function (target) { - return this.attr('target', target) - } - }, + // Link url + to (url) { + return this.attr('href', url, xlink) + } - // Add parent method - construct: { - // Create a hyperlink element - link: function (url) { - return this.put(new SVG.A()).to(url) - } + // Link target attribute + target (target) { + return this.attr('target', target) + } +} + +addFactory(Container, { + // Create a hyperlink element + link: function (url) { + return this.put(new A()).to(url) } }) -SVG.extend(SVG.Element, { +addFactory(Element, { // Create a hyperlink element linkTo: function (url) { - var link = new SVG.A() + var link = new A() if (typeof url === 'function') { url.call(link, link) } else { link.to(url) @@ -37,5 +36,4 @@ SVG.extend(SVG.Element, { return this.parent().put(link).put(this) } - }) diff --git a/src/Animator.js b/src/Animator.js index eb8ca72..d49ab12 100644 --- a/src/Animator.js +++ b/src/Animator.js @@ -1,65 +1,65 @@ -/* global requestAnimationFrame */ +import Queue from './Queue.js' -SVG.Animator = { +export default { nextDraw: null, - frames: new SVG.Queue(), - timeouts: new SVG.Queue(), + frames: new Queue(), + timeouts: new Queue(), timer: window.performance || window.Date, transforms: [], - frame: function (fn) { + frame (fn) { // Store the node - var node = SVG.Animator.frames.push({ run: fn }) + var node = Animator.frames.push({ run: fn }) // Request an animation frame if we don't have one - if (SVG.Animator.nextDraw === null) { - SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw) + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw) } // Return the node so we can remove it easily return node }, - transform_frame: function (fn, id) { - SVG.Animator.transforms[id] = fn + transform_frame (fn, id) { + Animator.transforms[id] = fn }, - timeout: function (fn, delay) { + timeout (fn, delay) { delay = delay || 0 // Work out when the event should fire - var time = SVG.Animator.timer.now() + delay + var time = Animator.timer.now() + delay // Add the timeout to the end of the queue - var node = SVG.Animator.timeouts.push({ run: fn, time: time }) + var node = Animator.timeouts.push({ run: fn, time: time }) // Request another animation frame if we need one - if (SVG.Animator.nextDraw === null) { - SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw) + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw) } return node }, - cancelFrame: function (node) { - SVG.Animator.frames.remove(node) + cancelFrame (node) { + Animator.frames.remove(node) }, - clearTimeout: function (node) { - SVG.Animator.timeouts.remove(node) + clearTimeout (node) { + Animator.timeouts.remove(node) }, - _draw: function (now) { + _draw (now) { // Run all the timeouts we can run, if they are not ready yet, add them // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) var nextTimeout = null - var lastTimeout = SVG.Animator.timeouts.last() - while ((nextTimeout = SVG.Animator.timeouts.shift())) { + var lastTimeout = Animator.timeouts.last() + while ((nextTimeout = Animator.timeouts.shift())) { // Run the timeout if its time, or push it to the end if (now >= nextTimeout.time) { nextTimeout.run() } else { - SVG.Animator.timeouts.push(nextTimeout) + Animator.timeouts.push(nextTimeout) } // If we hit the last item, we should stop shifting out more items @@ -68,16 +68,16 @@ SVG.Animator = { // Run all of the animation frames var nextFrame = null - var lastFrame = SVG.Animator.frames.last() - while ((nextFrame !== lastFrame) && (nextFrame = SVG.Animator.frames.shift())) { + var lastFrame = Animator.frames.last() + while ((nextFrame !== lastFrame) && (nextFrame = Animator.frames.shift())) { nextFrame.run() } - SVG.Animator.transforms.forEach(function (el) { el() }) + Animator.transforms.forEach(function (el) { el() }) // If we have remaining timeouts or frames, draw until we don't anymore - SVG.Animator.nextDraw = SVG.Animator.timeouts.first() || SVG.Animator.frames.first() - ? requestAnimationFrame(SVG.Animator._draw) + Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() + ? window.requestAnimationFrame(Animator._draw) : null } } diff --git a/src/ArrayPolyfill.js b/src/ArrayPolyfill.js new file mode 100644 index 0000000..596b2ca --- /dev/null +++ b/src/ArrayPolyfill.js @@ -0,0 +1 @@ +export default Array diff --git a/src/Bare.js b/src/Bare.js index 393ce6e..783fa6a 100644 --- a/src/Bare.js +++ b/src/Bare.js @@ -1,27 +1,13 @@ +import {nodeOrNew} from './tools.js' +import Parent from './Parent.js' -SVG.Bare = SVG.invent({ - // Initialize - create: function (element, inherit) { - // construct element - SVG.Element.call(this, SVG.create(element)) - - // inherit custom methods - if (inherit) { - for (var method in inherit.prototype) { - if (typeof inherit.prototype[method] === 'function') { - this[method] = inherit.prototype[method] - } - } +export default function Bare (element, inherit) { + return class Custom extends inherit { + constructor (node) { + super(nodeOrNew(element, node)) } - }, - // Inherit from - inherit: SVG.Element, - - // Add methods - extend: { - // Insert some plain text - words: function (text) { + words (text) { // remove contents while (this.node.hasChildNodes()) { this.node.removeChild(this.node.lastChild) @@ -33,11 +19,20 @@ SVG.Bare = SVG.invent({ return this } } -}) +} -SVG.extend(SVG.Parent, { +export let constructors = { // Create an element that is not described by SVG.js element: function (element, inherit) { - return this.put(new SVG.Bare(element, inherit)) + let custom = createCustom(element, inherit) + return this.put(new custom()) } -}) +} + +// extend(Parent, { +// // Create an element that is not described by SVG.js +// element: function (element, inherit) { +// let custom = createCustom(element, inherit) +// return this.put(new custom()) +// } +// }) diff --git a/src/Box.js b/src/Box.js index a9247ef..0c98dd5 100644 --- a/src/Box.js +++ b/src/Box.js @@ -1,9 +1,13 @@ -/* globals fullBox, domContains, isNulledBox, Exception */ - -SVG.Box = SVG.invent({ - create: function (source) { +import {Parent, Doc, Symbol, Image, Pattern, Marker, Point} from './classes.js' +import parser from './parser.js' +import {fullBox, domContains, isNulledBox} from './helpers.js' +import {extend} from './tools.js' +import {delimiter} from './regex.js' + +export default class Box { + constructor (source) { var base = [0, 0, 0, 0] - source = typeof source === 'string' ? source.split(SVG.regex.delimiter).map(parseFloat) + source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) : Array.isArray(source) ? source : typeof source === 'object' ? [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] @@ -17,125 +21,104 @@ SVG.Box = SVG.invent({ // add center, right, bottom... fullBox(this) - }, - extend: { - // Merge rect box with another, return a new instance - merge: function (box) { - var x = Math.min(this.x, box.x) - var y = Math.min(this.y, box.y) - - return new SVG.Box( - x, y, - Math.max(this.x + this.width, box.x + box.width) - x, - Math.max(this.y + this.height, box.y + box.height) - y - ) - }, - - transform: function (m) { - var xMin = Infinity - var xMax = -Infinity - var yMin = Infinity - var yMax = -Infinity - - var pts = [ - new SVG.Point(this.x, this.y), - new SVG.Point(this.x2, this.y), - new SVG.Point(this.x, this.y2), - new SVG.Point(this.x2, this.y2) - ] - - pts.forEach(function (p) { - p = p.transform(m) - xMin = Math.min(xMin, p.x) - xMax = Math.max(xMax, p.x) - yMin = Math.min(yMin, p.y) - yMax = Math.max(yMax, p.y) - }) - - return new SVG.Box( - xMin, yMin, - xMax - xMin, - yMax - yMin - ) - }, - - addOffset: function () { - // offset by window scroll position, because getBoundingClientRect changes when window is scrolled - this.x += window.pageXOffset - this.y += window.pageYOffset - return this - }, - toString: function () { - return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height - }, - toArray: function () { - return [this.x, this.y, this.width, this.height] - }, - morph: function (x, y, width, height) { - this.destination = new SVG.Box(x, y, width, height) - return this - }, - - at: function (pos) { - if (!this.destination) return this - - return new SVG.Box( - this.x + (this.destination.x - this.x) * pos - , this.y + (this.destination.y - this.y) * pos - , this.width + (this.destination.width - this.width) * pos - , this.height + (this.destination.height - this.height) * pos - ) - } + } + + // Merge rect box with another, return a new instance + merge (box) { + let x = Math.min(this.x, box.x) + let y = Math.min(this.y, box.y) + let width = Math.max(this.x + this.width, box.x + box.width) - x + let height = Math.max(this.y + this.height, box.y + box.height) - y + + return new Box(x, y, width, height) + } + + transform (m) { + let xMin = Infinity + let xMax = -Infinity + let yMin = Infinity + let yMax = -Infinity + + let pts = [ + new Point(this.x, this.y), + new Point(this.x2, this.y), + new Point(this.x, this.y2), + new Point(this.x2, this.y2) + ] + + pts.forEach(function (p) { + p = p.transform(m) + xMin = Math.min(xMin, p.x) + xMax = Math.max(xMax, p.x) + yMin = Math.min(yMin, p.y) + yMax = Math.max(yMax, p.y) + }) + + return new Box( + xMin, yMin, + xMax - xMin, + yMax - yMin + ) + } + + addOffset () { + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset + this.y += window.pageYOffset + return this + } + + toString () { + return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height + } + + toArray () { + return [this.x, this.y, this.width, this.height] + } +} + + +extend(Parent, { + // Get bounding box + bbox () { + return new Box(getBox((node) => node.getBBox())) }, - // Define Parent - parent: SVG.Element, - - // Constructor - construct: { - // Get bounding box - bbox: function () { - var box - - try { - // find native bbox - box = this.node.getBBox() - - if (isNulledBox(box) && !domContains(this.node)) { - throw new Exception('Element not in the dom') - } - } catch (e) { - try { - var clone = this.clone(SVG.parser().svg).show() - box = clone.node.getBBox() - clone.remove() - } catch (e) { - console.warn('Getting a bounding box of this element is not possible') - } - } - - return new SVG.Box(box) - }, - - rbox: function (el) { - // IE11 throws an error when element not in dom - try { - var box = new SVG.Box(this.node.getBoundingClientRect()) - if (el) return box.transform(el.screenCTM().inverse()) - return box.addOffset() - } catch (e) { - return new SVG.Box() - } - } + rbox (el) { + let box = new Box(getBox((node) => node.getBoundingClientRect())) + if (el) return box.transform(el.screenCTM().inverse()) + return box.addOffset() } }) -SVG.extend([SVG.Doc, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View], { +function getBox(cb) { + let box + + try { + box = cb(this.node) + + if (isNulledBox(box) && !domContains(this.node)) { + throw new Error('Element not in the dom') + } + } catch (e) { + try { + let clone = this.clone(parser().svg).show() + box = cb(clone.node) + clone.remove() + } catch (e) { + console.warn('Getting a bounding box of this element is not possible') + } + } + return box +} + + +extend([Doc, Symbol, Image, Pattern, Marker], { viewbox: function (x, y, width, height) { // act as getter - if (x == null) return new SVG.Box(this.attr('viewBox')) + if (x == null) return new Box(this.attr('viewBox')) // act as setter - return this.attr('viewBox', new SVG.Box(x, y, width, height)) + return this.attr('viewBox', new Box(x, y, width, height)) } }) diff --git a/src/Circle.js b/src/Circle.js new file mode 100644 index 0000000..fc8be72 --- /dev/null +++ b/src/Circle.js @@ -0,0 +1,34 @@ +import SVGNumber from './SVGNumber.js' +import Parent from './Parent.js' +import {x, y, cx, cy, width, height, size} from './circled.js' + +export default class Circle extends Shape { + constructor (node) { + super(nodeOrNew('circle', node)) + } + + radius (r) { + return this.attr('r', r) + } + + // Radius x value + rx (rx) { + return this.attr('r', rx) + } + + // Alias radius x value + ry (ry) { + return this.rx(ry) + } +} + +extend(Circle, {x, y, cx, cy, width, height, size}) + +addFactory(Parent, { + // Create circle element + circle (size) { + return this.put(new Circle()) + .radius(new SVGNumber(size).divide(2)) + .move(0, 0) + } +}) diff --git a/src/ClipPath.js b/src/ClipPath.js index 63fff74..ef820e5 100644 --- a/src/ClipPath.js +++ b/src/ClipPath.js @@ -1,53 +1,54 @@ -SVG.ClipPath = SVG.invent({ - // Initialize node - create: 'clipPath', - - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - // Unclip all clipped elements and remove itself - remove: function () { - // unclip all targets - this.targets().forEach(function (el) { - el.unclip() - }) - - // remove clipPath from parent - return SVG.Element.prototype.remove.call(this) - }, - - targets: function () { - return SVG.select('svg [clip-path*="' + this.id() + '"]') - } - }, +import Container from './Container.js' +import Element from './Element.js' +import {nodeOrNew, extend} from './tools.js' +import find from './selector.js' + +export default class ClipPath extends Container { + constructor (node) { + super(nodeOrNew('clipPath', node)) + } + + // Unclip all clipped elements and remove itself + remove () { + // unclip all targets + this.targets().forEach(function (el) { + el.unclip() + }) + + // remove clipPath from parent + return super.remove() + } - // Add parent method - construct: { - // Create clipping element - clip: function () { - return this.defs().put(new SVG.ClipPath()) - } + targets () { + return find('svg [clip-path*="' + this.id() + '"]') + } +} + +addFactory(Container, { + // Create clipping element + clip: function() { + return this.defs().put(new ClipPath) } }) -// -SVG.extend(SVG.Element, { +extend(Element, { // Distribute clipPath to svg element - clipWith: function (element) { + clipWith (element) { // use given clip or create a new one - var clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element) + let clipper = element instanceof ClipPath + ? element + : this.parent().clip().add(element) // apply mask return this.attr('clip-path', 'url("#' + clipper.id() + '")') }, + // Unclip element - unclip: function () { + unclip () { return this.attr('clip-path', null) }, - clipper: function () { + + clipper () { return this.reference('clip-path') } - }) diff --git a/src/Color.js b/src/Color.js index 43bafcb..1e2befb 100644 --- a/src/Color.js +++ b/src/Color.js @@ -29,120 +29,99 @@ SVG.hsl() SVG.lab('rgb(100, 100, 100)') */ -// Module for color convertions -SVG.Color = function (color, g, b) { - var match - - // initialize defaults - this.r = 0 - this.g = 0 - this.b = 0 - - if (!color) return - - // parse color - if (typeof color === 'string') { - if (SVG.regex.isRgb.test(color)) { - // get rgb values - match = SVG.regex.rgb.exec(color.replace(SVG.regex.whitespace, '')) - - // parse numeric values - this.r = parseInt(match[1]) - this.g = parseInt(match[2]) - this.b = parseInt(match[3]) - } else if (SVG.regex.isHex.test(color)) { - // get hex values - match = SVG.regex.hex.exec(fullHex(color)) - - // parse numeric values - this.r = parseInt(match[1], 16) - this.g = parseInt(match[2], 16) - this.b = parseInt(match[3], 16) +import {isHex, isRgb, whitespace, rgb} from './regex.js' + +export default class Color { + constructor (color, g, b) { + let match + + // initialize defaults + this.r = 0 + this.g = 0 + this.b = 0 + + if (!color) return + + // parse color + if (typeof color === 'string') { + if (isRgb.test(color)) { + // get rgb values + match = rgb.exec(color.replace(whitespace, '')) + + // parse numeric values + this.r = parseInt(match[1]) + this.g = parseInt(match[2]) + this.b = parseInt(match[3]) + } else if (isHex.test(color)) { + // get hex values + match = hex.exec(fullHex(color)) + + // parse numeric values + this.r = parseInt(match[1], 16) + this.g = parseInt(match[2], 16) + this.b = parseInt(match[3], 16) + } + } else if (Array.isArray(color)) { + this.r = color[0] + this.g = color[1] + this.b = color[2] + } else if (typeof color === 'object') { + this.r = color.r + this.g = color.g + this.b = color.b + } else if (arguments.length === 3) { + this.r = color + this.g = g + this.b = b } - } else if (Array.isArray(color)) { - this.r = color[0] - this.g = color[1] - this.b = color[2] - } else if (typeof color === 'object') { - this.r = color.r - this.g = color.g - this.b = color.b - } else if (arguments.length === 3) { - this.r = color - this.g = g - this.b = b } -} -SVG.extend(SVG.Color, { // Default to hex conversion - toString: function () { + toString () { return this.toHex() - }, - toArray: function () { + } + + toArray () { return [this.r, this.g, this.b] - }, - fromArray: function (a) { - return new SVG.Color(a) - }, + } + // Build hex value - toHex: function () { + toHex () { return '#' + compToHex(Math.round(this.r)) + compToHex(Math.round(this.g)) + compToHex(Math.round(this.b)) - }, + } + // Build rgb value - toRgb: function () { + toRgb () { return 'rgb(' + [this.r, this.g, this.b].join() + ')' - }, + } + // Calculate true brightness - brightness: function () { + brightness () { return (this.r / 255 * 0.30) + (this.g / 255 * 0.59) + (this.b / 255 * 0.11) - }, - // Make color morphable - morph: function (color) { - this.destination = new SVG.Color(color) - - return this - }, - // Get morphed color at given position - at: function (pos) { - // make sure a destination is defined - if (!this.destination) return this - - // normalise pos - pos = pos < 0 ? 0 : pos > 1 ? 1 : pos - - // generate morphed color - return new SVG.Color({ - r: ~~(this.r + (this.destination.r - this.r) * pos), - g: ~~(this.g + (this.destination.g - this.g) * pos), - b: ~~(this.b + (this.destination.b - this.b) * pos) - }) } -}) - -// Testers + // Testers -// Test if given value is a color string -SVG.Color.test = function (color) { - color += '' - return SVG.regex.isHex.test(color) || - SVG.regex.isRgb.test(color) -} + // Test if given value is a color string + static test (color) { + color += '' + return isHex.test(color) || isRgb.test(color) + } -// Test if given value is a rgb object -SVG.Color.isRgb = function (color) { - return color && typeof color.r === 'number' && - typeof color.g === 'number' && - typeof color.b === 'number' -} + // Test if given value is a rgb object + static isRgb (color) { + return color && typeof color.r === 'number' && + typeof color.g === 'number' && + typeof color.b === 'number' + } -// Test if given value is a color -SVG.Color.isColor = function (color) { - return SVG.Color.isRgb(color) || SVG.Color.test(color) + // Test if given value is a color + static isColor (color) { + return this.isRgb(color) || this.test(color) + } } diff --git a/src/Container.js b/src/Container.js index 8b324bd..5d6dc43 100644 --- a/src/Container.js +++ b/src/Container.js @@ -1,9 +1,2 @@ -SVG.Container = SVG.invent({ - // Initialize node - create: function (node) { - SVG.Element.call(this, node) - }, - - // Inherit from - inherit: SVG.Parent -}) +import Parent from './Parent.js' +export default class Container extends Parent {} diff --git a/src/Controller.js b/src/Controller.js index 842c772..81f6721 100644 --- a/src/Controller.js +++ b/src/Controller.js @@ -1,7 +1,5 @@ -// c = { -// finished: Whether or not we are finished -// } +import {timeline} from './defaults.js' /*** Base Class @@ -18,75 +16,62 @@ function makeSetterGetter (k, f) { } } -SVG.Stepper = SVG.invent({ - create: function () {} -}) +let easing = { + '-': function (pos) { return pos }, + '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, + '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, + '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }, + bezier: function (t0, x0, t1, x1) { + return function (t) { + // TODO: FINISH + } + } +} + + +export class Stepper { + done () { return false } +} /*** Easing Functions ================ ***/ -SVG.Ease = SVG.invent({ - inherit: SVG.Stepper, - - create: function (fn) { - SVG.Stepper.call(this, fn) - - this.ease = SVG.easing[fn || SVG.defaults.timeline.ease] || fn - }, - - extend: { - - step: function (from, to, pos) { - if (typeof from !== 'number') { - return pos < 1 ? from : to - } - return from + (to - from) * this.ease(pos) - }, - - done: function (dt, c) { - return false - } +export class Ease extends Stepper { + constructor (fn) { + super() + this.ease = easing[fn || timeline.ease] || fn } -}) -SVG.easing = { - '-': function (pos) { return pos }, - '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, - '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, - '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }, - bezier: function (t0, x0, t1, x1) { - return function (t) { - // TODO: FINISH + step (from, to, pos) { + if (typeof from !== 'number') { + return pos < 1 ? from : to } + return from + (to - from) * this.ease(pos) } } + /*** Controller Types ================ ***/ -SVG.Controller = SVG.invent({ - inherit: SVG.Stepper, - - create: function (fn) { - SVG.Stepper.call(this, fn) +export class Controller extends Stepper { + constructor (fn) { + super() this.stepper = fn - }, - - extend: { + } - step: function (current, target, dt, c) { - return this.stepper(current, target, dt, c) - }, + step (current, target, dt, c) { + return this.stepper(current, target, dt, c) + } - done: function (c) { - return c.done - } + done (c) { + return c.done } -}) +} function recalculate () { // Apply the default parameters @@ -105,89 +90,86 @@ function recalculate () { this.k = wn * wn } -SVG.Spring = SVG.invent({ - inherit: SVG.Controller, - - create: function (duration, overshoot) { +export class Spring extends Controller { + constructor (duration, overshoot) { + super() this.duration(duration || 500) .overshoot(overshoot || 0) - }, - - extend: { - step: function (current, target, dt, c) { - if (typeof current === 'string') return current - c.done = dt === Infinity - if (dt === Infinity) return target - if (dt === 0) return current + } - if (dt > 100) dt = 16 + step (current, target, dt, c) { + if (typeof current === 'string') return current + c.done = dt === Infinity + if (dt === Infinity) return target + if (dt === 0) return current - dt /= 1000 + if (dt > 100) dt = 16 - // Get the previous velocity - var velocity = c.velocity || 0 + dt /= 1000 - // Apply the control to get the new position and store it - var acceleration = -this.d * velocity - this.k * (current - target) - var newPosition = current + - velocity * dt + - acceleration * dt * dt / 2 + // Get the previous velocity + var velocity = c.velocity || 0 - // Store the velocity - c.velocity = velocity + acceleration * dt + // Apply the control to get the new position and store it + var acceleration = -this.d * velocity - this.k * (current - target) + var newPosition = current + + velocity * dt + + acceleration * dt * dt / 2 - // Figure out if we have converged, and if so, pass the value - c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002 - return c.done ? target : newPosition - }, + // Store the velocity + c.velocity = velocity + acceleration * dt - duration: makeSetterGetter('_duration', recalculate), - overshoot: makeSetterGetter('_overshoot', recalculate) + // Figure out if we have converged, and if so, pass the value + c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002 + return c.done ? target : newPosition } -}) +} -SVG.PID = SVG.invent({ - inherit: SVG.Controller, +extend(Spring, { + duration: makeSetterGetter('_duration', recalculate), + overshoot: makeSetterGetter('_overshoot', recalculate) +}) - create: function (p, i, d, windup) { - SVG.Controller.call(this) +export class PID extends Controller { + constructor (p, i, d, windup) { + super() p = p == null ? 0.1 : p i = i == null ? 0.01 : i d = d == null ? 0 : d windup = windup == null ? 1000 : windup this.p(p).i(i).d(d).windup(windup) - }, - - extend: { - step: function (current, target, dt, c) { - if (typeof current === 'string') return current - c.done = dt === Infinity + } - if (dt === Infinity) return target - if (dt === 0) return current + step (current, target, dt, c) { + if (typeof current === 'string') return current + c.done = dt === Infinity - var p = target - current - var i = (c.integral || 0) + p * dt - var d = (p - (c.error || 0)) / dt - var windup = this.windup + if (dt === Infinity) return target + if (dt === 0) return current - // antiwindup - if (windup !== false) { - i = Math.max(-windup, Math.min(i, windup)) - } + var p = target - current + var i = (c.integral || 0) + p * dt + var d = (p - (c.error || 0)) / dt + var windup = this.windup - c.error = p - c.integral = i + // antiwindup + if (windup !== false) { + i = Math.max(-windup, Math.min(i, windup)) + } - c.done = Math.abs(p) < 0.001 + c.error = p + c.integral = i - return c.done ? target : current + (this.P * p + this.I * i + this.D * d) - }, + c.done = Math.abs(p) < 0.001 - windup: makeSetterGetter('windup'), - p: makeSetterGetter('P'), - i: makeSetterGetter('I'), - d: makeSetterGetter('D') + return c.done ? target : current + (this.P * p + this.I * i + this.D * d) } +} + +extend(PID, { + windup: makeSetterGetter('windup'), + p: makeSetterGetter('P'), + i: makeSetterGetter('I'), + d: makeSetterGetter('D') }) diff --git a/src/Defs.js b/src/Defs.js index 3d6ebb9..21b6703 100644 --- a/src/Defs.js +++ b/src/Defs.js @@ -1,7 +1,8 @@ -SVG.Defs = SVG.invent({ - // Initialize node - create: 'defs', +import Container from './Container.js' +import {nodeOrNew} from './tools.js' - // Inherit from - inherit: SVG.Container -}) +export default class Defs extends Container { + constructor (node) { + super(nodeOrNew('defs', node)) + } +} diff --git a/src/Doc.js b/src/Doc.js index 423204f..e496996 100644 --- a/src/Doc.js +++ b/src/Doc.js @@ -1,70 +1,75 @@ -SVG.Doc = SVG.invent({ - // Initialize node - create: function (node) { - SVG.Element.call(this, node || SVG.create('svg')) +import Container from './Container.js' +import Parent from './Parent.js' +import {adopt, extend} from './tools.js' +import {ns, xlink, xmlns, svgjs} from './namespaces.js' - // set svg element attributes and ensure defs node - this.namespace() - }, +export default class Doc extends Container { + constructor (node) { + super(nodeOrNew('svg', node)) + this.namespace() + } - // Inherit from - inherit: SVG.Container, + isRoot () { + return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document' + } - // Add class methods - extend: { - isRoot: function () { - return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document' - }, - // Check if this is a root svg. If not, call docs from this element - doc: function () { - if (this.isRoot()) return this - return SVG.Element.prototype.doc.call(this) - }, - // Add namespaces - namespace: function () { - if (!this.isRoot()) return this.doc().namespace() - return this - .attr({ xmlns: SVG.ns, version: '1.1' }) - .attr('xmlns:xlink', SVG.xlink, SVG.xmlns) - .attr('xmlns:svgjs', SVG.svgjs, SVG.xmlns) - }, - // Creates and returns defs element - defs: function () { - if (!this.isRoot()) return this.doc().defs() - return SVG.adopt(this.node.getElementsByTagName('defs')[0]) || this.put(new SVG.Defs()) - }, - // custom parent method - parent: function (type) { - if (this.isRoot()) { - return this.node.parentNode.nodeName === '#document' ? null : this.node.parentNode - } + // Check if this is a root svg + // If not, call docs from this element + doc () { + if (this.isRoot()) return this + return super.doc() + } - return SVG.Element.prototype.parent.call(this, type) - }, - // Removes the doc from the DOM - remove: function () { - if (!this.isRoot()) { - return SVG.Element.prototype.remove.call(this) - } + // Add namespaces + namespace () { + if (!this.isRoot()) return this.doc().namespace() + return this + .attr({ xmlns: ns, version: '1.1' }) + .attr('xmlns:xlink', xlink, xmlns) + .attr('xmlns:svgjs', svgjs, xmlns) + } - if (this.parent()) { - this.parent().removeChild(this.node) - } + // Creates and returns defs element + defs () { + if (!this.isRoot()) return this.doc().defs() + return adopt(this.node.getElementsByTagName('defs')[0]) || + this.put(new Defs()) + } - return this - }, - clear: function () { - // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) - } - return this - } - }, - construct: { - // Create nested svg document - nested: function () { - return this.put(new SVG.Doc()) - } + // custom parent method + parent (type) { + if (this.isRoot()) { + return this.node.parentNode.nodeName === '#document' ? null : this.node.parentNode + } + + return super.parent(type) + } + + // Removes the doc from the DOM + remove () { + if (!this.isRoot()) { + return super.remove() + } + + if (this.parent()) { + this.parent().removeChild(this.node) + } + + return this + } + + clear () { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild) + } + return this + } +} + +addFactory(Container, { + // Create nested svg document + nested () { + return this.put(new Doc()) } }) diff --git a/src/Element.js b/src/Element.js index f0d9e8e..7667563 100644 --- a/src/Element.js +++ b/src/Element.js @@ -1,10 +1,15 @@ -/* global proportionalSize, assignNewId, createElement, matches, is */ - -SVG.Element = SVG.invent({ - inherit: SVG.EventTarget, - - // Initialize node - create: function (node) { +import {proportionalSize, assignNewId, makeInstance, matches} from './helpers.js' +import {eid} from './tools.js' +import {delimiter} from './regex.js' +import {ns} from './namespaces.js' +import {adopt} from './tools.js' +// import {Doc, EventTarget, Parent} from './classes.js' +import EventTarget from './EventTarget.js' +import Doc from './Doc.js' +import Parent from './Parent.js' + +export default class Element extends EventTarget { + constructor (node) { // event listener this.events = {} @@ -23,294 +28,275 @@ SVG.Element = SVG.invent({ this.setData(JSON.parse(node.getAttribute('svgjs:data')) || {}) } } - }, - - // 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) { - // write dom data to the dom so the clone can pickup the data - this.writeDataToDom() + } - // clone element and assign new id - var clone = assignNewId(this.node.cloneNode(true)) + // Move over x-axis + x (x) { + return this.attr('x', x) + } - // insert the clone in the given parent or after myself - if (parent) parent.add(clone) - else this.after(clone) + // Move over y-axis + y (y) { + return this.attr('y', y) + } - return clone - }, + // Move by center over x-axis + cx (x) { + return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2) + } - // Remove element - remove: function () { - if (this.parent()) { this.parent().removeElement(this) } + // Move by center over y-axis + cy (y) { + return y == null + ? this.y() + this.height() / 2 + : this.y(y - this.height() / 2) + } - return this - }, + // Move element to given x and y values + move (x, y) { + return this.x(x).y(y) + } - // Replace element - replace: function (element) { - this.after(element).remove() + // Move element by its center + center (x, y) { + return this.cx(x).cy(y) + } - return element - }, + // Set width of element + width (width) { + return this.attr('width', width) + } - // Add element to given container and return self - addTo: function (parent) { - return createElement(parent).put(this) - }, + // Set height of element + height (height) { + return this.attr('height', height) + } - // Add element to given container and return container - putIn: function (parent) { - return createElement(parent).add(this) - }, + // Set element size to given width and height + size (width, height) { + let p = proportionalSize(this, width, height) - // Get / set id - id: function (id) { - // generate new id if no id set - if (typeof id === 'undefined' && !this.node.id) { - this.node.id = SVG.eid(this.type) - } + return this + .width(new SVGNumber(p.width)) + .height(new SVGNumber(p.height)) + } - // dont't set directly width this.node.id to make `null` work correctly - 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.css('display', '') - }, - - // Hide element - hide: function () { - return this.css('display', 'none') - }, - - // Is element visible? - visible: function () { - return this.css('display') !== 'none' - }, - - // Return id on string conversion - toString: function () { - return this.id() - }, - - // Return array of classes on the node - classes: function () { - var attr = this.attr('class') - return attr == null ? [] : attr.trim().split(SVG.regex.delimiter) - }, - - // 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(' ')) - } + // Clone element + clone (parent) { + // write dom data to the dom so the clone can pickup the data + this.writeDataToDom() - return this - }, + // clone element and assign new id + let clone = assignNewId(this.node.cloneNode(true)) - // Remove class from the node - removeClass: function (name) { - if (this.hasClass(name)) { - this.attr('class', this.classes().filter(function (c) { - return c !== name - }).join(' ')) - } + // insert the clone in the given parent or after myself + if (parent) parent.add(clone) + else this.after(clone) - return this - }, + return clone + } - // Toggle the presence of a class on the node - toggleClass: function (name) { - return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) - }, + // Remove element + remove () { + if (this.parent()) { this.parent().removeElement(this) } - // Get referenced element form attribute value - reference: function (attr) { - return SVG.get(this.attr(attr)) - }, + return this + } - // Returns the parent element instance - parent: function (type) { - var parent = this + // Replace element + replace (element) { + this.after(element).remove() - // check for parent - if (!parent.node.parentNode) return null + return element + } - // get parent element - parent = SVG.adopt(parent.node.parentNode) + // Add element to given container and return self + addTo (parent) { + return makeInstance(parent).put(this) + } - if (!type) return parent + // Add element to given container and return container + putIn (parent) { + return makeInstance(parent).add(this) + } - // loop trough ancestors if type is given - while (parent && parent.node instanceof window.SVGElement) { - if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent - parent = SVG.adopt(parent.node.parentNode) - } - }, - - // Get parent document - doc: function () { - var p = this.parent(SVG.Doc) - return p && p.doc() - }, - - // Get defs - defs: function () { - return this.doc().defs() - }, - - // return array of all ancestors of given type up to the root svg - parents: function (type) { - var parents = [] - var 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) { - var well, len - - // act as a setter if svg is given - if (svg && this instanceof SVG.Parent) { - // create temporary holder - well = document.createElementNS(SVG.ns, 'svg') - // dump raw svg - well.innerHTML = svg - - // transplant nodes - for (len = well.children.length; len--;) { - this.node.appendChild(well.firstElementChild) - } - - // otherwise act as a getter - } else { - // write svgjs data to the dom - this.writeDataToDom() + // Get / set id + id (id) { + // generate new id if no id set + if (typeof id === 'undefined' && !this.node.id) { + this.node.id = eid(this.type) + } - return this.node.outerHTML - } + // dont't set directly width this.node.id to make `null` work correctly + return this.attr('id', id) + } - return this - }, + // Checks whether the given point inside the bounding box of the element + inside (x, y) { + let box = this.bbox() - // write svgjs data to the dom - writeDataToDom: function () { - // dump variables recursively - if (this.is(SVG.Parent)) { - this.each(function () { - this.writeDataToDom() - }) - } + return x > box.x && + y > box.y && + x < box.x + box.width && + y < box.y + box.height + } + + // Return id on string conversion + toString () { + return this.id() + } + + // Return array of classes on the node + classes () { + var attr = this.attr('class') + return attr == null ? [] : attr.trim().split(delimiter) + } + + // Return true if class exists on the node, false otherwise + hasClass (name) { + return this.classes().indexOf(name) !== -1 + } + + // Add class to the node + addClass (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 (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 (name) { + return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) + } + + // FIXME: getIdFromReference + // Get referenced element form attribute value + reference (attr) { + return get(this.attr(attr)) + } + + // Returns the parent element instance + parent (type) { + var parent = this - // remove previously set data - this.node.removeAttribute('svgjs:data') + // check for parent + if (!parent.node.parentNode) return null + + // get parent element + parent = adopt(parent.node.parentNode) + + if (!type) return parent + + // loop trough ancestors if type is given + while (parent && parent.node instanceof window.SVGElement) { + if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent + parent = adopt(parent.node.parentNode) + } + } - if (Object.keys(this.dom).length) { - this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)) // see #428 + // Get parent document + doc () { + let p = this.parent(Doc) + return p && p.doc() + } + + // Get defs + defs () { + return this.doc().defs() + } + + // return array of all ancestors of given type up to the root svg + parents (type) { + let parents = [] + let 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 (selector) { + return matches(this.node, selector) + } + + // Returns the svg node to call native svg methods on it + native () { + return this.node + } + + // Import raw svg + svg (svg) { + var well, len + + // act as a setter if svg is given + if (svg && this instanceof Parent) { + // create temporary holder + well = document.createElementNS(ns, 'svg') + // dump raw svg + well.innerHTML = svg + + // transplant nodes + for (len = well.children.length; len--;) { + this.node.appendChild(well.firstElementChild) } - 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) - }, - getEventTarget: function () { - return this.node + + // otherwise act as a getter + } else { + // write svgjs data to the dom + this.writeDataToDom() + + return this.node.outerHTML + } + + return this + } + + // write svgjs data to the dom + writeDataToDom () { + // dump variables recursively + if (this.is(Parent)) { + this.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 (o) { + this.dom = o + return this + } + + getEventTarget () { + return this.node } -}) +} diff --git a/src/Ellipse.js b/src/Ellipse.js index 8a8f027..2a6fc51 100644 --- a/src/Ellipse.js +++ b/src/Ellipse.js @@ -1,91 +1,17 @@ -/* global proportionalSize */ +import Parent from './Parent.js' +import * as circled from './circled.js' -SVG.Circle = SVG.invent({ - // Initialize node - create: 'circle', - - // Inherit from - inherit: SVG.Shape, - - // Add parent method - construct: { - // Create circle element, based on ellipse - circle: function (size) { - return this.put(new SVG.Circle()).rx(new SVG.Number(size).divide(2)).move(0, 0) - } - } -}) - -SVG.extend([SVG.Circle, SVG.Timeline], { - // Radius x value - rx: function (rx) { - return this.attr('r', rx) - }, - // Alias radius x value - ry: function (ry) { - return this.rx(ry) - } -}) - -SVG.Ellipse = SVG.invent({ - // Initialize node - create: 'ellipse', - - // Inherit from - inherit: SVG.Shape, - - // Add parent method - construct: { - // Create an ellipse - ellipse: function (width, height) { - return this.put(new SVG.Ellipse()).size(width, height).move(0, 0) - } +export default class Ellipse extends Shape { + constructor (node) { + super(nodeOrNew('ellipse', node)) } -}) - -SVG.extend([SVG.Ellipse, SVG.Rect, SVG.Timeline], { - // Radius x value - rx: function (rx) { - return this.attr('rx', rx) - }, - // Radius y value - ry: function (ry) { - return this.attr('ry', ry) - } -}) +} -// Add common method -SVG.extend([SVG.Circle, SVG.Ellipse], { - // Move over x-axis - x: function (x) { - return x == null ? this.cx() - this.rx() : this.cx(x + this.rx()) - }, - // Move over y-axis - y: function (y) { - return y == null ? this.cy() - this.ry() : this.cy(y + this.ry()) - }, - // Move by center over x-axis - cx: function (x) { - return x == null ? this.attr('cx') : this.attr('cx', x) - }, - // Move by center over y-axis - cy: function (y) { - return y == null ? this.attr('cy') : this.attr('cy', y) - }, - // Set width of element - width: function (width) { - return width == null ? this.rx() * 2 : this.rx(new SVG.Number(width).divide(2)) - }, - // Set height of element - height: function (height) { - return height == null ? this.ry() * 2 : this.ry(new SVG.Number(height).divide(2)) - }, - // Custom size function - size: function (width, height) { - var p = proportionalSize(this, width, height) +extend(Ellipse, circled) - return this - .rx(new SVG.Number(p.width).divide(2)) - .ry(new SVG.Number(p.height).divide(2)) +addFactory(Container, { + // Create an ellipse + ellipse: function (width, height) { + return this.put(new Ellipse()).size(width, height).move(0, 0) } }) diff --git a/src/EventTarget.js b/src/EventTarget.js index fbe4781..c762929 100644 --- a/src/EventTarget.js +++ b/src/EventTarget.js @@ -1,23 +1,25 @@ -SVG.EventTarget = SVG.invent({ - create: function () {}, - extend: { - // Bind given event to listener - on: function (event, listener, binding, options) { - SVG.on(this, event, listener, binding, options) - return this - }, - // Unbind event from listener - off: function (event, listener) { - SVG.off(this, event, listener) - return this - }, - dispatch: function (event, data) { - return SVG.dispatch(this, event, data) - }, - // Fire given event - fire: function (event, data) { - this.dispatch(event, data) - return this - } +import {on, off, dispatch} from './event.js' + +export default class EventTarget { + // Bind given event to listener + on (event, listener, binding, options) { + on(this, event, listener, binding, options) + return this } -}) + + // Unbind event from listener + off (event, listener) { + off(this, event, listener) + return this + } + + dispatch (event, data) { + return dispatch(this, event, data) + } + + // Fire given event + fire (event, data) { + this.dispatch(event, data) + return this + } +} diff --git a/src/G.js b/src/G.js index 0088a1c..2d60cfe 100644 --- a/src/G.js +++ b/src/G.js @@ -1,19 +1,15 @@ -SVG.G = SVG.invent({ - // Initialize node - create: 'g', +import Container from './Container.js' +import Parent from './Parent.js' - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - }, +export default class G extends Container { + constructor (node) { + super(nodeorNew('group', node)) + } +} - // Add parent method - construct: { - // Create a group element - group: function () { - return this.put(new SVG.G()) - } +addFactory(Parent, { + // Create a group element + group: function () { + return this.put(new G()) } }) diff --git a/src/Gradient.js b/src/Gradient.js index 45a4e08..da76666 100644 --- a/src/Gradient.js +++ b/src/Gradient.js @@ -1,104 +1,60 @@ -SVG.Gradient = SVG.invent({ - // Initialize node - create: function (type) { - SVG.Element.call(this, typeof type === 'object' ? type : SVG.create(type + 'Gradient')) - }, +import Stop from './Stop.js' +import * as gradiented from './gradiented.js' +import {nodeOrNew, extend, addFactory} from './tools.js' - // Inherit from - inherit: SVG.Container, +export default class Gradient extends Container { + constructor (type) { + super(nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type)) + } - // Add class methods - extend: { - // Add a color stop - stop: function (offset, color, opacity) { - return this.put(new SVG.Stop()).update(offset, color, opacity) - }, - // Update gradient - update: function (block) { - // remove all stops - this.clear() + // Add a color stop + stop (offset, color, opacity) { + return this.put(new Stop()).update(offset, color, opacity) + } - // invoke passed block - if (typeof block === 'function') { - block.call(this, this) - } + // Update gradient + update (block) { + // remove all stops + this.clear() - return this - }, - // Return the fill id - url: function () { - return 'url(#' + this.id() + ')' - }, - // Alias string convertion to fill - toString: function () { - return this.url() - }, - // custom attr to handle transform - attr: function (a, b, c) { - if (a === 'transform') a = 'gradientTransform' - return SVG.Container.prototype.attr.call(this, a, b, c) + // invoke passed block + if (typeof block === 'function') { + block.call(this, this) } - }, - // Add parent method - construct: { - // Create gradient element in defs - gradient: function (type, block) { - return this.defs().gradient(type, block) - } + return this } -}) -// Add animatable methods to both gradient and fx module -SVG.extend([SVG.Gradient, SVG.Timeline], { - // From position - from: function (x, y) { - return (this._target || this).type === 'radialGradient' - ? this.attr({ fx: new SVG.Number(x), fy: new SVG.Number(y) }) - : this.attr({ x1: new SVG.Number(x), y1: new SVG.Number(y) }) - }, - // To position - to: function (x, y) { - return (this._target || this).type === 'radialGradient' - ? this.attr({ cx: new SVG.Number(x), cy: new SVG.Number(y) }) - : this.attr({ x2: new SVG.Number(x), y2: new SVG.Number(y) }) + // Return the fill id + url () { + return 'url(#' + this.id() + ')' } -}) -// Base gradient generation -SVG.extend(SVG.Defs, { - // define gradient - gradient: function (type, block) { - return this.put(new SVG.Gradient(type)).update(block) + // Alias string convertion to fill + toString () { + return this.url() } -}) - -SVG.Stop = SVG.invent({ - // Initialize node - create: 'stop', - - // Inherit from - inherit: SVG.Element, + // custom attr to handle transform + attr (a, b, c) { + if (a === 'transform') a = 'gradientTransform' + return super.attr(a, b, c) + } +} - // Add class methods - extend: { - // add color stops - update: function (o) { - if (typeof o === 'number' || o instanceof SVG.Number) { - o = { - offset: arguments[0], - color: arguments[1], - opacity: arguments[2] - } - } +extend(Gradient, gradiented) - // set attributes - if (o.opacity != null) this.attr('stop-opacity', o.opacity) - if (o.color != null) this.attr('stop-color', o.color) - if (o.offset != null) this.attr('offset', new SVG.Number(o.offset)) +addFactory(Parent, { + // Create gradient element in defs + gradient (type, block) { + return this.defs().gradient(type, block) + } +}) - return this - } +// Base gradient generation +addFactory(Defs, { + // define gradient + gradient: function (type, block) { + return this.put(new Gradient(type)).update(block) } }) diff --git a/src/HtmlNode.js b/src/HtmlNode.js index e04b731..4a12d3f 100644 --- a/src/HtmlNode.js +++ b/src/HtmlNode.js @@ -1,29 +1,27 @@ -/* global createElement */ +import {makeInstance} from './helpers.js' +import EventTarget from './EventTarget.js' -SVG.HtmlNode = SVG.invent({ - inherit: SVG.EventTarget, - create: function (element) { +export default class HtmlNode extends EventTarget { + constructor (element) { this.node = element - }, + } - extend: { - add: function (element, i) { - element = createElement(element) + add (element, i) { + element = makeInstance(element) - if (element.node !== this.node.children[i]) { - this.node.insertBefore(element.node, this.node.children[i] || null) - } + if (element.node !== this.node.children[i]) { + this.node.insertBefore(element.node, this.node.children[i] || null) + } - return this - }, + return this + } - put: function (element, i) { - this.add(element, i) - return element - }, + put (element, i) { + this.add(element, i) + return element + } - getEventTarget: function () { - return this.node - } + getEventTarget () { + return this.node } -}) +} diff --git a/src/Image.js b/src/Image.js index f9395eb..c70be1d 100644 --- a/src/Image.js +++ b/src/Image.js @@ -1,57 +1,58 @@ -SVG.Image = SVG.invent({ - // Initialize node - create: 'image', - - // Inherit from - inherit: SVG.Shape, +import Shape from './Shape.js' +import Container from './Container.js' +import Pattern from './Pattern.js' +import {on, off} from './event.js' +import {nodeOrNew, addFactory} from './tools.js' +import {xlink} from './namespaces.js' + +export default class Image extends Shape { + constructor (node) { + super(nodeOrNew('image', node)) + } - // Add class methods - extend: { - // (re)load image - load: function (url, callback) { - if (!url) return this + // (re)load image + load (url, callback) { + if (!url) return this - var img = new window.Image() + var img = new window.Image() - SVG.on(img, 'load', function (e) { - var p = this.parent(SVG.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) - } + // ensure image size + if (this.width() === 0 && this.height() === 0) { + this.size(img.width, img.height) + } - if (p instanceof SVG.Pattern) { - // ensure pattern size if not set - if (p.width() === 0 && p.height() === 0) { - p.size(this.width(), this.height()) - } + if (p instanceof Pattern) { + // ensure pattern size if not set + if (p.width() === 0 && p.height() === 0) { + p.size(this.width(), this.height()) } + } + + if (typeof callback === 'function') { + callback.call(this, { + width: img.width, + height: img.height, + ratio: img.width / img.height, + url: url + }) + } + }, this) + + on(img, 'load error', function () { + // dont forget to unbind memory leaking events + off(img) + }) + + return this.attr('href', (img.src = url), xlink) + } +} - if (typeof callback === 'function') { - callback.call(this, { - width: img.width, - height: img.height, - ratio: img.width / img.height, - url: url - }) - } - }, this) - - SVG.on(img, 'load error', function () { - // dont forget to unbind memory leaking events - SVG.off(img) - }) - - return this.attr('href', (img.src = url), SVG.xlink) - } - }, - - // Add parent method - construct: { - // create image element, load image and set its size - image: function (source, callback) { - return this.put(new SVG.Image()).size(0, 0).load(source, callback) - } +addFactory(Container, { + // create image element, load image and set its size + image (source, callback) { + return this.put(new Image()).size(0, 0).load(source, callback) } }) diff --git a/src/Line.js b/src/Line.js index da0c0ca..ddd00e9 100644 --- a/src/Line.js +++ b/src/Line.js @@ -1,57 +1,55 @@ -/* global proportionalSize */ +import {proportionalSize} from './helpers.js' +import {nodeOrNew} from './tools.js' +import {Shape, Container, PointArray} from './classes.js' -SVG.Line = SVG.invent({ +export default class Line extends Shape { // Initialize node - create: 'line', - - // Inherit from - inherit: SVG.Shape, - - // Add class methods - extend: { - // Get array - array: function () { - return new SVG.PointArray([ - [ this.attr('x1'), this.attr('y1') ], - [ this.attr('x2'), this.attr('y2') ] - ]) - }, - - // Overwrite native plot() method - plot: function (x1, y1, x2, y2) { - if (x1 == null) { - return this.array() - } else if (typeof y1 !== 'undefined') { - x1 = { x1: x1, y1: y1, x2: x2, y2: y2 } - } else { - x1 = new SVG.PointArray(x1).toLine() - } - - return this.attr(x1) - }, - - // Move by left top corner - move: function (x, y) { - return this.attr(this.array().move(x, y).toLine()) - }, - - // Set element size to given width and height - size: function (width, height) { - var p = proportionalSize(this, width, height) - return this.attr(this.array().size(p.width, p.height).toLine()) - } - }, - - // Add parent method - construct: { - // Create a line element - line: function (x1, y1, x2, y2) { - // make sure plot is called as a setter - // x1 is not necessarily a number, it can also be an array, a string and a SVG.PointArray - return SVG.Line.prototype.plot.apply( - this.put(new SVG.Line()) - , x1 != null ? [x1, y1, x2, y2] : [0, 0, 0, 0] - ) + constructor (node) { + super(nodeOrNew('line', node)) + } + + // Get array + array () { + 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) { + return this.array() + } else if (typeof y1 !== 'undefined') { + x1 = { x1: x1, y1: y1, x2: x2, y2: y2 } + } else { + x1 = new PointArray(x1).toLine() } + + return this.attr(x1) + } + + // Move by left top corner + 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()) + } + +} + +addFactory(Container, { + // Create a line element + line (...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] + ) } }) diff --git a/src/Marker.js b/src/Marker.js index 32f8e4e..298ac6f 100644 --- a/src/Marker.js +++ b/src/Marker.js @@ -1,67 +1,71 @@ -SVG.Marker = SVG.invent({ +import Container from './Container.js' +import Defs from './Defs.js' +import Line from './Line.js' +import Polyline from './Polyline.js' +import Polygon from './Polygon.js' +import Path from './Path.js' + +export default class Marker extends Container { // Initialize node - create: 'marker', + constructor (node) { + super(nodeOrNew('marker', node)) + } + + // Set width of element + width (width) { + return this.attr('markerWidth', width) + } + + // Set height of element + height (height) { + return this.attr('markerHeight', height) + } - // Inherit from - inherit: SVG.Container, + // Set marker refX and refY + ref (x, y) { + return this.attr('refX', x).attr('refY', y) + } - // Add class methods - extend: { - // Set width of element - width: function (width) { - return this.attr('markerWidth', width) - }, - // Set height of element - height: function (height) { - return this.attr('markerHeight', height) - }, - // Set marker refX and refY - ref: function (x, y) { - return this.attr('refX', x).attr('refY', y) - }, - // Update marker - update: function (block) { - // remove all content - this.clear() + // Update marker + update (block) { + // remove all content + this.clear() - // invoke passed block - if (typeof block === 'function') { block.call(this, this) } + // invoke passed block + if (typeof block === 'function') { block.call(this, this) } - return this - }, - // Return the fill id - toString: function () { - return 'url(#' + this.id() + ')' - } - }, + return this + } - // Add parent method - construct: { - marker: function (width, height, block) { - // Create marker element in defs - return this.defs().marker(width, height, block) - } + // Return the fill id + toString () { + return 'url(#' + this.id() + ')' } +} +addFactory(Container, { + marker (width, height, block) { + // Create marker element in defs + return this.defs().marker(width, height, block) + } }) -SVG.extend(SVG.Defs, { +extend(Defs, { // Create marker - marker: function (width, height, block) { + marker (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 SVG.Marker()) + return this.put(new Marker()) .size(width, height) .ref(width / 2, height / 2) .viewbox(0, 0, width, height) .attr('orient', 'auto') .update(block) } - }) -SVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon, SVG.Path], { +extend([Line, Polyline, Polygon, Path], { // Create and attach markers - marker: function (marker, width, height, block) { + marker (marker, width, height, block) { var attr = ['marker'] // Build attribute name @@ -69,7 +73,7 @@ SVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon, SVG.Path], { attr = attr.join('-') // Set marker attribute - marker = arguments[1] instanceof SVG.Marker + marker = arguments[1] instanceof Marker ? arguments[1] : this.doc().marker(width, height, block) diff --git a/src/Mask.js b/src/Mask.js index e40d80f..bdd6086 100644 --- a/src/Mask.js +++ b/src/Mask.js @@ -1,51 +1,55 @@ -SVG.Mask = SVG.invent({ +import Container from './Container.js' +import Element from './Element.js' +import {nodeOrNew} from './tools.js' +import find from './selector.js' + +export default class Mask extends Container { // Initialize node - create: 'mask', - - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - // Unmask all masked elements and remove itself - remove: function () { - // unmask all targets - this.targets().forEach(function (el) { - el.unmask() - }) - - // remove mask from parent - return SVG.Element.prototype.remove.call(this) - }, - - targets: function () { - return SVG.select('svg [mask*="' + this.id() + '"]') - } - }, + constructor (node) { + super(nodeOrNew('mask', node)) + } + + // Unmask all masked elements and remove itself + remove () { + // unmask all targets + this.targets().forEach(function (el) { + el.unmask() + }) + + // remove mask from parent + return super.remove() + } - // Add parent method - construct: { - // Create masking element - mask: function () { - return this.defs().put(new SVG.Mask()) - } + targets () { + return find('svg [mask*="' + this.id() + '"]') + } + +} + +addFactory(Container, { + mask () { + return this.defs().put(new Mask()) } }) -SVG.extend(SVG.Element, { +extend(Element, { // Distribute mask to svg element - maskWith: function (element) { + maskWith (element) { // use given mask or create a new one - var masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element) + var masker = element instanceof Mask + ? element + : this.parent().mask().add(element) // apply mask return this.attr('mask', 'url("#' + masker.id() + '")') }, + // Unmask element - unmask: function () { + unmask () { return this.attr('mask', null) }, - masker: function () { + + masker () { return this.reference('mask') } }) diff --git a/src/Matrix.js b/src/Matrix.js index 666b898..5edbc5c 100644 --- a/src/Matrix.js +++ b/src/Matrix.js @@ -1,16 +1,20 @@ -/* global abcdef arrayToMatrix closeEnough formatTransforms isMatrixLike matrixMultiply */ +import {abcdef, arrayToMatrix, closeEnough, formatTransforms, isMatrixLike, matrixMultiply} from './helpers.js' +import {Element, Point, Doc} from './classes.js' +import {delimiter} from './regex.js' +import {radians} from './utils.js' +import parser from './parser.js' -SVG.Matrix = SVG.invent({ +export default class Matrix { // Initialize - create: function (source) { + constructor (source) { var base = arrayToMatrix([1, 0, 0, 1, 0, 0]) // ensure source as object - source = source instanceof SVG.Element ? source.matrixify() - : typeof source === 'string' ? arrayToMatrix(source.split(SVG.regex.delimiter).map(parseFloat)) + source = source instanceof Element ? source.matrixify() + : typeof source === 'string' ? arrayToMatrix(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? arrayToMatrix(source) : (typeof source === 'object' && isMatrixLike(source)) ? source - : (typeof source === 'object') ? new SVG.Matrix().transform(source) + : (typeof source === 'object') ? new Matrix().transform(source) : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) : base @@ -21,439 +25,408 @@ SVG.Matrix = SVG.invent({ this.d = source.d != null ? source.d : base.d this.e = source.e != null ? source.e : base.e this.f = source.f != null ? source.f : base.f - }, + } + + + // Clones this matrix + clone () { + return new Matrix(this) + } + + // Transform a matrix into another matrix by manipulating the space + transform (o) { + // Check if o is a matrix and then left multiply it directly + if (isMatrixLike(o)) { + var matrix = new Matrix(o) + return matrix.multiplyO(this) + } + + // Get the proposed transformations and the current transformations + var t = formatTransforms(o) + var current = this + let { x: ox, y: oy } = new Point(t.ox, t.oy).transform(current) + + // Construct the resulting matrix + var transformer = new Matrix() + .translateO(t.rx, t.ry) + .lmultiplyO(current) + .translateO(-ox, -oy) + .scaleO(t.scaleX, t.scaleY) + .skewO(t.skewX, t.skewY) + .shearO(t.shear) + .rotateO(t.theta) + .translateO(ox, oy) + + // If we want the origin at a particular place, we force it there + if (isFinite(t.px) || isFinite(t.py)) { + const origin = new Point(ox, oy).transform(transformer) + // TODO: Replace t.px with isFinite(t.px) + const dx = t.px ? t.px - origin.x : 0 + const dy = t.py ? t.py - origin.y : 0 + transformer.translateO(dx, dy) + } + + // Translate now after positioning + transformer.translateO(t.tx, t.ty) + return transformer + } + + // Applies a matrix defined by its affine parameters + compose (o) { + if (o.origin) { + o.originX = o.origin[0] + o.originY = o.origin[1] + } + // Get the parameters + var ox = o.originX || 0 + var oy = o.originY || 0 + var sx = o.scaleX || 1 + var sy = o.scaleY || 1 + var lam = o.shear || 0 + var theta = o.rotate || 0 + var tx = o.translateX || 0 + var ty = o.translateY || 0 + + // Apply the standard matrix + var result = new Matrix() + .translateO(-ox, -oy) + .scaleO(sx, sy) + .shearO(lam) + .rotateO(theta) + .translateO(tx, ty) + .lmultiplyO(this) + .translateO(ox, oy) + return result + } + + // Decomposes this matrix into its affine parameters + decompose (cx = 0, cy = 0) { + // Get the parameters from the matrix + var a = this.a + var b = this.b + var c = this.c + var d = this.d + var e = this.e + var f = this.f + + // Figure out if the winding direction is clockwise or counterclockwise + var determinant = a * d - b * c + var ccw = determinant > 0 ? 1 : -1 + + // Since we only shear in x, we can use the x basis to get the x scale + // and the rotation of the resulting matrix + var sx = ccw * Math.sqrt(a * a + b * b) + var thetaRad = Math.atan2(ccw * b, ccw * a) + var theta = 180 / Math.PI * thetaRad + var ct = Math.cos(thetaRad) + var st = Math.sin(thetaRad) + + // We can then solve the y basis vector simultaneously to get the other + // two affine parameters directly from these parameters + var lam = (a * c + b * d) / determinant + var sy = ((c * sx) / (lam * a - b)) || ((d * sx) / (lam * b + a)) + + // Use the translations + let tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy) + let ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy) + + // Construct the decomposition and return it + return { + // Return the affine parameters + scaleX: sx, + scaleY: sy, + shear: lam, + rotate: theta, + translateX: tx, + translateY: ty, + originX: cx, + originY: cy, + + // Return the matrix parameters + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + } + } + + // Left multiplies by the given matrix + multiply (matrix) { + return this.clone().multiplyO(matrix) + } + + multiplyO (matrix) { + // Get the matrices + var l = this + var r = matrix instanceof Matrix + ? matrix + : new Matrix(matrix) + + return matrixMultiply(l, r, this) + } + + lmultiply (matrix) { + return this.clone().lmultiplyO(matrix) + } + + lmultiplyO (matrix) { + var r = this + var l = matrix instanceof Matrix + ? matrix + : new Matrix(matrix) + + return matrixMultiply(l, r, this) + } + + // Inverses matrix + inverseO () { + // Get the current parameters out of the matrix + var a = this.a + var b = this.b + var c = this.c + var d = this.d + var e = this.e + var f = this.f + + // Invert the 2x2 matrix in the top left + var det = a * d - b * c + if (!det) throw new Error('Cannot invert ' + this) + + // Calculate the top 2x2 matrix + var na = d / det + var nb = -b / det + var nc = -c / det + var nd = a / det + + // Apply the inverted matrix to the top right + var ne = -(na * e + nc * f) + var nf = -(nb * e + nd * f) + + // Construct the inverted matrix + this.a = na + this.b = nb + this.c = nc + this.d = nd + this.e = ne + this.f = nf + + return this + } + + inverse () { + return this.clone().inverseO() + } + + // Translate matrix + translate (x, y) { + return this.clone().translateO(x, y) + } + + translateO (x, y) { + this.e += x || 0 + this.f += y || 0 + return this + } + + // Scale matrix + scale (x, y, cx, cy) { + return this.clone().scaleO(...arguments) + } + + scaleO (x, y = x, cx = 0, cy = 0) { + // Support uniform scaling + if (arguments.length === 3) { + cy = cx + cx = y + y = x + } + + let {a, b, c, d, e, f} = this + + this.a = a * x + this.b = b * y + this.c = c * x + this.d = d * y + this.e = e * x - cx * x + cx + this.f = f * y - cy * y + cy + + return this + } + + // Rotate matrix + rotate (r, cx, cy) { + return this.clone().rotateO(r, cx, cy) + } + + rotateO (r, cx = 0, cy = 0) { + // Convert degrees to radians + r = radians(r) + + let cos = Math.cos(r) + let sin = Math.sin(r) + + let {a, b, c, d, e, f} = this - // Add methods - extend: { - - // Clones this matrix - clone: function () { - return new SVG.Matrix(this) - }, - - // Transform a matrix into another matrix by manipulating the space - transform: function (o) { - // Check if o is a matrix and then left multiply it directly - if (isMatrixLike(o)) { - var matrix = new SVG.Matrix(o) - return matrix.multiplyO(this) - } - - // Get the proposed transformations and the current transformations - var t = formatTransforms(o) - var current = this - let { x: ox, y: oy } = new SVG.Point(t.ox, t.oy).transform(current) - - // Construct the resulting matrix - var transformer = new SVG.Matrix() - .translateO(t.rx, t.ry) - .lmultiplyO(current) - .translateO(-ox, -oy) - .scaleO(t.scaleX, t.scaleY) - .skewO(t.skewX, t.skewY) - .shearO(t.shear) - .rotateO(t.theta) - .translateO(ox, oy) - - // If we want the origin at a particular place, we force it there - if (isFinite(t.px) || isFinite(t.py)) { - const origin = new SVG.Point(ox, oy).transform(transformer) - // TODO: Replace t.px with isFinite(t.px) - const dx = t.px ? t.px - origin.x : 0 - const dy = t.py ? t.py - origin.y : 0 - transformer.translateO(dx, dy) - } - - // Translate now after positioning - transformer.translateO(t.tx, t.ty) - return transformer - }, - - // Applies a matrix defined by its affine parameters - compose: function (o) { - if (o.origin) { - o.originX = o.origin[0] - o.originY = o.origin[1] - } - // Get the parameters - var ox = o.originX || 0 - var oy = o.originY || 0 - var sx = o.scaleX || 1 - var sy = o.scaleY || 1 - var lam = o.shear || 0 - var theta = o.rotate || 0 - var tx = o.translateX || 0 - var ty = o.translateY || 0 - - // Apply the standard matrix - var result = new SVG.Matrix() - .translateO(-ox, -oy) - .scaleO(sx, sy) - .shearO(lam) - .rotateO(theta) - .translateO(tx, ty) - .lmultiplyO(this) - .translateO(ox, oy) - return result - }, - - // Decomposes this matrix into its affine parameters - decompose: function (cx = 0, cy = 0) { - // Get the parameters from the matrix - var a = this.a - var b = this.b - var c = this.c - var d = this.d - var e = this.e - var f = this.f - - // Figure out if the winding direction is clockwise or counterclockwise - var determinant = a * d - b * c - var ccw = determinant > 0 ? 1 : -1 - - // Since we only shear in x, we can use the x basis to get the x scale - // and the rotation of the resulting matrix - var sx = ccw * Math.sqrt(a * a + b * b) - var thetaRad = Math.atan2(ccw * b, ccw * a) - var theta = 180 / Math.PI * thetaRad - var ct = Math.cos(thetaRad) - var st = Math.sin(thetaRad) - - // We can then solve the y basis vector simultaneously to get the other - // two affine parameters directly from these parameters - var lam = (a * c + b * d) / determinant - var sy = ((c * sx) / (lam * a - b)) || ((d * sx) / (lam * b + a)) - - // Use the translations - let tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy) - let ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy) - - // Construct the decomposition and return it - return { - // Return the affine parameters - scaleX: sx, - scaleY: sy, - shear: lam, - rotate: theta, - translateX: tx, - translateY: ty, - originX: cx, - originY: cy, - - // Return the matrix parameters - a: this.a, - b: this.b, - c: this.c, - d: this.d, - e: this.e, - f: this.f - } - }, - - // Morph one matrix into another - morph: function (matrix) { - // Store new destination - this.destination = new SVG.Matrix(matrix) - return this - }, - - // Get morphed matrix at a given position - at: function (pos) { - // Make sure a destination is defined - if (!this.destination) return this - - // Calculate morphed matrix at a given position - var matrix = new SVG.Matrix({ - a: this.a + (this.destination.a - this.a) * pos, - b: this.b + (this.destination.b - this.b) * pos, - c: this.c + (this.destination.c - this.c) * pos, - d: this.d + (this.destination.d - this.d) * pos, - e: this.e + (this.destination.e - this.e) * pos, - f: this.f + (this.destination.f - this.f) * pos - }) - - return matrix - }, - - // Left multiplies by the given matrix - multiply: function (matrix) { - return this.clone().multiplyO(matrix) - }, - - multiplyO: function (matrix) { - // Get the matrices - var l = this - var r = matrix instanceof SVG.Matrix - ? matrix - : new SVG.Matrix(matrix) - - return matrixMultiply(l, r, this) - }, - - lmultiply: function (matrix) { - return this.clone().lmultiplyO(matrix) - }, - - lmultiplyO: function (matrix) { - var r = this - var l = matrix instanceof SVG.Matrix - ? matrix - : new SVG.Matrix(matrix) - - return matrixMultiply(l, r, this) - }, - - // Inverses matrix - inverseO: function () { - // Get the current parameters out of the matrix - var a = this.a - var b = this.b - var c = this.c - var d = this.d - var e = this.e - var f = this.f - - // Invert the 2x2 matrix in the top left - var det = a * d - b * c - if (!det) throw new Error('Cannot invert ' + this) - - // Calculate the top 2x2 matrix - var na = d / det - var nb = -b / det - var nc = -c / det - var nd = a / det - - // Apply the inverted matrix to the top right - var ne = -(na * e + nc * f) - var nf = -(nb * e + nd * f) - - // Construct the inverted matrix - this.a = na - this.b = nb - this.c = nc - this.d = nd - this.e = ne - this.f = nf - - return this - }, - - inverse: function () { - return this.clone().inverseO() - }, - - // Translate matrix - translate: function (x, y) { - return this.clone().translateO(x, y) - }, - - translateO: function (x, y) { - this.e += x || 0 - this.f += y || 0 - return this - }, - - // Scale matrix - scale: function (x, y, cx, cy) { - return this.clone().scaleO(...arguments) - }, - - scaleO: function (x, y = x, cx = 0, cy = 0) { - // Support uniform scaling - if (arguments.length === 3) { - cy = cx - cx = y - y = x - } - - let {a, b, c, d, e, f} = this - - this.a = a * x - this.b = b * y - this.c = c * x - this.d = d * y - this.e = e * x - cx * x + cx - this.f = f * y - cy * y + cy - - return this - }, - - // Rotate matrix - rotate: function (r, cx, cy) { - return this.clone().rotateO(r, cx, cy) - }, - - rotateO: function (r, cx = 0, cy = 0) { - // Convert degrees to radians - r = SVG.utils.radians(r) - - let cos = Math.cos(r) - let sin = Math.sin(r) - - let {a, b, c, d, e, f} = this - - this.a = a * cos - b * sin - this.b = b * cos + a * sin - this.c = c * cos - d * sin - this.d = d * cos + c * sin - this.e = e * cos - f * sin + cy * sin - cx * cos + cx - this.f = f * cos + e * sin - cx * sin - cy * cos + cy - - return this - }, - - // Flip matrix on x or y, at a given offset - flip: function (axis, around) { - return this.clone().flipO(axis, around) - }, - - flipO: function (axis, around) { - return axis === 'x' ? this.scaleO(-1, 1, around, 0) - : axis === 'y' ? this.scaleO(1, -1, 0, around) - : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point - }, - - // Shear matrix - shear: function (a, cx, cy) { - return this.clone().shearO(a, cx, cy) - }, - - shearO: function (lx, cx = 0, cy = 0) { - let {a, b, c, d, e, f} = this - - this.a = a + b * lx - this.c = c + d * lx - this.e = e + f * lx - cy * lx - - return this - }, - - // Skew Matrix - skew: function (x, y, cx, cy) { - return this.clone().skewO(...arguments) - }, - - skewO: function (x, y = x, cx = 0, cy = 0) { - // support uniformal skew - if (arguments.length === 3) { - cy = cx - cx = y - y = x - } - - // Convert degrees to radians - x = SVG.utils.radians(x) - y = SVG.utils.radians(y) - - let lx = Math.tan(x) - let ly = Math.tan(y) - - let {a, b, c, d, e, f} = this - - this.a = a + b * lx - this.b = b + a * ly - this.c = c + d * lx - this.d = d + c * ly - this.e = e + f * lx - cy * lx - this.f = f + e * ly - cx * ly - - return this - }, - - // SkewX - skewX: function (x, cx, cy) { - return this.skew(x, 0, cx, cy) - }, - - skewXO: function (x, cx, cy) { - return this.skewO(x, 0, cx, cy) - }, - - // SkewY - skewY: function (y, cx, cy) { - return this.skew(0, y, cx, cy) - }, - - skewYO: function (y, cx, cy) { - return this.skewO(0, y, cx, cy) - }, - - // Transform around a center point - aroundO: function (cx, cy, matrix) { - var dx = cx || 0 - var dy = cy || 0 - return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy) - }, - - around: function (cx, cy, matrix) { - return this.clone().aroundO(cx, cy, matrix) - }, - - // Convert to native SVGMatrix - native: function () { - // create new matrix - var matrix = SVG.parser.nodes.svg.node.createSVGMatrix() - - // update with current values - for (var i = abcdef.length - 1; i >= 0; i--) { - matrix[abcdef[i]] = this[abcdef[i]] - } - - return matrix - }, - - // Check if two matrices are equal - equals: function (other) { - var comp = new SVG.Matrix(other) - return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && - closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && - closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f) - }, - - // Convert matrix to string - toString: function () { - return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')' - }, - - toArray: function () { - return [this.a, this.b, this.c, this.d, this.e, this.f] - }, - - valueOf: function () { - return { - a: this.a, - b: this.b, - c: this.c, - d: this.d, - e: this.e, - f: this.f - } + this.a = a * cos - b * sin + this.b = b * cos + a * sin + this.c = c * cos - d * sin + this.d = d * cos + c * sin + this.e = e * cos - f * sin + cy * sin - cx * cos + cx + this.f = f * cos + e * sin - cx * sin - cy * cos + cy + + return this + } + + // Flip matrix on x or y, at a given offset + flip (axis, around) { + return this.clone().flipO(axis, around) + } + + flipO (axis, around) { + return axis === 'x' ? this.scaleO(-1, 1, around, 0) + : axis === 'y' ? this.scaleO(1, -1, 0, around) + : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point + } + + // Shear matrix + shear (a, cx, cy) { + return this.clone().shearO(a, cx, cy) + } + + shearO (lx, cx = 0, cy = 0) { + let {a, b, c, d, e, f} = this + + this.a = a + b * lx + this.c = c + d * lx + this.e = e + f * lx - cy * lx + + return this + } + + // Skew Matrix + skew (x, y, cx, cy) { + return this.clone().skewO(...arguments) + } + + skewO (x, y = x, cx = 0, cy = 0) { + // support uniformal skew + if (arguments.length === 3) { + cy = cx + cx = y + y = x + } + + // Convert degrees to radians + x = radians(x) + y = radians(y) + + let lx = Math.tan(x) + let ly = Math.tan(y) + + let {a, b, c, d, e, f} = this + + this.a = a + b * lx + this.b = b + a * ly + this.c = c + d * lx + this.d = d + c * ly + this.e = e + f * lx - cy * lx + this.f = f + e * ly - cx * ly + + return this + } + + // SkewX + skewX (x, cx, cy) { + return this.skew(x, 0, cx, cy) + } + + skewXO (x, cx, cy) { + return this.skewO(x, 0, cx, cy) + } + + // SkewY + skewY (y, cx, cy) { + return this.skew(0, y, cx, cy) + } + + skewYO (y, cx, cy) { + return this.skewO(0, y, cx, cy) + } + + // Transform around a center point + aroundO (cx, cy, matrix) { + var dx = cx || 0 + var dy = cy || 0 + return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy) + } + + around (cx, cy, matrix) { + return this.clone().aroundO(cx, cy, matrix) + } + + // Convert to native SVGMatrix + native () { + // create new matrix + var matrix = parser.nodes.node.createSVGMatrix() + + // update with current values + for (var i = abcdef.length - 1; i >= 0; i--) { + matrix[abcdef[i]] = this[abcdef[i]] } + + return matrix + } + + // Check if two matrices are equal + equals (other) { + var comp = new Matrix(other) + return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && + closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && + closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f) + } + + // Convert matrix to string + toString () { + return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')' + } + + toArray () { + return [this.a, this.b, this.c, this.d, this.e, this.f] + } + + valueOf () { + return { + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + } + } +} + +extend(Element, { + // Get current matrix + ctm () { + return new Matrix(this.node.getCTM()) }, - // Define parent - parent: SVG.Element, - - // Add parent method - construct: { - // Get current matrix - ctm: function () { - return new SVG.Matrix(this.node.getCTM()) - }, - // Get current screen matrix - screenCTM: function () { - /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 - This is needed because FF does not return the transformation matrix - for the inner coordinate system when getScreenCTM() is called on nested svgs. - However all other Browsers do that */ - if (this instanceof SVG.Doc && !this.isRoot()) { - var rect = this.rect(1, 1) - var m = rect.node.getScreenCTM() - rect.remove() - return new SVG.Matrix(m) - } - return new SVG.Matrix(this.node.getScreenCTM()) + // Get current screen matrix + screenCTM () { + /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 + This is needed because FF does not return the transformation matrix + for the inner coordinate system when getScreenCTM() is called on nested svgs. + However all other Browsers do that */ + if (this instanceof Doc && !this.isRoot()) { + var rect = this.rect(1, 1) + var m = rect.node.getScreenCTM() + rect.remove() + return new Matrix(m) } + return new Matrix(this.node.getScreenCTM()) } }) @@ -461,12 +434,12 @@ SVG.Matrix = SVG.invent({ // ['rotate'].forEach((method) => { // let methodO = method + 'O' // extensions[method] = function (...args) { -// return new SVG.Matrix(this)[methodO](...args) +// return new Matrix(this)[methodO](...args) // } // }) // -// SVG.extend(SVG.Matrix, extensions) +// extend(Matrix, extensions) // function matrixMultiplyParams (matrix, a, b, c, d, e, f) { -// return matrixMultiply({a, b, c, d, e, f}, matrix, matrix) +// return matrixMultiply({a, b, c, d, e, f} matrix, matrix) // } diff --git a/src/Morphable.js b/src/Morphable.js index acb9e21..1cb437e 100644 --- a/src/Morphable.js +++ b/src/Morphable.js @@ -1,130 +1,127 @@ +import {extend} from './tools.js' +import {Color, SVGNumber, SVGArray, PathArray} from './classes.js' -SVG.Morphable = SVG.invent({ - create: function (stepper) { +export default class Morphable { + constructor () { // FIXME: the default stepper does not know about easing - this._stepper = stepper || new SVG.Ease('-') + this._stepper = stepper || new Ease('-') this._from = null this._to = null this._type = null this._context = null this._morphObj = null - }, + } - extend: { + from (val) { + if (val == null) { + return this._from + } - from: function (val) { - if (val == null) { - return this._from - } + this._from = this._set(val) + return this + } - this._from = this._set(val) - return this - }, + to (val) { + if (val == null) { + return this._to + } - to: function (val) { - if (val == null) { - return this._to - } + this._to = this._set(val) + return this + } - this._to = this._set(val) - return this - }, + type (type) { + // getter + if (type == null) { + return this._type + } - type: function (type) { - // getter - if (type == null) { - return this._type - } + // setter + this._type = type + return this + } - // setter - this._type = type - return this - }, - - _set: function (value) { - if (!this._type) { - var type = typeof value - - if (type === 'number') { - this.type(SVG.Number) - } else if (type === 'string') { - if (SVG.Color.isColor(value)) { - this.type(SVG.Color) - } else if (SVG.regex.delimiter.test(value)) { - this.type(SVG.regex.pathLetters.test(value) - ? SVG.PathArray - : SVG.Array - ) - } else if (SVG.regex.numberAndUnit.test(value)) { - this.type(SVG.Number) - } else { - this.type(SVG.Morphable.NonMorphable) - } - } else if (SVG.MorphableTypes.indexOf(value.constructor) > -1) { - this.type(value.constructor) - } else if (Array.isArray(value)) { - this.type(SVG.Array) - } else if (type === 'object') { - this.type(SVG.Morphable.ObjectBag) + _set (value) { + if (!this._type) { + var type = typeof value + + if (type === 'number') { + this.type(SVGNumber) + } else if (type === 'string') { + if (Color.isColor(value)) { + this.type(Color) + } else if (regex.delimiter.test(value)) { + this.type(regex.pathLetters.test(value) + ? PathArray + : SVGArray + ) + } else if (regex.numberAndUnit.test(value)) { + this.type(SVGNumber) } else { - this.type(SVG.Morphable.NonMorphable) + this.type(Morphable.NonMorphable) } + } else if (MorphableTypes.indexOf(value.constructor) > -1) { + this.type(value.constructor) + } else if (Array.isArray(value)) { + this.type(SVGArray) + } else if (type === 'object') { + this.type(Morphable.ObjectBag) + } else { + this.type(Morphable.NonMorphable) } - - var result = (new this._type(value)).toArray() - this._morphObj = this._morphObj || new this._type() - this._context = this._context || - Array.apply(null, Array(result.length)).map(Object) - return result - }, - - stepper: function (stepper) { - if (stepper == null) return this._stepper - this._stepper = stepper - return this - }, - - done: function () { - var complete = this._context - .map(this._stepper.done) - .reduce(function (last, curr) { - return last && curr - }, true) - return complete - }, - - at: function (pos) { - var _this = this - - return this._morphObj.fromArray( - this._from.map(function (i, index) { - return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context) - }) - ) } + + var result = (new this._type(value)).toArray() + this._morphObj = this._morphObj || new this._type() + this._context = this._context || + Array.apply(null, Array(result.length)).map(Object) + return result } -}) -SVG.Morphable.NonMorphable = SVG.invent({ - create: function (val) { + stepper (stepper) { + if (stepper == null) return this._stepper + this._stepper = stepper + return this + } + + done () { + var complete = this._context + .map(this._stepper.done) + .reduce(function (last, curr) { + return last && curr + }, true) + return complete + } + + at (pos) { + var _this = this + + return this._morphObj.fromArray( + this._from.map(function (i, index) { + return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context) + }) + ) + } +} + +Morphable.NonMorphable = class { + constructor (val) { val = Array.isArray(val) ? val[0] : val this.value = val - }, + } - extend: { - valueOf: function () { - return this.value - }, + valueOf () { + return this.value + } - toArray: function () { - return [this.value] - } + toArray () { + return [this.value] } -}) +} -SVG.Morphable.TransformBag = SVG.invent({ - create: function (obj) { +Morphable.TransformBag = class { + constructor (obj) { if (Array.isArray(obj)) { obj = { scaleX: obj[0], @@ -138,28 +135,26 @@ SVG.Morphable.TransformBag = SVG.invent({ } } - Object.assign(this, SVG.Morphable.TransformBag.defaults, obj) - }, + Object.assign(this, Morphable.TransformBag.defaults, obj) + } - extend: { - toArray: function () { - var v = this - - return [ - v.scaleX, - v.scaleY, - v.shear, - v.rotate, - v.translateX, - v.translateY, - v.originX, - v.originY - ] - } + toArray () { + var v = this + + return [ + v.scaleX, + v.scaleY, + v.shear, + v.rotate, + v.translateX, + v.translateY, + v.originX, + v.originY + ] } -}) +} -SVG.Morphable.TransformBag.defaults = { +Morphable.TransformBag.defaults = { scaleX: 1, scaleY: 1, shear: 0, @@ -170,8 +165,8 @@ SVG.Morphable.TransformBag.defaults = { originY: 0 } -SVG.Morphable.ObjectBag = SVG.invent({ - create: function (objOrArr) { +Morphable.ObjectBag = class { + constructor (objOrArr) { this.values = [] if (Array.isArray(objOrArr)) { @@ -184,47 +179,45 @@ SVG.Morphable.ObjectBag = SVG.invent({ }) this.values = entries.reduce((last, curr) => last.concat(curr), []) - }, + } - extend: { - valueOf: function () { - var obj = {} - var arr = this.values + valueOf () { + var obj = {} + var arr = this.values - for (var i = 0, len = arr.length; i < len; i += 2) { - obj[arr[i]] = arr[i + 1] - } + for (var i = 0, len = arr.length; i < len; i += 2) { + obj[arr[i]] = arr[i + 1] + } - return obj - }, + return obj + } - toArray: function () { - return this.values - } + toArray () { + return this.values } -}) +} -SVG.MorphableTypes = [ - SVG.Number, - SVG.Color, - SVG.Box, - SVG.Matrix, - SVG.Array, - SVG.PointArray, - SVG.PathArray, - SVG.Morphable.NonMorphable, - SVG.Morphable.TransformBag, - SVG.Morphable.ObjectBag +let morphableTypes = [ + SVGNumber, + Color, + Box, + Matrix, + SVGArray, + PointArray, + PathArray, + Morphable.NonMorphable, + Morphable.TransformBag, + Morphable.ObjectBag ] -SVG.extend(SVG.MorphableTypes, { - to: function (val, args) { - return new SVG.Morphable() +extend(morphableTypes, { + to (val, args) { + return new Morphable() .type(this.constructor) .from(this.valueOf()) .to(val, args) }, - fromArray: function (arr) { + fromArray (arr) { this.constructor(arr) return this } diff --git a/src/Parent.js b/src/Parent.js index 6bdad58..ce22f80 100644 --- a/src/Parent.js +++ b/src/Parent.js @@ -1,92 +1,93 @@ -/* global createElement */ - -SVG.Parent = SVG.invent({ - // Initialize node - create: function (node) { - SVG.Element.call(this, node) - }, - - // Inherit from - inherit: SVG.Element, - - // Add class methods - extend: { - // Returns all child elements - children: function () { - return SVG.utils.map(this.node.children, function (node) { - return SVG.adopt(node) - }) - }, - // Add given element at a position - add: function (element, i) { - element = createElement(element) - - if (element.node !== this.node.children[i]) { - this.node.insertBefore(element.node, this.node.children[i] || null) - } +import {makeInstance} from './helpers.js' +import Element from './Element.js' +import {adopt} from './tools.js' +import {map} from './utils.js' + +export default class Parent extends Element { + // Returns all child elements + children () { + return map(this.node.children, function (node) { + return adopt(node) + }) + } + + // Add given element at a position + add (element, i) { + element = makeInstance(element) + + if (element.node !== this.node.children[i]) { + this.node.insertBefore(element.node, this.node.children[i] || null) + } + + return this + } - return this - }, - // Basically does the same as `add()` but returns the added element instead - put: function (element, i) { - this.add(element, i) - return element.instance || element - }, - // Checks if the given element is a child - has: function (element) { - return this.index(element) >= 0 - }, - // Gets index of given element - index: function (element) { - return [].slice.call(this.node.children).indexOf(element.node) - }, - // Get a element at the given index - get: function (i) { - return SVG.adopt(this.node.children[i]) - }, - // Get first child - first: function () { - return this.get(0) - }, - // Get the last child - last: function () { - return this.get(this.node.children.length - 1) - }, - // Iterates over all children and invokes a given block - each: function (block, deep) { - var children = this.children() - var i, il - - for (i = 0, il = children.length; i < il; i++) { - if (children[i] instanceof SVG.Element) { - block.apply(children[i], [i, children]) - } - - if (deep && (children[i] instanceof SVG.Parent)) { - children[i].each(block, deep) - } + // Basically does the same as `add()` but returns the added element instead + put (element, i) { + this.add(element, i) + return element.instance || element + } + + // Checks if the given element is a child + has (element) { + return this.index(element) >= 0 + } + + // Gets index of given element + index (element) { + return [].slice.call(this.node.children).indexOf(element.node) + } + + // Get a element at the given index + get (i) { + return adopt(this.node.children[i]) + } + + // Get first child + first () { + return this.get(0) + } + + // Get the last child + last () { + return this.get(this.node.children.length - 1) + } + + // Iterates over all children and invokes a given block + each (block, deep) { + var children = this.children() + var i, il + + for (i = 0, il = children.length; i < il; i++) { + if (children[i] instanceof Element) { + block.apply(children[i], [i, children]) } - return this - }, - // Remove a given child - removeElement: function (element) { - this.node.removeChild(element.node) - - return this - }, - // Remove all elements in this container - clear: function () { - // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) + if (deep && (children[i] instanceof Parent)) { + children[i].each(block, deep) } + } - // remove defs reference - delete this._defs + return this + } - return this - } + // Remove a given child + removeElement (element) { + this.node.removeChild(element.node) + + return this } -}) + // Remove all elements in this container + clear () { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild) + } + + // remove defs reference + delete this._defs + + return this + } +} diff --git a/src/Path.js b/src/Path.js index db3929b..7226977 100644 --- a/src/Path.js +++ b/src/Path.js @@ -1,63 +1,71 @@ -/* global proportionalSize */ +import {proportionalSize} from './helpers.js' +import {nodeOrNew} from './tools.js' +import Shape from './Shape.js' +import PathArray from './PathArray.js' -SVG.Path = SVG.invent({ +export default class Path extends Shape { // Initialize node - create: 'path', - - // Inherit from - inherit: SVG.Shape, - - // Add class methods - extend: { - // Define morphable array - MorphArray: SVG.PathArray, - // Get array - array: function () { - return this._array || (this._array = new SVG.PathArray(this.attr('d'))) - }, - // Plot new path - plot: function (d) { - return (d == null) ? this.array() - : this.clear().attr('d', typeof d === 'string' ? d : (this._array = new SVG.PathArray(d))) - }, - // Clear array cache - clear: function () { - delete this._array - return this - }, - // Move by left top corner - move: function (x, y) { - return this.attr('d', this.array().move(x, y)) - }, - // Move by left top corner over x-axis - x: function (x) { - return x == null ? this.bbox().x : this.move(x, this.bbox().y) - }, - // Move by left top corner over y-axis - y: function (y) { - return y == null ? this.bbox().y : this.move(this.bbox().x, y) - }, - // Set element size to given width and height - size: function (width, height) { - var p = proportionalSize(this, width, height) - return this.attr('d', this.array().size(p.width, p.height)) - }, - // Set width of element - width: function (width) { - return width == null ? this.bbox().width : this.size(width, this.bbox().height) - }, - // Set height of element - height: function (height) { - return height == null ? this.bbox().height : this.size(this.bbox().width, height) - } - }, + constructor (node) { + super(nodeOrNew('path', node)) + } + + // Get array + array () { + 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))) + } + + // 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 by left top corner over x-axis + 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) + } + + // 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)) + } + + // Set width of element + 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) + } +} + +// Define morphable array +Path.prototype.MorphArray = PathArray // Add parent method - construct: { - // Create a wrapped path element - path: function (d) { - // make sure plot is called as a setter - return this.put(new SVG.Path()).plot(d || new SVG.PathArray()) - } +addFactory(Container, { + // Create a wrapped path element + path (d) { + // make sure plot is called as a setter + return this.put(new Path()).plot(d || new PathArray()) } }) diff --git a/src/PathArray.js b/src/PathArray.js index 4432df3..24d8665 100644 --- a/src/PathArray.js +++ b/src/PathArray.js @@ -1,6 +1,9 @@ -/* globals arrayToString, pathRegReplace */ +import {arrayToString, pathRegReplace} from './helpers.js' +import parser from './parser.js' +import {numbersWithDots, pathLetters, hyphen, delimiter, isPathLetter} from './regex.js' +import Point from './Point.js' -var pathHandlers = { +let pathHandlers = { M: function (c, p, p0) { p.x = p0.x = c[0] p.y = p0.y = c[1] @@ -52,7 +55,7 @@ var pathHandlers = { } } -var mlhvqtcsaz = 'mlhvqtcsaz'.split('') +let mlhvqtcsaz = 'mlhvqtcsaz'.split('') for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { pathHandlers[mlhvqtcsaz[i]] = (function (i) { @@ -73,27 +76,24 @@ for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { })(mlhvqtcsaz[i].toUpperCase()) } -// Path points array -SVG.PathArray = function (array, fallback) { - SVG.Array.call(this, array, fallback || [['M', 0, 0]]) -} - -// Inherit from SVG.Array -SVG.PathArray.prototype = new SVG.Array() -SVG.PathArray.prototype.constructor = SVG.PathArray +export default class PathArray extends SVGArray { + constructor (array, fallback = [['M', 0, 0]]) { + super(array, fallback) + } -SVG.extend(SVG.PathArray, { // Convert array to string - toString: function () { + toString () { return arrayToString(this.value) - }, - toArray: function () { + } + + toArray () { return this.value.reduce(function (prev, curr) { return [].concat.call(prev, curr) }, []) - }, + } + // Move path string - move: function (x, y) { + move (x, y) { // get bounding box of current situation var box = this.bbox() @@ -131,9 +131,10 @@ SVG.extend(SVG.PathArray, { } return this - }, + } + // Resize path string - size: function (width, height) { + size (width, height) { // get bounding box of current situation var box = this.bbox() var i, l @@ -171,12 +172,13 @@ SVG.extend(SVG.PathArray, { } return this - }, + } + // Test if the passed path array use the same path data commands as this path array - equalCommands: function (pathArray) { + equalCommands (pathArray) { var i, il, equalCommands - pathArray = new SVG.PathArray(pathArray) + pathArray = new PathArray(pathArray) equalCommands = this.value.length === pathArray.value.length for (i = 0, il = this.value.length; equalCommands && i < il; i++) { @@ -184,10 +186,11 @@ SVG.extend(SVG.PathArray, { } return equalCommands - }, + } + // Make path array morphable - morph: function (pathArray) { - pathArray = new SVG.PathArray(pathArray) + morph (pathArray) { + pathArray = new PathArray(pathArray) if (this.equalCommands(pathArray)) { this.destination = pathArray @@ -196,16 +199,17 @@ SVG.extend(SVG.PathArray, { } return this - }, + } + // Get morphed path array at given position - at: function (pos) { + at (pos) { // make sure a destination is defined if (!this.destination) return this var sourceArray = this.value var destinationArray = this.destination.value var array = [] - var pathArray = new SVG.PathArray() + var pathArray = new PathArray() var i, il, j, jl // Animate has specified in the SVG spec @@ -229,11 +233,12 @@ SVG.extend(SVG.PathArray, { // Directly modify the value of a path array, this is done this way for performance pathArray.value = array return pathArray - }, + } + // Absolutize and parse path to array - parse: function (array) { + parse (array) { // if it's already a patharray, no need to parse it - if (array instanceof SVG.PathArray) return array.valueOf() + if (array instanceof PathArray) return array.valueOf() // prepare for parsing var s @@ -241,11 +246,11 @@ SVG.extend(SVG.PathArray, { if (typeof array === 'string') { array = array - .replace(SVG.regex.numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 - .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers - .replace(SVG.regex.hyphen, '$1 -') // add space before hyphen + .replace(regex.numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 + .replace(regex.pathLetters, ' $& ') // put some room between letters and numbers + .replace(regex.hyphen, '$1 -') // add space before hyphen .trim() // trim - .split(SVG.regex.delimiter) // split into array + .split(regex.delimiter) // split into array } else { array = array.reduce(function (prev, curr) { return [].concat.call(prev, curr) @@ -254,14 +259,14 @@ SVG.extend(SVG.PathArray, { // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] var result = [] - var p = new SVG.Point() - var p0 = new SVG.Point() + var p = new Point() + var p0 = new Point() var index = 0 var len = array.length do { // Test if we have a path letter - if (SVG.regex.isPathLetter.test(array[index])) { + if (regex.isPathLetter.test(array[index])) { s = array[index] ++index // If last letter was a move command and we got no new, it defaults to [L]ine @@ -279,11 +284,11 @@ SVG.extend(SVG.PathArray, { } while (len > index) return result - }, - // Get bounding box of path - bbox: function () { - SVG.parser().path.setAttribute('d', this.toString()) - return SVG.parser.nodes.path.getBBox() } -}) + // Get bounding box of path + bbox () { + parser().path.setAttribute('d', this.toString()) + return parser.nodes.path.getBBox() + } +} diff --git a/src/Pattern.js b/src/Pattern.js index d4c4116..00f9de5 100644 --- a/src/Pattern.js +++ b/src/Pattern.js @@ -1,53 +1,51 @@ -SVG.Pattern = SVG.invent({ - // Initialize node - create: 'pattern', - - // Inherit from - inherit: SVG.Container, - - // Add class methods - extend: { - // Return the fill id - url: function () { - return 'url(#' + this.id() + ')' - }, - // Update pattern by rebuilding - update: function (block) { - // remove content - this.clear() +import {Container, Defs} from './classes.js' +import {nodeOrNew} from './tools.js' - // invoke passed block - if (typeof block === 'function') { - block.call(this, this) - } +export default class Pattern extends Container { + // Initialize node + constructor (node) { + super(nodeOrNew('pattern', node)) + } - return this - }, - // Alias string convertion to fill - toString: function () { - return this.url() - }, - // custom attr to handle transform - attr: function (a, b, c) { - if (a === 'transform') a = 'patternTransform' - return SVG.Container.prototype.attr.call(this, a, b, c) + // Return the fill id + url () { + return 'url(#' + this.id() + ')' + } + // Update pattern by rebuilding + update (block) { + // remove content + this.clear() + + // invoke passed block + 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) + } +} // Add parent method - construct: { - // Create pattern element in defs - pattern: function (width, height, block) { - return this.defs().pattern(width, height, block) - } +addFactory(Container, { + // Create pattern element in defs + pattern (width, height, block) { + return this.defs().pattern(width, height, block) } }) -SVG.extend(SVG.Defs, { +extend(Defs, { // Define gradient - pattern: function (width, height, block) { - return this.put(new SVG.Pattern()).update(block).attr({ + pattern (width, height, block) { + return this.put(new Pattern()).update(block).attr({ x: 0, y: 0, width: width, @@ -55,5 +53,4 @@ SVG.extend(SVG.Defs, { patternUnits: 'userSpaceOnUse' }) } - }) diff --git a/src/Point.js b/src/Point.js index 6c64ed6..ff18473 100644 --- a/src/Point.js +++ b/src/Point.js @@ -1,8 +1,10 @@ +import parser from './parser.js' +import Element from './Element.js' -SVG.Point = SVG.invent({ +export default class Point { // Initialize - create: function (x, y, base) { - var source + constructor (x, y, base) { + let source base = base || {x: 0, y: 0} // ensure source as object @@ -13,62 +15,38 @@ SVG.Point = SVG.invent({ // merge source this.x = source.x == null ? base.x : source.x this.y = source.y == null ? base.y : source.y - }, - - // Add methods - extend: { - // Clone point - clone: function () { - return new SVG.Point(this) - }, - - // Morph one point into another - morph: function (x, y) { - // store new destination - this.destination = new SVG.Point(x, y) - return this - }, - - // Get morphed point at a given position - at: function (pos) { - // make sure a destination is defined - if (!this.destination) return this + } - // calculate morphed matrix at a given position - var point = new SVG.Point({ - x: this.x + (this.destination.x - this.x) * pos, - y: this.y + (this.destination.y - this.y) * pos - }) - return point - }, + // Clone point + clone () { + return new Point(this) + } - // Convert to native SVGPoint - native: function () { - // create new point - var point = SVG.parser.nodes.svg.node.createSVGPoint() + // Convert to native SVGPoint + native () { + // create new point + var point = parser().svg.createSVGPoint() - // update with current values - point.x = this.x - point.y = this.y - return point - }, + // update with current values + point.x = this.x + point.y = this.y + return point + } - // transform point with matrix - transform: function (m) { - // Perform the matrix multiplication - var x = m.a * this.x + m.c * this.y + m.e - var y = m.b * this.x + m.d * this.y + m.f + // transform point with matrix + transform (m) { + // Perform the matrix multiplication + var x = m.a * this.x + m.c * this.y + m.e + var y = m.b * this.x + m.d * this.y + m.f - // Return the required point - return new SVG.Point(x, y) - } + // Return the required point + return new Point(x, y) } -}) - -SVG.extend(SVG.Element, { +} +extend(Element, { // Get point point: function (x, y) { - return new SVG.Point(x, y).transform(this.screenCTM().inverse()) + return new Point(x, y).transform(this.screenCTM().inverse()) } }) diff --git a/src/PointArray.js b/src/PointArray.js index aa5f84a..cadff80 100644 --- a/src/PointArray.js +++ b/src/PointArray.js @@ -1,42 +1,39 @@ +import SVGArray from './SVGArray.js' +import {delimiter} from './regex.js' -// Poly points array -SVG.PointArray = function (array, fallback) { - SVG.Array.call(this, array, fallback || [[0, 0]]) -} - -// Inherit from SVG.Array -SVG.PointArray.prototype = new SVG.Array() -SVG.PointArray.prototype.constructor = SVG.PointArray +export default class PointArray extends SVGArray { + constructor (array, fallback = [[0, 0]]) { + super(array, fallback) + } -SVG.extend(SVG.PointArray, { // Convert array to string - toString: function () { + toString () { // convert to a poly point string for (var i = 0, il = this.value.length, array = []; i < il; i++) { array.push(this.value[i].join(',')) } return array.join(' ') - }, + } - toArray: function () { + toArray () { return this.value.reduce(function (prev, curr) { return [].concat.call(prev, curr) }, []) - }, + } // Convert array to line object - toLine: function () { + toLine () { return { x1: this.value[0][0], y1: this.value[0][1], x2: this.value[1][0], y2: this.value[1][1] } - }, + } // Get morphed array at given position - at: function (pos) { + at (pos) { // make sure a destination is defined if (!this.destination) return this @@ -48,11 +45,11 @@ SVG.extend(SVG.PointArray, { ]) } - return new SVG.PointArray(array) - }, + return new PointArray(array) + } // Parse point string and flat array - parse: function (array) { + parse (array) { var points = [] array = array.valueOf() @@ -65,7 +62,7 @@ SVG.extend(SVG.PointArray, { } } else { // Else, it is considered as a string // parse points - array = array.trim().split(SVG.regex.delimiter).map(parseFloat) + array = array.trim().split(delimiter).map(parseFloat) } // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints @@ -78,10 +75,10 @@ SVG.extend(SVG.PointArray, { } return points - }, + } // Move point string - move: function (x, y) { + move (x, y) { var box = this.bbox() // get relative offset @@ -96,9 +93,10 @@ SVG.extend(SVG.PointArray, { } return this - }, + } + // Resize poly string - size: function (width, height) { + size (width, height) { var i var box = this.bbox() @@ -109,10 +107,10 @@ SVG.extend(SVG.PointArray, { } return this - }, + } // Get bounding box of points - bbox: function () { + bbox () { var maxX = -Infinity var maxY = -Infinity var minX = Infinity @@ -125,4 +123,4 @@ SVG.extend(SVG.PointArray, { }) return {x: minX, y: minY, width: maxX - minX, height: maxY - minY} } -}) +} diff --git a/src/Polygon.js b/src/Polygon.js index 9625776..112d33b 100644 --- a/src/Polygon.js +++ b/src/Polygon.js @@ -1,67 +1,55 @@ -/* global proportionalSize */ +import {proportionalSize} from './helpers.js' +import Shape from './Shape.js' +import {nodeOrNew} from './tools.js' +import * as pointed from './pointed.js' +import PointArray from './PointArray.js' -SVG.Polyline = SVG.invent({ +export default class Polygon extends Shape { // Initialize node - create: 'polyline', - - // Inherit from - inherit: SVG.Shape, - - // Add parent method - construct: { - // Create a wrapped polyline element - polyline: function (p) { - // make sure plot is called as a setter - return this.put(new SVG.Polyline()).plot(p || new SVG.PointArray()) - } + constructor (node) { + super(nodeOrNew('polygon', node)) } -}) - -SVG.Polygon = SVG.invent({ - // Initialize node - create: 'polygon', - - // Inherit from - inherit: SVG.Shape, +} - // Add parent method - construct: { - // Create a wrapped polygon element - polygon: function (p) { - // make sure plot is called as a setter - return this.put(new SVG.Polygon()).plot(p || new SVG.PointArray()) - } +addFactory(Parent, { + // Create a wrapped polygon element + polygon (p) { + // make sure plot is called as a setter + return this.put(new Polygon()).plot(p || new PointArray()) } }) -// Add polygon-specific functions -SVG.extend([SVG.Polyline, SVG.Polygon], { - // Get array - array: function () { - return this._array || (this._array = new SVG.PointArray(this.attr('points'))) - }, - // Plot new path - plot: function (p) { - return (p == null) ? this.array() - : this.clear().attr('points', typeof p === 'string' ? p - : (this._array = new SVG.PointArray(p))) - }, - - // Clear array cache - clear: function () { - delete this._array - return this - }, - - // Move by left top corner - move: function (x, y) { - return this.attr('points', this.array().move(x, y)) - }, - - // Set element size to given width and height - size: function (width, height) { - var p = proportionalSize(this, width, height) - return this.attr('points', this.array().size(p.width, p.height)) - } -}) +// // Add polygon-specific functions +// extend([Polyline, Polygon], { +// // Get array +// array: function () { +// return this._array || (this._array = new PointArray(this.attr('points'))) +// }, +// +// // Plot new path +// plot: function (p) { +// return (p == null) ? this.array() +// : this.clear().attr('points', typeof p === 'string' ? p +// : (this._array = new PointArray(p))) +// }, +// +// // Clear array cache +// clear: function () { +// delete this._array +// return this +// }, +// +// // Move by left top corner +// move: function (x, y) { +// return this.attr('points', this.array().move(x, y)) +// }, +// +// // Set element size to given width and height +// size: function (width, height) { +// let p = proportionalSize(this, width, height) +// return this.attr('points', this.array().size(p.width, p.height)) +// } +// }) +// +// extend([Polyline, Polygon], pointed) diff --git a/src/Polyline.js b/src/Polyline.js new file mode 100644 index 0000000..9c28438 --- /dev/null +++ b/src/Polyline.js @@ -0,0 +1,19 @@ +import Shape from './Shape.js' +import {nodeOrNew} from './tools.js' +import PointArray from './PointArray.js' + +export default class Polyline extends Shape { + // Initialize node + constructor (node) { + super(nodeOrNew('polyline', node)) + } +} + +// Add parent method +addFactory (Parent, { + // Create a wrapped polyline element + polyline (p) { + // make sure plot is called as a setter + return this.put(new Polyline()).plot(p || new PointArray()) + } +}) diff --git a/src/Queue.js b/src/Queue.js index 621c887..14b92b4 100644 --- a/src/Queue.js +++ b/src/Queue.js @@ -1,61 +1,59 @@ -SVG.Queue = SVG.invent({ - create: function () { +export default class Queue { + constructor () { this._first = null this._last = null - }, - - extend: { - push: function (value) { - // An item stores an id and the provided value - var item = value.next ? value : { value: value, next: null, prev: null } - - // Deal with the queue being empty or populated - if (this._last) { - item.prev = this._last - this._last.next = item - this._last = item - } else { - this._last = item - this._first = item - } - - // Update the length and return the current item - return item - }, - - shift: function () { - // Check if we have a value - var remove = this._first - if (!remove) return null - - // If we do, remove it and relink things - this._first = remove.next - if (this._first) this._first.prev = null - this._last = this._first ? this._last : null - return remove.value - }, - - // Shows us the first item in the list - first: function () { - return this._first && this._first.value - }, - - // Shows us the last item in the list - last: function () { - return this._last && this._last.value - }, - - // Removes the item that was returned from the push - remove: function (item) { - // Relink the previous item - if (item.prev) item.prev.next = item.next - if (item.next) item.next.prev = item.prev - if (item === this._last) this._last = item.prev - if (item === this._first) this._first = item.next - - // Invalidate item - item.prev = null - item.next = null + } + + push (value) { + // An item stores an id and the provided value + var item = value.next ? value : { value: value, next: null, prev: null } + + // Deal with the queue being empty or populated + if (this._last) { + item.prev = this._last + this._last.next = item + this._last = item + } else { + this._last = item + this._first = item } + + // Update the length and return the current item + return item + } + + shift () { + // Check if we have a value + var remove = this._first + if (!remove) return null + + // If we do, remove it and relink things + this._first = remove.next + if (this._first) this._first.prev = null + this._last = this._first ? this._last : null + return remove.value + } + + // Shows us the first item in the list + first () { + return this._first && this._first.value + } + + // Shows us the last item in the list + last () { + return this._last && this._last.value + } + + // Removes the item that was returned from the push + remove (item) { + // Relink the previous item + if (item.prev) item.prev.next = item.next + if (item.next) item.next.prev = item.prev + if (item === this._last) this._last = item.prev + if (item === this._first) this._first = item.next + + // Invalidate item + item.prev = null + item.next = null } -}) +} diff --git a/src/Rect.js b/src/Rect.js index 35a3678..825adeb 100644 --- a/src/Rect.js +++ b/src/Rect.js @@ -1,16 +1,16 @@ +import Shape from './Shape.js' +import {nodeOrNew} from './tools.js' -SVG.Rect = SVG.invent({ +export default class Rect extends Shape { // Initialize node - create: 'rect', - - // Inherit from - inherit: SVG.Shape, + constructor (node) { + super(nodeOrNew('rect', node)) + } +} - // Add parent method - construct: { - // Create a rect element - rect: function (width, height) { - return this.put(new SVG.Rect()).size(width, height) - } +addFactory(Parent, { + // Create a rect element + rect (width, height) { + return this.put(new Rect()).size(width, height) } }) diff --git a/src/Runner.js b/src/Runner.js index 97e04e2..c29c72c 100644 --- a/src/Runner.js +++ b/src/Runner.js @@ -1,27 +1,33 @@ -/* global isMatrixLike getOrigin */ - -SVG.easing = { - '-': function (pos) { return pos }, - '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, - '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, - '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } -} - -SVG.Runner = SVG.invent({ - parent: SVG.Element, - - create: function (options) { +import {isMatrixLike, getOrigin} from './helpers.js' +import Matrix from './Matrix.js' +import Morphable from './Morphable.js' +import SVGNumber from './SVGNumber.js' +import Element from './Element.js' +import Timeline from './Timeline.js' +import {Controller, Ease, Stepper} from './Controller.js' +import {noop, timeline} from './defaults.js' + +// FIXME: What is this doing here? +// easing = { +// '-': function (pos) { return pos }, +// '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, +// '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, +// '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } +// } + +export default class Runner extends EventTarget { + constructor (options) { // Store a unique id on the runner, so that we can identify it later - this.id = SVG.Runner.id++ + this.id = Runner.id++ // Ensure a default value options = options == null - ? SVG.defaults.timeline.duration + ? timeline.duration : options // Ensure that we get a controller options = typeof options === 'function' - ? new SVG.Controller(options) + ? new Controller(options) : options // Declare all of the variables @@ -32,8 +38,8 @@ SVG.Runner = SVG.invent({ // Work out the stepper and the duration this._duration = typeof options === 'number' && options - this._isDeclarative = options instanceof SVG.Controller - this._stepper = this._isDeclarative ? options : new SVG.Ease() + this._isDeclarative = options instanceof Controller + this._stepper = this._isDeclarative ? options : new Ease() // We copy the current values from the timeline because they can change this._history = {} @@ -44,7 +50,7 @@ SVG.Runner = SVG.invent({ this._last = 0 // Save transforms applied to this runner - this.transforms = new SVG.Matrix() + this.transforms = new Matrix() this.transformId = 1 // Looping variables @@ -54,419 +60,415 @@ SVG.Runner = SVG.invent({ this._swing = false this._wait = 0 this._times = 1 - }, + } - construct: { + /* + Runner Definitions + ================== + These methods help us define the runtime behaviour of the Runner or they + help us make new runners from the current runner + */ + + element (element) { + if (element == null) return this._element + this._element = element + element._prepareRunner() + return this + } - animate: function (duration, delay, when) { - var o = SVG.Runner.sanitise(duration, delay, when) - var timeline = this.timeline() - return new SVG.Runner(o.duration) - .loop(o) - .element(this) - .timeline(timeline) - .schedule(delay, when) - }, - - delay: function (by, when) { - return this.animate(0, by, when) - } - }, + timeline (timeline) { + // check explicitly for undefined so we can set the timeline to null + if (typeof timeline === 'undefined') return this._timeline + this._timeline = timeline + return this + } - extend: { + animate (duration, delay, when) { + var o = Runner.sanitise(duration, delay, when) + var runner = new Runner(o.duration) + if (this._timeline) runner.timeline(this._timeline) + if (this._element) runner.element(this._element) + return runner.loop(o).schedule(delay, when) + } - /* - Runner Definitions - ================== - These methods help us define the runtime behaviour of the Runner or they - help us make new runners from the current runner - */ + schedule (timeline, delay, when) { + // The user doesn't need to pass a timeline if we already have one + if (!(timeline instanceof Timeline)) { + when = delay + delay = timeline + timeline = this.timeline() + } - element: function (element) { - if (element == null) return this._element - this._element = element - element._prepareRunner() - return this - }, + // If there is no timeline, yell at the user... + if (!timeline) { + throw Error('Runner cannot be scheduled without timeline') + } - timeline: function (timeline) { - // check explicitly for undefined so we can set the timeline to null - if (typeof timeline === 'undefined') return this._timeline - this._timeline = timeline - return this - }, - - animate: function (duration, delay, when) { - var o = SVG.Runner.sanitise(duration, delay, when) - var runner = new SVG.Runner(o.duration) - if (this._timeline) runner.timeline(this._timeline) - if (this._element) runner.element(this._element) - return runner.loop(o).schedule(delay, when) - }, - - schedule: function (timeline, delay, when) { - // The user doesn't need to pass a timeline if we already have one - if (!(timeline instanceof SVG.Timeline)) { - when = delay - delay = timeline - timeline = this.timeline() - } + // Schedule the runner on the timeline provided + timeline.schedule(this, delay, when) + return this + } - // If there is no timeline, yell at the user... - if (!timeline) { - throw Error('Runner cannot be scheduled without timeline') - } + unschedule () { + var timeline = this.timeline() + timeline && timeline.unschedule(this) + return this + } - // Schedule the runner on the timeline provided - timeline.schedule(this, delay, when) - return this - }, + loop (times, swing, wait) { + // Deal with the user passing in an object + if (typeof times === 'object') { + swing = times.swing + wait = times.wait + times = times.times + } - unschedule: function () { - var timeline = this.timeline() - timeline && timeline.unschedule(this) - return this - }, - - loop: function (times, swing, wait) { - // Deal with the user passing in an object - if (typeof times === 'object') { - swing = times.swing - wait = times.wait - times = times.times - } + // Sanitise the values and store them + this._times = times || Infinity + this._swing = swing || false + this._wait = wait || 0 + return this + } - // Sanitise the values and store them - this._times = times || Infinity - this._swing = swing || false - this._wait = wait || 0 - return this - }, + delay (delay) { + return this.animate(0, delay) + } - delay: function (delay) { - return this.animate(0, delay) - }, + /* + Basic Functionality + =================== + These methods allow us to attach basic functions to the runner directly + */ + + queue (initFn, runFn, isTransform) { + this._queue.push({ + initialiser: initFn || noop, + runner: runFn || noop, + isTransform: isTransform, + initialised: false, + finished: false + }) + var timeline = this.timeline() + timeline && this.timeline()._continue() + return this + } - /* - Basic Functionality - =================== - These methods allow us to attach basic functions to the runner directly - */ + during (fn) { + return this.queue(null, fn) + } - queue: function (initFn, runFn, isTransform) { - this._queue.push({ - initialiser: initFn || SVG.void, - runner: runFn || SVG.void, - isTransform: isTransform, - initialised: false, - finished: false - }) - var timeline = this.timeline() - timeline && this.timeline()._continue() - return this - }, + after (fn) { + return this.on('finish', fn) + } - during: function (fn) { - return this.queue(null, fn) - }, + /* + Runner animation methods + ======================== + Control how the animation plays + */ - after (fn) { - return this.on('finish', fn) - }, + time (time) { + if (time == null) { + return this._time + } + let dt = time - this._time + this.step(dt) + return this + } - /* - Runner animation methods - ======================== - Control how the animation plays - */ + duration () { + return this._times * (this._wait + this._duration) - this._wait + } - time: function (time) { - if (time == null) { - return this._time - } - let dt = time - this._time - this.step(dt) - return this - }, - - duration: function () { - return this._times * (this._wait + this._duration) - this._wait - }, - - loops: function (p) { - var loopDuration = this._duration + this._wait - if (p == null) { - var loopsDone = Math.floor(this._time / loopDuration) - var relativeTime = (this._time - loopsDone * loopDuration) - var position = relativeTime / this._duration - return Math.min(loopsDone + position, this._times) - } - var whole = Math.floor(p) - var partial = p % 1 - var time = loopDuration * whole + this._duration * partial - return this.time(time) - }, - - position: function (p) { - // Get all of the variables we need - var x = this._time - var d = this._duration - var w = this._wait - var t = this._times - var s = this._swing - var r = this._reverse - var position - - if (p == null) { - /* - This function converts a time to a position in the range [0, 1] - The full explanation can be found in this desmos demonstration - https://www.desmos.com/calculator/u4fbavgche - The logic is slightly simplified here because we can use booleans - */ - - // Figure out the value without thinking about the start or end time - const f = function (x) { - var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)) - var backwards = (swinging && !r) || (!swinging && r) - var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards - var clipped = Math.max(Math.min(uncliped, 1), 0) - return clipped - } + loops (p) { + var loopDuration = this._duration + this._wait + if (p == null) { + var loopsDone = Math.floor(this._time / loopDuration) + var relativeTime = (this._time - loopsDone * loopDuration) + var position = relativeTime / this._duration + return Math.min(loopsDone + position, this._times) + } + var whole = Math.floor(p) + var partial = p % 1 + var time = loopDuration * whole + this._duration * partial + return this.time(time) + } - // Figure out the value by incorporating the start time - var endTime = t * (w + d) - w - position = x <= 0 ? Math.round(f(1e-5)) - : x < endTime ? f(x) - : Math.round(f(endTime - 1e-5)) - return position + position (p) { + // Get all of the variables we need + var x = this._time + var d = this._duration + var w = this._wait + var t = this._times + var s = this._swing + var r = this._reverse + var position + + if (p == null) { + /* + This function converts a time to a position in the range [0, 1] + The full explanation can be found in this desmos demonstration + https://www.desmos.com/calculator/u4fbavgche + The logic is slightly simplified here because we can use booleans + */ + + // Figure out the value without thinking about the start or end time + const f = function (x) { + var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)) + var backwards = (swinging && !r) || (!swinging && r) + var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards + var clipped = Math.max(Math.min(uncliped, 1), 0) + return clipped } - // Work out the loops done and add the position to the loops done - var loopsDone = Math.floor(this.loops()) - var swingForward = s && (loopsDone % 2 === 0) - var forwards = (swingForward && !r) || (r && swingForward) - position = loopsDone + (forwards ? p : 1 - p) - return this.loops(position) - }, - - progress: function (p) { - if (p == null) { - return Math.min(1, this._time / this.duration()) - } - return this.time(p * this.duration()) - }, - - step: function (dt) { - // If we are inactive, this stepper just gets skipped - if (!this.enabled) return this - - // Update the time and get the new position - dt = dt == null ? 16 : dt - this._time += dt - var position = this.position() - - // Figure out if we need to run the stepper in this frame - var running = this._lastPosition !== position && this._time >= 0 - this._lastPosition = position - - // Figure out if we just started - var duration = this.duration() - var justStarted = this._lastTime < 0 && this._time > 0 - var justFinished = this._lastTime < this._time && this.time > duration - this._lastTime = this._time - if (justStarted) { - // this.fire('start', this) - } + // Figure out the value by incorporating the start time + var endTime = t * (w + d) - w + position = x <= 0 ? Math.round(f(1e-5)) + : x < endTime ? f(x) + : Math.round(f(endTime - 1e-5)) + return position + } - // Work out if the runner is finished set the done flag here so animations - // know, that they are running in the last step (this is good for - // transformations which can be merged) - var declarative = this._isDeclarative - this.done = !declarative && !justFinished && this._time >= duration + // Work out the loops done and add the position to the loops done + var loopsDone = Math.floor(this.loops()) + var swingForward = s && (loopsDone % 2 === 0) + var forwards = (swingForward && !r) || (r && swingForward) + position = loopsDone + (forwards ? p : 1 - p) + return this.loops(position) + } - // Call initialise and the run function - if (running || declarative) { - this._initialise(running) + progress (p) { + if (p == null) { + return Math.min(1, this._time / this.duration()) + } + return this.time(p * this.duration()) + } - // clear the transforms on this runner so they dont get added again and again - this.transforms = new SVG.Matrix() - var converged = this._run(declarative ? dt : position) - // this.fire('step', this) - } - // correct the done flag here - // declaritive animations itself know when they converged - this.done = this.done || (converged && declarative) - // if (this.done) { - // this.fire('finish', this) - // } - return this - }, + step (dt) { + // If we are inactive, this stepper just gets skipped + if (!this.enabled) return this + + // Update the time and get the new position + dt = dt == null ? 16 : dt + this._time += dt + var position = this.position() + + // Figure out if we need to run the stepper in this frame + var running = this._lastPosition !== position && this._time >= 0 + this._lastPosition = position + + // Figure out if we just started + var duration = this.duration() + var justStarted = this._lastTime < 0 && this._time > 0 + var justFinished = this._lastTime < this._time && this.time > duration + this._lastTime = this._time + if (justStarted) { + // this.fire('start', this) + } - finish: function () { - return this.step(Infinity) - }, + // Work out if the runner is finished set the done flag here so animations + // know, that they are running in the last step (this is good for + // transformations which can be merged) + var declarative = this._isDeclarative + this.done = !declarative && !justFinished && this._time >= duration - reverse: function (reverse) { - this._reverse = reverse == null ? !this._reverse : reverse - return this - }, + // Call initialise and the run function + if (running || declarative) { + this._initialise(running) - ease: function (fn) { - this._stepper = new SVG.Ease(fn) - return this - }, + // clear the transforms on this runner so they dont get added again and again + this.transforms = new Matrix() + var converged = this._run(declarative ? dt : position) + // this.fire('step', this) + } + // correct the done flag here + // declaritive animations itself know when they converged + this.done = this.done || (converged && declarative) + // if (this.done) { + // this.fire('finish', this) + // } + return this + } - active: function (enabled) { - if (enabled == null) return this.enabled - this.enabled = enabled - return this - }, + finish () { + return this.step(Infinity) + } - /* - Private Methods - =============== - Methods that shouldn't be used externally - */ + reverse (reverse) { + this._reverse = reverse == null ? !this._reverse : reverse + return this + } - // Save a morpher to the morpher list so that we can retarget it later - _rememberMorpher: function (method, morpher) { - this._history[method] = { - morpher: morpher, - caller: this._queue[this._queue.length - 1] - } - }, - - // Try to set the target for a morpher if the morpher exists, otherwise - // do nothing and return false - _tryRetarget: function (method, target) { - if (this._history[method]) { - // if the last method wasnt even initialised, throw it away - if (!this._history[method].caller.initialised) { - let index = this._queue.indexOf(this._history[method].caller) - this._queue.splice(index, 1) - return false - } + ease (fn) { + this._stepper = new Ease(fn) + return this + } - // for the case of transformations, we use the special retarget function - // which has access to the outer scope - if (this._history[method].caller.isTransform) { - this._history[method].caller.isTransform(target) - // for everything else a simple morpher change is sufficient - } else { - this._history[method].morpher.to(target) - } + active (enabled) { + if (enabled == null) return this.enabled + this.enabled = enabled + return this + } - this._history[method].caller.finished = false - var timeline = this.timeline() - timeline && timeline._continue() - return true - } - return false - }, - - // Run each initialise function in the runner if required - _initialise: function (running) { - // If we aren't running, we shouldn't initialise when not declarative - if (!running && !this._isDeclarative) return - - // Loop through all of the initialisers - for (var i = 0, len = this._queue.length; i < len; ++i) { - // Get the current initialiser - var current = this._queue[i] - - // Determine whether we need to initialise - var needsIt = this._isDeclarative || (!current.initialised && running) - running = !current.finished - - // Call the initialiser if we need to - if (needsIt && running) { - current.initialiser.call(this) - current.initialised = true - } + /* + Private Methods + =============== + Methods that shouldn't be used externally + */ + + // Save a morpher to the morpher list so that we can retarget it later + _rememberMorpher (method, morpher) { + this._history[method] = { + morpher: morpher, + caller: this._queue[this._queue.length - 1] + } + } + + // Try to set the target for a morpher if the morpher exists, otherwise + // do nothing and return false + _tryRetarget (method, target) { + if (this._history[method]) { + // if the last method wasnt even initialised, throw it away + if (!this._history[method].caller.initialised) { + let index = this._queue.indexOf(this._history[method].caller) + this._queue.splice(index, 1) + return false } - }, - - // Run each run function for the position or dt given - _run: function (positionOrDt) { - // Run all of the _queue directly - var allfinished = true - for (var i = 0, len = this._queue.length; i < len; ++i) { - // Get the current function to run - var current = this._queue[i] - - // Run the function if its not finished, we keep track of the finished - // flag for the sake of declarative _queue - var converged = current.runner.call(this, positionOrDt) - current.finished = current.finished || (converged === true) - allfinished = allfinished && current.finished + + // for the case of transformations, we use the special retarget function + // which has access to the outer scope + if (this._history[method].caller.isTransform) { + this._history[method].caller.isTransform(target) + // for everything else a simple morpher change is sufficient + } else { + this._history[method].morpher.to(target) } - // We report when all of the constructors are finished - return allfinished - }, + this._history[method].caller.finished = false + var timeline = this.timeline() + timeline && timeline._continue() + return true + } + return false + } + + // Run each initialise function in the runner if required + _initialise (running) { + // If we aren't running, we shouldn't initialise when not declarative + if (!running && !this._isDeclarative) return - addTransform: function (transform, index) { - this.transforms.lmultiplyO(transform) - return this - }, + // Loop through all of the initialisers + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current initialiser + var current = this._queue[i] - clearTransform: function () { - this.transforms = new SVG.Matrix() - return this + // Determine whether we need to initialise + var needsIt = this._isDeclarative || (!current.initialised && running) + running = !current.finished + + // Call the initialiser if we need to + if (needsIt && running) { + current.initialiser.call(this) + current.initialised = true + } } } -}) -SVG.Runner.id = 0 - -SVG.Runner.sanitise = function (duration, delay, when) { - // Initialise the default parameters - var times = 1 - var swing = false - var wait = 0 - duration = duration || SVG.defaults.timeline.duration - delay = delay || SVG.defaults.timeline.delay - when = when || 'last' - - // If we have an object, unpack the values - if (typeof duration === 'object' && !(duration instanceof SVG.Stepper)) { - delay = duration.delay || delay - when = duration.when || when - swing = duration.swing || swing - times = duration.times || times - wait = duration.wait || wait - duration = duration.duration || SVG.defaults.timeline.duration - } - - return { - duration: duration, - delay: delay, - swing: swing, - times: times, - wait: wait, - when: when + // Run each run function for the position or dt given + _run (positionOrDt) { + // Run all of the _queue directly + var allfinished = true + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current function to run + var current = this._queue[i] + + // Run the function if its not finished, we keep track of the finished + // flag for the sake of declarative _queue + var converged = current.runner.call(this, positionOrDt) + current.finished = current.finished || (converged === true) + allfinished = allfinished && current.finished + } + + // We report when all of the constructors are finished + return allfinished + } + + addTransform (transform, index) { + this.transforms.lmultiplyO(transform) + return this + } + + clearTransform () { + this.transforms = new Matrix() + return this + } + + static sanitise (duration, delay, when) { + // Initialise the default parameters + var times = 1 + var swing = false + var wait = 0 + duration = duration || timeline.duration + delay = delay || timeline.delay + when = when || 'last' + + // If we have an object, unpack the values + if (typeof duration === 'object' && !(duration instanceof Stepper)) { + delay = duration.delay || delay + when = duration.when || when + swing = duration.swing || swing + times = duration.times || times + wait = duration.wait || wait + duration = duration.duration || timeline.duration + } + + return { + duration: duration, + delay: delay, + swing: swing, + times: times, + wait: wait, + when: when + } } } -SVG.FakeRunner = class { - constructor (transforms = new SVG.Matrix(), id = -1, done = true) { +Runner.id = 0 + +extend(Element, { + animate (duration, delay, when) { + var o = Runner.sanitise(duration, delay, when) + var timeline = this.timeline() + return new Runner(o.duration) + .loop(o) + .element(this) + .timeline(timeline) + .schedule(delay, when) + }, + + delay (by, when) { + return this.animate(0, by, when) + } +}) + +class FakeRunner{ + constructor (transforms = new Matrix(), id = -1, done = true) { this.transforms = transforms this.id = id this.done = done } } -SVG.extend([SVG.Runner, SVG.FakeRunner], { +extend([Runner, FakeRunner], { mergeWith (runner) { - return new SVG.FakeRunner( + return new FakeRunner( runner.transforms.lmultiply(this.transforms), runner.id ) } }) -// SVG.FakeRunner.emptyRunner = new SVG.FakeRunner() +// FakeRunner.emptyRunner = new FakeRunner() const lmultiply = (last, curr) => last.lmultiplyO(curr) const getRunnerTransform = (runner) => runner.transforms @@ -476,7 +478,7 @@ function mergeTransforms () { let runners = this._transformationRunners.runners let netTransform = runners .map(getRunnerTransform) - .reduce(lmultiply, new SVG.Matrix()) + .reduce(lmultiply, new Matrix()) this.transform(netTransform) @@ -550,17 +552,17 @@ class RunnerArray { clearBefore (id) { let deleteCnt = this.ids.indexOf(id + 1) || 1 this.ids.splice(0, deleteCnt, 0) - this.runners.splice(0, deleteCnt, new SVG.FakeRunner()) + this.runners.splice(0, deleteCnt, new FakeRunner()) return this } } -SVG.extend(SVG.Element, { +extend(Element, { // this function searches for all runners on the element and deletes the ones // which run before the current one. This is because absolute transformations // overwfrite anything anyway so there is no need to waste time computing // other runners - _clearTransformRunnersBefore: function (currentRunner) { + _clearTransformRunnersBefore (currentRunner) { this._transformationRunners.clearBefore(currentRunner.id) }, @@ -571,36 +573,36 @@ SVG.extend(SVG.Element, { // taken into account .filter((runner) => runner.id <= current.id) .map(getRunnerTransform) - .reduce(lmultiply, new SVG.Matrix()) + .reduce(lmultiply, new Matrix()) }, - addRunner: function (runner) { + addRunner (runner) { this._transformationRunners.add(runner) - SVG.Animator.transform_frame( + Animator.transform_frame( mergeTransforms.bind(this), this._frameId ) }, - _prepareRunner: function () { + _prepareRunner () { if (this._frameId == null) { this._transformationRunners = new RunnerArray() - .add(new SVG.FakeRunner(new SVG.Matrix(this))) + .add(new FakeRunner(new Matrix(this))) - this._frameId = SVG.Element.frameId++ + this._frameId = Element.frameId++ } } }) -SVG.Element.frameId = 0 +Element.frameId = 0 -SVG.extend(SVG.Runner, { - attr: function (a, v) { +extend(Runner, { + attr (a, v) { return this.styleAttr('attr', a, v) }, // Add animatable styles - css: function (s, v) { + css (s, v) { return this.styleAttr('css', s, v) }, @@ -612,7 +614,7 @@ SVG.extend(SVG.Runner, { } } - var morpher = new SVG.Morphable(this._stepper).to(val) + var morpher = new Morphable(this._stepper).to(val) this.queue(function () { morpher = morpher.from(this.element()[type](name)) @@ -624,8 +626,8 @@ SVG.extend(SVG.Runner, { return this }, - zoom: function (level, point) { - var morpher = new SVG.Morphable(this._stepper).to(new SVG.Number(level)) + zoom (level, point) { + var morpher = new Morphable(this._stepper).to(new SVGNumber(level)) this.queue(function () { morpher = morpher.from(this.zoom()) @@ -654,7 +656,7 @@ SVG.extend(SVG.Runner, { // - Note F(1) = T // 4. Now you get the delta matrix as a result: D = F * inv(M) - transform: function (transforms, relative, affine) { + transform (transforms, relative, affine) { // If we have a declarative function, we should retarget it if possible relative = transforms.relative || relative if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { @@ -668,8 +670,8 @@ SVG.extend(SVG.Runner, { : (affine != null ? affine : !isMatrix) // Create a morepher and set its type - const morpher = new SVG.Morphable() - .type(affine ? SVG.Morphable.TransformBag : SVG.Matrix) + const morpher = new Morphable() + .type(affine ? Morphable.TransformBag : Matrix) .stepper(this._stepper) let origin @@ -683,7 +685,7 @@ SVG.extend(SVG.Runner, { element = element || this.element() origin = origin || getOrigin(transforms, element) - startTransform = new SVG.Matrix(relative ? undefined : element) + startTransform = new Matrix(relative ? undefined : element) // add the runner to the element so it can merge transformations element.addRunner(this) @@ -699,9 +701,9 @@ SVG.extend(SVG.Runner, { // on this runner. We are absolute. We dont need these! if (!relative) this.clearTransform() - let {x, y} = new SVG.Point(origin).transform(element._currentTransform(this)) + let {x, y} = new Point(origin).transform(element._currentTransform(this)) - let target = new SVG.Matrix({...transforms, origin: [x, y]}) + let target = new Matrix({...transforms, origin: [x, y]}) let start = this._isDeclarative && current ? current : startTransform @@ -724,7 +726,7 @@ SVG.extend(SVG.Runner, { if (relative) { // we have to be careful here not to overwrite the rotation - // with the rotate method of SVG.Matrix + // with the rotate method of Matrix if (!isMatrix) { target.rotate = transforms.rotate || 0 } @@ -738,7 +740,7 @@ SVG.extend(SVG.Runner, { let affineParameters = morpher.at(pos) currentAngle = affineParameters.rotate - current = new SVG.Matrix(affineParameters) + current = new Matrix(affineParameters) this.addTransform(current) return morpher.done() @@ -763,31 +765,31 @@ SVG.extend(SVG.Runner, { }, // Animatable x-axis - x: function (x, relative) { + x (x, relative) { return this._queueNumber('x', x) }, // Animatable y-axis - y: function (y) { + y (y) { return this._queueNumber('y', y) }, - dx: function (x) { + dx (x) { return this._queueNumberDelta('dx', x) }, - dy: function (y) { + dy (y) { return this._queueNumberDelta('dy', y) }, - _queueNumberDelta: function (method, to) { - to = new SVG.Number(to) + _queueNumberDelta (method, to) { + to = new SVGNumber(to) // Try to change the target if we have this method already registerd if (this._tryRetargetDelta(method, to)) return this // Make a morpher and queue the animation - var morpher = new SVG.Morphable(this._stepper).to(to) + var morpher = new Morphable(this._stepper).to(to) this.queue(function () { var from = this.element()[method]() morpher.from(from) @@ -802,12 +804,12 @@ SVG.extend(SVG.Runner, { return this }, - _queueObject: function (method, to) { + _queueObject (method, to) { // Try to change the target if we have this method already registerd if (this._tryRetarget(method, to)) return this // Make a morpher and queue the animation - var morpher = new SVG.Morphable(this._stepper).to(to) + var morpher = new Morphable(this._stepper).to(to) this.queue(function () { morpher.from(this.element()[method]()) }, function (pos) { @@ -820,32 +822,32 @@ SVG.extend(SVG.Runner, { return this }, - _queueNumber: function (method, value) { - return this._queueObject(method, new SVG.Number(value)) + _queueNumber (method, value) { + return this._queueObject(method, new SVGNumber(value)) }, // Animatable center x-axis - cx: function (x) { + cx (x) { return this._queueNumber('cx', x) }, // Animatable center y-axis - cy: function (y) { + cy (y) { return this._queueNumber('cy', y) }, // Add animatable move - move: function (x, y) { + move (x, y) { return this.x(x).y(y) }, // Add animatable center - center: function (x, y) { + center (x, y) { return this.cx(x).cy(y) }, // Add animatable size - size: function (width, height) { + size (width, height) { // animate bbox based size for all other elements var box @@ -867,17 +869,17 @@ SVG.extend(SVG.Runner, { }, // Add animatable width - width: function (width) { + width (width) { return this._queueNumber('width', width) }, // Add animatable height - height: function (height) { + height (height) { return this._queueNumber('height', height) }, // Add animatable plot - plot: function (a, b, c, d) { + plot (a, b, c, d) { // Lines can be plotted with 4 arguments if (arguments.length === 4) { return this.plot([a, b, c, d]) @@ -901,16 +903,16 @@ SVG.extend(SVG.Runner, { }, // Add leading method - leading: function (value) { + leading (value) { return this._queueNumber('leading', value) }, // Add animatable viewbox - viewbox: function (x, y, width, height) { - return this._queueObject('viewbox', new SVG.Box(x, y, width, height)) + viewbox (x, y, width, height) { + return this._queueObject('viewbox', new Box(x, y, width, height)) }, - update: function (o) { + update (o) { if (typeof o !== 'object') { return this.update({ offset: arguments[0], diff --git a/src/SVGArray.js b/src/SVGArray.js index aa43d5c..e7881df 100644 --- a/src/SVGArray.js +++ b/src/SVGArray.js @@ -1,92 +1,45 @@ /* global arrayClone */ - -// Module for array conversion -SVG.Array = function (array, fallback) { - array = (array || []).valueOf() - - // if array is empty and fallback is provided, use fallback - if (array.length === 0 && fallback) { - array = fallback.valueOf() +import {delimiter} from './regex.js' +import ArrayPolyfill from './ArrayPolyfill.js' + +let BaseArray = (function() { + try { + let b = class extends Array {} + return Array + } catch (e) { + return ArrayPolyfill } +})() - // parse array - this.value = this.parse(array) -} - -SVG.extend(SVG.Array, { - // Make array morphable - morph: function (array) { - this.destination = this.parse(array) - - // normalize length of arrays - if (this.value.length !== this.destination.length) { - var lastValue = this.value[this.value.length - 1] - var lastDestination = this.destination[this.destination.length - 1] - - while (this.value.length > this.destination.length) { - this.destination.push(lastDestination) - } - while (this.value.length < this.destination.length) { - this.value.push(lastValue) - } - } +export default class SVGArray extends BaseArray { + constructor (array, fallback) { + super() + this.push(...this.parse(array || fallback)) + } - return this - }, - // Clean up any duplicate points - settle: function () { - // find all unique values - for (var i = 0, il = this.value.length, seen = []; i < il; i++) { - if (seen.indexOf(this.value[i]) === -1) { - seen.push(this.value[i]) - } - } + toArray () { + return Array.prototype.slice(this) + } - // set new value - this.value = seen - return seen - }, - // Get morphed array at given position - at: function (pos) { - // make sure a destination is defined - if (!this.destination) return this + toString () { + this.join(' ') + } - // generate morphed array - for (var i = 0, il = this.value.length, array = []; i < il; i++) { - array.push(this.value[i] + (this.destination[i] - this.value[i]) * pos) - } + valueOf () { + return this.toArray() + } - return new SVG.Array(array) - }, - toArray: function () { - return this.value - }, - // Convert array to string - toString: function () { - return this.value.join(' ') - }, - // Real value - valueOf: function () { - return this.value - }, // Parse whitespace separated string - parse: function (array) { + parse (array) { array = array.valueOf() // if already is an array, no need to parse it if (Array.isArray(array)) return array - return array.trim().split(SVG.regex.delimiter).map(parseFloat) - }, - // Reverse array - reverse: function () { - this.value.reverse() + return array.trim().split(delimiter).map(parseFloat) + } - return this - }, - clone: function () { - var clone = new this.constructor() - clone.value = arrayClone(this.value) - return clone + clone () { + return new this.constructor(this) } -}) +} diff --git a/src/SVGNumber.js b/src/SVGNumber.js index 2135b61..cb1fd28 100644 --- a/src/SVGNumber.js +++ b/src/SVGNumber.js @@ -1,8 +1,9 @@ +import {numberAndUnit} from './regex.js' // Module for unit convertions -SVG.Number = SVG.invent({ +export default class SVGNumber { // Initialize - create: function (value, unit) { + constructor (value, unit) { unit = Array.isArray(value) ? value[1] : unit value = Array.isArray(value) ? value[0] : value @@ -15,7 +16,7 @@ SVG.Number = SVG.invent({ // ensure a valid numeric value this.value = isNaN(value) ? 0 : !isFinite(value) ? (value < 0 ? -3.4e+38 : +3.4e+38) : value } else if (typeof value === 'string') { - unit = value.match(SVG.regex.numberAndUnit) + unit = value.match(numberAndUnit) if (unit) { // make value numeric @@ -30,70 +31,54 @@ SVG.Number = SVG.invent({ this.unit = unit[5] } } else { - if (value instanceof SVG.Number) { + if (value instanceof SVGNumber) { this.value = value.valueOf() this.unit = value.unit } } - }, - // Add methods - extend: { - // Stringalize - toString: function () { - return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 - : this.unit === 's' ? this.value / 1e3 - : this.value - ) + this.unit - }, - toJSON: function () { - return this.toString() - }, // Convert to primitive - toArray: function () { - return [this.value, this.unit] - }, - valueOf: function () { - return this.value - }, - // Add number - plus: function (number) { - number = new SVG.Number(number) - return new SVG.Number(this + number, this.unit || number.unit) - }, - // Subtract number - minus: function (number) { - number = new SVG.Number(number) - return new SVG.Number(this - number, this.unit || number.unit) - }, - // Multiply number - times: function (number) { - number = new SVG.Number(number) - return new SVG.Number(this * number, this.unit || number.unit) - }, - // Divide number - divide: function (number) { - number = new SVG.Number(number) - return new SVG.Number(this / number, this.unit || number.unit) - }, - // Make number morphable - morph: function (number) { - this.destination = new SVG.Number(number) + } - if (number.relative) { - this.destination.value += this.value - } + toString () { + return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 + : this.unit === 's' ? this.value / 1e3 + : this.value + ) + this.unit + } + + toJSON () { + return this.toString() + } - return this - }, - // Get morphed number at given position - at: function (pos) { - // Make sure a destination is defined - if (!this.destination) return this - // Generate new morphed number - return new SVG.Number(this.destination) - .minus(this) - .times(pos) - .plus(this) - } + toArray () { + return [this.value, this.unit] + } + + valueOf () { + return this.value + } + + // Add number + plus (number) { + number = new SVGNumber(number) + return new SVGNumber(this + number, this.unit || number.unit) + } + + // Subtract number + minus (number) { + number = new SVGNumber(number) + return new SVGNumber(this - number, this.unit || number.unit) + } + + // Multiply number + times (number) { + number = new SVGNumber(number) + return new SVGNumber(this * number, this.unit || number.unit) + } + + // Divide number + divide (number) { + number = new SVGNumber(number) + return new SVGNumber(this / number, this.unit || number.unit) } -}) +} diff --git a/src/Shape.js b/src/Shape.js index cb15098..d73ffb6 100644 --- a/src/Shape.js +++ b/src/Shape.js @@ -1,10 +1,3 @@ +import Element from './Element.js' -SVG.Shape = SVG.invent({ - // Initialize node - create: function (node) { - SVG.Element.call(this, node) - }, - - // Inherit from - inherit: SVG.Element -}) +export default class Shape extends Element { } diff --git a/src/Symbol.js b/src/Symbol.js index ca67607..98d10ef 100644 --- a/src/Symbol.js +++ b/src/Symbol.js @@ -1,15 +1,16 @@ +import Container from './Container.js' +import {nodeOrNew} from './tools.js' -SVG.Symbol = SVG.invent({ +export default class Symbol extends Container { // Initialize node - create: 'symbol', - - // Inherit from - inherit: SVG.Container, + constructor (node) { + super(nodeOrNew('symbol', node)) + } +} - construct: { - // create symbol - symbol: function () { - return this.put(new SVG.Symbol()) - } +addFactory(Container, { + // create symbol + symbol () { + return this.put(new Symbol()) } }) diff --git a/src/Text.js b/src/Text.js index 8a50df9..3d9f074 100644 --- a/src/Text.js +++ b/src/Text.js @@ -1,205 +1,213 @@ -SVG.Text = SVG.invent({ +import Parent from './Parent.js' +import SVGNumber from './SVGNumber.js' +import {nodeOrNew, adopt} from './tools.js' +import {attrs} from './defaults.js' + +export default class Text extends Parent { // Initialize node - create: function (node) { - SVG.Element.call(this, node || SVG.create('text')) - this.dom.leading = new SVG.Number(1.3) // store leading value for rebuilding + constructor (node) { + super(nodeOrNew('text', node)) + + 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 + this._build = false // disable build mode for adding multiple lines // set default font - this.attr('font-family', SVG.defaults.attrs['font-family']) - }, + this.attr('font-family', attrs['font-family']) + } - // Inherit from - inherit: SVG.Parent, + // Move over x-axis + x (x) { + // act as getter + if (x == null) { + return this.attr('x') + } - // Add class methods - extend: { - // Move over x-axis - x: function (x) { - // act as getter - if (x == null) { - return this.attr('x') - } + return this.attr('x', x) + } - return this.attr('x', x) - }, - // Move over y-axis - y: function (y) { - var oy = this.attr('y') - var o = typeof oy === 'number' ? oy - this.bbox().y : 0 + // Move over y-axis + y (y) { + var oy = this.attr('y') + var o = typeof oy === 'number' ? oy - this.bbox().y : 0 - // act as getter - if (y == null) { - return typeof oy === 'number' ? oy - o : oy - } + // act as getter + if (y == null) { + return typeof oy === 'number' ? oy - o : oy + } - return this.attr('y', typeof y === 'number' ? y + o : y) - }, - // Move center over x-axis - cx: function (x) { - return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2) - }, - // Move center over y-axis - cy: function (y) { - return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2) - }, - // Set the text content - text: function (text) { - // act as getter - if (text === undefined) { - var children = this.node.childNodes - var firstLine = 0 - text = '' - - 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 - continue - } + return this.attr('y', typeof y === 'number' ? y + o : y) + } - // add newline if its not the first child and newLined is set to true - if (i !== firstLine && children[i].nodeType !== 3 && SVG.adopt(children[i]).dom.newLined === true) { - text += '\n' - } + // Move center over x-axis + 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) + } - // add content of this node - text += children[i].textContent + // Set the text content + text (text) { + // act as getter + if (text === undefined) { + var children = this.node.childNodes + var firstLine = 0 + text = '' + + 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 + continue } - return text + // 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) { + text += '\n' + } + + // add content of this node + text += children[i].textContent } - // remove existing content - this.clear().build(true) + return text + } - if (typeof text === 'function') { - // call block - text.call(this, this) - } else { - // store text and make sure text is not blank - text = text.split('\n') + // remove existing content + this.clear().build(true) - // build new lines - for (var j = 0, jl = text.length; j < jl; j++) { - this.tspan(text[j]).newLine() - } - } + if (typeof text === 'function') { + // call block + text.call(this, this) + } else { + // store text and make sure text is not blank + text = text.split('\n') - // disable build mode and rebuild lines - return this.build(false).rebuild() - }, - // Set / get leading - leading: function (value) { - // act as getter - if (value == null) { - return this.dom.leading + // build new lines + for (var j = 0, jl = text.length; j < jl; j++) { + this.tspan(text[j]).newLine() } + } - // act as setter - this.dom.leading = new SVG.Number(value) + // disable build mode and rebuild lines + return this.build(false).rebuild() + } - return this.rebuild() - }, - // Rebuild appearance type - rebuild: function (rebuild) { - // store new rebuild flag if given - if (typeof rebuild === 'boolean') { - this._rebuild = rebuild - } + // Set / get leading + leading (value) { + // act as getter + if (value == null) { + return this.dom.leading + } - // define position of all lines - if (this._rebuild) { - var self = this - var blankLineOffset = 0 - var dy = this.dom.leading * new SVG.Number(this.attr('font-size')) - - this.each(function () { - if (this.dom.newLined) { - this.attr('x', self.attr('x')) - - if (this.text() === '\n') { - blankLineOffset += dy - } else { - this.attr('dy', dy + blankLineOffset) - blankLineOffset = 0 - } - } - }) + // act as setter + this.dom.leading = new SVGNumber(value) - this.fire('rebuild') - } + return this.rebuild() + } - return this - }, - // Enable / disable build mode - build: function (build) { - this._build = !!build - return this - }, - // overwrite method from parent to set data properly - setData: function (o) { - this.dom = o - this.dom.leading = new SVG.Number(o.leading || 1.3) - return this + // Rebuild appearance type + rebuild (rebuild) { + // store new rebuild flag if given + if (typeof rebuild === 'boolean') { + this._rebuild = rebuild } - }, - // Add parent method - construct: { - // Create text element - text: function (text) { - return this.put(new SVG.Text()).text(text) - }, - // Create plain text element - plain: function (text) { - return this.put(new SVG.Text()).plain(text) + // define position of all lines + if (this._rebuild) { + var self = this + var blankLineOffset = 0 + var dy = this.dom.leading * new SVGNumber(this.attr('font-size')) + + this.each(function () { + if (this.dom.newLined) { + this.attr('x', self.attr('x')) + + if (this.text() === '\n') { + blankLineOffset += dy + } else { + this.attr('dy', dy + blankLineOffset) + blankLineOffset = 0 + } + } + }) + + this.fire('rebuild') } + + return this + } + + // Enable / disable build mode + build (build) { + this._build = !!build + return this + } + + // overwrite method from parent to set data properly + setData (o) { + this.dom = o + this.dom.leading = new SVGNumber(o.leading || 1.3) + return this } +} + +addFactory(Parent, { + // Create text element + text (text) { + return this.put(new Text()).text(text) + }, + + // Create plain text element + plain (text) { + return this.put(new Text()).plain(text) + } }) -SVG.Tspan = SVG.invent({ + +class Tspan extends Parent { // Initialize node - create: 'tspan', - - // Inherit from - inherit: SVG.Parent, - - // Add class methods - extend: { - // Set text content - text: function (text) { - if (text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '') - - typeof text === 'function' ? text.call(this, this) : this.plain(text) - - return this - }, - // Shortcut dx - dx: function (dx) { - return this.attr('dx', dx) - }, - // Shortcut dy - dy: function (dy) { - return this.attr('dy', dy) - }, - // Create new line - newLine: function () { - // fetch text parent - var t = this.parent(SVG.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()) - } + constructor (node) { + super(nodeOrNew('tspan', node)) } -}) -SVG.extend([SVG.Text, SVG.Tspan], { + // Set text content + text (text) { + if (text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '') + + typeof text === 'function' ? text.call(this, this) : this.plain(text) + + return this + } + + // Shortcut dx + dx (dx) { + return this.attr('dx', dx) + } + + // Shortcut dy + dy (dy) { + return this.attr('dy', dy) + } + + // Create new line + newLine () { + // fetch text parent + 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()) + } +} + +extend([Text, Tspan], { // Create plain text node plain: function (text) { // clear if build mode is disabled @@ -212,9 +220,10 @@ SVG.extend([SVG.Text, SVG.Tspan], { return this }, + // Create a tspan tspan: function (text) { - var tspan = new SVG.Tspan() + var tspan = new Tspan() // clear if build mode is disabled if (!this._build) { @@ -226,6 +235,7 @@ SVG.extend([SVG.Text, SVG.Tspan], { return tspan.text(text) }, + // FIXME: Does this also work for textpath? // Get length of text element length: function () { diff --git a/src/TextPath.js b/src/TextPath.js index 561f147..cd1757e 100644 --- a/src/TextPath.js +++ b/src/TextPath.js @@ -1,77 +1,80 @@ -SVG.TextPath = SVG.invent({ +import {Path, Text, PathArray} from './classes.js' +import {nodeOrNew} from './tools.js' +import {xlink} from './namespaces.js' + +export default class TextPath extends Text { // Initialize node - create: 'textPath', - - // Inherit from - inherit: SVG.Text, - - // Define parent class - parent: SVG.Parent, - - // Add parent method - extend: { - MorphArray: SVG.PathArray, - // return the array of the path track element - array: function () { - var track = this.track() - - return track ? track.array() : null - }, - // Plot path if any - plot: function (d) { - var track = this.track() - var pathArray = null - - if (track) { - pathArray = track.plot(d) - } - - return (d == null) ? pathArray : this - }, - // Get the path element - track: function () { - return this.reference('href') - } - }, - construct: { - textPath: function (text, path) { - return this.defs().path(path).text(text).addTo(this) + constructor (node) { + super(nodeOrNew('textPath', 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) { + var track = this.track() + var pathArray = null + + if (track) { + pathArray = track.plot(d) } + + return (d == null) ? pathArray : this + } + + // Get the path element + track () { + return this.reference('href') + } +} + +addFactory(Parent, { + textPath (text, path) { + return this.defs().path(path).text(text).addTo(this) } }) -SVG.extend([SVG.Text], { + +extend([Text], { // Create path for text to run on path: function (track) { - var path = new SVG.TextPath() + var path = new TextPath() // if d is a path, reuse it - if (!(track instanceof SVG.Path)) { + if (!(track instanceof Path)) { // create path element track = this.doc().defs().path(track) } // link textPath to path and add content - path.attr('href', '#' + track, SVG.xlink) + path.attr('href', '#' + track, xlink) // add textPath element as child node and return textPath return this.put(path) }, - // Todo: make this plural? + + // FIXME: make this plural? // Get the textPath children textPath: function () { return this.select('textPath') } }) -SVG.extend([SVG.Path], { +extend([Path], { // creates a textPath from this path text: function (text) { - if (text instanceof SVG.Text) { + if (text instanceof Text) { var txt = text.text() return text.clear().path(this).text(txt) } - return this.parent().put(new SVG.Text()).path(this).text(text) + return this.parent().put(new Text()).path(this).text(text) } - // TODO: Maybe add `targets` to get all textPaths associated with this path + // FIXME: Maybe add `targets` to get all textPaths associated with this path }) + +TextPath.prototype.MorphArray = PathArray diff --git a/src/Timeline.js b/src/Timeline.js index 0bf8ac5..01a8e22 100644 --- a/src/Timeline.js +++ b/src/Timeline.js @@ -1,11 +1,5 @@ - -// Must Change .... -SVG.easing = { - '-': function (pos) { return pos }, - '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, - '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, - '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } -} +import EventTarget from './EventTarget.js' +import Animator from './Animator.js' var time = window.performance || Date @@ -16,16 +10,14 @@ var makeSchedule = function (runnerInfo) { return {start: start, duration: duration, end: end, runner: runnerInfo.runner} } -SVG.Timeline = SVG.invent({ - inherit: SVG.EventTarget, - +export default class Timeline extends EventTarget { // Construct a new timeline on the given element - create: function () { + constructor () { this._timeSource = function () { return time.now() } - this._dispatcher = document.createElement('div') + this._dispatcher = document.makeInstance('div') // Store the timing variables this._startTime = 0 @@ -43,240 +35,235 @@ SVG.Timeline = SVG.invent({ this._time = 0 this._lastSourceTime = 0 this._lastStepTime = 0 - }, - - extend: { + } - getEventTarget () { - return this._dispatcher - }, + getEventTarget () { + return this._dispatcher + } - /** - * - */ + /** + * + */ - // schedules a runner on the timeline - schedule (runner, delay, when) { - if (runner == null) { - return this._runners.map(makeSchedule).sort(function (a, b) { - return (a.start - b.start) || (a.duration - b.duration) - }) - } + // schedules a runner on the timeline + schedule (runner, delay, when) { + if (runner == null) { + return this._runners.map(makeSchedule).sort(function (a, b) { + return (a.start - b.start) || (a.duration - b.duration) + }) + } - if (!this.active()) { - this._step() - if (when == null) { - when = 'now' - } + if (!this.active()) { + this._step() + if (when == null) { + when = 'now' } + } - // The start time for the next animation can either be given explicitly, - // derived from the current timeline time or it can be relative to the - // last start time to chain animations direclty - var absoluteStartTime = 0 - delay = delay || 0 - - // Work out when to start the animation - if (when == null || when === 'last' || when === 'after') { - // Take the last time and increment - absoluteStartTime = this._startTime - } else if (when === 'absolute' || when === 'start') { - absoluteStartTime = delay + // The start time for the next animation can either be given explicitly, + // derived from the current timeline time or it can be relative to the + // last start time to chain animations direclty + var absoluteStartTime = 0 + delay = delay || 0 + + // Work out when to start the animation + if (when == null || when === 'last' || when === 'after') { + // Take the last time and increment + absoluteStartTime = this._startTime + } else if (when === 'absolute' || when === 'start') { + absoluteStartTime = delay + delay = 0 + } else if (when === 'now') { + absoluteStartTime = this._time + } else if (when === 'relative') { + let runnerInfo = this._runners[runner.id] + if (runnerInfo) { + absoluteStartTime = runnerInfo.start + delay delay = 0 - } else if (when === 'now') { - absoluteStartTime = this._time - } else if (when === 'relative') { - let runnerInfo = this._runners[runner.id] - if (runnerInfo) { - absoluteStartTime = runnerInfo.start + delay - delay = 0 - } - } else { - throw new Error('Invalid value for the "when" parameter') } + } else { + throw new Error('Invalid value for the "when" parameter') + } - // Manage runner - runner.unschedule() - runner.timeline(this) - runner.time(-delay) + // Manage runner + runner.unschedule() + runner.timeline(this) + runner.time(-delay) - // Save startTime for next runner - this._startTime = absoluteStartTime + runner.duration() + delay + // Save startTime for next runner + this._startTime = absoluteStartTime + runner.duration() + delay - // Save runnerInfo - this._runners[runner.id] = { - persist: this.persist(), - runner: runner, - start: absoluteStartTime - } + // Save runnerInfo + this._runners[runner.id] = { + persist: this.persist(), + runner: runner, + start: absoluteStartTime + } - // Save order and continue - this._order.push(runner.id) - this._continue() - return this - }, - - // Remove the runner from this timeline - unschedule (runner) { - var index = this._order.indexOf(runner.id) - if (index < 0) return this - - delete this._runners[runner.id] - this._order.splice(index, 1) - runner.timeline(null) - return this - }, - - play () { - // Now make sure we are not paused and continue the animation - this._paused = false - return this._continue() - }, - - pause () { - // Cancel the next animation frame and pause - this._nextFrame = null - this._paused = true - return this - }, - - stop () { - // Cancel the next animation frame and go to start - this.seek(-this._time) - return this.pause() - }, - - finish () { - this.seek(Infinity) - return this.pause() - }, - - speed (speed) { - if (speed == null) return this._speed - this._speed = speed - return this - }, - - reverse (yes) { - var currentSpeed = this.speed() - if (yes == null) return this.speed(-currentSpeed) - - var positive = Math.abs(currentSpeed) - return this.speed(yes ? positive : -positive) - }, - - seek (dt) { - this._time += dt - return this._continue() - }, - - time (time) { - if (time == null) return this._time - this._time = time - return this - }, - - persist (dtOrForever) { - if (dtOrForever == null) return this._persist - this._persist = dtOrForever - return this - }, - - source (fn) { - if (fn == null) return this._timeSource - this._timeSource = fn - return this - }, - - _step () { - // If the timeline is paused, just do nothing - if (this._paused) return - - // Get the time delta from the last time and update the time - // TODO: Deal with window.blur window.focus to pause animations - var time = this._timeSource() - var dtSource = time - this._lastSourceTime - var dtTime = this._speed * dtSource + (this._time - this._lastStepTime) - this._lastSourceTime = time - - // Update the time - this._time += dtTime - this._lastStepTime = this._time - // this.fire('time', this._time) - - // Run all of the runners directly - var runnersLeft = false - for (var i = 0, len = this._order.length; i < len; i++) { - // Get and run the current runner and ignore it if its inactive - var runnerInfo = this._runners[this._order[i]] - var runner = runnerInfo.runner - let dt = dtTime - - // Make sure that we give the actual difference - // between runner start time and now - let dtToStart = this._time - runnerInfo.start - - // Dont run runner if not started yet - if (dtToStart < 0) { - runnersLeft = true - continue - } else if (dtToStart < dt) { - // Adjust dt to make sure that animation is on point - dt = dtToStart - } + // Save order and continue + this._order.push(runner.id) + this._continue() + return this + } - if (!runner.active()) continue - - // If this runner is still going, signal that we need another animation - // frame, otherwise, remove the completed runner - var finished = runner.step(dt).done - if (!finished) { - runnersLeft = true - // continue - } else if (runnerInfo.persist !== true) { - // runner is finished. And runner might get removed - - // TODO: Figure out end time of runner - var endTime = runner.duration() - runner.time() + this._time - - if (endTime + this._persist < this._time) { - // Delete runner and correct index - delete this._runners[this._order[i]] - this._order.splice(i--, 1) && --len - runner.timeline(null) - } - } - } + // Remove the runner from this timeline + unschedule (runner) { + var index = this._order.indexOf(runner.id) + if (index < 0) return this + + delete this._runners[runner.id] + this._order.splice(index, 1) + runner.timeline(null) + return this + } - // Get the next animation frame to keep the simulation going - if (runnersLeft) { - this._nextFrame = SVG.Animator.frame(this._step.bind(this)) - } else { - this._nextFrame = null + play () { + // Now make sure we are not paused and continue the animation + this._paused = false + return this._continue() + } + + pause () { + // Cancel the next animation frame and pause + this._nextFrame = null + this._paused = true + return this + } + + stop () { + // Cancel the next animation frame and go to start + this.seek(-this._time) + return this.pause() + } + + finish () { + this.seek(Infinity) + return this.pause() + } + + speed (speed) { + if (speed == null) return this._speed + this._speed = speed + return this + } + + reverse (yes) { + var currentSpeed = this.speed() + if (yes == null) return this.speed(-currentSpeed) + + var positive = Math.abs(currentSpeed) + return this.speed(yes ? positive : -positive) + } + + seek (dt) { + this._time += dt + return this._continue() + } + + time (time) { + if (time == null) return this._time + this._time = time + return this + } + + persist (dtOrForever) { + if (dtOrForever == null) return this._persist + this._persist = dtOrForever + return this + } + + source (fn) { + if (fn == null) return this._timeSource + this._timeSource = fn + return this + } + + _step () { + // If the timeline is paused, just do nothing + if (this._paused) return + + // Get the time delta from the last time and update the time + // TODO: Deal with window.blur window.focus to pause animations + var time = this._timeSource() + var dtSource = time - this._lastSourceTime + var dtTime = this._speed * dtSource + (this._time - this._lastStepTime) + this._lastSourceTime = time + + // Update the time + this._time += dtTime + this._lastStepTime = this._time + // this.fire('time', this._time) + + // Run all of the runners directly + var runnersLeft = false + for (var i = 0, len = this._order.length; i < len; i++) { + // Get and run the current runner and ignore it if its inactive + var runnerInfo = this._runners[this._order[i]] + var runner = runnerInfo.runner + let dt = dtTime + + // Make sure that we give the actual difference + // between runner start time and now + let dtToStart = this._time - runnerInfo.start + + // Dont run runner if not started yet + if (dtToStart < 0) { + runnersLeft = true + continue + } else if (dtToStart < dt) { + // Adjust dt to make sure that animation is on point + dt = dtToStart } - return this - }, - - // Checks if we are running and continues the animation - _continue () { - if (this._paused) return this - if (!this._nextFrame) { - this._nextFrame = SVG.Animator.frame(this._step.bind(this)) + + if (!runner.active()) continue + + // If this runner is still going, signal that we need another animation + // frame, otherwise, remove the completed runner + var finished = runner.step(dt).done + if (!finished) { + runnersLeft = true + // continue + } else if (runnerInfo.persist !== true) { + // runner is finished. And runner might get removed + + // TODO: Figure out end time of runner + var endTime = runner.duration() - runner.time() + this._time + + if (endTime + this._persist < this._time) { + // Delete runner and correct index + delete this._runners[this._order[i]] + this._order.splice(i--, 1) && --len + runner.timeline(null) + } } - return this - }, + } - active () { - return !!this._nextFrame + // Get the next animation frame to keep the simulation going + if (runnersLeft) { + this._nextFrame = Animator.frame(this._step.bind(this)) + } else { + this._nextFrame = null } - }, - - // These methods will be added to all SVG.Element objects - parent: SVG.Element, - construct: { - timeline: function () { - this._timeline = (this._timeline || new SVG.Timeline()) - return this._timeline + return this + } + + // Checks if we are running and continues the animation + _continue () { + if (this._paused) return this + if (!this._nextFrame) { + this._nextFrame = Animator.frame(this._step.bind(this)) } + return this + } + + active () { + return !!this._nextFrame + } +} + +extend(Element, { + timeline: function () { + this._timeline = (this._timeline || new Timeline()) + return this._timeline } }) diff --git a/src/arrange.js b/src/arrange.js index a908143..b6d5e26 100644 --- a/src/arrange.js +++ b/src/arrange.js @@ -1,97 +1,96 @@ -// ### This module adds backward / forward functionality to elements. - -// -SVG.extend(SVG.Element, { - // Get all siblings, including myself - siblings: function () { - return this.parent().children() - }, - - // Get the curent position siblings - position: function () { - return this.parent().index(this) - }, - - // Get the next element (will return null if there is none) - next: function () { - return this.siblings()[this.position() + 1] - }, - - // Get the next element (will return null if there is none) - prev: function () { - return this.siblings()[this.position() - 1] - }, - - // Send given element one step forward - forward: function () { - var i = this.position() + 1 - var p = this.parent() +import Doc from './Doc.js' - // move node one step forward - p.removeElement(this).add(this, i) +// ### This module adds backward / forward functionality to elements. - // make sure defs node is always at the top - if (p instanceof SVG.Doc) { - p.node.appendChild(p.defs().node) - } +// Get all siblings, including myself +export function siblings () { + return this.parent().children() +} + +// Get the curent position siblings +export function position () { + return this.parent().index(this) +} + +// Get the next element (will return null if there is none) +export function next () { + return this.siblings()[this.position() + 1] +} + +// Get the next element (will return null if there is none) +export function prev () { + return this.siblings()[this.position() - 1] +} + +// Send given element one step forward +export function forward () { + var i = this.position() + 1 + 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 (p instanceof Doc) { + p.node.appendChild(p.defs().node) + } - return this - }, + return this +} - // Send given element one step backward - backward: function () { - var i = this.position() +// Send given element one step backward +export function backward () { + var i = this.position() - if (i > 0) { - this.parent().removeElement(this).add(this, i - 1) - } + if (i > 0) { + this.parent().removeElement(this).add(this, i - 1) + } - return this - }, + return this +} - // Send given element all the way to the front - front: function () { - var p = this.parent() +// Send given element all the way to the front +export function front () { + var p = this.parent() - // Move node forward - p.node.appendChild(this.node) + // Move node forward + p.node.appendChild(this.node) - // Make sure defs node is always at the top - if (p instanceof SVG.Doc) { - p.node.appendChild(p.defs().node) - } + // Make sure defs node is always at the top + if (p instanceof Doc) { + p.node.appendChild(p.defs().node) + } - return this - }, + return this +} - // Send given element all the way to the back - back: function () { - if (this.position() > 0) { - this.parent().removeElement(this).add(this, 0) - } +// Send given element all the way to the back +export function back () { + if (this.position() > 0) { + this.parent().removeElement(this).add(this, 0) + } - return this - }, + return this +} - // Inserts a given element before the targeted element - before: function (element) { - element.remove() +// Inserts a given element before the targeted element +export function before (element) { + element.remove() - var i = this.position() + var i = this.position() - this.parent().add(element, i) + this.parent().add(element, i) - return this - }, + return this +} - // Insters a given element after the targeted element - after: function (element) { - element.remove() +// Inserts a given element after the targeted element +export function after (element) { + element.remove() - var i = this.position() + var i = this.position() - this.parent().add(element, i + 1) + this.parent().add(element, i + 1) - return this - } -}) + return this +} diff --git a/src/attr.js b/src/attr.js index 19c7525..a0c95b4 100644 --- a/src/attr.js +++ b/src/attr.js @@ -1,72 +1,78 @@ -SVG.extend(SVG.Element, { - // Set svg element attribute - attr: function (a, v, n) { - // act as full getter - if (a == null) { - // get an object of attributes - a = {} - v = this.node.attributes - for (n = v.length - 1; n >= 0; n--) { - a[v[n].nodeName] = SVG.regex.isNumber.test(v[n].nodeValue) - ? parseFloat(v[n].nodeValue) - : v[n].nodeValue - } - return a - } else if (typeof a === 'object') { - // apply every attribute individually if an object is passed - for (v in a) this.attr(v, a[v]) - } else if (v === null) { - // remove value - this.node.removeAttribute(a) - } else if (v == null) { - // act as a getter if the first and only argument is not an object - v = this.node.getAttribute(a) - return v == null ? SVG.defaults.attrs[a] - : SVG.regex.isNumber.test(v) ? parseFloat(v) - : v - } else { - // convert image fill and stroke to patterns - if (a === 'fill' || a === 'stroke') { - if (SVG.regex.isImage.test(v)) { - v = this.doc().defs().image(v) - } +import {isNumer, isImage} from './regex.js' +import {attrs as defaults} from './defaults.js' +import {Color, SVGArray, Image} from './classes.js' - if (v instanceof SVG.Image) { - v = this.doc().defs().pattern(0, 0, function () { - this.add(v) - }) - } - } +// Set svg element attribute +export default function attr (attr, val, ns) { + // act as full getter + if (attr == null) { + // get an object of attributes + attr = {} + val = this.node.attributes - // ensure correct numeric values (also accepts NaN and Infinity) - if (typeof v === 'number') { - v = new SVG.Number(v) - } else if (SVG.Color.isColor(v)) { - // ensure full hex color - v = new SVG.Color(v) - } else if (Array.isArray(v)) { - // parse array values - v = new SVG.Array(v) + for (let node of val) { + attr[node.nodeName] = isNumer.test(node.nodeValue) + ? parseFloat(node.nodeValue) + : node.nodeValue + } + + return attr + } else if (Array.isArray(attr)) { + // FIXME: implement + } else if (typeof attr === 'object') { + // apply every attribute individually if an object is passed + for (val in a) this.attr(val, attr[val]) + }else if (val === null) { + // remove value + this.node.removeAttribute(attr) + } else if (val == null) { + // act as a getter if the first and only argument is not an object + val = this.node.getAttribute(attr) + return val == null ? defaults[attr] // FIXME: do we need to return defaults? + : isNumber.test(val) ? parseFloat(val) + : val + } else { + // convert image fill and stroke to patterns + if (attr === 'fill' || attr === 'stroke') { + if (isImage.test(v)) { + val = this.doc().defs().image(val) } - // if the passed attribute is leading... - if (a === 'leading') { - // ... call the leading method instead - if (this.leading) { - this.leading(v) - } - } else { - // set given attribute on node - typeof n === 'string' ? this.node.setAttributeNS(n, a, v.toString()) - : this.node.setAttribute(a, v.toString()) + if (val instanceof Image) { + val = this.doc().defs().pattern(0, 0, function () { + this.add(val) + }) } + } - // rebuild if required - if (this.rebuild && (a === 'font-size' || a === 'x')) { - this.rebuild(a, v) + // ensure correct numeric values (also accepts NaN and Infinity) + if (typeof val === 'number') { + val = new SVGNumber(val) + } else if (isColor(val)) { + // ensure full hex color + val = new Color(val) + } else if (Array.isArray(val)) { + // parse array values + val = new SVGArray(val) + } + + // if the passed attribute is leading... + if (attr === 'leading') { + // ... call the leading method instead + if (this.leading) { + this.leading(val) } + } else { + // set given attribute on node + typeof ns === 'string' ? this.node.setAttributeNS(ns, attr, val.toString()) + : this.node.setAttribute(attr, val.toString()) } - return this + // rebuild if required + if (this.rebuild && (attr === 'font-size' || attr === 'x')) { + this.rebuild() + } } -}) + + return this +} diff --git a/src/circled.js b/src/circled.js new file mode 100644 index 0000000..70fafef --- /dev/null +++ b/src/circled.js @@ -0,0 +1,64 @@ +// FIXME: import this to runner +import {proportionalSize} from './helpers.js' +import SVGNumber from './SVGNumber.js' + +// Radius x value +export function rx (rx) { + return this.attr('rx', rx) +} + +// Radius y value +export function ry (ry) { + return this.attr('ry', ry) +} + +// Move over x-axis +export function x (x) { + return x == null + ? this.cx() - this.rx() + : this.cx(x + this.rx()) +} + +// Move over y-axis +export function y (y) { + return y == null + ? this.cy() - this.ry() + : this.cy(y + this.ry()) +} + +// Move by center over x-axis +export function cx (x) { + return x == null + ? this.attr('cx') + : this.attr('cx', x) +} + +// Move by center over y-axis +export function cy (y) { + return y == null + ? this.attr('cy') + : this.attr('cy', y) +} + +// Set width of element +export function width (width) { + return width == null + ? this.rx() * 2 + : this.rx(new SVGNumber(width).divide(2)) +} + +// Set height of element +export function height (height) { + return height == null + ? this.ry() * 2 + : this.ry(new SVGNumber(height).divide(2)) +} + +// Custom size function +export function 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)) +} diff --git a/src/classes.js b/src/classes.js new file mode 100644 index 0000000..df65151 --- /dev/null +++ b/src/classes.js @@ -0,0 +1,87 @@ +export {default as EventTarget} from './EventTarget.js' +export {default as Element} from './Element.js' +export {default as HtmlNode} from './HtmlNode.js' +export {default as Parent} from './Parent.js' +export {default as Container} from './Container.js' +export {default as Doc} from './Doc.js' +export {default as Defs} from './Defs.js' +export {default as G} from './G.js' +export {default as Animator} from './Animator.js' +export {default as Shape} from './Shape.js' +export {default as Bare} from './Bare.js' +export {default as Circle} from './Circle.js' +export {default as ClipPath} from './ClipPath.js' +export {default as A} from './A.js' +export {default as Ellipse} from './Ellipse.js' +export {default as Stop} from './Stop.js' +export {default as Gradient} from './Gradient.js' +export {default as Image} from './Image.js' +export {default as Line} from './Line.js' +export {default as Marker} from './Marker.js' +export {default as Mask} from './Mask.js' +export {default as Path} from './Path.js' +export {default as Pattern} from './Pattern.js' +export {default as Polygon} from './Polygon.js' +export {default as Polyline} from './Polyline.js' +export {default as Rect} from './Rect.js' +export {default as Symbol} from './Symbol.js' +export {default as Text} from './Text.js' +export {default as TextPath} from './TextPath.js' +export {default as Use} from './Use.js' +export {default as SVGNumber} from './SVGNumber.js' +export {default as SVGArray} from './SVGArray.js' +export {default as PathArray} from './PathArray.js' +export {default as PointArray} from './PointArray.js' +export {default as Matrix} from './Matrix.js' +export {default as Point} from './Point.js' +export {default as Box} from './Box.js' +export {default as Color} from './Color.js' +export {default as Morphable} from './Morphable.js' +export {default as Queue} from './Queue.js' +export {default as Runner} from './Runner.js' +export {default as Timeline} from './Timeline.js' +export {Controller, Ease, PID, Spring} from './Controller.js' + +// export {default as Animator} from './Animator.js' +// export {default as SVGArray} from './SVGArray.js' +// export {default as Bare} from './Bare.js' +// export {default as Box} from './Box.js' +// export {default as Circle} from './Circle.js' +// export {default as ClipPath} from './ClipPath.js' +// export {default as Color} from './Color.js' +// export {default as Container} from './Container.js' +// export {Controller, Ease, PID, Spring} from './Controller.js' +// export {default as Defs} from './Defs.js' +// export {default as Doc} from './Doc.js' +// export {default as Element} from './Element.js' +// export {default as Ellipse} from './Ellipse.js' +// export {default as EventTarget} from './EventTarget.js' +// export {default as Gradient} from './Gradient.js' +// export {default as G} from './G.js' +// export {default as HtmlNode} from './HtmlNode.js' +// export {default as A} from './A.js' +// export {default as Image} from './Image.js' +// export {default as Line} from './Line.js' +// export {default as Marker} from './Marker.js' +// export {default as Mask} from './Mask.js' +// export {default as Matrix} from './Matrix.js' +// export {default as Morphable} from './Morphable.js' +// export {default as SVGNumber} from './SVGNumber.js' +// export {default as Parent} from './Parent.js' +// export {default as Path} from './Path.js' +// export {default as PathArray} from './PathArray.js' +// export {default as Pattern} from './Pattern.js' +// export {default as Point} from './Point.js' +// export {default as PointArray} from './PointArray.js' +// export {default as Polygon} from './Polygon.js' +// export {default as Polyline} from './Polyline.js' +// export {default as Queue} from './Queue.js' +// export {default as Rect} from './Rect.js' +// export {default as Runner} from './Runner.js' +// export {default as Shape} from './Shape.js' +// export {default as Stop} from './Stop.js' +// export {default as Symbol} from './Symbol.js' +// export {default as Text} from './Text.js' +// export {default as TextPath} from './TextPath.js' +// export {default as Timeline} from './Timeline.js' +// export {default as Use} from './Use.js' diff --git a/src/css.js b/src/css.js index c549bd5..e5b0794 100644 --- a/src/css.js +++ b/src/css.js @@ -1,14 +1,19 @@ -/* global camelCase */ +import {camelCase} from './helpers.js' +import Element from './Element.js' +import {extend} from './tools.js' +import {isBlank} from './regex.js' -SVG.extend(SVG.Element, { +extend(Element, { // Dynamic style generator - css: function (s, v) { - var ret = {} - var t, i + css (style, val) { + let ret = {} + let i if (arguments.length === 0) { // get full style as object - this.node.style.cssText.split(/\s*;\s*/).filter(function (el) { return !!el.length }).forEach(function (el) { - t = el.split(/\s*:\s*/) + this.node.style.cssText.split(/\s*;\s*/) + .filter(function (el) { return !!el.length }) + .forEach(function (el) { + let t = el.split(/\s*:\s*/) ret[t[0]] = t[1] }) return ret @@ -16,32 +21,50 @@ SVG.extend(SVG.Element, { if (arguments.length < 2) { // get style properties in the array - if (Array.isArray(s)) { - for (i = s.length; i--;) { - ret[camelCase(s[i])] = this.node.style[camelCase(s[i])] + if (Array.isArray(style)) { + for (let name of style) { + let cased = camelCase(name) + ret[cased] = this.node.style(cased) } return ret } // get style for property - if (typeof s === 'string') { - return this.node.style[camelCase(s)] + if (typeof style === 'string') { + return this.node.style[camelCase(style)] } // set styles in object - if (typeof s === 'object') { - for (i in s) { + if (typeof style === 'object') { + for (name in style) { // set empty string if null/undefined/'' was given - this.node.style[camelCase(i)] = (s[i] == null || SVG.regex.isBlank.test(s[i])) ? '' : s[i] + this.node.style[camelCase(name)] = + (style[name] == null || isBlank.test(style[name])) ? '' : style[name] } } } // set style for property if (arguments.length === 2) { - this.node.style[camelCase(s)] = (v == null || SVG.regex.isBlank.test(v)) ? '' : v + this.node.style[camelCase(style)] = + (val == null || isBlank.test(val)) ? '' : val } return this + }, + + // Show element + show () { + return this.css('display', '') + }, + + // Hide element + hide () { + return this.css('display', 'none') + }, + + // Is element visible? + visible () { + return this.css('display') !== 'none' } }) diff --git a/src/data.js b/src/data.js index f7fcd55..530986d 100644 --- a/src/data.js +++ b/src/data.js @@ -1,7 +1,9 @@ +import Element from './Element.js' +import {extend} from './tools.js' -SVG.extend(SVG.Element, { +extend(Element, { // Store data values on svg nodes - data: function (a, v, r) { + data (a, v, r) { if (typeof a === 'object') { for (v in a) { this.data(v, a[v]) diff --git a/src/defaults.js b/src/defaults.js new file mode 100644 index 0000000..0d496bc --- /dev/null +++ b/src/defaults.js @@ -0,0 +1,48 @@ + +export function noop () {} + +// Default animation values +export let timeline = { + duration: 400, + ease: '>', + delay: 0 +} + +// Default attribute values +export let attrs = { + + // fill and stroke + 'fill-opacity': 1, + 'stroke-opacity': 1, + 'stroke-width': 0, + 'stroke-linejoin': 'miter', + 'stroke-linecap': 'butt', + fill: '#000000', + stroke: '#000000', + opacity: 1, + + // position + x: 0, + y: 0, + cx: 0, + cy: 0, + + // size + width: 0, + height: 0, + + // radius + r: 0, + rx: 0, + ry: 0, + + // gradient + offset: 0, + 'stop-opacity': 1, + 'stop-color': '#000000', + + // text + 'font-size': 16, + 'font-family': 'Helvetica, Arial, sans-serif', + 'text-anchor': 'start' +} diff --git a/src/event.js b/src/event.js index 4f16609..8d54782 100644 --- a/src/event.js +++ b/src/event.js @@ -1,38 +1,42 @@ -// Add events to elements -;[ 'click', - 'dblclick', - 'mousedown', - 'mouseup', - 'mouseover', - 'mouseout', - 'mousemove', - 'mouseenter', - 'mouseleave', - 'touchstart', - 'touchmove', - 'touchleave', - 'touchend', - 'touchcancel' ].forEach(function (event) { - // add event to SVG.Element - SVG.Element.prototype[event] = function (f) { - if (f === null) { - SVG.off(this, event) - } else { - SVG.on(this, event, f) - } - return this - } - }) - -SVG.listenerId = 0 +import EventTarget from './EventTarget.js' +import Element from './Element.js' +import {delimiter} from './regex.js' + +// // Add events to elements +// ;[ 'click', +// 'dblclick', +// 'mousedown', +// 'mouseup', +// 'mouseover', +// 'mouseout', +// 'mousemove', +// 'mouseenter', +// 'mouseleave', +// 'touchstart', +// 'touchmove', +// 'touchleave', +// 'touchend', +// 'touchcancel' ].forEach(function (event) { +// // add event to Element +// Element.prototype[event] = function (f) { +// if (f === null) { +// off(this, event) +// } else { +// on(this, event, f) +// } +// return this +// } +// }) + +let listenerId = 0 // Add event binder in the SVG namespace -SVG.on = function (node, events, listener, binding, options) { +export function on (node, events, listener, binding, options) { var l = listener.bind(binding || node) - var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node + var n = node instanceof EventTarget ? node.getEventTarget() : node // events can be an array of events or a string of events - events = Array.isArray(events) ? events : events.split(SVG.regex.delimiter) + events = Array.isArray(events) ? events : events.split(delimiter) // ensure instance object for nodes which are not adopted n.instance = n.instance || {events: {}} @@ -42,7 +46,7 @@ SVG.on = function (node, events, listener, binding, options) { // add id to listener if (!listener._svgjsListenerId) { - listener._svgjsListenerId = ++SVG.listenerId + listener._svgjsListenerId = ++listenerId } events.forEach(function (event) { @@ -62,8 +66,8 @@ SVG.on = function (node, events, listener, binding, options) { } // Add event unbinder in the SVG namespace -SVG.off = function (node, events, listener, options) { - var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node +export function off (node, events, listener, options) { + var n = node instanceof EventTarget ? node.getEventTarget() : node if (!n.instance) return // listener can be a function or a number @@ -76,7 +80,7 @@ SVG.off = function (node, events, listener, options) { var bag = n.instance.events // events can be an array of events or a string or undefined - events = Array.isArray(events) ? events : (events || '').split(SVG.regex.delimiter) + events = Array.isArray(events) ? events : (events || '').split(delimiter) events.forEach(function (event) { var ev = event && event.split('.')[0] @@ -94,7 +98,7 @@ SVG.off = function (node, events, listener, options) { } else if (ev && ns) { // remove all listeners for a namespaced event if (bag[ev] && bag[ev][ns]) { - for (l in bag[ev][ns]) { SVG.off(n, [ev, ns].join('.'), l) } + for (l in bag[ev][ns]) { off(n, [ev, ns].join('.'), l) } delete bag[ev][ns] } @@ -102,27 +106,27 @@ SVG.off = function (node, events, listener, options) { // remove all listeners for a specific namespace for (event in bag) { for (namespace in bag[event]) { - if (ns === namespace) { SVG.off(n, [event, ns].join('.')) } + if (ns === namespace) { off(n, [event, ns].join('.')) } } } } else if (ev) { // remove all listeners for the event if (bag[ev]) { - for (namespace in bag[ev]) { SVG.off(n, [ev, namespace].join('.')) } + for (namespace in bag[ev]) { off(n, [ev, namespace].join('.')) } delete bag[ev] } } else { // remove all listeners on a given node - for (event in bag) { SVG.off(n, event) } + for (event in bag) { off(n, event) } n.instance.events = {} } }) } -SVG.dispatch = function (node, event, data) { - var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node +export function dispatch (node, event, data) { + var n = node instanceof EventTarget ? node.getEventTarget() : node // Dispatch event if (event instanceof window.Event) { diff --git a/src/flatten.js b/src/flatten.js index 19eebd7..34a21bb 100644 --- a/src/flatten.js +++ b/src/flatten.js @@ -1,38 +1,42 @@ -SVG.extend(SVG.Parent, { - flatten: function (parent) { - // flattens is only possible for nested svgs and groups - if (!(this instanceof SVG.G || this instanceof SVG.Doc)) { - return this - } +import {Doc, G, Parent, Defs} from './classes.js' - parent = parent || (this instanceof SVG.Doc && this.isRoot() ? this : this.parent(SVG.Parent)) +export function flatten (parent) { + // flatten is only possible for svgs and groups + if (!(this instanceof G || this instanceof Doc)) { + return this + } + + parent = parent || + (this instanceof Doc && this.isRoot() + ? this + : this.parent(Parent)) + + this.each(function () { + if (this instanceof Defs) return this + if (this instanceof Parent) return this.flatten(parent) + return this.toParent(parent) + }) - this.each(function () { - if (this instanceof SVG.Defs) return this - if (this instanceof SVG.Parent) return this.flatten(parent) - return this.toParent(parent) - }) + // we need this so that Doc does not get removed + this.node.firstElementChild || this.remove() - // we need this so that SVG.Doc does not get removed - this.node.firstElementChild || this.remove() + return this +} +export function ungroup (parent) { + // ungroup is only possible for nested svgs and groups + if (!(this instanceof G || (this instanceof Doc && !this.isRoot()))) { return this - }, - ungroup: function (parent) { - // ungroup is only possible for nested svgs and groups - if (!(this instanceof SVG.G || (this instanceof SVG.Doc && !this.isRoot()))) { - return this - } + } - parent = parent || this.parent(SVG.Parent) + parent = parent || this.parent(Parent) - this.each(function () { - return this.toParent(parent) - }) + this.each(function () { + return this.toParent(parent) + }) - // we need this so that SVG.Doc does not get removed - this.remove() + // we need this so that Doc does not get removed + this.remove() - return this - } -}) + return this +} diff --git a/src/gradiented.js b/src/gradiented.js new file mode 100644 index 0000000..da2bc41 --- /dev/null +++ b/src/gradiented.js @@ -0,0 +1,14 @@ +// FIXME: add to runner +import SVGNumber from './SVGNumber.js' + +export function from (x, y) { + return (this._element || this).type === 'radialGradient' + ? this.attr({ fx: new SVGNumber(x), fy: new SVGNumber(y) }) + : this.attr({ x1: new SVGNumber(x), y1: new SVGNumber(y) }) +} + +export function to (x, y) { + return (this._element || this).type === 'radialGradient' + ? this.attr({ cx: new SVGNumber(x), cy: new SVGNumber(y) }) + : this.attr({ x2: new SVGNumber(x), y2: new SVGNumber(y) }) +} diff --git a/src/helpers.js b/src/helpers.js index c2073cf..b4bddf9 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -1,33 +1,35 @@ -/* eslint no-unused-vars: 0 */ +import {Doc, Point, Element} from './classes.js' +import {adopt, eid, makeNode} from './tools.js' +import {dots, reference} from './regex.js' -function createElement (element, makeNested) { - if (element instanceof SVG.Element) return element +export function makeInstance (element, makeNested) { + if (element instanceof Element) return element if (typeof element === 'object') { - return SVG.adopt(element) + return adopt(element) } if (element == null) { - return new SVG.Doc() + return new Doc() } if (typeof element === 'string' && element.charAt(0) !== '<') { - return SVG.adopt(document.querySelector(element)) + return adopt(document.querySelector(element)) } - var node = SVG.create('svg') + var node = makeNode('svg') node.innerHTML = element - element = SVG.adopt(node.firstElementChild) + element = adopt(node.firstElementChild) return element } -function isNulledBox (box) { +export function isNulledBox (box) { return !box.w && !box.h && !box.x && !box.y } -function domContains (node) { +export function domContains (node) { return (document.documentElement.contains || function (node) { // This is IE - it does not support contains() for top-level SVGs while (node.parentNode) { @@ -37,12 +39,12 @@ function domContains (node) { }).call(document.documentElement, node) } -function pathRegReplace (a, b, c, d) { - return c + d.replace(SVG.regex.dots, ' .') +export function pathRegReplace (a, b, c, d) { + return c + d.replace(dots, ' .') } // creates deep clone of array -function arrayClone (arr) { +export function arrayClone (arr) { var clone = arr.slice(0) for (var i = clone.length; i--;) { if (Array.isArray(clone[i])) { @@ -52,30 +54,25 @@ function arrayClone (arr) { return clone } -// tests if a given element is instance of an object -function is (el, obj) { - return el instanceof obj -} - // tests if a given selector matches an element -function matches (el, selector) { +export function matches (el, selector) { return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector) } // Convert dash-separated-string to camelCase -function camelCase (s) { +export function camelCase (s) { return s.toLowerCase().replace(/-(.)/g, function (m, g) { return g.toUpperCase() }) } // Capitalize first letter of a string -function capitalize (s) { +export function capitalize (s) { return s.charAt(0).toUpperCase() + s.slice(1) } // Ensure to six-based hex -function fullHex (hex) { +export function fullHex (hex) { return hex.length === 4 ? [ '#', hex.substring(1, 2), hex.substring(1, 2), @@ -86,13 +83,13 @@ function fullHex (hex) { } // Component to hex value -function compToHex (comp) { +export function compToHex (comp) { var hex = comp.toString(16) return hex.length === 1 ? '0' + hex : hex } // Calculate proportional width and height values when necessary -function proportionalSize (element, width, height) { +export function proportionalSize (element, width, height) { if (width == null || height == null) { var box = element.bbox() @@ -110,18 +107,18 @@ function proportionalSize (element, width, height) { } // Map matrix array to object -function arrayToMatrix (a) { +export function arrayToMatrix (a) { return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] } } // Add centre point to transform object -function ensureCentre (o, target) { +export function ensureCentre (o, target) { o.cx = o.cx == null ? target.bbox().cx : o.cx o.cy = o.cy == null ? target.bbox().cy : o.cy } // PathArray Helpers -function arrayToString (a) { +export function arrayToString (a) { for (var i = 0, il = a.length, s = ''; i < il; i++) { s += a[i][0] @@ -158,21 +155,21 @@ function arrayToString (a) { } // Deep new id assignment -function assignNewId (node) { +export function assignNewId (node) { // do the same for SVG child nodes as well for (var i = node.children.length - 1; i >= 0; i--) { assignNewId(node.children[i]) } if (node.id) { - return SVG.adopt(node).id(SVG.eid(node.nodeName)) + return adopt(node).id(eid(node.nodeName)) } - return SVG.adopt(node) + return adopt(node) } // Add more bounding box properties -function fullBox (b) { +export function fullBox (b) { if (b.x == null) { b.x = 0 b.y = 0 @@ -191,20 +188,20 @@ function fullBox (b) { } // Get id from reference string -function idFromReference (url) { - var m = (url || '').toString().match(SVG.regex.reference) +export function idFromReference (url) { + var m = (url || '').toString().match(reference) if (m) return m[1] } // Create matrix array for looping -var abcdef = 'abcdef'.split('') +export let abcdef = 'abcdef'.split('') -function closeEnough (a, b, threshold) { +export function closeEnough (a, b, threshold) { return Math.abs(b - a) < (threshold || 1e-6) } -function isMatrixLike (o) { +export function isMatrixLike (o) { return ( o.a != null || o.b != null || @@ -216,7 +213,7 @@ function isMatrixLike (o) { } // TODO: Refactor this to a static function of matrix.js -function formatTransforms (o) { +export function formatTransforms (o) { // Get all of the parameters required to form the matrix var flipBoth = o.flip === 'both' || o.flip === true var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1 @@ -239,16 +236,16 @@ function formatTransforms (o) { : flipY var shear = o.shear || 0 var theta = o.rotate || o.theta || 0 - var origin = new SVG.Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY) + var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY) var ox = origin.x var oy = origin.y - var position = new SVG.Point(o.position || o.px || o.positionX, o.py || o.positionY) + var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY) var px = position.x var py = position.y - var translate = new SVG.Point(o.translate || o.tx || o.translateX, o.ty || o.translateY) + var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY) var tx = translate.x var ty = translate.y - var relative = new SVG.Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY) + var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY) var rx = relative.x var ry = relative.y @@ -259,7 +256,7 @@ function formatTransforms (o) { } // left matrix, right matrix, target matrix which is overwritten -function matrixMultiply (l, r, o) { +export function matrixMultiply (l, r, o) { // Work out the product directly var a = l.a * r.a + l.c * r.b var b = l.b * r.a + l.d * r.b @@ -279,7 +276,7 @@ function matrixMultiply (l, r, o) { return o } -function getOrigin (o, element) { +export function getOrigin (o, element) { // Allow origin or around as the names let origin = o.origin // o.around == null ? o.origin : o.around let ox, oy diff --git a/src/memory.js b/src/memory.js index 57dfa02..bc13196 100644 --- a/src/memory.js +++ b/src/memory.js @@ -1,7 +1,8 @@ +import Element from './Element.js' -SVG.extend(SVG.Element, { +extend(Element, { // Remember arbitrary data - remember: function (k, v) { + remember (k, v) { // remember every item in an object individually if (typeof arguments[0] === 'object') { for (var key in k) { @@ -19,7 +20,7 @@ SVG.extend(SVG.Element, { }, // Erase a given memory - forget: function () { + forget () { if (arguments.length === 0) { this._memory = {} } else { @@ -28,10 +29,10 @@ SVG.extend(SVG.Element, { } } return this - }, + } // Initialize or return local memory object - memory: function () { + memory () { return this._memory || (this._memory = {}) } }) diff --git a/src/namespaces.js b/src/namespaces.js new file mode 100644 index 0000000..3791298 --- /dev/null +++ b/src/namespaces.js @@ -0,0 +1,5 @@ +// Default namespaces +export let ns = 'http://www.w3.org/2000/svg' +export let xmlns = 'http://www.w3.org/2000/xmlns/' +export let xlink = 'http://www.w3.org/1999/xlink' +export let svgjs = 'http://svgjs.com/svgjs' diff --git a/src/parser.js b/src/parser.js index 84c8d77..c51ad71 100644 --- a/src/parser.js +++ b/src/parser.js @@ -1,17 +1,16 @@ +import Doc from './Doc.js' -SVG.parser = function () { - var b - - if (!SVG.parser.nodes.svg.node.parentNode) { - b = document.body || document.documentElement - SVG.parser.nodes.svg.addTo(b) +let parser = function () { + if (!parser.nodes.svg.node.parentNode) { + let b = document.body || document.documentElement + parser.nodes.svg.addTo(b) } - return SVG.parser.nodes + return parser.nodes } -SVG.parser.nodes = { - svg: SVG().size(2, 0).css({ +parser.nodes = { + svg: new Doc().size(2, 0).css({ opacity: 0, position: 'absolute', left: '-100%', @@ -20,4 +19,6 @@ SVG.parser.nodes = { }) } -SVG.parser.nodes.path = SVG.parser.nodes.svg.path().node +parser.nodes.path = parser.nodes.svg.path().node + +export default parser diff --git a/src/pointed.js b/src/pointed.js index 6493964..11df4f3 100644 --- a/src/pointed.js +++ b/src/pointed.js @@ -1,25 +1,25 @@ -// unify all point to point elements -SVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon], { - // Define morphable array - MorphArray: SVG.PointArray, - // Move by left top corner over x-axis - x: function (x) { - return x == null ? this.bbox().x : this.move(x, this.bbox().y) - }, - // Move by left top corner over y-axis - y: function (y) { - return y == null ? this.bbox().y : this.move(this.bbox().x, y) - }, - // Set width of element - width: function (width) { - var b = this.bbox() +import PointArray from './PointArray.js' - return width == null ? b.width : this.size(width, b.height) - }, - // Set height of element - height: function (height) { - var b = this.bbox() +export let MorphArray = PointArray - return height == null ? b.height : this.size(b.width, height) - } -}) +// Move by left top corner over x-axis +export function x (x) { + return x == null ? this.bbox().x : this.move(x, this.bbox().y) +} + +// Move by left top corner over y-axis +export function y (y) { + return y == null ? this.bbox().y : this.move(this.bbox().x, y) +} + +// Set width of element +export function width (width) { + let b = this.bbox() + return width == null ? b.width : this.size(width, b.height) +} + +// Set height of element +export function height (height) { + let b = this.bbox() + return height == null ? b.height : this.size(b.width, height) +} diff --git a/src/regex.js b/src/regex.js index 5a3e3eb..5477b81 100644 --- a/src/regex.js +++ b/src/regex.js @@ -1,61 +1,58 @@ -// Storage for regular expressions -SVG.regex = { - // Parse unit value - numberAndUnit: /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i, +// Parse unit value +export let numberAndUnit = /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i - // Parse hex value - hex: /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i, +// Parse hex value +export let hex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i - // Parse rgb value - rgb: /rgb\((\d+),(\d+),(\d+)\)/, +// Parse rgb value +export let rgb = /rgb\((\d+),(\d+),(\d+)\)/ - // Parse reference id - reference: /#([a-z0-9\-_]+)/i, +// Parse reference id +export let reference = /#([a-z0-9\-_]+)/i - // splits a transformation chain - transforms: /\)\s*,?\s*/, +// splits a transformation chain +export let transforms = /\)\s*,?\s*/ - // Whitespace - whitespace: /\s/g, +// Whitespace +export let whitespace = /\s/g - // Test hex value - isHex: /^#[a-f0-9]{3,6}$/i, +// Test hex value +export let isHex = /^#[a-f0-9]{3,6}$/i - // Test rgb value - isRgb: /^rgb\(/, +// Test rgb value +export let isRgb = /^rgb\(/ - // Test css declaration - isCss: /[^:]+:[^;]+;?/, +// Test css declaration +export let isCss = /[^:]+:[^;]+;?/ - // Test for blank string - isBlank: /^(\s+)?$/, +// Test for blank string +export let isBlank = /^(\s+)?$/ - // Test for numeric string - isNumber: /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i, +// Test for numeric string +export let isNumber = /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i - // Test for percent value - isPercent: /^-?[\d.]+%$/, +// Test for percent value +export let isPercent = /^-?[\d.]+%$/ - // Test for image url - isImage: /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i, +// Test for image url +export let isImage = /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i - // split at whitespace and comma - delimiter: /[\s,]+/, +// split at whitespace and comma +export let delimiter = /[\s,]+/ - // The following regex are used to parse the d attribute of a path +// The following regex are used to parse the d attribute of a path - // Matches all hyphens which are not after an exponent - hyphen: /([^e])-/gi, +// Matches all hyphens which are not after an exponent +export let hyphen = /([^e])-/gi - // Replaces and tests for all path letters - pathLetters: /[MLHVCSQTAZ]/gi, +// Replaces and tests for all path letters +export let pathLetters = /[MLHVCSQTAZ]/gi - // yes we need this one, too - isPathLetter: /[MLHVCSQTAZ]/i, +// yes we need this one, too +export let isPathLetter = /[MLHVCSQTAZ]/i - // matches 0.154.23.45 - numbersWithDots: /((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi, +// matches 0.154.23.45 +export let numbersWithDots = /((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi - // matches . - dots: /\./g -} +// matches . +export let dots = /\./g diff --git a/src/selector.js b/src/selector.js index b4ea05f..a148b56 100644 --- a/src/selector.js +++ b/src/selector.js @@ -1,31 +1,46 @@ -/* global idFromReference */ +import {idFromReference} from './helpers.js' +import {map} from './utils.js' +import {adopt} from './tools.js' -// Method for getting an element by id -SVG.get = function (id) { - var node = document.getElementById(idFromReference(id) || id) - 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) - }) -} +// // Method for getting an element by id +// SVG.get = function (id) { +// var node = document.getElementById(idFromReference(id) || id) +// 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.$$ = function (query, parent) { +// return SVG.utils.map((parent || document).querySelectorAll(query), function (node) { +// return SVG.adopt(node) +// }) +// } +// +// SVG.$ = function (query, parent) { +// return SVG.adopt((parent || document).querySelector(query)) +// } -SVG.$$ = function (query, parent) { - return SVG.utils.map((parent || document).querySelectorAll(query), function (node) { - return SVG.adopt(node) +export default function find (query, parent) { + return utils.map((parent || document).querySelectorAll(query), function (node) { + return adopt(node) }) } -SVG.$ = function (query, parent) { - return SVG.adopt((parent || document).querySelector(query)) -} - -SVG.extend(SVG.Parent, { +export let mixings = { // Scoped select method select: function (query) { - return SVG.select(query, this.node) + return find(query, this.node) } -}) +} + +// extend(SVG.Parent, { +// // Scoped select method +// select: function (query) { +// return SVG.select(query, this.node) +// } +// }) diff --git a/src/stop.js b/src/stop.js new file mode 100644 index 0000000..6bce999 --- /dev/null +++ b/src/stop.js @@ -0,0 +1,27 @@ +import Element from './Element.js' +import SVGNumber from './SVGNumber.js' +import {nodeOrNew} from './tools.js' + +export default class Stop extends Element { + constructor (node) { + super(nodeOrNew('stop', node)) + } + + // add color stops + 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)) + + return this + } +} diff --git a/src/sugar.js b/src/sugar.js index ad991af..e33fb10 100644 --- a/src/sugar.js +++ b/src/sugar.js @@ -1,3 +1,5 @@ +import {Color, Element, Runner} from './classes.js' + // Define list of available attributes for stroke and fill var sugar = { stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], @@ -16,7 +18,7 @@ var sugar = { if (typeof o === 'undefined') { return this } - if (typeof o === 'string' || SVG.Color.isRgb(o) || (o && typeof o.fill === 'function')) { + if (typeof o === 'string' || Color.isRgb(o) || (o && typeof o.fill === 'function')) { this.attr(m, o) } else { // set all attributes from sugar.fill and sugar.stroke list @@ -30,19 +32,19 @@ var sugar = { return this } - SVG.extend([SVG.Element, SVG.Timeline], extension) + extend([Element, Runner], extension) }) -SVG.extend([SVG.Element, SVG.Timeline], { +extend([Element, Runner], { // Let the user set the matrix directly matrix: function (mat, b, c, d, e, f) { // Act as a getter if (mat == null) { - return new SVG.Matrix(this) + return new Matrix(this) } // Act as a setter, the user can pass a matrix or a set of numbers - return this.attr('transform', new SVG.Matrix(mat, b, c, d, e, f)) + return this.attr('transform', new Matrix(mat, b, c, d, e, f)) }, // Map rotation to transform @@ -98,12 +100,12 @@ SVG.extend([SVG.Element, SVG.Timeline], { // Relative move over x axis dx: function (x) { - return this.x(new SVG.Number(x).plus(this instanceof SVG.Timeline ? 0 : this.x()), true) + return this.x(new SVGNumber(x).plus(this instanceof Runner ? 0 : this.x()), true) }, // Relative move over y axis dy: function (y) { - return this.y(new SVG.Number(y).plus(this instanceof SVG.Timeline ? 0 : this.y()), true) + return this.y(new SVGNumber(y).plus(this instanceof Runner ? 0 : this.y()), true) }, // Relative move over x and y axes @@ -112,28 +114,28 @@ SVG.extend([SVG.Element, SVG.Timeline], { } }) -SVG.extend([SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.Timeline], { +extend([Rect, Ellipse, Circle, Gradient, Runner], { // Add x and y radius radius: function (x, y) { var type = (this._target || this).type return type === 'radialGradient' || type === 'radialGradient' - ? this.attr('r', new SVG.Number(x)) + ? this.attr('r', new SVGNumber(x)) : this.rx(x).ry(y == null ? x : y) } }) -SVG.extend(SVG.Path, { +extend(Path, { // Get path length length: function () { return this.node.getTotalLength() }, // Get point at length pointAt: function (length) { - return new SVG.Point(this.node.getPointAtLength(length)) + return new Point(this.node.getPointAtLength(length)) } }) -SVG.extend([SVG.Parent, SVG.Text, SVG.Tspan, SVG.Timeline], { +extend([Parent, Text, Tspan, Runner], { // Set font font: function (a, v) { if (typeof a === 'object') { diff --git a/src/svg.js b/src/svg.js index bf02df0..6f8fd2d 100644 --- a/src/svg.js +++ b/src/svg.js @@ -1,102 +1,11 @@ -/* global createElement, capitalize */ -/* eslint-disable new-cap */ +import {makeInstance} from './helpers.js' +import * as Classes from './classes.js' +import * as tools from './tools.js' // The main wrapping element -var SVG = window.SVG = function (element) { - if (SVG.supported) { - element = createElement(element) - return element - } +export default function SVG (element) { + return makeInstance(element) } -// Svg must be supported if we reached this stage -SVG.supported = true - -// Default namespaces -SVG.ns = 'http://www.w3.org/2000/svg' -SVG.xmlns = 'http://www.w3.org/2000/xmlns/' -SVG.xlink = 'http://www.w3.org/1999/xlink' -SVG.svgjs = 'http://svgjs.com/svgjs' - -// Element id sequence -SVG.did = 1000 - -// Get next named element id -SVG.eid = function (name) { - return 'Svgjs' + capitalize(name) + (SVG.did++) -} - -// Method for element creation -SVG.create = function (name) { - // create element - return document.createElementNS(this.ns, name) -} - -// Method for extending objects -SVG.extend = function (modules, methods) { - var key, i - - modules = Array.isArray(modules) ? modules : [modules] - - for (i = modules.length - 1; i >= 0; i--) { - if (modules[i]) { - for (key in methods) { - modules[i].prototype[key] = methods[key] - } - } - } -} - -// Invent new element -SVG.invent = function (config) { - // Create element initializer - var initializer = typeof config.create === 'function' ? config.create - : function (node) { - config.inherit.call(this, node || SVG.create(config.create)) - } - - // Inherit prototype - if (config.inherit) { - initializer.prototype = new config.inherit() - initializer.prototype.constructor = initializer - } - - // Extend with methods - if (config.extend) { - SVG.extend(initializer, config.extend) - } - - // Attach construct method to parent - if (config.construct) { SVG.extend(config.parent || SVG.Container, config.construct) } - - return initializer -} - -// Adopt existing svg elements -SVG.adopt = function (node) { - // check for presence of node - if (!node) return null - - // make sure a node isn't already adopted - if (node.instance instanceof SVG.Element) return node.instance - - if (!(node instanceof window.SVGElement)) { - return new SVG.HtmlNode(node) - } - - // initialize variables - var element - - // adopt with element-specific settings - if (node.nodeName === 'svg') { - element = new SVG.Doc(node) - } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') { - element = new SVG.Gradient(node) - } else if (SVG[capitalize(node.nodeName)]) { - element = new SVG[capitalize(node.nodeName)](node) - } else { - element = new SVG.Parent(node) - } - - return element -} +Object.assign(SVG, Classes) +Object.assign(SVG, tools) diff --git a/src/tools.js b/src/tools.js new file mode 100644 index 0000000..e77d653 --- /dev/null +++ b/src/tools.js @@ -0,0 +1,94 @@ +import {ns} from './namespaces.js' +import {Container, Element, HtmlNode, Doc, Gradient, Parent} from './classes.js' + +// Element id sequence +let did = 1000 + +// Get next named element id +export function eid (name) { + return 'Svgjs' + capitalize(name) + (did++) +} + +export function nodeOrNew (name, node) { + return node || makeNode(name) +} + +// Method for element creation +export function makeNode (name) { + // create element + return document.createElementNS(ns, name) +} + +// Method for extending objects +export function extend (modules, methods) { + var key, i + + modules = Array.isArray(modules) ? modules : [modules] + + for (i = modules.length - 1; i >= 0; i--) { + if (modules[i]) { + for (key in methods) { + modules[i].prototype[key] = methods[key] + } + } + } +} + +// FIXME: enhanced constructors here +export function addFactory (modules, methods) { + extend(modules, methods) +} + +// Invent new element +export function invent (config) { + // Create element initializer + var initializer = typeof config.create === 'function' ? config.create + : function (node) { + config.inherit.call(this, node || makeNode(config.create)) + } + + // Inherit prototype + if (config.inherit) { + initializer.prototype = new config.inherit() + initializer.prototype.constructor = initializer + } + + // Extend with methods + if (config.extend) { + extend(initializer, config.extend) + } + + // Attach construct method to parent + if (config.construct) { extend(config.parent || Container, config.construct) } + + return initializer +} + +// Adopt existing svg elements +export function adopt (node) { + // check for presence of node + if (!node) return null + + // make sure a node isn't already adopted + if (node.instance instanceof Element) return node.instance + + if (!(node instanceof window.SVGElement)) { + return new HtmlNode(node) + } + + // initialize variables + var element + + // adopt with element-specific settings + if (node.nodeName === 'svg') { + element = new Doc(node) + } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') { + element = new Gradient(node) + } else if (SVG[capitalize(node.nodeName)]) { + element = new SVG[capitalize(node.nodeName)](node) + } else { + element = new Parent(node) + } + + return element +} diff --git a/src/transform.js b/src/transform.js index 96c0aec..d6516a2 100644 --- a/src/transform.js +++ b/src/transform.js @@ -1,70 +1,67 @@ -/* global arrayToMatrix getOrigin isMatrixLike */ +import {arrayToMatrix, getOrigin, isMatrixLike} from './helpers.js' +import Matrix from './Matrix.js' +import {delimiter, transforms} from './regex.js' -SVG.extend(SVG.Element, { - // Reset all transformations - untransform: function () { - return this.attr('transform', null) - }, +// Reset all transformations +export function untransform () { + return this.attr('transform', null) +} - // merge the whole transformation chain into one matrix and returns it - matrixify: function () { - var matrix = (this.attr('transform') || '') - // split transformations - .split(SVG.regex.transforms).slice(0, -1).map(function (str) { - // generate key => value pairs - var kv = str.trim().split('(') - return [kv[0], - kv[1].split(SVG.regex.delimiter) - .map(function (str) { return parseFloat(str) }) - ] - }) - .reverse() - // merge every transformation into one matrix - .reduce(function (matrix, transform) { - if (transform[0] === 'matrix') { - return matrix.lmultiply(arrayToMatrix(transform[1])) - } - return matrix[transform[0]].apply(matrix, transform[1]) - }, new SVG.Matrix()) +// merge the whole transformation chain into one matrix and returns it +export function matrixify () { + var matrix = (this.attr('transform') || '') + // split transformations + .split(transforms).slice(0, -1).map(function (str) { + // generate key => value pairs + var kv = str.trim().split('(') + return [kv[0], + kv[1].split(delimiter) + .map(function (str) { return parseFloat(str) }) + ] + }) + .reverse() + // merge every transformation into one matrix + .reduce(function (matrix, transform) { + if (transform[0] === 'matrix') { + return matrix.lmultiply(arrayToMatrix(transform[1])) + } + return matrix[transform[0]].apply(matrix, transform[1]) + }, new Matrix()) - return matrix - }, + return matrix +} - // add an element to another parent without changing the visual representation on the screen - toParent: function (parent) { - if (this === parent) return this - var ctm = this.screenCTM() - var pCtm = parent.screenCTM().inverse() +// add an element to another parent without changing the visual representation on the screen +export function toParent (parent) { + if (this === parent) return this + var ctm = this.screenCTM() + var pCtm = parent.screenCTM().inverse() - this.addTo(parent).untransform().transform(pCtm.multiply(ctm)) + this.addTo(parent).untransform().transform(pCtm.multiply(ctm)) - return this - }, + return this +} - // same as above with parent equals root-svg - toDoc: function () { - return this.toParent(this.doc()) - } -}) - -SVG.extend(SVG.Element, { - - // Add transformations - transform: function (o, relative) { - // Act as a getter if no object was passed - if (o == null || typeof o === 'string') { - var decomposed = new SVG.Matrix(this).decompose() - return decomposed[o] || decomposed - } +// same as above with parent equals root-svg +export function toDoc () { + return this.toParent(this.doc()) +} - if (!isMatrixLike(o)) { - // Set the origin according to the defined transform - o = {...o, origin: getOrigin(o, this)} - } +// Add transformations +export function transform (o, relative) { + // Act as a getter if no object was passed + if (o == null || typeof o === 'string') { + var decomposed = new Matrix(this).decompose() + return decomposed[o] || decomposed + } - // The user can pass a boolean, an SVG.Element or an SVG.Matrix or nothing - var cleanRelative = relative === true ? this : (relative || false) - var result = new SVG.Matrix(cleanRelative).transform(o) - return this.attr('transform', result) + if (!isMatrixLike(o)) { + // Set the origin according to the defined transform + o = {...o, origin: getOrigin(o, this)} } -}) + + // The user can pass a boolean, an Element or an Matrix or nothing + var cleanRelative = relative === true ? this : (relative || false) + var result = new Matrix(cleanRelative).transform(o) + return this.attr('transform', result) +} diff --git a/src/use.js b/src/use.js index 2b8e65e..9cf1711 100644 --- a/src/use.js +++ b/src/use.js @@ -1,25 +1,21 @@ +import {Shape, Container} from './classes.js' +import {xlink} from './namespaces.js' -SVG.Use = SVG.invent({ - // Initialize node - create: 'use', - - // Inherit from - inherit: SVG.Shape, +export default class Use extends Shape { + constructor (node) { + super(nodeOrNew('use', node)) + } - // Add class methods - extend: { - // Use element as a reference - element: function (element, file) { - // Set lined element - return this.attr('href', (file || '') + '#' + element, SVG.xlink) - } - }, + // Use element as a reference + element (element, file) { + // Set lined element + return this.attr('href', (file || '') + '#' + element, xlink) + } +} - // Add parent method - construct: { - // Create a use element - use: function (element, file) { - return this.put(new SVG.Use()).element(element, file) - } +addFactory(Container, { + // Create a use element + use: function (element, file) { + return this.put(new Use()).element(element, file) } }) diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..c7407de --- /dev/null +++ b/src/utils.js @@ -0,0 +1,40 @@ + +// Map function +export function map (array, block) { + var i + var il = array.length + var result = [] + + for (i = 0; i < il; i++) { + result.push(block(array[i])) + } + + return result +} + +// Filter function +export function filter (array, block) { + var i + var il = array.length + var result = [] + + for (i = 0; i < il; i++) { + if (block(array[i])) { result.push(array[i]) } + } + + return result +} + +// Degrees to radians +export function radians (d) { + return d % 360 * Math.PI / 180 +} + +// Radians to degrees +export function degrees (r) { + return r * 180 / Math.PI % 360 +} + +export function filterSVGElements (nodes) { + return this.filter(nodes, function (el) { return el instanceof window.SVGElement }) +} -- cgit v1.2.3 From b1b776a710d0ce0a6259043b8ce0665e205195fa Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Fri, 26 Oct 2018 12:01:39 +0200 Subject: rename files --- src/Stop.js | 27 +++++++++++++++++++++++++++ src/Use.js | 21 +++++++++++++++++++++ src/stop.js | 27 --------------------------- src/use.js | 21 --------------------- 4 files changed, 48 insertions(+), 48 deletions(-) create mode 100644 src/Stop.js create mode 100644 src/Use.js delete mode 100644 src/stop.js delete mode 100644 src/use.js (limited to 'src') diff --git a/src/Stop.js b/src/Stop.js new file mode 100644 index 0000000..6bce999 --- /dev/null +++ b/src/Stop.js @@ -0,0 +1,27 @@ +import Element from './Element.js' +import SVGNumber from './SVGNumber.js' +import {nodeOrNew} from './tools.js' + +export default class Stop extends Element { + constructor (node) { + super(nodeOrNew('stop', node)) + } + + // add color stops + 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)) + + return this + } +} diff --git a/src/Use.js b/src/Use.js new file mode 100644 index 0000000..9cf1711 --- /dev/null +++ b/src/Use.js @@ -0,0 +1,21 @@ +import {Shape, Container} from './classes.js' +import {xlink} from './namespaces.js' + +export default class Use extends Shape { + constructor (node) { + super(nodeOrNew('use', node)) + } + + // Use element as a reference + element (element, file) { + // Set lined element + return this.attr('href', (file || '') + '#' + element, xlink) + } +} + +addFactory(Container, { + // Create a use element + use: function (element, file) { + return this.put(new Use()).element(element, file) + } +}) diff --git a/src/stop.js b/src/stop.js deleted file mode 100644 index 6bce999..0000000 --- a/src/stop.js +++ /dev/null @@ -1,27 +0,0 @@ -import Element from './Element.js' -import SVGNumber from './SVGNumber.js' -import {nodeOrNew} from './tools.js' - -export default class Stop extends Element { - constructor (node) { - super(nodeOrNew('stop', node)) - } - - // add color stops - 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)) - - return this - } -} diff --git a/src/use.js b/src/use.js deleted file mode 100644 index 9cf1711..0000000 --- a/src/use.js +++ /dev/null @@ -1,21 +0,0 @@ -import {Shape, Container} from './classes.js' -import {xlink} from './namespaces.js' - -export default class Use extends Shape { - constructor (node) { - super(nodeOrNew('use', node)) - } - - // Use element as a reference - element (element, file) { - // Set lined element - return this.attr('href', (file || '') + '#' + element, xlink) - } -} - -addFactory(Container, { - // Create a use element - use: function (element, file) { - return this.put(new Use()).element(element, file) - } -}) -- cgit v1.2.3 From 1c75fcaf02ceb144152d59557643c6fdd7264065 Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Sat, 27 Oct 2018 20:43:35 +0200 Subject: resolve circular references and make example working again --- abilities | 156 ++++++ dirty.html | 15 +- package.json | 3 +- src/A.js | 39 +- src/Animator.js | 4 +- src/Bare.js | 23 +- src/Base.js | 14 + src/Box.js | 41 +- src/Circle.js | 25 +- src/ClipPath.js | 62 +-- src/Color.js | 9 +- src/Container.js | 2 - src/Controller.js | 1 + src/Defs.js | 9 +- src/Doc.js | 134 ++--- src/Element.js | 395 +++++++-------- src/Ellipse.js | 19 +- src/EventTarget.js | 38 +- src/G.js | 19 +- src/Gradient.js | 37 +- src/HtmlNode.js | 7 +- src/Image.js | 21 +- src/Line.js | 29 +- src/Marker.js | 82 ++-- src/Mask.js | 58 +-- src/Matrix.js | 53 +- src/Morphable.js | 25 +- src/Parent.js | 194 +++++--- src/Path.js | 22 +- src/PathArray.js | 85 ++-- src/Pattern.js | 47 +- src/Point.js | 13 +- src/Polygon.js | 59 +-- src/Polyline.js | 28 +- src/Rect.js | 25 +- src/Runner.js | 108 +++-- src/SVGArray.js | 8 +- src/SVGNumber.js | 6 +- src/Shape.js | 3 - src/Stop.js | 6 +- src/Symbol.js | 17 +- src/Text.js | 103 +--- src/TextPath.js | 77 ++- src/Timeline.js | 17 +- src/Tspan.js | 43 ++ src/Use.js | 18 +- src/adopter.js | 56 +++ src/attr.js | 15 +- src/classes.js | 5 - src/containers.js | 11 + src/css.js | 100 ++-- src/data.js | 45 +- src/default.js | 51 -- src/elements.js | 24 + src/event.js | 16 +- src/flatten.js | 42 -- src/fx.js | 1368 ---------------------------------------------------- src/helpers.js | 30 +- src/memory.js | 61 +-- src/parser.js | 32 +- src/poly.js | 30 ++ src/selector.js | 11 +- src/set.js | 17 + src/svg.js | 87 +++- src/textable.js | 35 ++ src/tools.js | 48 +- src/utilities.js | 43 -- 67 files changed, 1641 insertions(+), 2685 deletions(-) create mode 100644 abilities create mode 100644 src/Base.js delete mode 100644 src/Container.js delete mode 100644 src/Shape.js create mode 100644 src/Tspan.js create mode 100644 src/adopter.js create mode 100644 src/containers.js delete mode 100644 src/default.js create mode 100644 src/elements.js delete mode 100644 src/flatten.js delete mode 100644 src/fx.js create mode 100644 src/poly.js create mode 100644 src/set.js create mode 100644 src/textable.js delete mode 100644 src/utilities.js (limited to 'src') diff --git a/abilities b/abilities new file mode 100644 index 0000000..4d5aa11 --- /dev/null +++ b/abilities @@ -0,0 +1,156 @@ + + +>> Element << + Stop + Bare + >> Parent << + Text + TextPath + >> Container<< + Doc + G + Symbol + Defs + ClipPath + Mask + A + Gradient + Shape + Rect + Circle + Path + Ellipse + Polygon + Polyline + Line + Image + +Animate +Box +Color +Controller + + +===================================================================== + + +classes: + + // MetaData + Title + + // Parents + SVG + G + + // Elements + Rect + Circle + Path + Ellipse + Polygon + Polyline + Line + Image + + // Text Stuff + TSpan + TextPath + + // Data Type + Box + Matrix + SVGNumber + SVGArray + PointArray + PathArray + Color + Controller + +abilities: + Animate + Container + Event + Doc + Movements + Dom + Create + + + + +// DocAbility.js + +import SVG from 'Svg.js' +export default function ( ...worksOn ) { + let workSet = new Set(worksOn) + return { + + doc: function () { + return this.parent(SVG) + } + + } +} + +-> svg.js -> DocAbility.js -> 'Svg.js' + +extend ( [ Rect ], DocAbility() ) + + + +// DomAbility.js + +import {makeInstance} from 'helpers.js' + +export default function ( ...worksOn ) { + let workSet = new Set(worksOn) + let maker = makeInstance(workSet) + + return { + + addTo (parent) { + return maker(parent).put(this) + } + + } +} + +class Rect { + + + static tagName = 'Rect' +} + + + + +new SVG[capitalize[node.nodeName]] + + + +new SVG.Doc() -> ...... + +// SVG.js + +extend( [ ...Parents ], Container(...Elements, ...Parents) ) ) +extend( [ Text ], Container( TSpan, TextPath ) ) + + + +Element.js + +new Element () + +export default class Element { + + static + + static + +} + +Rect.js + +import Element from Element.js +export default class Rect extends Element diff --git a/dirty.html b/dirty.html index f3e739a..5f605de 100644 --- a/dirty.html +++ b/dirty.html @@ -4,14 +4,7 @@ - - - - - - - - + @@ -30,7 +23,11 @@ ---> @@ -25,9 +25,9 @@ --> + @@ -25,9 +25,9 @@ - - - - - - - - - + + --> diff --git a/bench/tests/10000-rects.js b/bench/tests/10000-rects.js index 98b7ac9..d6ef518 100644 --- a/bench/tests/10000-rects.js +++ b/bench/tests/10000-rects.js @@ -17,102 +17,95 @@ SVG.bench.describe('Generate 10000 rects', function(bench) { }) }) - -SVG.bench.describe('Generate 10000 rects with fill', function(bench) { - bench.test('using SVG.js v2.5.3', function() { - for (var i = 0; i < 10000; i++) - bench.draw.rect(100,100).fill('#f06') - }) - bench.test('using vanilla js', function() { - for (var i = 0; i < 10000; i++) { - var rect = document.createElementNS(SVG.ns, 'rect') - rect.setAttributeNS(null, 'height', 100) - rect.setAttributeNS(null, 'width', 100) - rect.setAttributeNS(null, 'fill', '#f06') - bench.raw.appendChild(rect) - } - }) - bench.test('using Snap.svg v0.5.1', function() { - for (var i = 0; i < 10000; i++) - bench.snap.rect(50, 50, 100, 100).attr('fill', '#f06') - }) -}) - - -SVG.bench.describe('Generate 10000 rects with position and fill', function(bench) { - bench.test('using SVG.js v2.5.3', function() { - for (var i = 0; i < 10000; i++) - bench.draw.rect(100,100).move(50,50).fill('#f06') - }) - bench.test('using vanilla js', function() { - for (var i = 0; i < 10000; i++) { - var rect = document.createElementNS(SVG.ns, 'rect') - rect.setAttributeNS(null, 'height', 100) - rect.setAttributeNS(null, 'width', 100) - rect.setAttributeNS(null, 'fill', '#f06') - rect.setAttributeNS(null, 'x', 50) - rect.setAttributeNS(null, 'y', 50) - bench.raw.appendChild(rect) - } - }) - bench.test('using Snap.svg v0.5.1', function() { - for (var i = 0; i < 10000; i++) - bench.snap.rect(50, 50, 100, 100).attr('fill', '#f06') - }) -}) - - -SVG.bench.describe('Generate 10000 rects with gradient fill', function(bench) { - bench.test('using SVG.js v2.5.3', function() { - for (var i = 0; i < 10000; i++) { - var g = bench.draw.gradient('linear', function(add) { - add.stop(0, '#000') - add.stop(0.25, '#f00') - add.stop(1, '#fff') - }) - - bench.draw.rect(100,100).fill(g) - } - }) - bench.test('using vanilla js', function() { - for (var i = 0; i < 10000; i++) { - var g = document.createElementNS(SVG.ns, 'linearGradient') - var stop = document.createElementNS(SVG.ns, 'stop') - stop.setAttributeNS(null, 'offset', '0%') - stop.setAttributeNS(null, 'color', '#000') - g.appendChild(stop) - stop = document.createElementNS(SVG.ns, 'stop') - stop.setAttributeNS(null, 'offset', '25%') - stop.setAttributeNS(null, 'color', '#f00') - g.appendChild(stop) - stop = document.createElementNS(SVG.ns, 'stop') - stop.setAttributeNS(null, 'offset', '100%') - stop.setAttributeNS(null, 'color', '#fff') - g.appendChild(stop) - bench.raw.appendChild(g) - - var rect = document.createElementNS(SVG.ns, 'rect') - rect.setAttributeNS(null, 'height', 100) - rect.setAttributeNS(null, 'width', 100) - rect.setAttributeNS(null, 'fill', '#f06') - bench.raw.appendChild(rect) - } - }) - bench.test('using Snap.svg v0.5.1', function() { - for (var i = 0; i < 10000; i++) { - var g = bench.snap.gradient("L(0, 0, 100, 100)#000-#f00:25%-#fff") - - bench.snap.rect(50, 50, 100, 100).attr({ - fill: g - }) - } - }) -}) - - - - - - - - +// +// SVG.bench.describe('Generate 10000 rects with fill', function(bench) { +// bench.test('using SVG.js v2.5.3', function() { +// for (var i = 0; i < 10000; i++) +// bench.draw.rect(100,100).fill('#f06') +// }) +// bench.test('using vanilla js', function() { +// for (var i = 0; i < 10000; i++) { +// var rect = document.createElementNS(SVG.ns, 'rect') +// rect.setAttributeNS(null, 'height', 100) +// rect.setAttributeNS(null, 'width', 100) +// rect.setAttributeNS(null, 'fill', '#f06') +// bench.raw.appendChild(rect) +// } +// }) +// bench.test('using Snap.svg v0.5.1', function() { +// for (var i = 0; i < 10000; i++) +// bench.snap.rect(50, 50, 100, 100).attr('fill', '#f06') +// }) +// }) +// +// +// SVG.bench.describe('Generate 10000 rects with position and fill', function(bench) { +// bench.test('using SVG.js v2.5.3', function() { +// for (var i = 0; i < 10000; i++) +// bench.draw.rect(100,100).move(50,50).fill('#f06') +// }) +// bench.test('using vanilla js', function() { +// for (var i = 0; i < 10000; i++) { +// var rect = document.createElementNS(SVG.ns, 'rect') +// rect.setAttributeNS(null, 'height', 100) +// rect.setAttributeNS(null, 'width', 100) +// rect.setAttributeNS(null, 'fill', '#f06') +// rect.setAttributeNS(null, 'x', 50) +// rect.setAttributeNS(null, 'y', 50) +// bench.raw.appendChild(rect) +// } +// }) +// bench.test('using Snap.svg v0.5.1', function() { +// for (var i = 0; i < 10000; i++) +// bench.snap.rect(50, 50, 100, 100).attr('fill', '#f06') +// }) +// }) +// +// +// SVG.bench.describe('Generate 10000 rects with gradient fill', function(bench) { +// bench.test('using SVG.js v2.5.3', function() { +// for (var i = 0; i < 10000; i++) { +// var g = bench.draw.gradient('linear', function(add) { +// add.stop(0, '#000') +// add.stop(0.25, '#f00') +// add.stop(1, '#fff') +// }) +// +// bench.draw.rect(100,100).fill(g) +// } +// }) +// bench.test('using vanilla js', function() { +// for (var i = 0; i < 10000; i++) { +// var g = document.createElementNS(SVG.ns, 'linearGradient') +// var stop = document.createElementNS(SVG.ns, 'stop') +// stop.setAttributeNS(null, 'offset', '0%') +// stop.setAttributeNS(null, 'color', '#000') +// g.appendChild(stop) +// stop = document.createElementNS(SVG.ns, 'stop') +// stop.setAttributeNS(null, 'offset', '25%') +// stop.setAttributeNS(null, 'color', '#f00') +// g.appendChild(stop) +// stop = document.createElementNS(SVG.ns, 'stop') +// stop.setAttributeNS(null, 'offset', '100%') +// stop.setAttributeNS(null, 'color', '#fff') +// g.appendChild(stop) +// bench.raw.appendChild(g) +// +// var rect = document.createElementNS(SVG.ns, 'rect') +// rect.setAttributeNS(null, 'height', 100) +// rect.setAttributeNS(null, 'width', 100) +// rect.setAttributeNS(null, 'fill', '#f06') +// bench.raw.appendChild(rect) +// } +// }) +// bench.test('using Snap.svg v0.5.1', function() { +// for (var i = 0; i < 10000; i++) { +// var g = bench.snap.gradient("L(0, 0, 100, 100)#000-#f00:25%-#fff") +// +// bench.snap.rect(50, 50, 100, 100).attr({ +// fill: g +// }) +// } +// }) +// }) +// diff --git a/dist/svg.js b/dist/svg.js index 7c9bc18..44978bd 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -715,31 +715,61 @@ var SVG = (function () { var methods = {}; var constructors = {}; function registerMethods(name, m) { + if (Array.isArray(name)) { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = name[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var _name = _step.value; + registerMethods(_name, m); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + return; + } + if (_typeof(name) == 'object') { var _arr = Object.entries(name); for (var _i = 0; _i < _arr.length; _i++) { var _arr$_i = _slicedToArray(_arr[_i], 2), - _name = _arr$_i[0], + _name2 = _arr$_i[0], _m = _arr$_i[1]; - registerMethods(_name, _m); + registerMethods(_name2, _m); } + + return; } methods[name] = Object.assign(methods[name] || {}, m); } function getMethodsFor(name) { - return methods[name]; + return methods[name] || {}; } // FIXME: save memory? function registerConstructor(name, setup) { constructors[name] = setup; } function getConstructor(name) { - return { + return constructors[name] ? { setup: constructors[name], name: name - }; + } : {}; } var Doc$1 = @@ -1053,7 +1083,7 @@ var SVG = (function () { } }); - var SVGNumber = + var SVGNumber$1 = /*#__PURE__*/ function () { // Initialize @@ -1178,16 +1208,16 @@ var SVG = (function () { } // Set width of element function width(width) { - return width == null ? this.rx() * 2 : this.rx(new SVGNumber(width).divide(2)); + return width == null ? this.rx() * 2 : this.rx(new SVGNumber$1(width).divide(2)); } // Set height of element function height(height) { - return height == null ? this.ry() * 2 : this.ry(new SVGNumber(height).divide(2)); + return height == null ? this.ry() * 2 : this.ry(new SVGNumber$1(height).divide(2)); } // Custom size function function size(width, height) { var p = proportionalSize$1(this, width, height); - return this.rx(new SVGNumber(p.width).divide(2)).ry(new SVGNumber(p.height).divide(2)); + return this.rx(new SVGNumber$1(p.width).divide(2)).ry(new SVGNumber$1(p.height).divide(2)); } var circled = /*#__PURE__*/Object.freeze({ @@ -1247,7 +1277,7 @@ var SVG = (function () { Element: { // Create circle element circle: function circle(size$$1) { - return this.put(new Circle()).radius(new SVGNumber(size$$1).divide(2)).move(0, 0); + return this.put(new Circle()).radius(new SVGNumber$1(size$$1).divide(2)).move(0, 0); } } }); @@ -1354,7 +1384,7 @@ var SVG = (function () { function size$1(width, height) { var p = proportionalSize$1(this, width, height); - return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height)); + return this.width(new SVGNumber$1(p.width)).height(new SVGNumber$1(p.height)); } // Clone element function clone(parent) { @@ -1380,6 +1410,10 @@ var SVG = (function () { return element; } // Add element to given container and return self + function addTo(parent) { + return makeInstance(parent).put(this); + } // Add element to given container and return container + function putIn(parent) { return makeInstance(parent).add(this); } // Get / set id @@ -1508,6 +1542,7 @@ var SVG = (function () { clone: clone, remove: remove, replace: replace, + addTo: addTo, putIn: putIn, id: id$1, inside: inside, @@ -1675,7 +1710,7 @@ var SVG = (function () { _createClass(Stop, [{ key: "update", value: function update(o) { - if (typeof o === 'number' || o instanceof SVGNumber) { + if (typeof o === 'number' || o instanceof SVGNumber$1) { o = { offset: arguments[0], color: arguments[1], @@ -1686,7 +1721,7 @@ var SVG = (function () { 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.offset != null) this.attr('offset', new SVGNumber$1(o.offset)); return this; } }]); @@ -1698,20 +1733,20 @@ var SVG = (function () { // FIXME: add to runner function from(x, y) { return (this._element || this).type === 'radialGradient' ? this.attr({ - fx: new SVGNumber(x), - fy: new SVGNumber(y) + fx: new SVGNumber$1(x), + fy: new SVGNumber$1(y) }) : this.attr({ - x1: new SVGNumber(x), - y1: new SVGNumber(y) + x1: new SVGNumber$1(x), + y1: new SVGNumber$1(y) }); } function to(x, y) { return (this._element || this).type === 'radialGradient' ? this.attr({ - cx: new SVGNumber(x), - cy: new SVGNumber(y) + cx: new SVGNumber$1(x), + cy: new SVGNumber$1(y) }) : this.attr({ - x2: new SVGNumber(x), - y2: new SVGNumber(y) + x2: new SVGNumber$1(x), + y2: new SVGNumber$1(y) }); } @@ -2010,7 +2045,7 @@ var SVG = (function () { if (typeof val === 'number') { - val = new SVGNumber(val); + val = new SVGNumber$1(val); } else if (Color.isColor(val)) { // ensure full hex color val = new Color(val); @@ -2774,7 +2809,7 @@ var SVG = (function () { return parser.nodes; } - var Point = + var Point$1 = /*#__PURE__*/ function () { // Initialize @@ -2837,7 +2872,7 @@ var SVG = (function () { Element: { // Get point point: function point(x, y) { - return new Point(x, y).transform(this.screenCTM().inverse()); + return new Point$1(x, y).transform(this.screenCTM().inverse()); } } }); @@ -3115,8 +3150,8 @@ var SVG = (function () { var result = []; - var p = new Point(); - var p0 = new Point(); + var p = new Point$1(); + var p0 = new Point$1(); var index = 0; var len = array.length; @@ -3433,7 +3468,7 @@ var SVG = (function () { _classCallCheck(this, Text); _this = _possibleConstructorReturn(this, _getPrototypeOf(Text).call(this, nodeOrNew$1('text', node), Text)); - _this.dom.leading = new SVGNumber(1.3); // store leading value for rebuilding + _this.dom.leading = new SVGNumber$1(1.3); // store leading value for rebuilding _this._rebuild = true; // enable automatic updating of dy values @@ -3538,7 +3573,7 @@ var SVG = (function () { } // act as setter - this.dom.leading = new SVGNumber(value); + this.dom.leading = new SVGNumber$1(value); return this.rebuild(); } // Rebuild appearance type @@ -3554,7 +3589,7 @@ var SVG = (function () { if (this._rebuild) { var self = this; var blankLineOffset = 0; - var dy = this.dom.leading * new SVGNumber(this.attr('font-size')); + var dy = this.dom.leading * new SVGNumber$1(this.attr('font-size')); this.each(function () { if (this.dom.newLined) { this.attr('x', self.attr('x')); @@ -3584,7 +3619,7 @@ var SVG = (function () { key: "setData", value: function setData(o) { this.dom = o; - this.dom.leading = new SVGNumber(o.leading || 1.3); + this.dom.leading = new SVGNumber$1(o.leading || 1.3); return this; } }]); @@ -3789,7 +3824,7 @@ var SVG = (function () { }); register(Use); - var Matrix = + var Matrix$1 = /*#__PURE__*/ function () { function Matrix() { @@ -3833,7 +3868,7 @@ var SVG = (function () { var t = Matrix.formatTransforms(o); var current = this; - var _transform = new Point(t.ox, t.oy).transform(current), + var _transform = new Point$1(t.ox, t.oy).transform(current), ox = _transform.x, oy = _transform.y; // Construct the resulting matrix @@ -3841,7 +3876,7 @@ var SVG = (function () { var transformer = new Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy); // If we want the origin at a particular place, we force it there if (isFinite(t.px) || isFinite(t.py)) { - var origin = new Point(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px) + var origin = new Point$1(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px) var dx = t.px ? t.px - origin.x : 0; var dy = t.py ? t.py - origin.y : 0; @@ -4229,16 +4264,16 @@ var SVG = (function () { var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY; var shear = o.shear || 0; var theta = o.rotate || o.theta || 0; - var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY); + var origin = new Point$1(o.origin || o.around || o.ox || o.originX, o.oy || o.originY); var ox = origin.x; var oy = origin.y; - var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY); + var position = new Point$1(o.position || o.px || o.positionX, o.py || o.positionY); var px = position.x; var py = position.y; - var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY); + var translate = new Point$1(o.translate || o.tx || o.translateX, o.ty || o.translateY); var tx = translate.x; var ty = translate.y; - var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY); + var relative = new Point$1(o.relative || o.rx || o.relativeX, o.ry || o.relativeY); var rx = relative.x; var ry = relative.y; // Populate all of the values @@ -4287,7 +4322,7 @@ var SVG = (function () { Element: { // Get current matrix ctm: function ctm() { - return new Matrix(this.node.getCTM()); + return new Matrix$1(this.node.getCTM()); }, // Get current screen matrix screenCTM: function screenCTM() { @@ -4299,10 +4334,10 @@ var SVG = (function () { var rect = this.rect(1, 1); var m = rect.node.getScreenCTM(); rect.remove(); - return new Matrix(m); + return new Matrix$1(m); } - return new Matrix(this.node.getScreenCTM()); + return new Matrix$1(this.node.getScreenCTM()); } } }); @@ -4345,7 +4380,7 @@ var SVG = (function () { var xMax = -Infinity; var yMin = Infinity; var yMax = -Infinity; - var pts = [new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2)]; + var pts = [new Point$1(this.x, this.y), new Point$1(this.x2, this.y), new Point$1(this.x, this.y2), new Point$1(this.x2, this.y2)]; pts.forEach(function (p) { p = p.transform(m); xMin = Math.min(xMin, p.x); @@ -4709,14 +4744,14 @@ var SVG = (function () { var type = _typeof(value); if (type === 'number') { - this.type(SVGNumber); + this.type(SVGNumber$1); } else if (type === 'string') { if (Color.isColor(value)) { this.type(Color); } else if (regex.delimiter.test(value)) { this.type(regex.pathLetters.test(value) ? PathArray : SVGArray); } else if (regex.numberAndUnit.test(value)) { - this.type(SVGNumber); + this.type(SVGNumber$1); } else { this.type(Morphable.NonMorphable); } @@ -4893,7 +4928,7 @@ var SVG = (function () { return _class3; }(); - var morphableTypes = [SVGNumber, Color, Box$1, Matrix, SVGArray, PointArray$1, PathArray, Morphable.NonMorphable, Morphable.TransformBag, Morphable.ObjectBag]; + var morphableTypes = [SVGNumber$1, Color, Box$1, Matrix$1, SVGArray, PointArray$1, PathArray, Morphable.NonMorphable, Morphable.TransformBag, Morphable.ObjectBag]; extend$1(morphableTypes, { to: function to(val, args) { return new Morphable().type(this.constructor).from(this.valueOf()).to(val, args); @@ -5205,7 +5240,7 @@ var SVG = (function () { // '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } // } - var Runner = + var Runner$1 = /*#__PURE__*/ function () { function Runner(options) { @@ -5233,7 +5268,7 @@ var SVG = (function () { this._time = 0; this._last = 0; // Save transforms applied to this runner - this.transforms = new Matrix(); + this.transforms = new Matrix$1(); this.transformId = 1; // Looping variables this._haveReversed = false; @@ -5474,7 +5509,7 @@ var SVG = (function () { this._initialise(running); // clear the transforms on this runner so they dont get added again and again - this.transforms = new Matrix(); + this.transforms = new Matrix$1(); var converged = this._run(declarative ? dt : position); // this.fire('step', this) @@ -5608,7 +5643,7 @@ var SVG = (function () { }, { key: "clearTransform", value: function clearTransform() { - this.transforms = new Matrix(); + this.transforms = new Matrix$1(); return this; } }], [{ @@ -5644,10 +5679,10 @@ var SVG = (function () { return Runner; }(); - Runner.id = 0; + Runner$1.id = 0; var FakeRunner = function FakeRunner() { - var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix(); + var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix$1(); var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; var done = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; @@ -5658,7 +5693,7 @@ var SVG = (function () { this.done = done; }; - extend$1([Runner, FakeRunner], { + extend$1([Runner$1, FakeRunner], { mergeWith: function mergeWith(runner) { return new FakeRunner(runner.transforms.lmultiply(this.transforms), runner.id); } @@ -5675,7 +5710,7 @@ var SVG = (function () { function mergeTransforms() { // Find the matrix to apply to the element and apply it var runners = this._transformationRunners.runners; - var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix()); + var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix$1()); this.transform(netTransform); this._transformationRunners.merge(); @@ -5769,9 +5804,9 @@ var SVG = (function () { registerMethods({ Element: { animate: function animate(duration, delay, when) { - var o = Runner.sanitise(duration, delay, when); + var o = Runner$1.sanitise(duration, delay, when); var timeline$$1 = this.timeline(); - return new Runner(o.duration).loop(o).element(this).timeline(timeline$$1).schedule(delay, when); + return new Runner$1(o.duration).loop(o).element(this).timeline(timeline$$1).schedule(delay, when); }, delay: function delay(by, when) { return this.animate(0, by, when); @@ -5789,7 +5824,7 @@ var SVG = (function () { // taken into account .filter(function (runner) { return runner.id <= current.id; - }).map(getRunnerTransform).reduce(lmultiply, new Matrix()); + }).map(getRunnerTransform).reduce(lmultiply, new Matrix$1()); }, addRunner: function addRunner(runner) { this._transformationRunners.add(runner); @@ -5798,13 +5833,13 @@ var SVG = (function () { }, _prepareRunner: function _prepareRunner() { if (this._frameId == null) { - this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix(this))); + this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix$1(this))); this._frameId = frameId++; } } } }); - extend$1(Runner, { + extend$1(Runner$1, { attr: function attr(a, v) { return this.styleAttr('attr', a, v); }, @@ -5830,7 +5865,7 @@ var SVG = (function () { return this; }, zoom: function zoom(level, point) { - var morpher = new Morphable(this._stepper).to(new SVGNumber(level)); + var morpher = new Morphable(this._stepper).to(new SVGNumber$1(level)); this.queue(function () { morpher = morpher.from(this.zoom()); }, function (pos) { @@ -5867,7 +5902,7 @@ var SVG = (function () { var isMatrix = isMatrixLike(transforms); affine = transforms.affine != null ? transforms.affine : affine != null ? affine : !isMatrix; // Create a morepher and set its type - var morpher = new Morphable().type(affine ? Morphable.TransformBag : Matrix).stepper(this._stepper); + var morpher = new Morphable().type(affine ? Morphable.TransformBag : Matrix$1).stepper(this._stepper); var origin; var element; var current; @@ -5878,7 +5913,7 @@ var SVG = (function () { // make sure element and origin is defined element = element || this.element(); origin = origin || getOrigin(transforms, element); - startTransform = new Matrix(relative ? undefined : element); // add the runner to the element so it can merge transformations + startTransform = new Matrix$1(relative ? undefined : element); // add the runner to the element so it can merge transformations element.addRunner(this); // Deactivate all transforms that have run so far if we are absolute @@ -5892,11 +5927,11 @@ var SVG = (function () { // on this runner. We are absolute. We dont need these! if (!relative) this.clearTransform(); - var _transform = new Point(origin).transform(element._currentTransform(this)), + var _transform = new Point$1(origin).transform(element._currentTransform(this)), x = _transform.x, y = _transform.y; - var target = new Matrix(_objectSpread({}, transforms, { + var target = new Matrix$1(_objectSpread({}, transforms, { origin: [x, y] })); var start = this._isDeclarative && current ? current : startTransform; @@ -5933,7 +5968,7 @@ var SVG = (function () { morpher.to(target); var affineParameters = morpher.at(pos); currentAngle = affineParameters.rotate; - current = new Matrix(affineParameters); + current = new Matrix$1(affineParameters); this.addTransform(current); return morpher.done(); } @@ -5969,7 +6004,7 @@ var SVG = (function () { return this._queueNumberDelta('dy', y); }, _queueNumberDelta: function _queueNumberDelta(method, to) { - to = new SVGNumber(to); // Try to change the target if we have this method already registerd + to = new SVGNumber$1(to); // Try to change the target if we have this method already registerd if (this._tryRetargetDelta(method, to)) return this; // Make a morpher and queue the animation @@ -6004,7 +6039,7 @@ var SVG = (function () { return this; }, _queueNumber: function _queueNumber(method, value) { - return this._queueObject(method, new SVGNumber(value)); + return this._queueObject(method, new SVGNumber$1(value)); }, // Animatable center x-axis cx: function cx(x) { @@ -6163,17 +6198,17 @@ var SVG = (function () { TextPath: TextPath, Tspan: Tspan, Use: Use, - SVGNumber: SVGNumber, + SVGNumber: SVGNumber$1, SVGArray: SVGArray, PathArray: PathArray, PointArray: PointArray$1, - Matrix: Matrix, - Point: Point, + Matrix: Matrix$1, + Point: Point$1, Box: Box$1, Color: Color, Morphable: Morphable, Queue: Queue, - Runner: Runner, + Runner: Runner$1, Timeline: Timeline, Controller: Controller, Ease: Ease, @@ -6334,7 +6369,7 @@ var SVG = (function () { } return matrix[transform[0]].apply(matrix, transform[1]); - }, new Matrix()); + }, new Matrix$1()); return matrix; } // add an element to another parent without changing the visual representation on the screen @@ -6353,7 +6388,7 @@ var SVG = (function () { function transform(o, relative) { // Act as a getter if no object was passed if (o == null || typeof o === 'string') { - var decomposed = new Matrix(this).decompose(); + var decomposed = new Matrix$1(this).decompose(); return decomposed[o] || decomposed; } @@ -6366,7 +6401,7 @@ var SVG = (function () { var cleanRelative = relative === true ? this : relative || false; - var result = new Matrix(cleanRelative).transform(o); + var result = new Matrix$1(cleanRelative).transform(o); return this.attr('transform', result); } registerMethods('Element', { @@ -6420,6 +6455,157 @@ var SVG = (function () { }); registerConstructor('Memory', setup$1); + var sugar = { + stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], + fill: ['color', 'opacity', 'rule'], + prefix: function prefix(t, a) { + return a === 'color' ? t : t + '-' + a; + } // Add sugar for fill and stroke + + }; + ['fill', 'stroke'].forEach(function (m) { + var extension = {}; + var i; + + extension[m] = function (o) { + if (typeof o === 'undefined') { + return this; + } + + if (typeof o === 'string' || Color.isRgb(o) || o && typeof o.fill === 'function') { + this.attr(m, o); + } else { + // set all attributes from sugar.fill and sugar.stroke list + for (i = sugar[m].length - 1; i >= 0; i--) { + if (o[sugar[m][i]] != null) { + this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]]); + } + } + } + + return this; + }; + + registerMethods(['Element', 'Runner'], extension); + }); + registerMethods(['Element', 'Runner'], { + // Let the user set the matrix directly + matrix: function matrix(mat, b, c, d, e, f) { + // Act as a getter + if (mat == null) { + return new Matrix(this); + } // Act as a setter, the user can pass a matrix or a set of numbers + + + return this.attr('transform', new Matrix(mat, b, c, d, e, f)); + }, + // Map rotation to transform + rotate: function rotate(angle, cx, cy) { + return this.transform({ + rotate: angle, + ox: cx, + oy: cy + }, true); + }, + // Map skew to transform + skew: function skew(x, y, cx, cy) { + return arguments.length === 1 || arguments.length === 3 ? this.transform({ + skew: x, + ox: y, + oy: cx + }, true) : this.transform({ + skew: [x, y], + ox: cx, + oy: cy + }, true); + }, + shear: function shear(lam, cx, cy) { + return this.transform({ + shear: lam, + ox: cx, + oy: cy + }, true); + }, + // Map scale to transform + scale: function scale(x, y, cx, cy) { + return arguments.length === 1 || arguments.length === 3 ? this.transform({ + scale: x, + ox: y, + oy: cx + }, true) : this.transform({ + scale: [x, y], + ox: cx, + oy: cy + }, true); + }, + // Map translate to transform + translate: function translate(x, y) { + return this.transform({ + translate: [x, y] + }, true); + }, + // Map relative translations to transform + relative: function relative(x, y) { + return this.transform({ + relative: [x, y] + }, true); + }, + // Map flip to transform + flip: function flip(direction, around) { + var directionString = typeof direction === 'string' ? direction : isFinite(direction) ? 'both' : 'both'; + var origin = direction === 'both' && isFinite(around) ? [around, around] : direction === 'x' ? [around, 0] : direction === 'y' ? [0, around] : isFinite(direction) ? [direction, direction] : [0, 0]; + this.transform({ + flip: directionString, + origin: origin + }, true); + }, + // Opacity + opacity: function opacity(value) { + return this.attr('opacity', value); + }, + // Relative move over x axis + dx: function dx(x) { + return this.x(new SVGNumber(x).plus(this instanceof Runner ? 0 : this.x()), true); + }, + // Relative move over y axis + dy: function dy(y) { + return this.y(new SVGNumber(y).plus(this instanceof Runner ? 0 : this.y()), true); + }, + // Relative move over x and y axes + dmove: function dmove(x, y) { + return this.dx(x).dy(y); + } + }); + registerMethods('radius', { + // Add x and y radius + radius: function radius(x, y) { + var type = (this._target || this).type; + return type === 'radialGradient' || type === 'radialGradient' ? this.attr('r', new SVGNumber(x)) : this.rx(x).ry(y == null ? x : y); + } + }); + registerMethods('Path', { + // Get path length + length: function length() { + return this.node.getTotalLength(); + }, + // Get point at length + pointAt: function pointAt(length) { + return new Point(this.node.getPointAtLength(length)); + } + }); + registerMethods(['Container', 'Runner'], { + // Set font + font: function font(a, v) { + if (_typeof(a) === 'object') { + for (v in a) { + this.font(v, a[v]); + } + } + + return a === 'leading' ? this.leading(v) : a === 'anchor' ? this.attr('text-anchor', v) : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style' ? this.attr('font-' + a, v) : this.attr(a, v); + } + }); + function setup$2() { var node = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; this.events = node.events || {}; @@ -6462,8 +6648,10 @@ var SVG = (function () { function add(element, i) { element = makeInstance(element); - if (element.node !== this.node.children[i]) { - this.node.insertBefore(element.node, this.node.children[i] || null); + 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; @@ -6606,6 +6794,7 @@ var SVG = (function () { extend$2(Path, getMethodsFor('Path')); extend$2(Defs, getMethodsFor('Defs')); extend$2([Text$1, Tspan], getMethodsFor('Tspan')); + extend$2([Rect, Ellipse, Circle, Gradient], getMethodsFor('radius')); var containerMethods = getMethodsFor('Container'); // FIXME: We need a container array for (var i$1 in containers) { diff --git a/dist/svg.min.js b/dist/svg.min.js index 9d05a1f..4571bd5 100644 --- a/dist/svg.min.js +++ b/dist/svg.min.js @@ -1 +1 @@ -var SVG=function(){"use strict";function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function c(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;n=e.time?e.run():dt.timeouts.push(e),e!==n););for(var i=null,r=dt.frames.last();i!==r&&(i=dt.frames.shift());)i.run();dt.transforms.forEach(function(t){t()}),dt.nextDraw=dt.timeouts.first()||dt.frames.first()?window.requestAnimationFrame(dt._draw):null}},vt=function(t){function i(t,e){var n;return c(this,i),n=f(this,o(i).call(this,Y(null,t),i)),extend(r(r(n)),e),n}return u(i,d),a(i,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),i}();W(vt),ut("Bare",{element:function(t,e){var n=createCustom(t,e);return this.put(new n)}});var yt=function(){function n(){c(this,n),this.init.apply(this,arguments)}return a(n,[{key:"init",value:function(t,e){e=Array.isArray(t)?t[1]:e,t=Array.isArray(t)?t[0]:t,this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-34e37:34e37:"string"==typeof t?(e=t.match(h))&&(this.value=parseFloat(e[1]),"%"===e[5]?this.value/=100:"s"===e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof n&&(this.value=t.valueOf(),this.unit=t.unit)}},{key:"toString",value:function(){return("%"===this.unit?~~(1e8*this.value)/1e6:"s"===this.unit?this.value/1e3:this.value)+this.unit}},{key:"toJSON",value:function(){return this.toString()}},{key:"toArray",value:function(){return[this.value,this.unit]}},{key:"valueOf",value:function(){return this.value}},{key:"plus",value:function(t){return new n(this+(t=new n(t)),this.unit||t.unit)}},{key:"minus",value:function(t){return new n(this-(t=new n(t)),this.unit||t.unit)}},{key:"times",value:function(t){return new n(this*(t=new n(t)),this.unit||t.unit)}},{key:"divide",value:function(t){return new n(this/(t=new n(t)),this.unit||t.unit)}}]),n}();function pt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function mt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function gt(t){return null==t?this.attr("cx"):this.attr("cx",t)}function wt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function kt(t){return null==t?2*this.rx():this.rx(new yt(t).divide(2))}function xt(t){return null==t?2*this.ry():this.ry(new yt(t).divide(2))}function bt(t,e){var n=P(this,t,e);return this.rx(new yt(n.width).divide(2)).ry(new yt(n.height).divide(2))}var _t=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:pt,y:mt,cx:gt,cy:wt,width:kt,height:xt,size:bt}),Ot=function(t){function e(t){return c(this,e),f(this,o(e).call(this,Y("circle",t),e))}return u(e,d),a(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function At(t){return t%360*Math.PI/180}function Mt(t,e){return utils.map((e||document).querySelectorAll(t),function(t){return $(t)})}H(Ot,{x:pt,y:mt,cx:gt,cy:wt,width:kt,height:xt,size:bt}),ut({Element:{circle:function(t){return this.put(new Ot).radius(new yt(t).divide(2)).move(0,0)}}}),W(Ot),ut("Container",{find:function(t){return Mt(t,this.node)}});var Tt=Z(U);function Ct(){return this.parent()&&this.parent().removeElement(this),this}ut("Element",{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var n=P(this,t,e);return this.width(new yt(n.width)).height(new yt(n.height))},clone:function(t){this.writeDataToDom();var e=tt(this.node.cloneNode(!0));return t?t.add(e):this.after(e),e},remove:Ct,replace:function(t){return this.after(t).remove(),t},putIn:function(t){return Q(t).add(this)},id:function(t){return void 0!==t||this.node.id||(this.node.id=K(this.type)),this.attr("id",t)},inside:function(t,e){var n=this.bbox();return t>n.x&&e>n.y&&t",It=0,Lt={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},Rt=function(){function t(){c(this,t),this.init.apply(this,arguments)}return a(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?g.test(t)?(i=y.exec(t.replace(p,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):m.test(t)&&(i=v.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+N(Math.round(this.r))+N(Math.round(this.g))+N(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",m.test(t)||g.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}(),Bt=function(){try{return Array}catch(t){return Array}}(),Xt=function(t){function n(){var t,e;return c(this,n),(t=e=f(this,o(n).call(this))).init.apply(t,arguments),e}return u(n,Bt),a(n,[{key:"init",value:function(t,e){this.length=0,this.push.apply(this,O(this.parse(t||e)))}},{key:"toArray",value:function(){return Array.prototype.slice(this)}},{key:"toString",value:function(){this.join(" ")}},{key:"valueOf",value:function(){return this.toArray()}},{key:"parse",value:function(t){return t=t.valueOf(),Array.isArray(t)?t:t.trim().split(b).map(parseFloat)}},{key:"clone",value:function(){return new this.constructor(this)}},{key:"toSet",value:function(){return new Set(this)}}]),n}();function Yt(t,e,n){if(null==t){t={},e=this.node.attributes;var i=!0,r=!1,s=void 0;try{for(var u,a=e[Symbol.iterator]();!(i=(u=a.next()).done);i=!0){var o=u.value;t[o.nodeName]=isNumer.test(o.nodeValue)?parseFloat(o.nodeValue):o.nodeValue}}catch(t){r=!0,s=t}finally{try{i||null==a.return||a.return()}finally{if(r)throw s}}return t}if(Array.isArray(t));else if("object"===l(t))for(e in t)this.attr(e,t[e]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return null==(e=this.node.getAttribute(t))?Lt[t]:k.test(e)?parseFloat(e):e;for("fill"!==t&&"stroke"!==t||x.test(e)&&(e=this.doc().defs().image(e));"function"==typeof e.attrHook;)e=e.attrHook(this,t);"number"==typeof e?e=new yt(e):Rt.isColor(e)?e=new Rt(e):Array.isArray(e)&&(e=new Xt(e)),"leading"===t?this.leading&&this.leading(e):"string"==typeof n?this.node.setAttributeNS(n,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!==t&&"x"!==t||this.rebuild()}return this}ut("Element",{attr:Yt});var Ft=function(t){function e(t){return c(this,e),f(this,o(e).call(this,Y(t+"Gradient","string"==typeof t?null:t),e))}return u(e,d),a(e,[{key:"stop",value:function(t,e,n){return this.put(new Nt).update(t,e,n)}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="gradientTransform"),Yt.call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}}]),e}();H(Ft,Pt),ut({Container:{gradient:function(t,e){return this.defs().gradient(t,e)}},Defs:{gradient:function(t,e){return this.put(new Ft(t)).update(e)}}}),W(Ft);var Ht=function(t){function e(t){return c(this,e),f(this,o(e).call(this,Y("pattern",t)))}return u(e,d),a(e,[{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="patternTransform"),Yt.call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}}]),e}();ut({Container:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}},Defs:{pattern:function(t,e,n){return this.put(new Ht).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}}),W(Ht);var Gt=0;function Vt(t){return t instanceof Base&&t.is("EventTarget")?t.getEventTarget():t}function Ut(t,e,i,n,r){var s=i.bind(n||t),u=Vt(t);e=Array.isArray(e)?e:e.split(b),u.instance=u.instance||{events:{}};var a=u.instance.events;i._svgjsListenerId||(i._svgjsListenerId=++Gt),e.forEach(function(t){var e=t.split(".")[0],n=t.split(".")[1]||"*";a[e]=a[e]||{},a[e][n]=a[e][n]||{},a[e][n][i._svgjsListenerId]=s,u.addEventListener(e,s,r||!1)})}function Qt(t,e,s,u){var a=Vt(t);if(a.instance&&("function"!=typeof s||(s=s._svgjsListenerId))){var o=a.instance.events;(e=Array.isArray(e)?e:(e||"").split(b)).forEach(function(t){var e,n,i=t&&t.split(".")[0],r=t&&t.split(".")[1];if(s)o[i]&&o[i][r||"*"]&&(a.removeEventListener(i,o[i][r||"*"][s],u||!1),delete o[i][r||"*"][s]);else if(i&&r){if(o[i]&&o[i][r]){for(n in o[i][r])Qt(a,[i,r].join("."),n);delete o[i][r]}}else if(r)for(t in o)for(e in o[t])r===e&&Qt(a,[t,r].join("."));else if(i){if(o[i]){for(e in o[i])Qt(a,[i,e].join("."));delete o[i]}}else{for(t in o)Qt(a,t);a.instance.events={}}})}}var $t=function(t){function e(t){return c(this,e),f(this,o(e).call(this,Y("image",t),e))}return u(e,d),a(e,[{key:"load",value:function(n,i){if(!n)return this;var r=new window.Image;return Ut(r,"load",function(t){var e=this.parent(Ht);0===this.width()&&0===this.height()&&this.size(r.width,r.height),e instanceof Ht&&0===e.width()&&0===e.height()&&e.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:r.width,height:r.height,ratio:r.width/r.height,url:n})},this),Ut(r,"load error",function(){Qt(r)}),this.attr("href",r.src=n,X)}},{key:"attrHook",value:function(t){var e=this;return t.doc().defs().pattern(0,0,function(t){t.add(e)})}}]),e}();ut({Container:{image:function(t,e){return this.put(new $t).size(0,0).load(t,e)}}}),W($t);var Wt=function(t){function r(t){var e=1":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Ae=function(){function t(){c(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),Me=function(t){function n(t){var e;return c(this,n),(e=f(this,o(n).call(this))).ease=Oe[t||qt]||t,e}return u(n,Ae),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),Te=function(t){function n(t){var e;return c(this,n),(e=f(this,o(n).call(this))).stepper=t,e}return u(n,Ae),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Ce(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var je=function(t){function i(t,e){var n;return c(this,i),(n=f(this,o(i).call(this))).duration(t||500).overshoot(e||0),n}return u(i,Te),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i);this._lastTime=this._time;var s=this._isDeclarative;if(this.done=!s&&!r&&this._time>=i,n||s){this._initialise(n),this.transforms=new ke;var u=this._run(s?t:e)}return this.done=this.done||u&&s,this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new Me(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e=e.time?e.run():dt.timeouts.push(e),e!==n););for(var i=null,r=dt.frames.last();i!==r&&(i=dt.frames.shift());)i.run();dt.transforms.forEach(function(t){t()}),dt.nextDraw=dt.timeouts.first()||dt.frames.first()?window.requestAnimationFrame(dt._draw):null}},vt=function(t){function i(t,e){var n;return c(this,i),n=f(this,o(i).call(this,X(null,t),i)),extend(r(r(n)),e),n}return u(i,s),a(i,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),i}();W(vt),ut("Bare",{element:function(t,e){var n=createCustom(t,e);return this.put(new n)}});var yt=function(){function n(){c(this,n),this.init.apply(this,arguments)}return a(n,[{key:"init",value:function(t,e){e=Array.isArray(t)?t[1]:e,t=Array.isArray(t)?t[0]:t,this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-34e37:34e37:"string"==typeof t?(e=t.match(h))&&(this.value=parseFloat(e[1]),"%"===e[5]?this.value/=100:"s"===e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof n&&(this.value=t.valueOf(),this.unit=t.unit)}},{key:"toString",value:function(){return("%"===this.unit?~~(1e8*this.value)/1e6:"s"===this.unit?this.value/1e3:this.value)+this.unit}},{key:"toJSON",value:function(){return this.toString()}},{key:"toArray",value:function(){return[this.value,this.unit]}},{key:"valueOf",value:function(){return this.value}},{key:"plus",value:function(t){return new n(this+(t=new n(t)),this.unit||t.unit)}},{key:"minus",value:function(t){return new n(this-(t=new n(t)),this.unit||t.unit)}},{key:"times",value:function(t){return new n(this*(t=new n(t)),this.unit||t.unit)}},{key:"divide",value:function(t){return new n(this/(t=new n(t)),this.unit||t.unit)}}]),n}();function pt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function mt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function gt(t){return null==t?this.attr("cx"):this.attr("cx",t)}function wt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function xt(t){return null==t?2*this.rx():this.rx(new yt(t).divide(2))}function kt(t){return null==t?2*this.ry():this.ry(new yt(t).divide(2))}function bt(t,e){var n=P(this,t,e);return this.rx(new yt(n.width).divide(2)).ry(new yt(n.height).divide(2))}var _t=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:pt,y:mt,cx:gt,cy:wt,width:xt,height:kt,size:bt}),Ot=function(t){function e(t){return c(this,e),f(this,o(e).call(this,X("circle",t),e))}return u(e,s),a(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function At(t){return t%360*Math.PI/180}function Mt(t,e){return utils.map((e||document).querySelectorAll(t),function(t){return $(t)})}G(Ot,{x:pt,y:mt,cx:gt,cy:wt,width:xt,height:kt,size:bt}),ut({Element:{circle:function(t){return this.put(new Ot).radius(new yt(t).divide(2)).move(0,0)}}}),W(Ot),ut("Container",{find:function(t){return Mt(t,this.node)}});var Tt=Z(U);function Ct(){return this.parent()&&this.parent().removeElement(this),this}ut("Element",{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var n=P(this,t,e);return this.width(new yt(n.width)).height(new yt(n.height))},clone:function(t){this.writeDataToDom();var e=tt(this.node.cloneNode(!0));return t?t.add(e):this.after(e),e},remove:Ct,replace:function(t){return this.after(t).remove(),t},addTo:function(t){return Q(t).put(this)},putIn:function(t){return Q(t).add(this)},id:function(t){return void 0!==t||this.node.id||(this.node.id=K(this.type)),this.attr("id",t)},inside:function(t,e){var n=this.bbox();return t>n.x&&e>n.y&&t",Rt=0,Lt={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},Ft=function(){function t(){c(this,t),this.init.apply(this,arguments)}return a(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?g.test(t)?(i=y.exec(t.replace(p,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):m.test(t)&&(i=v.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+N(Math.round(this.r))+N(Math.round(this.g))+N(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",m.test(t)||g.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}(),It=function(){try{return Array}catch(t){return Array}}(),Bt=function(t){function n(){var t,e;return c(this,n),(t=e=f(this,o(n).call(this))).init.apply(t,arguments),e}return u(n,It),a(n,[{key:"init",value:function(t,e){this.length=0,this.push.apply(this,O(this.parse(t||e)))}},{key:"toArray",value:function(){return Array.prototype.slice(this)}},{key:"toString",value:function(){this.join(" ")}},{key:"valueOf",value:function(){return this.toArray()}},{key:"parse",value:function(t){return t=t.valueOf(),Array.isArray(t)?t:t.trim().split(b).map(parseFloat)}},{key:"clone",value:function(){return new this.constructor(this)}},{key:"toSet",value:function(){return new Set(this)}}]),n}();function Xt(t,e,n){if(null==t){t={},e=this.node.attributes;var i=!0,r=!1,s=void 0;try{for(var u,a=e[Symbol.iterator]();!(i=(u=a.next()).done);i=!0){var o=u.value;t[o.nodeName]=isNumer.test(o.nodeValue)?parseFloat(o.nodeValue):o.nodeValue}}catch(t){r=!0,s=t}finally{try{i||null==a.return||a.return()}finally{if(r)throw s}}return t}if(Array.isArray(t));else if("object"===l(t))for(e in t)this.attr(e,t[e]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return null==(e=this.node.getAttribute(t))?Lt[t]:x.test(e)?parseFloat(e):e;for("fill"!==t&&"stroke"!==t||k.test(e)&&(e=this.doc().defs().image(e));"function"==typeof e.attrHook;)e=e.attrHook(this,t);"number"==typeof e?e=new yt(e):Ft.isColor(e)?e=new Ft(e):Array.isArray(e)&&(e=new Bt(e)),"leading"===t?this.leading&&this.leading(e):"string"==typeof n?this.node.setAttributeNS(n,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!==t&&"x"!==t||this.rebuild()}return this}ut("Element",{attr:Xt});var Yt=function(t){function e(t){return c(this,e),f(this,o(e).call(this,X(t+"Gradient","string"==typeof t?null:t),e))}return u(e,s),a(e,[{key:"stop",value:function(t,e,n){return this.put(new Nt).update(t,e,n)}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="gradientTransform"),Xt.call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}}]),e}();G(Yt,Pt),ut({Container:{gradient:function(t,e){return this.defs().gradient(t,e)}},Defs:{gradient:function(t,e){return this.put(new Yt(t)).update(e)}}}),W(Yt);var Gt=function(t){function e(t){return c(this,e),f(this,o(e).call(this,X("pattern",t)))}return u(e,s),a(e,[{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="patternTransform"),Xt.call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}}]),e}();ut({Container:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}},Defs:{pattern:function(t,e,n){return this.put(new Gt).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}}),W(Gt);var Ht=0;function Vt(t){return t instanceof Base&&t.is("EventTarget")?t.getEventTarget():t}function Ut(t,e,i,n,r){var s=i.bind(n||t),u=Vt(t);e=Array.isArray(e)?e:e.split(b),u.instance=u.instance||{events:{}};var a=u.instance.events;i._svgjsListenerId||(i._svgjsListenerId=++Ht),e.forEach(function(t){var e=t.split(".")[0],n=t.split(".")[1]||"*";a[e]=a[e]||{},a[e][n]=a[e][n]||{},a[e][n][i._svgjsListenerId]=s,u.addEventListener(e,s,r||!1)})}function Qt(t,e,s,u){var a=Vt(t);if(a.instance&&("function"!=typeof s||(s=s._svgjsListenerId))){var o=a.instance.events;(e=Array.isArray(e)?e:(e||"").split(b)).forEach(function(t){var e,n,i=t&&t.split(".")[0],r=t&&t.split(".")[1];if(s)o[i]&&o[i][r||"*"]&&(a.removeEventListener(i,o[i][r||"*"][s],u||!1),delete o[i][r||"*"][s]);else if(i&&r){if(o[i]&&o[i][r]){for(n in o[i][r])Qt(a,[i,r].join("."),n);delete o[i][r]}}else if(r)for(t in o)for(e in o[t])r===e&&Qt(a,[t,r].join("."));else if(i){if(o[i]){for(e in o[i])Qt(a,[i,e].join("."));delete o[i]}}else{for(t in o)Qt(a,t);a.instance.events={}}})}}var $t=function(t){function e(t){return c(this,e),f(this,o(e).call(this,X("image",t),e))}return u(e,s),a(e,[{key:"load",value:function(n,i){if(!n)return this;var r=new window.Image;return Ut(r,"load",function(t){var e=this.parent(Gt);0===this.width()&&0===this.height()&&this.size(r.width,r.height),e instanceof Gt&&0===e.width()&&0===e.height()&&e.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:r.width,height:r.height,ratio:r.width/r.height,url:n})},this),Ut(r,"load error",function(){Qt(r)}),this.attr("href",r.src=n,B)}},{key:"attrHook",value:function(t){var e=this;return t.doc().defs().pattern(0,0,function(t){t.add(e)})}}]),e}();ut({Container:{image:function(t,e){return this.put(new $t).size(0,0).load(t,e)}}}),W($t);var Wt=function(t){function r(t){var e=1":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Ae=function(){function t(){c(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),Me=function(t){function n(t){var e;return c(this,n),(e=f(this,o(n).call(this))).ease=Oe[t||qt]||t,e}return u(n,Ae),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),Te=function(t){function n(t){var e;return c(this,n),(e=f(this,o(n).call(this))).stepper=t,e}return u(n,Ae),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Ce(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var je=function(t){function i(t,e){var n;return c(this,i),(n=f(this,o(i).call(this))).duration(t||500).overshoot(e||0),n}return u(i,Te),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i);this._lastTime=this._time;var s=this._isDeclarative;if(this.done=!s&&!r&&this._time>=i,n||s){this._initialise(n),this.transforms=new xe;var u=this._run(s?t:e)}return this.done=this.done||u&&s,this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new Me(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e Date: Sun, 4 Nov 2018 15:59:57 +0100 Subject: implement registerMethods(), introduce real arrays for modern browsers, fix some tests --- dist/svg.js | 2820 +++++++++++++++++++++++++++--------------------- dist/svg.min.js | 2 +- spec/SpecRunner.html | 7 - spec/spec/adopter.js | 16 +- spec/spec/array.js | 266 ++--- spec/spec/boxes.js | 34 - spec/spec/color.js | 42 +- spec/spec/container.js | 13 +- spec/spec/element.js | 14 +- spec/spec/selector.js | 26 +- src/ArrayPolyfill.js | 32 +- src/Bare.js | 14 +- src/Box.js | 12 +- src/Doc.js | 9 +- src/Element.js | 8 +- src/Ellipse.js | 2 +- src/EventTarget.js | 2 +- src/G.js | 3 +- src/Mask.js | 2 +- src/Matrix.js | 2 +- src/Morphable.js | 63 +- src/Parent.js | 1 + src/PathArray.js | 260 ++++- src/Pattern.js | 2 +- src/PointArray.js | 192 +++- src/Polygon.js | 2 +- src/Polyline.js | 2 +- src/Runner.js | 4 +- src/SVGArray.js | 106 +- src/TextPath.js | 2 +- src/Tspan.js | 1 + src/Use.js | 1 + src/adopter.js | 4 +- src/arrange.js | 7 +- src/attr.js | 4 +- src/containers.js | 4 + src/elements.js | 1 + src/elemnts-svg.js | 2 +- src/event.js | 1 + src/helpers.js | 1 + src/memory.js | 2 +- src/poly.js | 1 + src/regex.js | 2 +- src/selector.js | 2 +- src/sugar.js | 5 +- src/svg.js | 34 +- src/tools.js | 19 +- 47 files changed, 2372 insertions(+), 1679 deletions(-) (limited to 'src') diff --git a/dist/svg.js b/dist/svg.js index 44978bd..d8edd95 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -102,74 +102,6 @@ var SVG = (function () { return _setPrototypeOf(o, p); } - function isNativeReflectConstruct() { - if (typeof Reflect === "undefined" || !Reflect.construct) return false; - if (Reflect.construct.sham) return false; - if (typeof Proxy === "function") return true; - - try { - Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); - return true; - } catch (e) { - return false; - } - } - - function _construct(Parent, args, Class) { - if (isNativeReflectConstruct()) { - _construct = Reflect.construct; - } else { - _construct = function _construct(Parent, args, Class) { - var a = [null]; - a.push.apply(a, args); - var Constructor = Function.bind.apply(Parent, a); - var instance = new Constructor(); - if (Class) _setPrototypeOf(instance, Class.prototype); - return instance; - }; - } - - return _construct.apply(null, arguments); - } - - function _isNativeFunction(fn) { - return Function.toString.call(fn).indexOf("[native code]") !== -1; - } - - function _wrapNativeSuper(Class) { - var _cache = typeof Map === "function" ? new Map() : undefined; - - _wrapNativeSuper = function _wrapNativeSuper(Class) { - if (Class === null || !_isNativeFunction(Class)) return Class; - - if (typeof Class !== "function") { - throw new TypeError("Super expression must either be null or a function"); - } - - if (typeof _cache !== "undefined") { - if (_cache.has(Class)) return _cache.get(Class); - - _cache.set(Class, Wrapper); - } - - function Wrapper() { - return _construct(Class, arguments, _getPrototypeOf(this).constructor); - } - - Wrapper.prototype = Object.create(Class.prototype, { - constructor: { - value: Wrapper, - enumerable: false, - writable: true, - configurable: true - } - }); - return _setPrototypeOf(Wrapper, Class); - }; - - return _wrapNativeSuper(Class); - } - function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); @@ -244,7 +176,7 @@ var SVG = (function () { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } - var Base$1 = + var Base = /*#__PURE__*/ function () { function Base(node, _ref) { @@ -297,6 +229,8 @@ var SVG = (function () { var rgb = /rgb\((\d+),(\d+),(\d+)\)/; // Parse reference id + var reference = /(#[a-z0-9\-_]+)/i; // splits a transformation chain + var transforms = /\)\s*,?\s*/; // Whitespace var whitespace = /\s/g; // Test hex value @@ -305,10 +239,14 @@ var SVG = (function () { var isRgb = /^rgb\(/; // Test css declaration + var isCss = /[^:]+:[^;]+;?/; // Test for blank string + var isBlank = /^(\s+)?$/; // Test for numeric string var isNumber = /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i; // Test for percent value + var isPercent = /^-?[\d.]+%$/; // Test for image url + var isImage = /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i; // split at whitespace and comma var delimiter = /[\s,]+/; // The following regex are used to parse the d attribute of a path @@ -324,6 +262,28 @@ var SVG = (function () { var dots = /\./g; + var regex$1 = /*#__PURE__*/Object.freeze({ + numberAndUnit: numberAndUnit, + hex: hex, + rgb: rgb, + reference: reference, + transforms: transforms, + whitespace: whitespace, + isHex: isHex, + isRgb: isRgb, + isCss: isCss, + isBlank: isBlank, + isNumber: isNumber, + isPercent: isPercent, + isImage: isImage, + delimiter: delimiter, + hyphen: hyphen, + pathLetters: pathLetters, + isPathLetter: isPathLetter, + numbersWithDots: numbersWithDots, + dots: dots + }); + function isNulledBox(box) { return !box.w && !box.h && !box.x && !box.y; } @@ -441,10 +401,16 @@ var SVG = (function () { return b; } // Get id from reference string + function idFromReference(url) { + var m = (url || '').toString().match(reference); + if (m) return m[1]; + } // Create matrix array for looping + var abcdef = 'abcdef'.split(''); function closeEnough(a, b, threshold) { return Math.abs(b - a) < (threshold || 1e-6); - } + } // move this to static matrix method + function isMatrixLike(o) { return o.a != null || o.b != null || o.c != null || o.d != null || o.e != null || o.f != null; } @@ -485,6 +451,13 @@ var SVG = (function () { var xlink = 'http://www.w3.org/1999/xlink'; var svgjs = 'http://svgjs.com/svgjs'; + var ns$2 = /*#__PURE__*/Object.freeze({ + ns: ns$1, + xmlns: xmlns, + xlink: xlink, + svgjs: svgjs + }); + function nodeOrNew$1(name, node) { return node || makeNode(name); } // Method for element creation @@ -494,16 +467,8 @@ var SVG = (function () { return document.createElementNS(ns$1, name); } // Method for extending objects - function extend$1(modules, methods) { + function extend(modules, methods) { var key, i; - - if (Array.isArray(methods)) { - methods.forEach(function (method) { - extend$1(modules, method); - }); - return; - } - modules = Array.isArray(modules) ? modules : [modules]; for (i = modules.length - 1; i >= 0; i--) { @@ -516,10 +481,20 @@ var SVG = (function () { modules[i].prototype[key] = methods[key]; } } + } + function extend2(modules, methods) { + var key, i; + modules = Array.isArray(modules) ? modules : [modules]; + + for (i = modules.length - 1; i >= 0; i--) { + for (key in methods) { + modules[i].prototype[key] = methods[key]; + } + } } // FIXME: enhanced constructors here function addFactory(modules, methods) { - extend$1(modules, methods); + extend(modules, methods); } // Invent new element function invent(config) { @@ -535,12 +510,12 @@ var SVG = (function () { if (config.extend) { - extend$1(initializer, config.extend); + extend(initializer, config.extend); } // Attach construct method to parent if (config.construct) { - extend$1(config.parent || Container, config.construct); + extend(config.parent || Container, config.construct); } return initializer; @@ -549,7 +524,8 @@ var SVG = (function () { var tools = /*#__PURE__*/Object.freeze({ nodeOrNew: nodeOrNew$1, makeNode: makeNode, - extend: extend$1, + extend: extend, + extend2: extend2, addFactory: addFactory, invent: invent }); @@ -557,7 +533,7 @@ var SVG = (function () { var elements = {}; var root = Symbol('root'); function makeInstance(element) { - if (element instanceof Base$1) return element; + if (element instanceof Base) return element; if (_typeof(element) === 'object') { return adopt$1(element); @@ -572,8 +548,10 @@ var SVG = (function () { } var node = makeNode('svg'); - node.innerHTML = element; - element = adopt$1(node.firstElementChild); + node.innerHTML = element; // We can use firstChild here because we know, + // that the first char is < and thus an element + + element = adopt$1(node.firstChild); return element; } // Adopt existing svg elements @@ -581,7 +559,7 @@ var SVG = (function () { // check for presence of node if (!node) return null; // make sure a node isn't already adopted - if (node.instance instanceof Base$1) return node.instance; + if (node.instance instanceof Base) return node.instance; if (!(node instanceof window.SVGElement)) { return new elements.HtmlNode(node); @@ -682,7 +660,7 @@ var SVG = (function () { }]); return HtmlNode; - }(Base$1); + }(Base); register(HtmlNode); var Defs = @@ -709,7 +687,7 @@ var SVG = (function () { }]); return Defs; - }(Base$1); + }(Base); register(Defs); var methods = {}; @@ -772,150 +750,493 @@ var SVG = (function () { } : {}; } - var Doc$1 = + var SVGNumber = /*#__PURE__*/ - function (_Base) { - _inherits(Doc, _Base); + function () { + // Initialize + function SVGNumber() { + _classCallCheck(this, SVGNumber); - function Doc(node) { - var _this; + this.init.apply(this, arguments); + } - _classCallCheck(this, Doc); + _createClass(SVGNumber, [{ + key: "init", + value: function init(value, unit) { + unit = Array.isArray(value) ? value[1] : unit; + value = Array.isArray(value) ? value[0] : value; // initialize defaults - _this = _possibleConstructorReturn(this, _getPrototypeOf(Doc).call(this, nodeOrNew$1('svg', node), Doc)); + this.value = 0; + this.unit = unit || ''; // parse value - _this.namespace(); + if (typeof value === 'number') { + // ensure a valid numeric value + this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; + } else if (typeof value === 'string') { + unit = value.match(numberAndUnit); - return _this; - } + if (unit) { + // make value numeric + this.value = parseFloat(unit[1]); // normalize - _createClass(Doc, [{ - key: "isRoot", - value: function isRoot() { - return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document'; - } // Check if this is a root svg - // If not, call docs from this element + if (unit[5] === '%') { + this.value /= 100; + } else if (unit[5] === 's') { + this.value *= 1000; + } // store unit - }, { - key: "doc", - value: function doc() { - if (this.isRoot()) return this; - return Element.doc.call(this); - } // Add namespaces + this.unit = unit[5]; + } + } else { + if (value instanceof SVGNumber) { + this.value = value.valueOf(); + this.unit = value.unit; + } + } + } }, { - key: "namespace", - value: function namespace() { - if (!this.isRoot()) return this.doc().namespace(); - return this.attr({ - xmlns: ns$1, - version: '1.1' - }).attr('xmlns:xlink', xlink, xmlns).attr('xmlns:svgjs', svgjs, xmlns); - } // Creates and returns defs element - + key: "toString", + value: function toString() { + return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; + } }, { - key: "defs", - value: function defs() { - if (!this.isRoot()) return this.doc().defs(); - return adopt$1(this.node.getElementsByTagName('defs')[0]) || this.put(new Defs()); - } // custom parent method - + key: "toJSON", + value: function toJSON() { + return this.toString(); + } }, { - key: "parent", - value: function parent(type) { - if (this.isRoot()) { - return this.node.parentNode.nodeName === '#document' ? null : this.node.parentNode; - } - - return Element.parent.call(this, type); - } // Removes the doc from the DOM + key: "toArray", + value: function toArray() { + return [this.value, this.unit]; + } + }, { + key: "valueOf", + value: function valueOf() { + return this.value; + } // Add number }, { - key: "remove", - value: function remove() { - if (!this.isRoot()) { - return Element.remove.call(this); - } + key: "plus", + value: function plus(number) { + number = new SVGNumber(number); + return new SVGNumber(this + number, this.unit || number.unit); + } // Subtract number - if (this.parent()) { - this.parent().removeChild(this.node); - } + }, { + key: "minus", + value: function minus(number) { + number = new SVGNumber(number); + return new SVGNumber(this - number, this.unit || number.unit); + } // Multiply number - return this; - } }, { - key: "clear", - value: function clear() { - // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild); - } + key: "times", + value: function times(number) { + number = new SVGNumber(number); + return new SVGNumber(this * number, this.unit || number.unit); + } // Divide number - return this; + }, { + key: "divide", + value: function divide(number) { + number = new SVGNumber(number); + return new SVGNumber(this / number, this.unit || number.unit); } }]); - return Doc; - }(Base$1); - registerMethods({ - Container: { - // Create nested svg document - nested: function nested() { - return this.put(new Doc$1()); - } - } - }); - register(Doc$1, 'Doc', true); + return SVGNumber; + }(); - var G = - /*#__PURE__*/ - function (_Base) { - _inherits(G, _Base); + var Doc = getClass(root); + function setup(node) { + // initialize data object + this.dom = {}; // create circular reference - function G(node) { - _classCallCheck(this, G); + this.node = node; + this.type = node.nodeName; + this.node.instance = this; - return _possibleConstructorReturn(this, _getPrototypeOf(G).call(this, nodeorNew('g', node), G)); + 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')) || {}); } + } // Move over x-axis - return G; - }(Base$1); - registerMethods({ - Element: { - // Create a group element - group: function group() { - return this.put(new G()); - } - } - }); - register(G); + function x(x) { + return this.attr('x', x); + } // Move over y-axis - var Queue = - /*#__PURE__*/ - function () { - function Queue() { - _classCallCheck(this, Queue); + function y(y) { + return this.attr('y', y); + } // Move by center over x-axis - this._first = null; - this._last = null; - } + function cx(x) { + return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2); + } // Move by center over y-axis - _createClass(Queue, [{ - key: "push", - value: function push(value) { - // An item stores an id and the provided value - var item = value.next ? value : { - value: value, - next: null, - prev: null // Deal with the queue being empty or populated + function cy(y) { + return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2); + } // Move element to given x and y values - }; + function move(x, y) { + return this.x(x).y(y); + } // Move element by its center - if (this._last) { - item.prev = this._last; - this._last.next = item; - this._last = item; - } else { + function center(x, y) { + return this.cx(x).cy(y); + } // Set width of element + + function width(width) { + return this.attr('width', width); + } // Set height of element + + function height(height) { + return this.attr('height', height); + } // Set element size to given width and height + + function size(width, height) { + var p = proportionalSize$1(this, width, height); + return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height)); + } // Clone element + + function clone(parent) { + // write dom data to the dom so the clone can pickup the data + this.writeDataToDom(); // 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 + + function remove() { + if (this.parent()) { + this.parent().removeElement(this); + } + + return this; + } // Replace element + + function replace(element) { + this.after(element).remove(); + return element; + } // Add element to given container and return self + + function addTo(parent) { + return makeInstance(parent).put(this); + } // Add element to given container and return container + + function putIn(parent) { + return makeInstance(parent).add(this); + } // Get / set id + + function id$1(id) { + // generate new id if no id set + 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); + } // Checks whether the given point inside the bounding box of the element + + function inside(x, y) { + var box = this.bbox(); + return x > box.x && y > box.y && x < box.x + box.width && y < box.y + box.height; + } // Return id on string conversion + + function toString() { + return this.id(); + } // Return array of classes on the node + + function classes() { + var attr = this.attr('class'); + return attr == null ? [] : attr.trim().split(delimiter); + } // Return true if class exists on the node, false otherwise + + function hasClass(name) { + return this.classes().indexOf(name) !== -1; + } // Add class to the node + + function addClass(name) { + if (!this.hasClass(name)) { + var array = this.classes(); + array.push(name); + this.attr('class', array.join(' ')); + } + + return this; + } // Remove class from the node + + function removeClass(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 + + function toggleClass(name) { + return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); + } // Get referenced element form attribute value + + function reference$1(attr) { + var id = idFromReference(this.attr(attr)); + return id ? makeInstance(id) : null; + } // Returns the parent element instance + + function parent(type) { + var parent = this; // check for parent + + if (!parent.node.parentNode) return null; // get parent element + + parent = adopt$1(parent.node.parentNode); + if (!type) return parent; // loop trough ancestors if type is given + + while (parent && parent.node instanceof window.SVGElement) { + if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent; + parent = adopt$1(parent.node.parentNode); + } + } // Get parent document + + function doc() { + var p = this.parent(Doc); + return p && p.doc(); + } // Get defs + + function defs() { + return this.doc().defs(); + } // return array of all ancestors of given type up to the root svg + + function parents(type) { + var parents = []; + var 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 + + function matches(selector) { + return matches(this.node, selector); + } // Returns the svg node to call native svg methods on it + + function native() { + return this.node; + } // Import raw svg + + function svg() { + // write svgjs data to the dom + this.writeDataToDom(); + return this.node.outerHTML; + } // write svgjs data to the dom + + function 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 + + function setData(o) { + this.dom = o; + return this; + } + function getEventTarget() { + return this.node; + } + registerMethods('Element', { + x: x, + y: y, + cx: cx, + cy: cy, + move: move, + center: center, + width: width, + height: height, + size: size, + clone: clone, + remove: remove, + replace: replace, + addTo: addTo, + putIn: putIn, + id: id$1, + inside: inside, + toString: toString, + classes: classes, + hasClass: hasClass, + addClass: addClass, + removeClass: removeClass, + toggleClass: toggleClass, + reference: reference$1, + doc: doc, + defs: defs, + parent: parent, + parents: parents, + matches: matches, + native: native, + svg: svg, + writeDataToDom: writeDataToDom, + setData: setData, + getEventTarget: getEventTarget + }); + registerConstructor('Element', setup); + + var Doc$1 = + /*#__PURE__*/ + function (_Base) { + _inherits(Doc, _Base); + + function Doc(node) { + var _this; + + _classCallCheck(this, Doc); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Doc).call(this, nodeOrNew$1('svg', node), Doc)); + + _this.namespace(); + + return _this; + } + + _createClass(Doc, [{ + key: "isRoot", + value: function isRoot() { + return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document'; + } // Check if this is a root svg + // If not, call docs from this element + + }, { + key: "doc", + value: function doc$$1() { + if (this.isRoot()) return this; + return doc.call(this); + } // Add namespaces + + }, { + key: "namespace", + value: function namespace() { + if (!this.isRoot()) return this.doc().namespace(); + return this.attr({ + xmlns: ns$1, + version: '1.1' + }).attr('xmlns:xlink', xlink, xmlns).attr('xmlns:svgjs', svgjs, xmlns); + } // Creates and returns defs element + + }, { + key: "defs", + value: function defs$$1() { + if (!this.isRoot()) return this.doc().defs(); + return adopt$1(this.node.getElementsByTagName('defs')[0]) || this.put(new Defs()); + } // custom parent method + + }, { + key: "parent", + value: function parent$$1(type) { + if (this.isRoot()) { + return this.node.parentNode.nodeName === '#document' ? null : adopt$1(this.node.parentNode); + } + + return parent.call(this, type); + } // Removes the doc from the DOM + + }, { + key: "remove", + value: function remove$$1() { + if (!this.isRoot()) { + return remove.call(this); + } + + if (this.parent()) { + this.parent().removeChild(this.node); + } + + return this; + } + }, { + key: "clear", + value: function clear() { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } + + return this; + } + }]); + + return Doc; + }(Base); + registerMethods({ + Container: { + // Create nested svg document + nested: function nested() { + return this.put(new Doc$1()); + } + } + }); + register(Doc$1, 'Doc', true); + + var G = + /*#__PURE__*/ + function (_Base) { + _inherits(G, _Base); + + function G(node) { + _classCallCheck(this, G); + + return _possibleConstructorReturn(this, _getPrototypeOf(G).call(this, nodeOrNew$1('g', node), G)); + } + + return G; + }(Base); + registerMethods({ + Element: { + // Create a group element + group: function group() { + return this.put(new G()); + } + } + }); + register(G); + + var Queue = + /*#__PURE__*/ + function () { + function Queue() { + _classCallCheck(this, Queue); + + this._first = null; + this._last = null; + } + + _createClass(Queue, [{ + key: "push", + value: function push(value) { + // An item stores an id and the provided value + var item = value.next ? value : { + value: value, + next: null, + prev: null // Deal with the queue being empty or populated + + }; + + if (this._last) { + item.prev = this._last; + this._last.next = item; + this._last = item; + } else { this._last = item; this._first = item; } // Update the length and return the current item @@ -1048,14 +1369,11 @@ var SVG = (function () { function (_Base) { _inherits(Bare, _Base); - function Bare(node, inherit) { - var _this; + function Bare(node) { _classCallCheck(this, Bare); - _this = _possibleConstructorReturn(this, _getPrototypeOf(Bare).call(this, nodeOrNew$1(null, node), Bare)); - extend(_assertThisInitialized(_assertThisInitialized(_this)), inherit); - return _this; + return _possibleConstructorReturn(this, _getPrototypeOf(Bare).call(this, nodeOrNew$1(node, typeof node === 'string' ? null : node), Bare)); //extend(this, inherit) } _createClass(Bare, [{ @@ -1063,123 +1381,24 @@ var SVG = (function () { value: function words(text) { // remove contents while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild); - } // create text node - - - this.node.appendChild(document.createTextNode(text)); - return this; - } - }]); - - return Bare; - }(Base$1); - register(Bare); - registerMethods('Bare', { - // Create an element that is not described by SVG.js - element: function element(_element, inherit) { - var custom = createCustom(_element, inherit); - return this.put(new custom()); - } - }); - - var SVGNumber$1 = - /*#__PURE__*/ - function () { - // Initialize - function SVGNumber() { - _classCallCheck(this, SVGNumber); - - this.init.apply(this, arguments); - } - - _createClass(SVGNumber, [{ - key: "init", - value: function init(value, unit) { - unit = Array.isArray(value) ? value[1] : unit; - value = Array.isArray(value) ? value[0] : value; // initialize defaults - - this.value = 0; - this.unit = unit || ''; // parse value - - if (typeof value === 'number') { - // ensure a valid numeric value - this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; - } else if (typeof value === 'string') { - unit = value.match(numberAndUnit); - - if (unit) { - // make value numeric - this.value = parseFloat(unit[1]); // normalize - - if (unit[5] === '%') { - this.value /= 100; - } else if (unit[5] === 's') { - this.value *= 1000; - } // store unit - - - this.unit = unit[5]; - } - } else { - if (value instanceof SVGNumber) { - this.value = value.valueOf(); - this.unit = value.unit; - } - } - } - }, { - key: "toString", - value: function toString() { - return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; - } - }, { - key: "toJSON", - value: function toJSON() { - return this.toString(); - } - }, { - key: "toArray", - value: function toArray() { - return [this.value, this.unit]; - } - }, { - key: "valueOf", - value: function valueOf() { - return this.value; - } // Add number - - }, { - key: "plus", - value: function plus(number) { - number = new SVGNumber(number); - return new SVGNumber(this + number, this.unit || number.unit); - } // Subtract number - - }, { - key: "minus", - value: function minus(number) { - number = new SVGNumber(number); - return new SVGNumber(this - number, this.unit || number.unit); - } // Multiply number + this.node.removeChild(this.node.lastChild); + } // create text node - }, { - key: "times", - value: function times(number) { - number = new SVGNumber(number); - return new SVGNumber(this * number, this.unit || number.unit); - } // Divide number - }, { - key: "divide", - value: function divide(number) { - number = new SVGNumber(number); - return new SVGNumber(this / number, this.unit || number.unit); + this.node.appendChild(document.createTextNode(text)); + return this; } }]); - return SVGNumber; - }(); + return Bare; + }(Base); + register(Bare); + registerMethods('Container', { + // Create an element that is not described by SVG.js + element: function element(node, inherit) { + return this.put(new Bare(node, inherit)); + } + }); // FIXME: import this to runner @@ -1191,45 +1410,45 @@ var SVG = (function () { return this.attr('ry', ry); } // Move over x-axis - function x(x) { + function x$1(x) { return x == null ? this.cx() - this.rx() : this.cx(x + this.rx()); } // Move over y-axis - function y(y) { + function y$1(y) { return y == null ? this.cy() - this.ry() : this.cy(y + this.ry()); } // Move by center over x-axis - function cx(x) { + function cx$1(x) { return x == null ? this.attr('cx') : this.attr('cx', x); } // Move by center over y-axis - function cy(y) { + function cy$1(y) { return y == null ? this.attr('cy') : this.attr('cy', y); } // Set width of element - function width(width) { - return width == null ? this.rx() * 2 : this.rx(new SVGNumber$1(width).divide(2)); + function width$1(width) { + return width == null ? this.rx() * 2 : this.rx(new SVGNumber(width).divide(2)); } // Set height of element - function height(height) { - return height == null ? this.ry() * 2 : this.ry(new SVGNumber$1(height).divide(2)); + function height$1(height) { + return height == null ? this.ry() * 2 : this.ry(new SVGNumber(height).divide(2)); } // Custom size function - function size(width, height) { + function size$1(width, height) { var p = proportionalSize$1(this, width, height); - return this.rx(new SVGNumber$1(p.width).divide(2)).ry(new SVGNumber$1(p.height).divide(2)); + return this.rx(new SVGNumber(p.width).divide(2)).ry(new SVGNumber(p.height).divide(2)); } var circled = /*#__PURE__*/Object.freeze({ rx: rx, ry: ry, - x: x, - y: y, - cx: cx, - cy: cy, - width: width, - height: height, - size: size + x: x$1, + y: y$1, + cx: cx$1, + cy: cy$1, + width: width$1, + height: height$1, + size: size$1 }); var Circle = @@ -1250,320 +1469,121 @@ var SVG = (function () { } // Radius x value }, { - key: "rx", - value: function rx$$1(_rx) { - return this.attr('r', _rx); - } // Alias radius x value - - }, { - key: "ry", - value: function ry$$1(_ry) { - return this.rx(_ry); - } - }]); - - return Circle; - }(Base$1); - extend$1(Circle, { - x: x, - y: y, - cx: cx, - cy: cy, - width: width, - height: height, - size: size - }); - registerMethods({ - Element: { - // Create circle element - circle: function circle(size$$1) { - return this.put(new Circle()).radius(new SVGNumber$1(size$$1).divide(2)).move(0, 0); - } - } - }); - register(Circle); - - // Map function - function map(array, block) { - var i; - var il = array.length; - var result = []; - - for (i = 0; i < il; i++) { - result.push(block(array[i])); - } - - return result; - } // Filter function - - function radians(d) { - return d % 360 * Math.PI / 180; - } // Radians to degrees - - // SVG.get = function (id) { - // var node = document.getElementById(idFromReference(id) || id) - // 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.$$ = function (query, parent) { - // return SVG.utils.map((parent || document).querySelectorAll(query), function (node) { - // return SVG.adopt(node) - // }) - // } - // - // SVG.$ = function (query, parent) { - // return SVG.adopt((parent || document).querySelector(query)) - // } - - function baseFind(query, parent) { - return utils.map((parent || document).querySelectorAll(query), function (node) { - return adopt$1(node); - }); - } // Scoped find method - - function find$1(query) { - return baseFind(query, this.node); - } - registerMethods('Container', { - find: find$1 - }); - - var Doc$2 = getClass(root); - function setup(node) { - // initialize data object - this.dom = {}; // create circular reference - - this.node = node; - this.type = node.nodeName; - this.node.instance = this; - - 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')) || {}); - } - } // Move over x-axis - - function x$1(x) { - return this.attr('x', x); - } // Move over y-axis - - function y$1(y) { - return this.attr('y', y); - } // Move by center over x-axis - - function cx$1(x) { - return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2); - } // Move by center over y-axis - - function cy$1(y) { - return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2); - } // Move element to given x and y values - - function move(x, y) { - return this.x(x).y(y); - } // Move element by its center - - function center(x, y) { - return this.cx(x).cy(y); - } // Set width of element - - function width$1(width) { - return this.attr('width', width); - } // Set height of element - - function height$1(height) { - return this.attr('height', height); - } // Set element size to given width and height - - function size$1(width, height) { - var p = proportionalSize$1(this, width, height); - return this.width(new SVGNumber$1(p.width)).height(new SVGNumber$1(p.height)); - } // Clone element - - function clone(parent) { - // write dom data to the dom so the clone can pickup the data - this.writeDataToDom(); // 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 - - function remove() { - if (this.parent()) { - this.parent().removeElement(this); - } - - return this; - } // Replace element - - function replace(element) { - this.after(element).remove(); - return element; - } // Add element to given container and return self - - function addTo(parent) { - return makeInstance(parent).put(this); - } // Add element to given container and return container - - function putIn(parent) { - return makeInstance(parent).add(this); - } // Get / set id - - function id$1(id) { - // generate new id if no id set - 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); - } // Checks whether the given point inside the bounding box of the element - - function inside(x, y) { - var box = this.bbox(); - return x > box.x && y > box.y && x < box.x + box.width && y < box.y + box.height; - } // Return id on string conversion - - function toString() { - return this.id(); - } // Return array of classes on the node - - function classes() { - var attr = this.attr('class'); - return attr == null ? [] : attr.trim().split(delimiter); - } // Return true if class exists on the node, false otherwise - - function hasClass(name) { - return this.classes().indexOf(name) !== -1; - } // Add class to the node - - function addClass(name) { - if (!this.hasClass(name)) { - var array = this.classes(); - array.push(name); - this.attr('class', array.join(' ')); - } - - return this; - } // Remove class from the node - - function removeClass(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 + key: "rx", + value: function rx$$1(_rx) { + return this.attr('r', _rx); + } // Alias radius x value - function toggleClass(name) { - return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); - } // FIXME: getIdFromReference - // Get referenced element form attribute value + }, { + key: "ry", + value: function ry$$1(_ry) { + return this.rx(_ry); + } + }]); - function reference$1(attr) { - return get(this.attr(attr)); - } // Returns the parent element instance + return Circle; + }(Base); + extend(Circle, { + x: x$1, + y: y$1, + cx: cx$1, + cy: cy$1, + width: width$1, + height: height$1, + size: size$1 + }); + registerMethods({ + Element: { + // Create circle element + circle: function circle(size) { + return this.put(new Circle()).radius(new SVGNumber(size).divide(2)).move(0, 0); + } + } + }); + register(Circle); - function doc() { - var p = this.parent(Doc$2); - return p && p.doc(); - } // Get defs + // Map function + function map(array, block) { + var i; + var il = array.length; + var result = []; - function defs() { - return this.doc().defs(); - } // return array of all ancestors of given type up to the root svg + for (i = 0; i < il; i++) { + result.push(block(array[i])); + } - function parents(type) { - var parents = []; - var parent = this; + return result; + } // Filter function - do { - parent = parent.parent(type); - if (!parent || !parent.node) break; - parents.push(parent); - } while (parent.parent); + function filter(array, block) { + var i; + var il = array.length; + var result = []; - return parents; - } // matches the element vs a css selector + for (i = 0; i < il; i++) { + if (block(array[i])) { + result.push(array[i]); + } + } - function matches(selector) { - return matches(this.node, selector); - } // Returns the svg node to call native svg methods on it + return result; + } // Degrees to radians - function native() { - return this.node; - } // Import raw svg + function radians(d) { + return d % 360 * Math.PI / 180; + } // Radians to degrees - function svg() { - // write svgjs data to the dom - this.writeDataToDom(); - return this.node.outerHTML; - } // write svgjs data to the dom + function degrees(r) { + return r * 180 / Math.PI % 360; + } + function filterSVGElements(nodes) { + return this.filter(nodes, function (el) { + return el instanceof window.SVGElement; + }); + } - function writeDataToDom() { - // remove previously set data - this.node.removeAttribute('svgjs:data'); + var utils = /*#__PURE__*/Object.freeze({ + map: map, + filter: filter, + radians: radians, + degrees: degrees, + filterSVGElements: filterSVGElements + }); - if (Object.keys(this.dom).length) { - this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)); // see #428 - } + // SVG.get = function (id) { + // var node = document.getElementById(idFromReference(id) || id) + // 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.$$ = function (query, parent) { + // return SVG.utils.map((parent || document).querySelectorAll(query), function (node) { + // return SVG.adopt(node) + // }) + // } + // + // SVG.$ = function (query, parent) { + // return SVG.adopt((parent || document).querySelector(query)) + // } - return this; - } // set given data to the elements data property + function baseFind(query, parent) { + return map((parent || document).querySelectorAll(query), function (node) { + return adopt$1(node); + }); + } // Scoped find method - function setData(o) { - this.dom = o; - return this; - } - function getEventTarget() { - return this.node; + function find$1(query) { + return baseFind(query, this.node); } - registerMethods('Element', { - x: x$1, - y: y$1, - cx: cx$1, - cy: cy$1, - move: move, - center: center, - width: width$1, - height: height$1, - size: size$1, - clone: clone, - remove: remove, - replace: replace, - addTo: addTo, - putIn: putIn, - id: id$1, - inside: inside, - toString: toString, - classes: classes, - hasClass: hasClass, - addClass: addClass, - removeClass: removeClass, - toggleClass: toggleClass, - reference: reference$1, - doc: doc, - defs: defs, - parents: parents, - matches: matches, - native: native, - svg: svg, - writeDataToDom: writeDataToDom, - setData: setData, - getEventTarget: getEventTarget + registerMethods('Container', { + find: find$1 }); - registerConstructor('Element', setup); var ClipPath = /*#__PURE__*/ @@ -1595,7 +1615,7 @@ var SVG = (function () { }]); return ClipPath; - }(Base$1); + }(Base); registerMethods({ Container: { // Create clipping element @@ -1648,7 +1668,7 @@ var SVG = (function () { }]); return A; - }(Base$1); + }(Base); registerMethods({ Container: { // Create a hyperlink element @@ -1681,16 +1701,16 @@ var SVG = (function () { function Ellipse(node) { _classCallCheck(this, Ellipse); - return _possibleConstructorReturn(this, _getPrototypeOf(Ellipse).call(this, nodeOrNew('ellipse', node), Ellipse)); + return _possibleConstructorReturn(this, _getPrototypeOf(Ellipse).call(this, nodeOrNew$1('ellipse', node), Ellipse)); } return Ellipse; - }(Base$1); - extend$1(Ellipse, circled); + }(Base); + extend(Ellipse, circled); registerMethods('Container', { // Create an ellipse - ellipse: function ellipse(width$$1, height$$1) { - return this.put(new Ellipse()).size(width$$1, height$$1).move(0, 0); + ellipse: function ellipse(width, height) { + return this.put(new Ellipse()).size(width, height).move(0, 0); } }); register(Ellipse); @@ -1710,7 +1730,7 @@ var SVG = (function () { _createClass(Stop, [{ key: "update", value: function update(o) { - if (typeof o === 'number' || o instanceof SVGNumber$1) { + if (typeof o === 'number' || o instanceof SVGNumber) { o = { offset: arguments[0], color: arguments[1], @@ -1721,32 +1741,32 @@ var SVG = (function () { 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$1(o.offset)); + if (o.offset != null) this.attr('offset', new SVGNumber(o.offset)); return this; } }]); return Stop; - }(Base$1); + }(Base); register(Stop); // FIXME: add to runner function from(x, y) { return (this._element || this).type === 'radialGradient' ? this.attr({ - fx: new SVGNumber$1(x), - fy: new SVGNumber$1(y) + fx: new SVGNumber(x), + fy: new SVGNumber(y) }) : this.attr({ - x1: new SVGNumber$1(x), - y1: new SVGNumber$1(y) + x1: new SVGNumber(x), + y1: new SVGNumber(y) }); } function to(x, y) { return (this._element || this).type === 'radialGradient' ? this.attr({ - cx: new SVGNumber$1(x), - cy: new SVGNumber$1(y) + cx: new SVGNumber(x), + cy: new SVGNumber(y) }) : this.attr({ - x2: new SVGNumber$1(x), - y2: new SVGNumber$1(y) + x2: new SVGNumber(x), + y2: new SVGNumber(y) }); } @@ -1898,92 +1918,107 @@ var SVG = (function () { return Color; }(); - var BaseArray = function () { + var subClassArray = function () { try { - var b = - /*#__PURE__*/ - function (_Array) { - _inherits(b, _Array); - - function b() { - _classCallCheck(this, b); + //throw 'asdad' + // try es6 subclassing + return Function('name', 'baseClass', '_constructor', ['baseClass = baseClass || Array', 'return {', '[name]: class extends baseClass {', 'constructor (...args) {', 'super(...args)', '_constructor && _constructor.apply(this, args)', '}', '}', '}[name]'].join('\n')); + } catch (e) { + // Use es5 approach + return function (name) { + var baseClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Array; - return _possibleConstructorReturn(this, _getPrototypeOf(b).apply(this, arguments)); - } + var _constructor = arguments.length > 2 ? arguments[2] : undefined; - return b; - }(_wrapNativeSuper(Array)); + var Arr = function Arr() { + baseClass.apply(this, arguments); + _constructor && _constructor.apply(this, arguments); + }; - return Array; - } catch (e) { - return Array; + Arr.prototype = Object.create(baseClass.prototype); + Arr.prototype.constructor = Arr; + return Arr; + }; } }(); - var SVGArray = - /*#__PURE__*/ - function (_BaseArray) { - _inherits(SVGArray, _BaseArray); - - function SVGArray() { - var _this2; - - var _this; - - _classCallCheck(this, SVGArray); - - _this = _possibleConstructorReturn(this, _getPrototypeOf(SVGArray).call(this)); - - (_this2 = _this).init.apply(_this2, arguments); + var SVGArray = subClassArray('SVGArray', Array, function () { + this.init.apply(this, arguments); + }); + extend2(SVGArray, { + init: function init() { + //this.splice(0, this.length) + this.length = 0; + this.push.apply(this, _toConsumableArray(this.parse.apply(this, arguments))); + }, + toArray: function toArray() { + var ret = []; + ret.push.apply(ret, _toConsumableArray(this)); //Array.prototype.push.apply(ret, this) - return _this; + return ret; //return Array.prototype.concat.apply([], this) + }, + toString: function toString() { + return this.join(' '); + }, + valueOf: function valueOf() { + return this.toArray(); + }, + // Parse whitespace separated string + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + //array = array.valueOf() + // If already is an array, no need to parse it + if (array instanceof Array) return array; + return array.trim().split(delimiter).map(parseFloat); + }, + clone: function clone() { + return new this.constructor(this); + }, + toSet: function toSet() { + return new Set(this); } - - _createClass(SVGArray, [{ - key: "init", - value: function init(array, fallback) { - //this.splice(0, this.length) - this.length = 0; - this.push.apply(this, _toConsumableArray(this.parse(array || fallback))); - } - }, { - key: "toArray", - value: function toArray() { - return Array.prototype.slice(this); - } - }, { - key: "toString", - value: function toString() { - this.join(' '); - } - }, { - key: "valueOf", - value: function valueOf() { - return this.toArray(); - } // Parse whitespace separated string - - }, { - key: "parse", - value: function parse(array) { - array = array.valueOf(); // if already is an array, no need to parse it - - if (Array.isArray(array)) return array; - return array.trim().split(delimiter).map(parseFloat); - } - }, { - key: "clone", - value: function clone() { - return new this.constructor(this); - } - }, { - key: "toSet", - value: function toSet() { - return new Set(this); - } - }]); - - return SVGArray; - }(BaseArray); + }); // export default class SVGArray extends BaseArray { + // constructor (...args) { + // super() + // this.init(...args) + // } + // + // init (array, fallback = []) { + // //this.splice(0, this.length) + // this.length = 0 + // this.push(...this.parse(array || fallback)) + // } + // + // toArray () { + // return [].concat(this) + // } + // + // toString () { + // return this.join(' ') + // } + // + // valueOf () { + // return this.toArray() + // } + // + // // Parse whitespace separated string + // parse (array) { + // array = array.valueOf() + // + // // if already is an array, no need to parse it + // if (Array.isArray(array)) return array + // + // return array.trim().split(delimiter).map(parseFloat) + // } + // + // clone () { + // return new this.constructor(this) + // } + // + // toSet () { + // return new Set(this) + // } + // } function attr(attr, val, ns) { // act as full getter @@ -2045,12 +2080,12 @@ var SVG = (function () { if (typeof val === 'number') { - val = new SVGNumber$1(val); + val = new SVGNumber(val); } else if (Color.isColor(val)) { // ensure full hex color val = new Color(val); - } else if (Array.isArray(val)) { - // parse array values + } else if (val.constructor === Array) { + // Check for plain arrays and parse array values val = new SVGArray(val); } // if the passed attribute is leading... @@ -2134,8 +2169,8 @@ var SVG = (function () { }]); return Gradient; - }(Base$1); - extend$1(Gradient, gradiented); + }(Base); + extend(Gradient, gradiented); registerMethods({ Container: { // Create gradient element in defs @@ -2161,7 +2196,7 @@ var SVG = (function () { function Pattern(node) { _classCallCheck(this, Pattern); - return _possibleConstructorReturn(this, _getPrototypeOf(Pattern).call(this, nodeOrNew$1('pattern', node))); + return _possibleConstructorReturn(this, _getPrototypeOf(Pattern).call(this, nodeOrNew$1('pattern', node), Pattern)); } // Return the fill id @@ -2204,7 +2239,7 @@ var SVG = (function () { }]); return Pattern; - }(Base$1); + }(Base); registerMethods({ Container: { // Create pattern element in defs @@ -2419,161 +2454,248 @@ var SVG = (function () { return obj.doc().defs().pattern(0, 0, function (pattern) { pattern.add(_this); - }); - } - }]); - - return Image; - }(Base$1); - registerMethods({ - Container: { - // create image element, load image and set its size - image: function image(source, callback) { - return this.put(new Image()).size(0, 0).load(source, callback); - } - } - }); - register(Image); - - var PointArray$1 = - /*#__PURE__*/ - function (_SVGArray) { - _inherits(PointArray, _SVGArray); - - function PointArray(array) { - var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [[0, 0]]; - - _classCallCheck(this, PointArray); - - return _possibleConstructorReturn(this, _getPrototypeOf(PointArray).call(this, array, fallback)); - } // Convert array to string - - - _createClass(PointArray, [{ - key: "toString", - value: function toString() { - // convert to a poly point string - for (var i = 0, il = this.value.length, array = []; i < il; i++) { - array.push(this.value[i].join(',')); - } - - return array.join(' '); - } - }, { - key: "toArray", - value: function toArray() { - return this.value.reduce(function (prev, curr) { - return [].concat.call(prev, curr); - }, []); - } // Convert array to line object - - }, { - key: "toLine", - value: function toLine() { - return { - x1: this.value[0][0], - y1: this.value[0][1], - x2: this.value[1][0], - y2: this.value[1][1] - }; - } // Get morphed array at given position - - }, { - key: "at", - value: function at(pos) { - // make sure a destination is defined - if (!this.destination) return this; // generate morphed point string - - for (var i = 0, il = this.value.length, array = []; i < il; i++) { - array.push([this.value[i][0] + (this.destination[i][0] - this.value[i][0]) * pos, this.value[i][1] + (this.destination[i][1] - this.value[i][1]) * pos]); - } - - return new PointArray(array); - } // Parse point string and flat array + }); + } + }]); - }, { - key: "parse", - value: function parse(array) { - var points = []; - array = array.valueOf(); // if it is an array + return Image; + }(Base); + registerMethods({ + Container: { + // create image element, load image and set its size + image: function image(source, callback) { + return this.put(new Image()).size(0, 0).load(source, callback); + } + } + }); + register(Image); - if (Array.isArray(array)) { - // and it is not flat, there is no need to parse it - if (Array.isArray(array[0])) { - return array; - } - } else { - // Else, it is considered as a string - // parse points - array = array.trim().split(delimiter).map(parseFloat); - } // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints - // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. + var PointArray = subClassArray('PointArray', SVGArray); + extend2(PointArray, { + // Convert array to string + toString: function toString() { + // convert to a poly point string + for (var i = 0, il = this.length, array = []; i < il; i++) { + array.push(this[i].join(',')); + } + return array.join(' '); + }, + // Convert array to line object + toLine: function toLine() { + return { + x1: this[0][0], + y1: this[0][1], + x2: this[1][0], + y2: this[1][1] + }; + }, + // Get morphed array at given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; // generate morphed point string - if (array.length % 2 !== 0) array.pop(); // wrap points in two-tuples and parse points as floats + for (var i = 0, il = this.length, array = []; i < il; i++) { + array.push([this[i][0] + (this.destination[i][0] - this[i][0]) * pos, this[i][1] + (this.destination[i][1] - this[i][1]) * pos]); + } - for (var i = 0, len = array.length; i < len; i = i + 2) { - points.push([array[i], array[i + 1]]); + return new PointArray(array); + }, + // Parse point string and flat array + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [[0, 0]]; + var points = []; // if it is an array + + if (array instanceof Array) { + // and it is not flat, there is no need to parse it + if (array[0] instanceof Array) { + return array; } + } else { + // Else, it is considered as a string + // parse points + array = array.trim().split(delimiter).map(parseFloat); + } // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints + // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. - return points; - } // Move point string - - }, { - key: "move", - value: function move(x, y) { - var box = this.bbox(); // get relative offset - x -= box.x; - y -= box.y; // move every point + if (array.length % 2 !== 0) array.pop(); // wrap points in two-tuples and parse points as floats - if (!isNaN(x) && !isNaN(y)) { - for (var i = this.value.length - 1; i >= 0; i--) { - this.value[i] = [this.value[i][0] + x, this.value[i][1] + y]; - } - } + for (var i = 0, len = array.length; i < len; i = i + 2) { + points.push([array[i], array[i + 1]]); + } - return this; - } // Resize poly string + return points; + }, + // Move point string + move: function move(x, y) { + var box = this.bbox(); // get relative offset - }, { - key: "size", - value: function size(width, height) { - var i; - var box = this.bbox(); // recalculate position of all points according to new size + x -= box.x; + y -= box.y; // move every point - for (i = this.value.length - 1; i >= 0; i--) { - if (box.width) this.value[i][0] = (this.value[i][0] - box.x) * width / box.width + box.x; - if (box.height) this.value[i][1] = (this.value[i][1] - box.y) * height / box.height + box.y; + if (!isNaN(x) && !isNaN(y)) { + for (var i = this.length - 1; i >= 0; i--) { + this[i] = [this[i][0] + x, this[i][1] + y]; } + } - return this; - } // Get bounding box of points - - }, { - key: "bbox", - value: function bbox() { - var maxX = -Infinity; - var maxY = -Infinity; - var minX = Infinity; - var minY = Infinity; - this.value.forEach(function (el) { - maxX = Math.max(el[0], maxX); - maxY = Math.max(el[1], maxY); - minX = Math.min(el[0], minX); - minY = Math.min(el[1], minY); - }); - return { - x: minX, - y: minY, - width: maxX - minX, - height: maxY - minY - }; + return this; + }, + // Resize poly string + size: function size(width, height) { + var i; + var box = this.bbox(); // recalculate position of all points according to new size + + for (i = this.length - 1; i >= 0; i--) { + if (box.width) this[i][0] = (this[i][0] - box.x) * width / box.width + box.x; + if (box.height) this[i][1] = (this[i][1] - box.y) * height / box.height + box.y; } - }]); - return PointArray; - }(SVGArray); + return this; + }, + // Get bounding box of points + bbox: function bbox() { + var maxX = -Infinity; + var maxY = -Infinity; + var minX = Infinity; + var minY = Infinity; + this.forEach(function (el) { + maxX = Math.max(el[0], maxX); + maxY = Math.max(el[1], maxY); + minX = Math.min(el[0], minX); + minY = Math.min(el[1], minY); + }); + return { + x: minX, + y: minY, + width: maxX - minX, + height: maxY - minY + }; + } + }); // export default class PointArray extends SVGArray { + // constructor (array, fallback = [[0, 0]]) { + // super(array, fallback) + // } + // + // // Convert array to string + // toString () { + // // convert to a poly point string + // for (var i = 0, il = this.length, array = []; i < il; i++) { + // array.push(this[i].join(',')) + // } + // + // return array.join(' ') + // } + // + // // toArray () { + // // return this.reduce(function (prev, curr) { + // // return [].concat.call(prev, curr) + // // }, []) + // // } + // + // // Convert array to line object + // toLine () { + // return { + // x1: this[0][0], + // y1: this[0][1], + // x2: this[1][0], + // y2: this[1][1] + // } + // } + // + // // Get morphed array at given position + // at (pos) { + // // make sure a destination is defined + // if (!this.destination) return this + // + // // generate morphed point string + // for (var i = 0, il = this.length, array = []; i < il; i++) { + // array.push([ + // this[i][0] + (this.destination[i][0] - this[i][0]) * pos, + // this[i][1] + (this.destination[i][1] - this[i][1]) * pos + // ]) + // } + // + // return new PointArray(array) + // } + // + // // Parse point string and flat array + // parse (array) { + // var points = [] + // + // array = array.valueOf() + // + // // if it is an array + // if (Array.isArray(array)) { + // // and it is not flat, there is no need to parse it + // if (Array.isArray(array[0])) { + // return array + // } + // } else { // Else, it is considered as a string + // // parse points + // array = array.trim().split(delimiter).map(parseFloat) + // } + // + // // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints + // // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. + // if (array.length % 2 !== 0) array.pop() + // + // // wrap points in two-tuples and parse points as floats + // for (var i = 0, len = array.length; i < len; i = i + 2) { + // points.push([ array[i], array[i + 1] ]) + // } + // + // return points + // } + // + // // Move point string + // move (x, y) { + // var box = this.bbox() + // + // // get relative offset + // x -= box.x + // y -= box.y + // + // // move every point + // if (!isNaN(x) && !isNaN(y)) { + // for (var i = this.length - 1; i >= 0; i--) { + // this[i] = [this[i][0] + x, this[i][1] + y] + // } + // } + // + // return this + // } + // + // // Resize poly string + // size (width, height) { + // var i + // var box = this.bbox() + // + // // recalculate position of all points according to new size + // for (i = this.length - 1; i >= 0; i--) { + // if (box.width) this[i][0] = ((this[i][0] - box.x) * width) / box.width + box.x + // if (box.height) this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y + // } + // + // return this + // } + // + // // Get bounding box of points + // bbox () { + // var maxX = -Infinity + // var maxY = -Infinity + // var minX = Infinity + // var minY = Infinity + // this.forEach(function (el) { + // maxX = Math.max(el[0], maxX) + // maxY = Math.max(el[1], maxY) + // minX = Math.min(el[0], minX) + // minY = Math.min(el[1], minY) + // }) + // return {x: minX, y: minY, width: maxX - minX, height: maxY - minY} + // } + // } var Line = /*#__PURE__*/ @@ -2591,7 +2713,7 @@ var SVG = (function () { _createClass(Line, [{ key: "array", value: function array() { - return new PointArray$1([[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 }, { @@ -2607,7 +2729,7 @@ var SVG = (function () { y2: y2 }; } else { - x1 = new PointArray$1(x1).toLine(); + x1 = new PointArray(x1).toLine(); } return this.attr(x1); @@ -2628,7 +2750,7 @@ var SVG = (function () { }]); return Line; - }(Base$1); + }(Base); registerMethods({ Container: { // Create a line element @@ -2697,7 +2819,7 @@ var SVG = (function () { }]); return Marker; - }(Base$1); + }(Base); registerMethods({ Container: { marker: function marker(width, height, block) { @@ -2736,7 +2858,7 @@ var SVG = (function () { function Mask(node) { _classCallCheck(this, Mask); - return _possibleConstructorReturn(this, _getPrototypeOf(Mask).call(this, nodeOrNew$1('mask', node))); + return _possibleConstructorReturn(this, _getPrototypeOf(Mask).call(this, nodeOrNew$1('mask', node), Mask)); } // Unmask all masked elements and remove itself @@ -2758,7 +2880,7 @@ var SVG = (function () { }]); return Mask; - }(Base$1); + }(Base); registerMethods({ Container: { mask: function mask() { @@ -2877,6 +2999,7 @@ var SVG = (function () { } }); + var PathArray = subClassArray('PathArray', SVGArray); var pathHandlers = { M: function M(c, p, p0) { p.x = p0.x = c[0]; @@ -2945,243 +3068,421 @@ var SVG = (function () { }(mlhvqtcsaz[i].toUpperCase()); } - var PathArray = - /*#__PURE__*/ - function (_SVGArray) { - _inherits(PathArray, _SVGArray); - - function PathArray(array) { - var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [['M', 0, 0]]; - - _classCallCheck(this, PathArray); - - return _possibleConstructorReturn(this, _getPrototypeOf(PathArray).call(this, array, fallback)); - } // Convert array to string - - - _createClass(PathArray, [{ - key: "toString", - value: function toString() { - return arrayToString(this); - } - }, { - key: "toArray", - value: function toArray() { - return this.reduce(function (prev, curr) { - return [].concat.call(prev, curr); - }, []); - } // Move path string - - }, { - key: "move", - value: function move(x, y) { - // get bounding box of current situation - var box = this.bbox(); // get relative offset - - x -= box.x; - y -= box.y; - - if (!isNaN(x) && !isNaN(y)) { - // move every point - for (var l, i = this.length - 1; i >= 0; i--) { - l = this[i][0]; - - if (l === 'M' || l === 'L' || l === 'T') { - this[i][1] += x; - this[i][2] += y; - } else if (l === 'H') { - this[i][1] += x; - } else if (l === 'V') { - this[i][1] += y; - } else if (l === 'C' || l === 'S' || l === 'Q') { - this[i][1] += x; - this[i][2] += y; - this[i][3] += x; - this[i][4] += y; - - if (l === 'C') { - this[i][5] += x; - this[i][6] += y; - } - } else if (l === 'A') { - this[i][6] += x; - this[i][7] += y; - } - } - } - - return this; - } // Resize path string + extend2(PathArray, { + // Convert array to string + toString: function toString() { + return arrayToString(this); + }, + // Move path string + move: function move(x, y) { + // get bounding box of current situation + var box = this.bbox(); // get relative offset - }, { - key: "size", - value: function size(width, height) { - // get bounding box of current situation - var box = this.bbox(); - var i, l; // recalculate position of all points according to new size + x -= box.x; + y -= box.y; - for (i = this.length - 1; i >= 0; i--) { + if (!isNaN(x) && !isNaN(y)) { + // move every point + for (var l, i = this.length - 1; i >= 0; i--) { l = this[i][0]; if (l === 'M' || l === 'L' || l === 'T') { - this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; - this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; + this[i][1] += x; + this[i][2] += y; } else if (l === 'H') { - this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + this[i][1] += x; } else if (l === 'V') { - this[i][1] = (this[i][1] - box.y) * height / box.height + box.y; + this[i][1] += y; } else if (l === 'C' || l === 'S' || l === 'Q') { - this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; - this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; - this[i][3] = (this[i][3] - box.x) * width / box.width + box.x; - this[i][4] = (this[i][4] - box.y) * height / box.height + box.y; + this[i][1] += x; + this[i][2] += y; + this[i][3] += x; + this[i][4] += y; if (l === 'C') { - this[i][5] = (this[i][5] - box.x) * width / box.width + box.x; - this[i][6] = (this[i][6] - box.y) * height / box.height + box.y; + this[i][5] += x; + this[i][6] += y; } } else if (l === 'A') { - // resize radii - this[i][1] = this[i][1] * width / box.width; - this[i][2] = this[i][2] * height / box.height; // move position values - - this[i][6] = (this[i][6] - box.x) * width / box.width + box.x; - this[i][7] = (this[i][7] - box.y) * height / box.height + box.y; + this[i][6] += x; + this[i][7] += y; } } + } - return this; - } // Test if the passed path array use the same path data commands as this path array - - }, { - key: "equalCommands", - value: function equalCommands(pathArray) { - var i, il, equalCommands; - pathArray = new PathArray(pathArray); - equalCommands = this.length === pathArray.value.length; + return this; + }, + // Resize path string + size: function size(width, height) { + // get bounding box of current situation + var box = this.bbox(); + var i, l; // recalculate position of all points according to new size + + for (i = this.length - 1; i >= 0; i--) { + l = this[i][0]; + + if (l === 'M' || l === 'L' || l === 'T') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; + } else if (l === 'H') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + } else if (l === 'V') { + this[i][1] = (this[i][1] - box.y) * height / box.height + box.y; + } else if (l === 'C' || l === 'S' || l === 'Q') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; + this[i][3] = (this[i][3] - box.x) * width / box.width + box.x; + this[i][4] = (this[i][4] - box.y) * height / box.height + box.y; + + if (l === 'C') { + this[i][5] = (this[i][5] - box.x) * width / box.width + box.x; + this[i][6] = (this[i][6] - box.y) * height / box.height + box.y; + } + } else if (l === 'A') { + // resize radii + this[i][1] = this[i][1] * width / box.width; + this[i][2] = this[i][2] * height / box.height; // move position values - for (i = 0, il = this.length; equalCommands && i < il; i++) { - equalCommands = this[i][0] === pathArray.value[i][0]; + this[i][6] = (this[i][6] - box.x) * width / box.width + box.x; + this[i][7] = (this[i][7] - box.y) * height / box.height + box.y; } + } - return equalCommands; - } // Make path array morphable + return this; + }, + // Test if the passed path array use the same path data commands as this path array + equalCommands: function equalCommands(pathArray) { + var i, il, equalCommands; + pathArray = new PathArray(pathArray); + equalCommands = this.length === pathArray.length; - }, { - key: "morph", - value: function morph(pathArray) { - pathArray = new PathArray(pathArray); + for (i = 0, il = this.length; equalCommands && i < il; i++) { + equalCommands = this[i][0] === pathArray[i][0]; + } - if (this.equalCommands(pathArray)) { - this.destination = pathArray; - } else { - this.destination = null; - } + return equalCommands; + }, + // Make path array morphable + morph: function morph(pathArray) { + pathArray = new PathArray(pathArray); - return this; - } // Get morphed path array at given position + if (this.equalCommands(pathArray)) { + this.destination = pathArray; + } else { + this.destination = null; + } - }, { - key: "at", - value: function at(pos) { - // make sure a destination is defined - if (!this.destination) return this; - var sourceArray = this; - var destinationArray = this.destination.value; - var array = []; - var pathArray = new PathArray(); - var i, il, j, jl; // Animate has specified in the SVG spec - // See: https://www.w3.org/TR/SVG11/paths.html#PathElement - - for (i = 0, il = sourceArray.length; i < il; i++) { - array[i] = [sourceArray[i][0]]; - - for (j = 1, jl = sourceArray[i].length; j < jl; j++) { - array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos; - } // For the two flags of the elliptical arc command, the SVG spec say: - // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true - // Elliptical arc command as an array followed by corresponding indexes: - // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] - // 0 1 2 3 4 5 6 7 - - - if (array[i][0] === 'A') { - array[i][4] = +(array[i][4] !== 0); - array[i][5] = +(array[i][5] !== 0); - } - } // Directly modify the value of a path array, this is done this way for performance - - - pathArray.value = array; - return pathArray; - } // Absolutize and parse path to array - - }, { - key: "parse", - value: function parse(array) { - // if it's already a patharray, no need to parse it - if (array instanceof PathArray) return array.valueOf(); // prepare for parsing - - var s; - var paramCnt = { - 'M': 2, - 'L': 2, - 'H': 1, - 'V': 1, - 'C': 6, - 'S': 4, - 'Q': 4, - 'T': 2, - 'A': 7, - 'Z': 0 - }; + return this; + }, + // Get morphed path array at given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; + var sourceArray = this; + var destinationArray = this.destination.value; + var array = []; + var pathArray = new PathArray(); + var i, il, j, jl; // Animate has specified in the SVG spec + // See: https://www.w3.org/TR/SVG11/paths.html#PathElement + + for (i = 0, il = sourceArray.length; i < il; i++) { + array[i] = [sourceArray[i][0]]; + + for (j = 1, jl = sourceArray[i].length; j < jl; j++) { + array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos; + } // For the two flags of the elliptical arc command, the SVG spec say: + // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true + // Elliptical arc command as an array followed by corresponding indexes: + // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // 0 1 2 3 4 5 6 7 + + + if (array[i][0] === 'A') { + array[i][4] = +(array[i][4] !== 0); + array[i][5] = +(array[i][5] !== 0); + } + } // Directly modify the value of a path array, this is done this way for performance - if (typeof array === 'string') { - array = array.replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 - .replace(pathLetters, ' $& ') // put some room between letters and numbers - .replace(hyphen, '$1 -') // add space before hyphen - .trim() // trim - .split(delimiter); // split into array - } else { - array = array.reduce(function (prev, curr) { - return [].concat.call(prev, curr); - }, []); - } // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] - - - var result = []; - var p = new Point$1(); - var p0 = new Point$1(); - var index = 0; - var len = array.length; - - do { - // Test if we have a path letter - if (isPathLetter.test(array[index])) { - s = array[index]; - ++index; // If last letter was a move command and we got no new, it defaults to [L]ine - } else if (s === 'M') { - s = 'L'; - } else if (s === 'm') { - s = 'l'; - } - result.push(pathHandlers[s].call(null, array.slice(index, index = index + paramCnt[s.toUpperCase()]).map(parseFloat), p, p0)); - } while (len > index); + pathArray.value = array; + return pathArray; + }, + // Absolutize and parse path to array + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [['M', 0, 0]]; + // if it's already a patharray, no need to parse it + if (array instanceof PathArray) return array; // prepare for parsing + + var s; + var paramCnt = { + 'M': 2, + 'L': 2, + 'H': 1, + 'V': 1, + 'C': 6, + 'S': 4, + 'Q': 4, + 'T': 2, + 'A': 7, + 'Z': 0 + }; - return result; - } // Get bounding box of path + if (typeof array === 'string') { + array = array.replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 + .replace(pathLetters, ' $& ') // put some room between letters and numbers + .replace(hyphen, '$1 -') // add space before hyphen + .trim() // trim + .split(delimiter); // split into array + } else { + array = array.reduce(function (prev, curr) { + return [].concat.call(prev, curr); + }, []); + } // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] + + + var result = []; + var p = new Point$1(); + var p0 = new Point$1(); + var index = 0; + var len = array.length; + + do { + // Test if we have a path letter + if (isPathLetter.test(array[index])) { + s = array[index]; + ++index; // If last letter was a move command and we got no new, it defaults to [L]ine + } else if (s === 'M') { + s = 'L'; + } else if (s === 'm') { + s = 'l'; + } - }, { - key: "bbox", - value: function bbox() { - parser().path.setAttribute('d', this.toString()); - return parser.nodes.path.getBBox(); - } - }]); + result.push(pathHandlers[s].call(null, array.slice(index, index = index + paramCnt[s.toUpperCase()]).map(parseFloat), p, p0)); + } while (len > index); - return PathArray; - }(SVGArray); + return result; + }, + // Get bounding box of path + bbox: function bbox() { + parser().path.setAttribute('d', this.toString()); + return parser.nodes.path.getBBox(); + } + }); // export default class PathArray extends SVGArray { + // constructor (array, fallback = [['M', 0, 0]]) { + // super(array, fallback) + // } + // + // // Convert array to string + // toString () { + // return arrayToString(this) + // } + // + // toArray () { + // return this.reduce(function (prev, curr) { + // return [].concat.call(prev, curr) + // }, []) + // } + // + // // Move path string + // move (x, y) { + // // get bounding box of current situation + // var box = this.bbox() + // + // // get relative offset + // x -= box.x + // y -= box.y + // + // if (!isNaN(x) && !isNaN(y)) { + // // move every point + // for (var l, i = this.length - 1; i >= 0; i--) { + // l = this[i][0] + // + // if (l === 'M' || l === 'L' || l === 'T') { + // this[i][1] += x + // this[i][2] += y + // } else if (l === 'H') { + // this[i][1] += x + // } else if (l === 'V') { + // this[i][1] += y + // } else if (l === 'C' || l === 'S' || l === 'Q') { + // this[i][1] += x + // this[i][2] += y + // this[i][3] += x + // this[i][4] += y + // + // if (l === 'C') { + // this[i][5] += x + // this[i][6] += y + // } + // } else if (l === 'A') { + // this[i][6] += x + // this[i][7] += y + // } + // } + // } + // + // return this + // } + // + // // Resize path string + // size (width, height) { + // // get bounding box of current situation + // var box = this.bbox() + // var i, l + // + // // recalculate position of all points according to new size + // for (i = this.length - 1; i >= 0; i--) { + // l = this[i][0] + // + // if (l === 'M' || l === 'L' || l === 'T') { + // this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x + // this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y + // } else if (l === 'H') { + // this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x + // } else if (l === 'V') { + // this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y + // } else if (l === 'C' || l === 'S' || l === 'Q') { + // this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x + // this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y + // this[i][3] = ((this[i][3] - box.x) * width) / box.width + box.x + // this[i][4] = ((this[i][4] - box.y) * height) / box.height + box.y + // + // if (l === 'C') { + // this[i][5] = ((this[i][5] - box.x) * width) / box.width + box.x + // this[i][6] = ((this[i][6] - box.y) * height) / box.height + box.y + // } + // } else if (l === 'A') { + // // resize radii + // this[i][1] = (this[i][1] * width) / box.width + // this[i][2] = (this[i][2] * height) / box.height + // + // // move position values + // this[i][6] = ((this[i][6] - box.x) * width) / box.width + box.x + // this[i][7] = ((this[i][7] - box.y) * height) / box.height + box.y + // } + // } + // + // return this + // } + // + // // Test if the passed path array use the same path data commands as this path array + // equalCommands (pathArray) { + // var i, il, equalCommands + // + // pathArray = new PathArray(pathArray) + // + // equalCommands = this.length === pathArray.value.length + // for (i = 0, il = this.length; equalCommands && i < il; i++) { + // equalCommands = this[i][0] === pathArray.value[i][0] + // } + // + // return equalCommands + // } + // + // // Make path array morphable + // morph (pathArray) { + // pathArray = new PathArray(pathArray) + // + // if (this.equalCommands(pathArray)) { + // this.destination = pathArray + // } else { + // this.destination = null + // } + // + // return this + // } + // + // // Get morphed path array at given position + // at (pos) { + // // make sure a destination is defined + // if (!this.destination) return this + // + // var sourceArray = this + // var destinationArray = this.destination.value + // var array = [] + // var pathArray = new PathArray() + // var i, il, j, jl + // + // // Animate has specified in the SVG spec + // // See: https://www.w3.org/TR/SVG11/paths.html#PathElement + // for (i = 0, il = sourceArray.length; i < il; i++) { + // array[i] = [sourceArray[i][0]] + // for (j = 1, jl = sourceArray[i].length; j < jl; j++) { + // array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos + // } + // // For the two flags of the elliptical arc command, the SVG spec say: + // // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true + // // Elliptical arc command as an array followed by corresponding indexes: + // // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // // 0 1 2 3 4 5 6 7 + // if (array[i][0] === 'A') { + // array[i][4] = +(array[i][4] !== 0) + // array[i][5] = +(array[i][5] !== 0) + // } + // } + // + // // Directly modify the value of a path array, this is done this way for performance + // pathArray.value = array + // return pathArray + // } + // + // // Absolutize and parse path to array + // parse (array) { + // // if it's already a patharray, no need to parse it + // if (array instanceof PathArray) return array.valueOf() + // + // // prepare for parsing + // var s + // var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 } + // + // if (typeof array === 'string') { + // array = array + // .replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 + // .replace(pathLetters, ' $& ') // put some room between letters and numbers + // .replace(hyphen, '$1 -') // add space before hyphen + // .trim() // trim + // .split(delimiter) // split into array + // } else { + // array = array.reduce(function (prev, curr) { + // return [].concat.call(prev, curr) + // }, []) + // } + // + // // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] + // var result = [] + // var p = new Point() + // var p0 = new Point() + // var index = 0 + // var len = array.length + // + // do { + // // Test if we have a path letter + // if (isPathLetter.test(array[index])) { + // s = array[index] + // ++index + // // If last letter was a move command and we got no new, it defaults to [L]ine + // } else if (s === 'M') { + // s = 'L' + // } else if (s === 'm') { + // s = 'l' + // } + // + // result.push(pathHandlers[s].call(null, + // array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), + // p, p0 + // ) + // ) + // } while (len > index) + // + // return result + // } + // + // // Get bounding box of path + // bbox () { + // parser().path.setAttribute('d', this.toString()) + // return parser.nodes.path.getBBox() + // } + // } var Path = /*#__PURE__*/ @@ -3259,7 +3560,7 @@ var SVG = (function () { }]); return Path; - }(Base$1); // Define morphable array + }(Base); // Define morphable array Path.prototype.MorphArray = PathArray; // Add parent method registerMethods({ @@ -3273,7 +3574,7 @@ var SVG = (function () { }); register(Path); - var MorphArray = PointArray$1; // Move by left top corner over x-axis + var MorphArray = PointArray; // Move by left top corner over x-axis function x$2(x) { return x == null ? this.bbox().x : this.move(x, this.bbox().y); @@ -3302,7 +3603,7 @@ var SVG = (function () { }); // Add polygon-specific functions - // Get array + function array() { return this._array || (this._array = new PointArray(this.attr('points'))); } // Plot new path @@ -3346,18 +3647,18 @@ var SVG = (function () { } return Polygon; - }(Base$1); + }(Base); registerMethods({ - Parent: { + Container: { // Create a wrapped polygon element polygon: function polygon(p) { // make sure plot is called as a setter - return this.put(new Polygon()).plot(p || new PointArray$1()); + return this.put(new Polygon()).plot(p || new PointArray()); } } }); - extend$1(Polygon, pointed); - extend$1(Polygon, poly); + extend(Polygon, pointed); + extend(Polygon, poly); register(Polygon); var Polyline = @@ -3373,18 +3674,18 @@ var SVG = (function () { } return Polyline; - }(Base$1); + }(Base); registerMethods({ - Parent: { + Container: { // Create a wrapped polygon element polyline: function polyline(p) { // make sure plot is called as a setter - return this.put(new Polyline()).plot(p || new PointArray$1()); + return this.put(new Polyline()).plot(p || new PointArray()); } } }); - extend$1(Polyline, pointed); - extend$1(Polyline, poly); + extend(Polyline, pointed); + extend(Polyline, poly); register(Polyline); var Rect = @@ -3400,7 +3701,7 @@ var SVG = (function () { } return Rect; - }(Base$1); + }(Base); registerMethods({ Container: { // Create a rect element @@ -3424,7 +3725,7 @@ var SVG = (function () { } return _Symbol; - }(Base$1); + }(Base); registerMethods({ Container: { symbol: function symbol() { @@ -3456,7 +3757,7 @@ var SVG = (function () { length: length }); - var Text$1 = + var Text = /*#__PURE__*/ function (_Base) { _inherits(Text, _Base); @@ -3468,7 +3769,7 @@ var SVG = (function () { _classCallCheck(this, Text); _this = _possibleConstructorReturn(this, _getPrototypeOf(Text).call(this, nodeOrNew$1('text', node), Text)); - _this.dom.leading = new SVGNumber$1(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 @@ -3573,7 +3874,7 @@ var SVG = (function () { } // act as setter - this.dom.leading = new SVGNumber$1(value); + this.dom.leading = new SVGNumber(value); return this.rebuild(); } // Rebuild appearance type @@ -3589,7 +3890,7 @@ var SVG = (function () { if (this._rebuild) { var self = this; var blankLineOffset = 0; - var dy = this.dom.leading * new SVGNumber$1(this.attr('font-size')); + var dy = this.dom.leading * new SVGNumber(this.attr('font-size')); this.each(function () { if (this.dom.newLined) { this.attr('x', self.attr('x')); @@ -3619,27 +3920,27 @@ var SVG = (function () { key: "setData", value: function setData(o) { this.dom = o; - this.dom.leading = new SVGNumber$1(o.leading || 1.3); + this.dom.leading = new SVGNumber(o.leading || 1.3); return this; } }]); return Text; - }(Base$1); - extend$1(Text$1, textable); + }(Base); + extend(Text, textable); registerMethods({ Container: { // Create text element text: function text(_text2) { - return this.put(new Text$1()).text(_text2); + return this.put(new Text()).text(_text2); }, // Create plain text element plain: function plain$$1(text) { - return this.put(new Text$1()).plain(text); + return this.put(new Text()).plain(text); } } }); - register(Text$1); + register(Text); var TextPath = /*#__PURE__*/ @@ -3650,7 +3951,7 @@ var SVG = (function () { function TextPath(node) { _classCallCheck(this, TextPath); - return _possibleConstructorReturn(this, _getPrototypeOf(TextPath).call(this, nodeOrNew$1('textPath', node))); + return _possibleConstructorReturn(this, _getPrototypeOf(TextPath).call(this, nodeOrNew$1('textPath', node), TextPath)); } // return the array of the path track element @@ -3682,7 +3983,7 @@ var SVG = (function () { }]); return TextPath; - }(Text$1); + }(Text); registerMethods({ Container: { textPath: function textPath(text, path) { @@ -3713,13 +4014,13 @@ var SVG = (function () { Path: { // creates a textPath from this path text: function text(_text) { - if (_text instanceof Text$1) { + if (_text instanceof Text) { var txt = _text.text(); return _text.clear().path(this).text(txt); } - return this.parent().put(new Text$1()).path(this).text(_text); + return this.parent().put(new Text()).path(this).text(_text); } // FIXME: Maybe add `targets` to get all textPaths associated with this path } @@ -3773,8 +4074,8 @@ var SVG = (function () { }]); return Tspan; - }(Base$1); - extend$1(Tspan, textable); + }(Base); + extend(Tspan, textable); registerMethods({ Tspan: { tspan: function tspan(text) { @@ -3800,7 +4101,7 @@ var SVG = (function () { function Use(node) { _classCallCheck(this, Use); - return _possibleConstructorReturn(this, _getPrototypeOf(Use).call(this, nodeOrNew('use', node), Use)); + return _possibleConstructorReturn(this, _getPrototypeOf(Use).call(this, nodeOrNew$1('use', node), Use)); } // Use element as a reference @@ -3813,7 +4114,7 @@ var SVG = (function () { }]); return Use; - }(Base$1); + }(Base); registerMethods({ Container: { // Create a use element @@ -3839,7 +4140,7 @@ var SVG = (function () { value: function init(source) { var base = arrayToMatrix([1, 0, 0, 1, 0, 0]); // ensure source as object - source = source instanceof Base$1 && source.is('Element') ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? arrayToMatrix(source) : _typeof(source) === 'object' && isMatrixLike(source) ? source : _typeof(source) === 'object' ? new Matrix().transform(source) : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) : base; // Merge the source matrix with the base matrix + source = source instanceof Base && source.is('Element') ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? arrayToMatrix(source) : _typeof(source) === 'object' && isMatrixLike(source) ? source : _typeof(source) === 'object' ? new Matrix().transform(source) : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) : base; // Merge the source matrix with the base matrix this.a = source.a != null ? source.a : base.a; this.b = source.b != null ? source.b : base.b; @@ -4330,7 +4631,7 @@ var SVG = (function () { This is needed because FF does not return the transformation matrix for the inner coordinate system when getScreenCTM() is called on nested svgs. However all other Browsers do that */ - if (this instanceof Doc && !this.isRoot()) { + if (typeof this.isRoot === 'function' && !this.isRoot()) { var rect = this.rect(1, 1); var m = rect.node.getScreenCTM(); rect.remove(); @@ -4452,11 +4753,13 @@ var SVG = (function () { return box.addOffset(); } }, - viewbox: function viewbox(x, y, width, height) { - // act as getter - if (x == null) return new Box$1(this.attr('viewBox')); // act as setter + viewbox: { + viewbox: function viewbox(x, y, width, height) { + // act as getter + if (x == null) return new Box$1(this.attr('viewBox')); // act as setter - return this.attr('viewBox', new Box$1(x, y, width, height)); + return this.attr('viewBox', new Box$1(x, y, width, height)); + } } }); @@ -4633,7 +4936,7 @@ var SVG = (function () { return Spring; }(Controller); - extend$1(Spring, { + extend(Spring, { duration: makeSetterGetter('_duration', recalculate), overshoot: makeSetterGetter('_overshoot', recalculate) }); @@ -4683,7 +4986,7 @@ var SVG = (function () { return PID; }(Controller); - extend$1(PID, { + extend(PID, { windup: makeSetterGetter('windup'), p: makeSetterGetter('P'), i: makeSetterGetter('I'), @@ -4744,25 +5047,25 @@ var SVG = (function () { var type = _typeof(value); if (type === 'number') { - this.type(SVGNumber$1); + this.type(SVGNumber); } else if (type === 'string') { if (Color.isColor(value)) { this.type(Color); } else if (regex.delimiter.test(value)) { this.type(regex.pathLetters.test(value) ? PathArray : SVGArray); } else if (regex.numberAndUnit.test(value)) { - this.type(SVGNumber$1); + this.type(SVGNumber); } else { - this.type(Morphable.NonMorphable); + this.type(NonMorphable); } - } else if (MorphableTypes.indexOf(value.constructor) > -1) { + } else if (morphableTypes.indexOf(value.constructor) > -1) { this.type(value.constructor); } else if (Array.isArray(value)) { this.type(SVGArray); } else if (type === 'object') { - this.type(Morphable.ObjectBag); + this.type(ObjectBag); } else { - this.type(Morphable.NonMorphable); + this.type(NonMorphable); } } @@ -4800,17 +5103,16 @@ var SVG = (function () { return Morphable; }(); - - Morphable.NonMorphable = + var NonMorphable = /*#__PURE__*/ function () { - function _class() { - _classCallCheck(this, _class); + function NonMorphable() { + _classCallCheck(this, NonMorphable); this.init.apply(this, arguments); } - _createClass(_class, [{ + _createClass(NonMorphable, [{ key: "init", value: function init(val) { val = Array.isArray(val) ? val[0] : val; @@ -4828,19 +5130,18 @@ var SVG = (function () { } }]); - return _class; + return NonMorphable; }(); - - Morphable.TransformBag = + var TransformBag = /*#__PURE__*/ function () { - function _class2() { - _classCallCheck(this, _class2); + function TransformBag() { + _classCallCheck(this, TransformBag); this.init.apply(this, arguments); } - _createClass(_class2, [{ + _createClass(TransformBag, [{ key: "init", value: function init(obj) { if (Array.isArray(obj)) { @@ -4856,7 +5157,7 @@ var SVG = (function () { }; } - Object.assign(this, Morphable.TransformBag.defaults, obj); + Object.assign(this, TransformBag.defaults, obj); } }, { key: "toArray", @@ -4866,10 +5167,9 @@ var SVG = (function () { } }]); - return _class2; + return TransformBag; }(); - - Morphable.TransformBag.defaults = { + TransformBag.defaults = { scaleX: 1, scaleY: 1, shear: 0, @@ -4879,17 +5179,16 @@ var SVG = (function () { originX: 0, originY: 0 }; - - Morphable.ObjectBag = + var ObjectBag = /*#__PURE__*/ function () { - function _class3() { - _classCallCheck(this, _class3); + function ObjectBag() { + _classCallCheck(this, ObjectBag); this.init.apply(this, arguments); } - _createClass(_class3, [{ + _createClass(ObjectBag, [{ key: "init", value: function init(objOrArr) { this.values = []; @@ -4925,19 +5224,24 @@ var SVG = (function () { } }]); - return _class3; + return ObjectBag; }(); - - var morphableTypes = [SVGNumber$1, Color, Box$1, Matrix$1, SVGArray, PointArray$1, PathArray, Morphable.NonMorphable, Morphable.TransformBag, Morphable.ObjectBag]; - extend$1(morphableTypes, { - to: function to(val, args) { - return new Morphable().type(this.constructor).from(this.valueOf()).to(val, args); - }, - fromArray: function fromArray(arr) { - this.init(arr); - return this; - } - }); + var morphableTypes = [NonMorphable, TransformBag, ObjectBag]; + function registerMorphableType() { + var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + morphableTypes.push.apply(morphableTypes, _toConsumableArray([].concat(type))); + } + function makeMorphable() { + extend(morphableTypes, { + to: function to(val, args) { + return new Morphable().type(this.constructor).from(this.valueOf()).to(val, args); + }, + fromArray: function fromArray(arr) { + this.init(arr); + return this; + } + }); + } var time = window.performance || Date; @@ -5240,7 +5544,7 @@ var SVG = (function () { // '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } // } - var Runner$1 = + var Runner = /*#__PURE__*/ function () { function Runner(options) { @@ -5679,7 +5983,7 @@ var SVG = (function () { return Runner; }(); - Runner$1.id = 0; + Runner.id = 0; var FakeRunner = function FakeRunner() { var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix$1(); @@ -5693,7 +5997,7 @@ var SVG = (function () { this.done = done; }; - extend$1([Runner$1, FakeRunner], { + extend([Runner, FakeRunner], { mergeWith: function mergeWith(runner) { return new FakeRunner(runner.transforms.lmultiply(this.transforms), runner.id); } @@ -5804,9 +6108,9 @@ var SVG = (function () { registerMethods({ Element: { animate: function animate(duration, delay, when) { - var o = Runner$1.sanitise(duration, delay, when); + var o = Runner.sanitise(duration, delay, when); var timeline$$1 = this.timeline(); - return new Runner$1(o.duration).loop(o).element(this).timeline(timeline$$1).schedule(delay, when); + return new Runner(o.duration).loop(o).element(this).timeline(timeline$$1).schedule(delay, when); }, delay: function delay(by, when) { return this.animate(0, by, when); @@ -5839,7 +6143,7 @@ var SVG = (function () { } } }); - extend$1(Runner$1, { + extend(Runner, { attr: function attr(a, v) { return this.styleAttr('attr', a, v); }, @@ -5865,7 +6169,7 @@ var SVG = (function () { return this; }, zoom: function zoom(level, point) { - var morpher = new Morphable(this._stepper).to(new SVGNumber$1(level)); + var morpher = new Morphable(this._stepper).to(new SVGNumber(level)); this.queue(function () { morpher = morpher.from(this.zoom()); }, function (pos) { @@ -5902,7 +6206,7 @@ var SVG = (function () { var isMatrix = isMatrixLike(transforms); affine = transforms.affine != null ? transforms.affine : affine != null ? affine : !isMatrix; // Create a morepher and set its type - var morpher = new Morphable().type(affine ? Morphable.TransformBag : Matrix$1).stepper(this._stepper); + var morpher = new Morphable().type(affine ? TransformBag : Matrix$1).stepper(this._stepper); var origin; var element; var current; @@ -6004,7 +6308,7 @@ var SVG = (function () { return this._queueNumberDelta('dy', y); }, _queueNumberDelta: function _queueNumberDelta(method, to) { - to = new SVGNumber$1(to); // Try to change the target if we have this method already registerd + to = new SVGNumber(to); // Try to change the target if we have this method already registerd if (this._tryRetargetDelta(method, to)) return this; // Make a morpher and queue the animation @@ -6039,7 +6343,7 @@ var SVG = (function () { return this; }, _queueNumber: function _queueNumber(method, value) { - return this._queueObject(method, new SVGNumber$1(value)); + return this._queueObject(method, new SVGNumber(value)); }, // Animatable center x-axis cx: function cx(x) { @@ -6194,21 +6498,21 @@ var SVG = (function () { Polyline: Polyline, Rect: Rect, Symbol: _Symbol, - Text: Text$1, + Text: Text, TextPath: TextPath, Tspan: Tspan, Use: Use, - SVGNumber: SVGNumber$1, + SVGNumber: SVGNumber, SVGArray: SVGArray, PathArray: PathArray, - PointArray: PointArray$1, + PointArray: PointArray, Matrix: Matrix$1, Point: Point$1, Box: Box$1, Color: Color, Morphable: Morphable, Queue: Queue, - Runner: Runner$1, + Runner: Runner, Timeline: Timeline, Controller: Controller, Ease: Ease, @@ -6229,7 +6533,10 @@ var SVG = (function () { Marker: Marker, Mask: Mask, Pattern: Pattern, - Symbol: _Symbol + Symbol: _Symbol, + Text: Text, + Tspan: Tspan, + TextPath: TextPath }); @@ -6256,13 +6563,99 @@ var SVG = (function () { Rect: Rect, Stop: Stop, Symbol: _Symbol, - Text: Text$1, + Text: Text, TextPath: TextPath, + Tspan: Tspan, Use: Use }); // ### This module adds backward / forward functionality to elements. + function siblings() { + return this.parent().children(); + } // Get the curent position siblings + + function position() { + return this.parent().index(this); + } // Get the next element (will return null if there is none) + + function next() { + return this.siblings()[this.position() + 1]; + } // Get the next element (will return null if there is none) + + function prev() { + return this.siblings()[this.position() - 1]; + } // Send given element one step forward + + function forward() { + var i = this.position() + 1; + 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); + } + + return this; + } // Send given element one step backward + + function backward() { + var i = this.position(); + + if (i > 0) { + this.parent().removeElement(this).add(this, i - 1); + } + + return this; + } // Send given element all the way to the front + + function front() { + var p = this.parent(); // Move node forward + + p.node.appendChild(this.node); // Make sure defs node is always at the top + + if (typeof p.isRoot == 'function' && p.isRoot()) { + p.node.appendChild(p.defs().node); + } + + return this; + } // Send given element all the way to the back + + function back() { + if (this.position() > 0) { + this.parent().removeElement(this).add(this, 0); + } + + return this; + } // Inserts a given element before the targeted element + + function before(element) { + element.remove(); + var i = this.position(); + this.parent().add(element, i); + return this; + } // Inserts a given element after the targeted element + + function after(element) { + element.remove(); + var i = this.position(); + this.parent().add(element, i + 1); + return this; + } + registerMethods('Element', { + siblings: siblings, + position: position, + next: next, + prev: prev, + forward: forward, + backward: backward, + front: front, + back: back, + before: before, + after: after + }); + // Dynamic style generator function css(style, val) { @@ -6443,7 +6836,7 @@ var SVG = (function () { } return this; - } // Initialize or return local memory object + } // return local memory object function memory() { return this._memory; @@ -6593,7 +6986,7 @@ var SVG = (function () { return new Point(this.node.getPointAtLength(length)); } }); - registerMethods(['Container', 'Runner'], { + registerMethods(['Parent', 'Runner'], { // Set font font: function font(a, v) { if (_typeof(a) === 'object') { @@ -6631,7 +7024,6 @@ var SVG = (function () { return this; } registerMethods('EventTarget', { - setup: setup$2, on: on$1, off: off$1, dispatch: dispatch$1, @@ -6667,19 +7059,19 @@ var SVG = (function () { } // Gets index of given element function index(element) { - return [].slice.call(this.node.children).indexOf(element.node); + return [].slice.call(this.node.childNodes).indexOf(element.node); } // Get a element at the given index - function get$1(i) { - return adopt$1(this.node.children[i]); + function get(i) { + return adopt$1(this.node.childNodes[i]); } // Get first child function first() { - return this.get(0); + return adopt$1(this.node.firstChild); } // Get the last child function last() { - return this.get(this.node.children.length - 1); + return adopt$1(this.node.lastChild); } // Iterates over all children and invokes a given block function each(block, deep) { @@ -6774,7 +7166,7 @@ var SVG = (function () { put: put, has: has, index: index, - get: get$1, + get: get, first: first, last: last, each: each, @@ -6787,29 +7179,33 @@ var SVG = (function () { }); // import {extend} from './tools.js' - var extend$2 = extend$1; - extend$2([Doc$1, _Symbol, Image, Pattern, Marker], getMethodsFor('viewbox')); - extend$2([Line, Polyline, Polygon, Path], getMethodsFor('marker')); - extend$2(Text$1, getMethodsFor('Text')); - extend$2(Path, getMethodsFor('Path')); - extend$2(Defs, getMethodsFor('Defs')); - extend$2([Text$1, Tspan], getMethodsFor('Tspan')); - extend$2([Rect, Ellipse, Circle, Gradient], getMethodsFor('radius')); + var extend$1 = extend; + extend$1([Doc$1, _Symbol, Image, Pattern, Marker], getMethodsFor('viewbox')); + extend$1([Line, Polyline, Polygon, Path], getMethodsFor('marker')); + extend$1(Text, getMethodsFor('Text')); + extend$1(Path, getMethodsFor('Path')); + extend$1(Defs, getMethodsFor('Defs')); + extend$1([Text, Tspan], getMethodsFor('Tspan')); + extend$1([Rect, Ellipse, Circle, Gradient], getMethodsFor('radius')); var containerMethods = getMethodsFor('Container'); // FIXME: We need a container array for (var i$1 in containers) { - extend$2(containers[i$1], containerMethods); + extend$1(containers[i$1], containerMethods); } var elementMethods = getMethodsFor('Element'); + var eventTargetMethods = getMethodsFor('EventTarget'); for (var _i in elements$1) { - extend$2(elements$1[_i], elementMethods); - extend$2(elements$1[_i], getConstructor('EventTarget')); - extend$2(elements$1[_i], getConstructor('Element')); - extend$2(elements$1[_i], getConstructor('Memory')); - } // The main wrapping element + extend$1(elements$1[_i], elementMethods); + extend$1(elements$1[_i], eventTargetMethods); + extend$1(elements$1[_i], getConstructor('EventTarget')); + extend$1(elements$1[_i], getConstructor('Element')); + extend$1(elements$1[_i], getConstructor('Memory')); + } + registerMorphableType([SVGNumber, Color, Box$1, Matrix$1, SVGArray, PointArray, PathArray]); + makeMorphable(); // The main wrapping element function SVG(element) { return makeInstance(element); @@ -6817,6 +7213,12 @@ var SVG = (function () { Object.assign(SVG, Classes); Object.assign(SVG, tools); Object.assign(SVG, adopter); + SVG.utils = utils; + SVG.regex = regex$1; // satisfy tests, fix later + SVG.get = SVG; + SVG.select = baseFind; + Object.assign(SVG, ns$2); + SVG.Element = SVG.Parent = SVG.Shape = SVG.Container = Base; return SVG; diff --git a/dist/svg.min.js b/dist/svg.min.js index 4571bd5..c2bd909 100644 --- a/dist/svg.min.js +++ b/dist/svg.min.js @@ -1 +1 @@ -var SVG=function(){"use strict";function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function c(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;n=e.time?e.run():dt.timeouts.push(e),e!==n););for(var i=null,r=dt.frames.last();i!==r&&(i=dt.frames.shift());)i.run();dt.transforms.forEach(function(t){t()}),dt.nextDraw=dt.timeouts.first()||dt.frames.first()?window.requestAnimationFrame(dt._draw):null}},vt=function(t){function i(t,e){var n;return c(this,i),n=f(this,o(i).call(this,X(null,t),i)),extend(r(r(n)),e),n}return u(i,s),a(i,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),i}();W(vt),ut("Bare",{element:function(t,e){var n=createCustom(t,e);return this.put(new n)}});var yt=function(){function n(){c(this,n),this.init.apply(this,arguments)}return a(n,[{key:"init",value:function(t,e){e=Array.isArray(t)?t[1]:e,t=Array.isArray(t)?t[0]:t,this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-34e37:34e37:"string"==typeof t?(e=t.match(h))&&(this.value=parseFloat(e[1]),"%"===e[5]?this.value/=100:"s"===e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof n&&(this.value=t.valueOf(),this.unit=t.unit)}},{key:"toString",value:function(){return("%"===this.unit?~~(1e8*this.value)/1e6:"s"===this.unit?this.value/1e3:this.value)+this.unit}},{key:"toJSON",value:function(){return this.toString()}},{key:"toArray",value:function(){return[this.value,this.unit]}},{key:"valueOf",value:function(){return this.value}},{key:"plus",value:function(t){return new n(this+(t=new n(t)),this.unit||t.unit)}},{key:"minus",value:function(t){return new n(this-(t=new n(t)),this.unit||t.unit)}},{key:"times",value:function(t){return new n(this*(t=new n(t)),this.unit||t.unit)}},{key:"divide",value:function(t){return new n(this/(t=new n(t)),this.unit||t.unit)}}]),n}();function pt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function mt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function gt(t){return null==t?this.attr("cx"):this.attr("cx",t)}function wt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function xt(t){return null==t?2*this.rx():this.rx(new yt(t).divide(2))}function kt(t){return null==t?2*this.ry():this.ry(new yt(t).divide(2))}function bt(t,e){var n=P(this,t,e);return this.rx(new yt(n.width).divide(2)).ry(new yt(n.height).divide(2))}var _t=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:pt,y:mt,cx:gt,cy:wt,width:xt,height:kt,size:bt}),Ot=function(t){function e(t){return c(this,e),f(this,o(e).call(this,X("circle",t),e))}return u(e,s),a(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function At(t){return t%360*Math.PI/180}function Mt(t,e){return utils.map((e||document).querySelectorAll(t),function(t){return $(t)})}G(Ot,{x:pt,y:mt,cx:gt,cy:wt,width:xt,height:kt,size:bt}),ut({Element:{circle:function(t){return this.put(new Ot).radius(new yt(t).divide(2)).move(0,0)}}}),W(Ot),ut("Container",{find:function(t){return Mt(t,this.node)}});var Tt=Z(U);function Ct(){return this.parent()&&this.parent().removeElement(this),this}ut("Element",{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var n=P(this,t,e);return this.width(new yt(n.width)).height(new yt(n.height))},clone:function(t){this.writeDataToDom();var e=tt(this.node.cloneNode(!0));return t?t.add(e):this.after(e),e},remove:Ct,replace:function(t){return this.after(t).remove(),t},addTo:function(t){return Q(t).put(this)},putIn:function(t){return Q(t).add(this)},id:function(t){return void 0!==t||this.node.id||(this.node.id=K(this.type)),this.attr("id",t)},inside:function(t,e){var n=this.bbox();return t>n.x&&e>n.y&&t",Rt=0,Lt={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},Ft=function(){function t(){c(this,t),this.init.apply(this,arguments)}return a(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?g.test(t)?(i=y.exec(t.replace(p,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):m.test(t)&&(i=v.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+N(Math.round(this.r))+N(Math.round(this.g))+N(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",m.test(t)||g.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}(),It=function(){try{return Array}catch(t){return Array}}(),Bt=function(t){function n(){var t,e;return c(this,n),(t=e=f(this,o(n).call(this))).init.apply(t,arguments),e}return u(n,It),a(n,[{key:"init",value:function(t,e){this.length=0,this.push.apply(this,O(this.parse(t||e)))}},{key:"toArray",value:function(){return Array.prototype.slice(this)}},{key:"toString",value:function(){this.join(" ")}},{key:"valueOf",value:function(){return this.toArray()}},{key:"parse",value:function(t){return t=t.valueOf(),Array.isArray(t)?t:t.trim().split(b).map(parseFloat)}},{key:"clone",value:function(){return new this.constructor(this)}},{key:"toSet",value:function(){return new Set(this)}}]),n}();function Xt(t,e,n){if(null==t){t={},e=this.node.attributes;var i=!0,r=!1,s=void 0;try{for(var u,a=e[Symbol.iterator]();!(i=(u=a.next()).done);i=!0){var o=u.value;t[o.nodeName]=isNumer.test(o.nodeValue)?parseFloat(o.nodeValue):o.nodeValue}}catch(t){r=!0,s=t}finally{try{i||null==a.return||a.return()}finally{if(r)throw s}}return t}if(Array.isArray(t));else if("object"===l(t))for(e in t)this.attr(e,t[e]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return null==(e=this.node.getAttribute(t))?Lt[t]:x.test(e)?parseFloat(e):e;for("fill"!==t&&"stroke"!==t||k.test(e)&&(e=this.doc().defs().image(e));"function"==typeof e.attrHook;)e=e.attrHook(this,t);"number"==typeof e?e=new yt(e):Ft.isColor(e)?e=new Ft(e):Array.isArray(e)&&(e=new Bt(e)),"leading"===t?this.leading&&this.leading(e):"string"==typeof n?this.node.setAttributeNS(n,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!==t&&"x"!==t||this.rebuild()}return this}ut("Element",{attr:Xt});var Yt=function(t){function e(t){return c(this,e),f(this,o(e).call(this,X(t+"Gradient","string"==typeof t?null:t),e))}return u(e,s),a(e,[{key:"stop",value:function(t,e,n){return this.put(new Nt).update(t,e,n)}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="gradientTransform"),Xt.call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}}]),e}();G(Yt,Pt),ut({Container:{gradient:function(t,e){return this.defs().gradient(t,e)}},Defs:{gradient:function(t,e){return this.put(new Yt(t)).update(e)}}}),W(Yt);var Gt=function(t){function e(t){return c(this,e),f(this,o(e).call(this,X("pattern",t)))}return u(e,s),a(e,[{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="patternTransform"),Xt.call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}}]),e}();ut({Container:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}},Defs:{pattern:function(t,e,n){return this.put(new Gt).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}}),W(Gt);var Ht=0;function Vt(t){return t instanceof Base&&t.is("EventTarget")?t.getEventTarget():t}function Ut(t,e,i,n,r){var s=i.bind(n||t),u=Vt(t);e=Array.isArray(e)?e:e.split(b),u.instance=u.instance||{events:{}};var a=u.instance.events;i._svgjsListenerId||(i._svgjsListenerId=++Ht),e.forEach(function(t){var e=t.split(".")[0],n=t.split(".")[1]||"*";a[e]=a[e]||{},a[e][n]=a[e][n]||{},a[e][n][i._svgjsListenerId]=s,u.addEventListener(e,s,r||!1)})}function Qt(t,e,s,u){var a=Vt(t);if(a.instance&&("function"!=typeof s||(s=s._svgjsListenerId))){var o=a.instance.events;(e=Array.isArray(e)?e:(e||"").split(b)).forEach(function(t){var e,n,i=t&&t.split(".")[0],r=t&&t.split(".")[1];if(s)o[i]&&o[i][r||"*"]&&(a.removeEventListener(i,o[i][r||"*"][s],u||!1),delete o[i][r||"*"][s]);else if(i&&r){if(o[i]&&o[i][r]){for(n in o[i][r])Qt(a,[i,r].join("."),n);delete o[i][r]}}else if(r)for(t in o)for(e in o[t])r===e&&Qt(a,[t,r].join("."));else if(i){if(o[i]){for(e in o[i])Qt(a,[i,e].join("."));delete o[i]}}else{for(t in o)Qt(a,t);a.instance.events={}}})}}var $t=function(t){function e(t){return c(this,e),f(this,o(e).call(this,X("image",t),e))}return u(e,s),a(e,[{key:"load",value:function(n,i){if(!n)return this;var r=new window.Image;return Ut(r,"load",function(t){var e=this.parent(Gt);0===this.width()&&0===this.height()&&this.size(r.width,r.height),e instanceof Gt&&0===e.width()&&0===e.height()&&e.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:r.width,height:r.height,ratio:r.width/r.height,url:n})},this),Ut(r,"load error",function(){Qt(r)}),this.attr("href",r.src=n,B)}},{key:"attrHook",value:function(t){var e=this;return t.doc().defs().pattern(0,0,function(t){t.add(e)})}}]),e}();ut({Container:{image:function(t,e){return this.put(new $t).size(0,0).load(t,e)}}}),W($t);var Wt=function(t){function r(t){var e=1":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Ae=function(){function t(){c(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),Me=function(t){function n(t){var e;return c(this,n),(e=f(this,o(n).call(this))).ease=Oe[t||qt]||t,e}return u(n,Ae),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),Te=function(t){function n(t){var e;return c(this,n),(e=f(this,o(n).call(this))).stepper=t,e}return u(n,Ae),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Ce(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var je=function(t){function i(t,e){var n;return c(this,i),(n=f(this,o(i).call(this))).duration(t||500).overshoot(e||0),n}return u(i,Te),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i);this._lastTime=this._time;var s=this._isDeclarative;if(this.done=!s&&!r&&this._time>=i,n||s){this._initialise(n),this.transforms=new xe;var u=this._run(s?t:e)}return this.done=this.done||u&&s,this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new Me(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;en.x&&e>n.y&&t=e.time?e.run():_t.timeouts.push(e),e!==n););for(var i=null,r=_t.frames.last();i!==r&&(i=_t.frames.shift());)i.run();_t.transforms.forEach(function(t){t()}),_t.nextDraw=_t.timeouts.first()||_t.frames.first()?window.requestAnimationFrame(_t._draw):null}},kt=function(t){function e(t){return c(this,e),a(this,u(e).call(this,B(t,"string"==typeof t?null:t),e))}return r(e,s),o(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function Ot(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function At(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function Ct(t){return null==t?this.attr("cx"):this.attr("cx",t)}function Mt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function jt(t){return null==t?2*this.rx():this.rx(new vt(t).divide(2))}function Tt(t){return null==t?2*this.ry():this.ry(new vt(t).divide(2))}function St(t,e){var n=D(this,t,e);return this.rx(new vt(n.width).divide(2)).ry(new vt(n.height).divide(2))}tt(kt),lt("Container",{element:function(t,e){return this.put(new kt(t,e))}});var Et=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:Ot,y:At,cx:Ct,cy:Mt,width:jt,height:Tt,size:St}),Nt=function(t){function e(t){return c(this,e),a(this,u(e).call(this,B("circle",t),e))}return r(e,s),o(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Pt(t,e){var n,i=t.length,r=[];for(n=0;n",Bt=0,Vt={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},Ut=function(){function t(){c(this,t),this.init.apply(this,arguments)}return o(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?g.test(t)?(i=v.exec(t.replace(p,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):m.test(t)&&(i=d.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+P(Math.round(this.r))+P(Math.round(this.g))+P(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",m.test(t)||g.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}(),Qt=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Pe=function(){function t(){c(this,t)}return o(t,[{key:"done",value:function(){return!1}}]),t}(),De=function(t){function n(t){var e;return c(this,n),(e=a(this,u(n).call(this))).ease=Ne[t||Ht]||t,e}return r(n,Pe),o(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),ze=function(t){function n(t){var e;return c(this,n),(e=a(this,u(n).call(this))).stepper=t,e}return r(n,Pe),o(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Re(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var qe=function(t){function i(t,e){var n;return c(this,i),(n=a(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,ze),o(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i);this._lastTime=this._time;var s=this._isDeclarative;if(this.done=!s&&!r&&this._time>=i,n||s){this._initialise(n),this.transforms=new je;var u=this._run(s?t:e)}return this.done=this.done||u&&s,this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new De(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e - - - - - - - diff --git a/spec/spec/adopter.js b/spec/spec/adopter.js index 0398cb3..90e0411 100644 --- a/spec/spec/adopter.js +++ b/spec/spec/adopter.js @@ -2,11 +2,11 @@ describe('Adopter', function() { var path, polyline, polygon, linearGradient, radialGradient beforeEach(function() { - path = SVG.get('lineAB') - polyline = SVG.get('inlineSVG').select('polyline')[0] - polygon = SVG.get('inlineSVG').select('polygon')[0] - linearGradient = SVG.get('inlineSVG').select('linearGradient')[0] - radialGradient = SVG.get('inlineSVG').select('radialGradient')[0] + path = SVG('#lineAB') + polyline = SVG('#inlineSVG').find('polyline')[0] + polygon = SVG('#inlineSVG').find('polygon')[0] + linearGradient = SVG('#inlineSVG').find('linearGradient')[0] + radialGradient = SVG('#inlineSVG').find('radialGradient')[0] }) describe('with SVG.Doc instance', function() { @@ -51,7 +51,7 @@ describe('Adopter', function() { expect(polygon.array() instanceof SVG.PointArray).toBeTruthy() }) }) - + describe('with linear SVG.Gradient instance', function() { it('is instance of SVG.Gradient', function() { expect(linearGradient instanceof SVG.Gradient).toBeTruthy() @@ -72,10 +72,10 @@ describe('Adopter', function() { describe('with node that has no matching svg.js class', function() { it('wraps the node in the base SVG.Element class', function() { - var desc = SVG.get('inlineSVG').select('desc')[0] + var desc = SVG('#inlineSVG').find('desc')[0] expect(desc instanceof SVG.Element).toBeTruthy() }) }) -}) \ No newline at end of file +}) diff --git a/spec/spec/array.js b/spec/spec/array.js index 7530ea1..2ec69dd 100644 --- a/spec/spec/array.js +++ b/spec/spec/array.js @@ -2,7 +2,7 @@ describe('Array', function () { var array, arr1, arr2 it('parses a matrix array correctly to string', function() { - array = new SVG.Array([ .343, .669, .119, 0, 0 + array = new SVG.SVGArray([ .343, .669, .119, 0, 0 , .249, -.626, .130, 0, 0 , .172, .334, .111, 0, 0 , .000, .000, .000, 1, -0 ]) @@ -10,35 +10,35 @@ describe('Array', function () { expect(array + '').toBe('0.343 0.669 0.119 0 0 0.249 -0.626 0.13 0 0 0.172 0.334 0.111 0 0 0 0 0 1 0') }) it('parses space seperated string and converts it to array', function() { - expect((new SVG.Array('1 2 3 4')).value).toEqual([1,2,3,4]) + expect((new SVG.SVGArray('1 2 3 4')).valueOf()).toEqual([1,2,3,4]) }) it('parses comma seperated string and converts it to array', function() { - expect((new SVG.Array('1,2,3,4')).value).toEqual([1,2,3,4]) + expect((new SVG.SVGArray('1,2,3,4')).valueOf()).toEqual([1,2,3,4]) }) describe('reverse()', function() { it('reverses the array', function() { - array = new SVG.Array([1 ,2 ,3, 4, 5]).reverse() - expect(array.value).toEqual([5, 4, 3, 2, 1]) + array = new SVG.SVGArray([1 ,2 ,3, 4, 5]).reverse() + expect(array.valueOf()).toEqual([5, 4, 3, 2, 1]) }) it('returns itself', function() { - array = new SVG.Array() + array = new SVG.SVGArray() expect(array.reverse()).toBe(array) }) }) describe('clone()', function() { it('creates a deep clone of the array', function() { - array = new SVG.Array([1, 2, 3, 4, 5]) + array = new SVG.SVGArray([1, 2, 3, 4, 5]) clone = array.clone() expect(array).toEqual(clone) expect(array).not.toBe(clone) - array = new SVG.Array([[1,2], [3, 4], [5]]) + array = new SVG.SVGArray([[1,2], [3, 4], [5]]) clone = array.clone() expect(array).toEqual(array) - for(var i = 0, len = array.value.length; i; ++i){ + for(var i = 0, len = array.length; i; ++i){ expect(array[i]).not.toBe(clone[i]) } }) @@ -49,7 +49,7 @@ describe('Array', function () { expect(array).toEqual(clone) expect(array).not.toBe(clone) - for(var i = 0, len = array.value.length; i; ++i){ + for(var i = 0, len = array.length; i; ++i){ expect(array[i]).not.toBe(clone[i]) } }) @@ -60,63 +60,11 @@ describe('Array', function () { expect(array).toEqual(clone) expect(array).not.toBe(clone) - for(var i = 0, len = array.value.length; i; ++i){ + for(var i = 0, len = array.length; i; ++i){ expect(array[i]).not.toBe(clone[i]) } }) }) - describe('morph()', function() { - it('adds entries so that destination array has equal length', function() { - - arr1 = new SVG.Array([1,2,3,4,5]) - arr2 = new SVG.Array([1,2,3,4]) - - arr1.morph(arr2) - - expect(arr1.destination.length).toBe(arr1.value.length) - }) - it('does the same the other way round', function() { - - arr1 = new SVG.Array([1,2,3,4]) - arr2 = new SVG.Array([1,2,3,4,5]) - - arr1.morph(arr2) - - expect(arr1.destination.length).toBe(arr1.value.length) - }) - }) - describe('settle()', function() { - it('cleans up any duplicate value', function() { - array = new SVG.Array([1,2,3,4,5,4,3,2,1]) - expect(array.settle().sort()).toEqual([1,2,3,4,5].sort()) - }) - }) - describe('at()', function() { - beforeEach(function() { - arr1 = new SVG.Array([1,2,3,4]) - arr2 = new SVG.Array([2,3,4,5]) - }) - - it('returns a new array instance', function() { - arr1.morph(arr2) - - start = arr1.at(0) - end = arr1.at(1) - - expect(start instanceof SVG.Array).toBeTruthy() - expect(start).not.toBe(arr1) - - expect(end instanceof SVG.Array).toBeTruthy() - expect(end).not.toBe(arr2) - }) - it('morphs all values of the array', function() { - arr1.morph(arr2) - expect(arr1.at(0.5).value).toEqual([1.5, 2.5, 3.5, 4.5]) - }) - it('returns itself if no destination was specified', function() { - expect(arr1.at(0.5)).toBe(arr1) - }) - }) }) @@ -134,7 +82,7 @@ describe('PointArray', function () { it('parses a flat array of x/y coordinates to a point array', function() { var array = new SVG.PointArray([1,4, 5,68, 12,24]) - expect(array.value).toEqual([[1,4], [5,68], [12,24]]) + expect(array.valueOf()).toEqual([[1,4], [5,68], [12,24]]) }) it('parses points with space delimitered x/y coordinates', function() { var array = new SVG.PointArray('221.08 191.79 0.46 191.79 0.46 63.92 63.8 0.46 284.46 0.46 284.46 128.37 221.08 191.79') @@ -178,7 +126,7 @@ describe('PointArray', function () { var array = new SVG.PointArray([1, 2, 3]) - expect(array.value).toEqual([[1,2]]) + expect(array.valueOf()).toEqual([[1,2]]) }) describe('size()', function() { @@ -196,35 +144,6 @@ describe('PointArray', function () { }) }) - - describe('at()', function() { - var arr1, arr2 - - beforeEach(function() { - arr1 = new SVG.PointArray([[1,2],[3,4]]) - arr2 = new SVG.Array([[2,3],[4,5]]) - }) - - it('returns a new array instance', function() { - arr1.morph(arr2) - - start = arr1.at(0) - end = arr1.at(1) - - expect(start instanceof SVG.PointArray).toBeTruthy() - expect(start).not.toBe(arr1) - - expect(end instanceof SVG.PointArray).toBeTruthy() - expect(end).not.toBe(arr2) - }) - it('morphs all values of the array', function() { - arr1.morph(arr2) - expect(arr1.at(0.5).value).toEqual([[1.5, 2.5], [3.5, 4.5]]) - }) - it('returns itself if no destination was specified', function() { - expect(arr1.at(0.5)).toBe(arr1) - }) - }) }) describe('PathArray', function () { @@ -251,12 +170,12 @@ describe('PathArray', function () { it('parses difficult syntax correctly', function() { expect(p5.toString()).toBe('M10 10L-45 -30.5L0.5 0.89L0.02 0.5L0.5 -0.5C0.5 0.5 0.5 0.5 0.5 0.5L-3 -4Z ') }) - + it('parses flat arrays correctly', function() { p6 = new SVG.PathArray([ 'M', 0, 0, 'L', 100, 100, 'z' ]) expect(p6.toString()).toBe('M0 0L100 100Z ') - }) - + }) + it('parses nested arrays correctly', function() { p7 = new SVG.PathArray([ ['M', 0, 0], ['L', 100, 100], ['z'] ]) expect(p7.toString()).toBe('M0 0L100 100Z ') @@ -266,7 +185,7 @@ describe('PathArray', function () { it('returns the valueOf when PathArray is given', function() { var p = new SVG.PathArray('m10 10 h 80 v 80 h -80 l 300 400 z') - expect((new SVG.PathArray(p)).value).toEqual(p.value) + expect((new SVG.PathArray(p))).toEqual(p) }) it('can handle all formats which can be used', function() { @@ -304,10 +223,11 @@ describe('PathArray', function () { ['Z'] ] - var toBeTested = p3.size(600,200).value - for(var i in toBeTested) { + var toBeTested = p3.size(600,200) + + for(var i = toBeTested.legth; --i;) { expect(toBeTested[i].shift().toUpperCase()).toBe(expected[i].shift().toUpperCase()) - for(var j in toBeTested[i]) { + for(var j = toBeTested[i].length; --j;) { expect(toBeTested[i][j]).toBeCloseTo(expected[i][j]) } } @@ -328,77 +248,77 @@ describe('PathArray', function () { expect(pathArray1.equalCommands(pathArray2)).toBe(false) }) }) - - describe('morph()', function() { - it('should set the attribute destination to the passed path array when it have the same comands as this path array', function() { - var pathArray1 = new SVG.PathArray('m -1500,-478 a 292,195 0 0 1 262,205 l -565,319 c 0,0 -134,-374 51,-251 185,122 251,-273 251,-273 z') - , pathArray2 = new SVG.PathArray('m -680, 527 a 292,195 0 0 1 262,205 l -565,319 c 0,0 -134,-374 51,-251 185,122 251,-273 251,-273 z') - - pathArray1.morph(pathArray2) - expect(pathArray1.destination).toEqual(pathArray2) - }) - it('should set the attribute destination to null when the passed path array does not have the same comands as this path array', function() { - var pathArray1 = new SVG.PathArray('m -1500,-478 a 292,195 0 0 1 262,205 l -565,319 c 0,0 -134,-374 51,-251 185,122 251,-273 251,-273 z') - , pathArray2 = new SVG.PathArray('m - 663, 521 c 147,178 118,-25 245,210 l -565,319 c 0,0 -134,-374 51,-251 185,122 268,-278 268,-278 z') - - pathArray1.morph(pathArray2) - expect(pathArray1.destination).toBeNull() - }) - }) - - describe('at()', function() { - it('returns a morphed path array at a given position', function() { - var pathArray1 = new SVG.PathArray("M 63 25 A 15 15 0 0 1 73 40 A 15 15 0 0 1 61 53 C 49 36 50 59 50 59 L 33 55 Z") - , pathArray2 = new SVG.PathArray("M 132 40 A 15 15 0 0 1 141 54 A 15 15 0 0 1 130 67 C 118 51 119 73 119 73 L 103 69 Z") - , morphedPathArray = pathArray1.morph(pathArray2).at(0.5) - , sourceArray = pathArray1.value, destinationArray = pathArray1.destination.value - , morphedArray = morphedPathArray.value - , i, il, j, jl - - expect(morphedArray.length).toBe(sourceArray.length) - - // For all the commands - for(i = 0, il = sourceArray.length; i < il; i++) { - // Expect the current command to be the same - expect(morphedArray[i][0]).toBe(sourceArray[i][0]) - expect(morphedArray[i].length).toBe(sourceArray[i].length) - - // For all the parameters of the current command - for(j = 1, jl = sourceArray[i].length; j < jl; j++) { - expect(morphedArray[i][j]).toBe((sourceArray[i][j] + destinationArray[i][j]) / 2) - } - } - }) - it('should interpolate flags and booleans as fractions between zero and one, with any non-zero value considered to be a value of one/true', function() { - // Only the Elliptical arc command use flags, it has the following form: - // A rx ry x-axis-rotation large-arc-flag sweep-flag x y - var pathArray1 = new SVG.PathArray('M 13 13 A 25 37 0 0 1 43 25') - , pathArray2 = new SVG.PathArray('M 101 55 A 25 37 0 1 0 130 67') - , morphedPathArray - - pathArray1.morph(pathArray2) - - // The morphedPathArray.value contain 2 commands: [['M', ...], ['A', ...]] - // Elliptical arc command in a path array followed by corresponding indexes: - // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] - // 0 1 2 3 4 5 6 7 - morphedPathArray = pathArray1.at(0) - expect(morphedPathArray.value[1][4]).toBe(0) - expect(morphedPathArray.value[1][5]).toBe(1) - - morphedPathArray = pathArray1.at(0.5) - expect(morphedPathArray.value[1][4]).toBe(1) - expect(morphedPathArray.value[1][5]).toBe(1) - - morphedPathArray = pathArray1.at(1) - expect(morphedPathArray.value[1][4]).toBe(1) - expect(morphedPathArray.value[1][5]).toBe(0) - }) - it('return itself if the destination attribute is null', function(){ - var pathArray = new SVG.PathArray('M 13 13 A 25 37 0 0 1 43 25') - pathArray.destination = null - expect(pathArray.at(0.45)).toBe(pathArray) - }) - }) + // + // describe('morph()', function() { + // it('should set the attribute destination to the passed path array when it have the same comands as this path array', function() { + // var pathArray1 = new SVG.PathArray('m -1500,-478 a 292,195 0 0 1 262,205 l -565,319 c 0,0 -134,-374 51,-251 185,122 251,-273 251,-273 z') + // , pathArray2 = new SVG.PathArray('m -680, 527 a 292,195 0 0 1 262,205 l -565,319 c 0,0 -134,-374 51,-251 185,122 251,-273 251,-273 z') + // + // pathArray1.morph(pathArray2) + // expect(pathArray1.destination).toEqual(pathArray2) + // }) + // it('should set the attribute destination to null when the passed path array does not have the same comands as this path array', function() { + // var pathArray1 = new SVG.PathArray('m -1500,-478 a 292,195 0 0 1 262,205 l -565,319 c 0,0 -134,-374 51,-251 185,122 251,-273 251,-273 z') + // , pathArray2 = new SVG.PathArray('m - 663, 521 c 147,178 118,-25 245,210 l -565,319 c 0,0 -134,-374 51,-251 185,122 268,-278 268,-278 z') + // + // pathArray1.morph(pathArray2) + // expect(pathArray1.destination).toBeNull() + // }) + // }) + // + // describe('at()', function() { + // it('returns a morphed path array at a given position', function() { + // var pathArray1 = new SVG.PathArray("M 63 25 A 15 15 0 0 1 73 40 A 15 15 0 0 1 61 53 C 49 36 50 59 50 59 L 33 55 Z") + // , pathArray2 = new SVG.PathArray("M 132 40 A 15 15 0 0 1 141 54 A 15 15 0 0 1 130 67 C 118 51 119 73 119 73 L 103 69 Z") + // , morphedPathArray = pathArray1.morph(pathArray2).at(0.5) + // , sourceArray = pathArray1, destinationArray = pathArray1.destination + // , morphedArray = morphedPathArray + // , i, il, j, jl + // + // expect(morphedArray.length).toBe(sourceArray.length) + // + // // For all the commands + // for(i = 0, il = sourceArray.length; i < il; i++) { + // // Expect the current command to be the same + // expect(morphedArray[i][0]).toBe(sourceArray[i][0]) + // expect(morphedArray[i].length).toBe(sourceArray[i].length) + // + // // For all the parameters of the current command + // for(j = 1, jl = sourceArray[i].length; j < jl; j++) { + // expect(morphedArray[i][j]).toBe((sourceArray[i][j] + destinationArray[i][j]) / 2) + // } + // } + // }) + // it('should interpolate flags and booleans as fractions between zero and one, with any non-zero value considered to be a value of one/true', function() { + // // Only the Elliptical arc command use flags, it has the following form: + // // A rx ry x-axis-rotation large-arc-flag sweep-flag x y + // var pathArray1 = new SVG.PathArray('M 13 13 A 25 37 0 0 1 43 25') + // , pathArray2 = new SVG.PathArray('M 101 55 A 25 37 0 1 0 130 67') + // , morphedPathArray + // + // pathArray1.morph(pathArray2) + // + // // The morphedPathArray contain 2 commands: [['M', ...], ['A', ...]] + // // Elliptical arc command in a path array followed by corresponding indexes: + // // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // // 0 1 2 3 4 5 6 7 + // morphedPathArray = pathArray1.at(0) + // expect(morphedPathArray[1][4]).toBe(0) + // expect(morphedPathArray[1][5]).toBe(1) + // + // morphedPathArray = pathArray1.at(0.5) + // expect(morphedPathArray[1][4]).toBe(1) + // expect(morphedPathArray[1][5]).toBe(1) + // + // morphedPathArray = pathArray1.at(1) + // expect(morphedPathArray[1][4]).toBe(1) + // expect(morphedPathArray[1][5]).toBe(0) + // }) + // it('return itself if the destination attribute is null', function(){ + // var pathArray = new SVG.PathArray('M 13 13 A 25 37 0 0 1 43 25') + // pathArray.destination = null + // expect(pathArray.at(0.45)).toBe(pathArray) + // }) + // }) }) diff --git a/spec/spec/boxes.js b/spec/spec/boxes.js index 934f472..2fcbd8b 100644 --- a/spec/spec/boxes.js +++ b/spec/spec/boxes.js @@ -119,40 +119,6 @@ describe('Box', function() { })) }) }) - - describe('morph()', function() { - it('stores a given box for morphing', function() { - var box1 = new SVG.Box(10, 100, 200, 300) - , box2 = new SVG.Box(50, -100, 300, 300) - - box1.morph(box2) - - expect(box1.destination).toEqual(box2) - }) - it('stores a clone, not the given viewbox itself', function() { - var box1 = new SVG.Box(10, 100, 200, 300) - , box2 = new SVG.Box(50, -100, 300, 300) - - box1.morph(box2) - expect(box1.destination).not.toBe(box2) - }) - }) - - describe('at()', function() { - it('returns a morphed box at a given position', function() { - var box1 = new SVG.Box(10, 100, 200, 300) - , box2 = new SVG.Box(50, -100, 300, 300) - , box3 = box1.morph(box2).at(0.5) - - expect(box1.toString()).toBe('10 100 200 300') - expect(box2.toString()).toBe('50 -100 300 300') - expect(box3.toString()).toBe('30 0 250 300') - }) - it('returns itself when no destination given', function() { - var box = new SVG.Box(10, 100, 200, 300) - expect(box.at(0.5)).toBe(box) - }) - }) }) diff --git a/spec/spec/color.js b/spec/spec/color.js index 1e86544..410577f 100644 --- a/spec/spec/color.js +++ b/spec/spec/color.js @@ -11,7 +11,7 @@ describe('Color', function() { expect(color.g).toBe(0) expect(color.b).toBe(128) }) - + it('correclty parses a 3 digit hex string', function() { color = new SVG.Color('#f06') expect(color.r).toBe(255) @@ -43,44 +43,4 @@ describe('Color', function() { expect(color.brightness()).toBe(0.346) }) }) - - describe('morph()', function() { - it('prepares the color for morphing', function() { - var destination = new SVG.Color - color.morph(destination) - expect(color.destination).toEqual(destination) - }) - }) - - describe('at()', function() { - it('morphes color to a given position', function() { - var destination = new SVG.Color - var morphed = color.morph(destination).at(0.5) - expect(morphed.r).toBe(0) - expect(morphed.g).toBe(51) - expect(morphed.b).toBe(127) - }) - - it('morphes color to 1 with higher values', function() { - var destination = new SVG.Color('#fff') - var morphed = color.morph(destination).at(2) - expect(morphed.r).toBe(255) - expect(morphed.g).toBe(255) - expect(morphed.b).toBe(255) - }) - - it('morphes color to 0 with lower values', function() { - var destination = new SVG.Color('#fff') - var morphed = color.morph(destination).at(-3) - expect(morphed.r).toBe(0) - expect(morphed.g).toBe(102) - expect(morphed.b).toBe(255) - }) - - it('returns itself when no destination specified', function() { - expect(color.at(0.5)).toBe(color) - }) - }) - }) - diff --git a/spec/spec/container.js b/spec/spec/container.js index 3e49e37..a1bfa6e 100644 --- a/spec/spec/container.js +++ b/spec/spec/container.js @@ -236,7 +236,7 @@ describe('Container', function() { }) expect(children).toEqual((parserInDoc ? [parser[0].type] : []).concat(['rect', 'ellipse', 'polygon'])) }) - it('should only include the its own children', function() { + it('should only include its own children', function() { var children = [] , group = draw.group() @@ -375,14 +375,3 @@ describe('Container', function() { }) }) - - - - - - - - - - - diff --git a/spec/spec/element.js b/spec/spec/element.js index 41f2af4..5907f17 100644 --- a/spec/spec/element.js +++ b/spec/spec/element.js @@ -26,7 +26,7 @@ describe('Element', function() { afterEach(function() { rect.remove() - //draw.defs().select('pattern').forEach(function(el) { el.remove() }) + //draw.defs().find('pattern').forEach(function(el) { el.remove() }) draw.defs().clear() }) @@ -95,15 +95,15 @@ describe('Element', function() { }) it('creates an image in defs when image path is specified for fill', function() { rect.attr('fill', imageUrl) - expect(draw.defs().select('pattern').length).toBe(1) - expect(draw.defs().select('pattern image').length).toBe(1) - expect(draw.defs().select('pattern image')[0].attr('href')).toBe(imageUrl) + expect(draw.defs().find('pattern').length).toBe(1) + expect(draw.defs().find('pattern image').length).toBe(1) + expect(draw.defs().find('pattern image')[0].attr('href')).toBe(imageUrl) }) it('creates pattern in defs when image object is specified for fill', function() { rect.attr('fill', new SVG.Image().load(imageUrl)) - expect(draw.defs().select('pattern').length).toBe(1) - expect(draw.defs().select('pattern image').length).toBe(1) - expect(draw.defs().select('pattern image')[0].attr('href')).toBe(imageUrl) + expect(draw.defs().find('pattern').length).toBe(1) + expect(draw.defs().find('pattern image').length).toBe(1) + expect(draw.defs().find('pattern image')[0].attr('href')).toBe(imageUrl) }) it('correctly creates SVG.Array if array given', function() { rect.attr('something', [2,3,4]) diff --git a/spec/spec/selector.js b/spec/spec/selector.js index 92aa66f..e2b6318 100644 --- a/spec/spec/selector.js +++ b/spec/spec/selector.js @@ -3,13 +3,13 @@ describe('Selector', function() { describe('get()', function() { it('gets an element\'s instance by id', function() { var rect = draw.rect(111, 333) - - expect(SVG.get(rect.id())).toBe(rect) + + expect(SVG('#'+rect.id())).toBe(rect) }) it('makes all the element\'s methods available', function() { var element = draw.group() - , got = SVG.get(element.id()) - + , got = SVG('#'+element.id()) + expect(got.attr()).toEqual(element.attr()) }) it('gets a referenced element by attribute value', function() { @@ -18,12 +18,12 @@ describe('Selector', function() { , mark = draw.marker(10, 10) , path = draw.path(svgPath).marker('end', mark) - expect(SVG.get(use.attr('href'))).toBe(rect) - expect(SVG.get(path.attr('marker-end'))).toBe(mark) + expect(SVG('#'+use.attr('href'))).toBe(rect) + expect(SVG('#'+path.attr('marker-end'))).toBe(mark) }) }) - describe('select()', function() { + describe('find()', function() { var e1, e2, e3, e4 ,e5 beforeEach(function() { @@ -34,14 +34,14 @@ describe('Selector', function() { e5 = draw.rect(100, 100).addClass('selectable-element') }) it('gets all elements with a given class name', function() { - expect(SVG.select('rect.selectable-element').valueOf()).toEqual([e1, e3, e5]) + expect(SVG.find('rect.selectable-element').valueOf()).toEqual([e1, e3, e5]) }) it('returns an Array', function() { - expect(SVG.select('rect.selectable-element') instanceof Array).toBe(true) + expect(SVG.find('rect.selectable-element') instanceof Array).toBe(true) }) }) - describe('Parent#select()', function() { + describe('Parent#find()', function() { it('gets all elements with a given class name inside a given element', function() { var group = draw.group() , e1 = draw.rect(100, 100).addClass('selectable-element') @@ -50,8 +50,8 @@ describe('Selector', function() { , e4 = draw.rect(100, 100).addClass('unselectable-element') , e5 = group.rect(100, 100).addClass('selectable-element') - expect(group.select('rect.selectable-element').valueOf()).toEqual([e3, e5]) + expect(group.find('rect.selectable-element').valueOf()).toEqual([e3, e5]) }) }) - -}) \ No newline at end of file + +}) diff --git a/src/ArrayPolyfill.js b/src/ArrayPolyfill.js index 596b2ca..9c3ee61 100644 --- a/src/ArrayPolyfill.js +++ b/src/ArrayPolyfill.js @@ -1 +1,31 @@ -export default Array +export const subClassArray = (function () { + try { + //throw 'asdad' + // try es6 subclassing + return Function('name', 'baseClass', '_constructor', [ + 'baseClass = baseClass || Array', + 'return {', + '[name]: class extends baseClass {', + 'constructor (...args) {', + 'super(...args)', + '_constructor && _constructor.apply(this, args)', + '}', + '}', + '}[name]' + ].join('\n')) + + } catch (e) { + // Use es5 approach + return (name, baseClass = Array, _constructor) => { + const Arr = function () { + baseClass.apply(this, arguments) + _constructor && _constructor.apply(this, arguments) + } + + Arr.prototype = Object.create(baseClass.prototype) + Arr.prototype.constructor = Arr + + return Arr + } + } +})() diff --git a/src/Bare.js b/src/Bare.js index 5dde370..e0d8cdd 100644 --- a/src/Bare.js +++ b/src/Bare.js @@ -2,12 +2,13 @@ import {nodeOrNew} from './tools.js' import {register} from './adopter.js' import Base from './Base.js' import {registerMethods} from './methods.js' +import {extend} from './tools.js' export default class Bare extends Base { - constructor (node, inherit) { - super(nodeOrNew(null, node), Bare) - extend(this, inherit) + constructor (node, inherit = {}) { + super(nodeOrNew(node, typeof node === 'string' ? null : node), Bare) + //extend(this, inherit) } words (text) { @@ -25,10 +26,9 @@ export default class Bare extends Base { register(Bare) -registerMethods('Bare', { +registerMethods('Container', { // Create an element that is not described by SVG.js - element (element, inherit) { - let custom = createCustom(element, inherit) - return this.put(new custom()) + element (node, inherit) { + return this.put(new Bare(node, inherit)) } }) diff --git a/src/Box.js b/src/Box.js index 478f971..1cb46b0 100644 --- a/src/Box.js +++ b/src/Box.js @@ -118,11 +118,13 @@ registerMethods({ return box.addOffset() } }, - viewbox: function (x, y, width, height) { - // act as getter - if (x == null) return new Box(this.attr('viewBox')) + viewbox: { + viewbox (x, y, width, height) { + // act as getter + if (x == null) return new Box(this.attr('viewBox')) - // act as setter - return this.attr('viewBox', new Box(x, y, width, height)) + // act as setter + return this.attr('viewBox', new Box(x, y, width, height)) + } } }) diff --git a/src/Doc.js b/src/Doc.js index 5ccb831..b5e4ffd 100644 --- a/src/Doc.js +++ b/src/Doc.js @@ -4,6 +4,7 @@ import { extend, nodeOrNew } from './tools.js' import { ns, xlink, xmlns, svgjs } from './namespaces.js' import {adopt, register} from './adopter.js' import {registerMethods} from './methods.js' +import {remove, parent, doc} from './Element.js' export default class Doc extends Base { constructor(node) { @@ -21,7 +22,7 @@ export default class Doc extends Base { // If not, call docs from this element doc() { if (this.isRoot()) return this - return Element.doc.call(this) + return doc.call(this) } // Add namespaces @@ -46,16 +47,16 @@ export default class Doc extends Base { if (this.isRoot()) { return this.node.parentNode.nodeName === '#document' ? null - : this.node.parentNode + : adopt(this.node.parentNode) } - return Element.parent.call(this, type) + return parent.call(this, type) } // Removes the doc from the DOM remove() { if (!this.isRoot()) { - return Element.remove.call(this) + return remove.call(this) } if (this.parent()) { diff --git a/src/Element.js b/src/Element.js index d852ced..0494965 100644 --- a/src/Element.js +++ b/src/Element.js @@ -1,4 +1,4 @@ -import {proportionalSize, matcher} from './helpers.js' +import {proportionalSize, matcher, idFromReference} from './helpers.js' import {makeInstance, adopt, assignNewId, eid, root, getClass} from './adopter.js' import {delimiter} from './regex.js' import {ns} from './namespaces.js' @@ -180,10 +180,10 @@ export function toggleClass (name) { return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) } -// FIXME: getIdFromReference // Get referenced element form attribute value export function reference (attr) { - return get(this.attr(attr)) + let id = idFromReference(this.attr(attr)) + return id ? makeInstance(id) : null } // Returns the parent element instance @@ -273,7 +273,7 @@ export function getEventTarget () { registerMethods('Element', { x, y, cx, cy, move, center, width, height, size, clone, remove, replace, addTo, putIn, id, inside, toString, classes, hasClass, addClass, removeClass, - toggleClass, reference, doc, defs, parents, matches, native, svg, + toggleClass, reference, doc, defs, parent, parents, matches, native, svg, writeDataToDom, setData, getEventTarget }) diff --git a/src/Ellipse.js b/src/Ellipse.js index c38d322..b5bd436 100644 --- a/src/Ellipse.js +++ b/src/Ellipse.js @@ -1,6 +1,6 @@ import Base from './Base.js' import * as circled from './circled.js' -import {extend} from './tools.js' +import {extend, nodeOrNew} from './tools.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' diff --git a/src/EventTarget.js b/src/EventTarget.js index b4496ff..8702894 100644 --- a/src/EventTarget.js +++ b/src/EventTarget.js @@ -31,7 +31,7 @@ export function fire (event, data) { } registerMethods('EventTarget', { - setup, on, off, dispatch, fire + on, off, dispatch, fire }) registerConstructor('EventTarget', setup) diff --git a/src/G.js b/src/G.js index d6d16ed..58962e0 100644 --- a/src/G.js +++ b/src/G.js @@ -1,10 +1,11 @@ import Base from './Base.js' +import {nodeOrNew} from './tools.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' export default class G extends Base { constructor (node) { - super(nodeorNew('g', node), G) + super(nodeOrNew('g', node), G) } } diff --git a/src/Mask.js b/src/Mask.js index 8edf4ec..b61c336 100644 --- a/src/Mask.js +++ b/src/Mask.js @@ -8,7 +8,7 @@ import {registerMethods} from './methods.js' export default class Mask extends Base { // Initialize node constructor (node) { - super(nodeOrNew('mask', node)) + super(nodeOrNew('mask', node), Mask) } // Unmask all masked elements and remove itself diff --git a/src/Matrix.js b/src/Matrix.js index 11ec53e..7f3afe5 100644 --- a/src/Matrix.js +++ b/src/Matrix.js @@ -492,7 +492,7 @@ registerMethods({ This is needed because FF does not return the transformation matrix for the inner coordinate system when getScreenCTM() is called on nested svgs. However all other Browsers do that */ - if (this instanceof Doc && !this.isRoot()) { + if (typeof this.isRoot === 'function' && !this.isRoot()) { var rect = this.rect(1, 1) var m = rect.node.getScreenCTM() rect.remove() diff --git a/src/Morphable.js b/src/Morphable.js index a181b49..d927733 100644 --- a/src/Morphable.js +++ b/src/Morphable.js @@ -66,16 +66,16 @@ export default class Morphable { } else if (regex.numberAndUnit.test(value)) { this.type(SVGNumber) } else { - this.type(Morphable.NonMorphable) + this.type(NonMorphable) } - } else if (MorphableTypes.indexOf(value.constructor) > -1) { + } else if (morphableTypes.indexOf(value.constructor) > -1) { this.type(value.constructor) } else if (Array.isArray(value)) { this.type(SVGArray) } else if (type === 'object') { - this.type(Morphable.ObjectBag) + this.type(ObjectBag) } else { - this.type(Morphable.NonMorphable) + this.type(NonMorphable) } } @@ -112,7 +112,7 @@ export default class Morphable { } } -Morphable.NonMorphable = class { +export class NonMorphable { constructor (...args) { this.init(...args) } @@ -131,7 +131,7 @@ Morphable.NonMorphable = class { } } -Morphable.TransformBag = class { +export class TransformBag { constructor (...args) { this.init(...args) } @@ -150,7 +150,7 @@ Morphable.TransformBag = class { } } - Object.assign(this, Morphable.TransformBag.defaults, obj) + Object.assign(this, TransformBag.defaults, obj) } toArray () { @@ -169,7 +169,7 @@ Morphable.TransformBag = class { } } -Morphable.TransformBag.defaults = { +TransformBag.defaults = { scaleX: 1, scaleY: 1, shear: 0, @@ -180,7 +180,7 @@ Morphable.TransformBag.defaults = { originY: 0 } -Morphable.ObjectBag = class { +export class ObjectBag { constructor (...args) { this.init(...args) } @@ -216,28 +216,27 @@ Morphable.ObjectBag = class { } } -let morphableTypes = [ - SVGNumber, - Color, - Box, - Matrix, - SVGArray, - PointArray, - PathArray, - Morphable.NonMorphable, - Morphable.TransformBag, - Morphable.ObjectBag +const morphableTypes = [ + NonMorphable, + TransformBag, + ObjectBag ] -extend(morphableTypes, { - to (val, args) { - return new Morphable() - .type(this.constructor) - .from(this.valueOf()) - .to(val, args) - }, - fromArray (arr) { - this.init(arr) - return this - } -}) +export function registerMorphableType (type = []) { + morphableTypes.push(...[].concat(type)) +} + +export function makeMorphable () { + extend(morphableTypes, { + to (val, args) { + return new Morphable() + .type(this.constructor) + .from(this.valueOf()) + .to(val, args) + }, + fromArray (arr) { + this.init(arr) + return this + } + }) +} diff --git a/src/Parent.js b/src/Parent.js index ee8e3b0..769cd49 100644 --- a/src/Parent.js +++ b/src/Parent.js @@ -1,6 +1,7 @@ import {makeInstance, adopt} from './adopter.js' import {map} from './utils.js' import {registerMethods} from './methods.js' +import Base from './Base.js' // Returns all child elements export function children () { diff --git a/src/PathArray.js b/src/PathArray.js index 20c80c6..b05bd92 100644 --- a/src/PathArray.js +++ b/src/PathArray.js @@ -3,8 +3,14 @@ import parser from './parser.js' import {numbersWithDots, pathLetters, hyphen, delimiter, isPathLetter} from './regex.js' import Point from './Point.js' import SVGArray from './SVGArray.js' +import {subClassArray} from './ArrayPolyfill.js' +import {extend2} from './tools.js' -let pathHandlers = { +const PathArray = subClassArray('PathArray', SVGArray) + +export default PathArray + +const pathHandlers = { M: function (c, p, p0) { p.x = p0.x = c[0] p.y = p0.y = c[1] @@ -77,21 +83,12 @@ for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { })(mlhvqtcsaz[i].toUpperCase()) } -export default class PathArray extends SVGArray { - constructor (array, fallback = [['M', 0, 0]]) { - super(array, fallback) - } +extend2(PathArray, { // Convert array to string toString () { return arrayToString(this) - } - - toArray () { - return this.reduce(function (prev, curr) { - return [].concat.call(prev, curr) - }, []) - } + }, // Move path string move (x, y) { @@ -132,7 +129,7 @@ export default class PathArray extends SVGArray { } return this - } + }, // Resize path string size (width, height) { @@ -173,7 +170,7 @@ export default class PathArray extends SVGArray { } return this - } + }, // Test if the passed path array use the same path data commands as this path array equalCommands (pathArray) { @@ -181,13 +178,13 @@ export default class PathArray extends SVGArray { pathArray = new PathArray(pathArray) - equalCommands = this.length === pathArray.value.length + equalCommands = this.length === pathArray.length for (i = 0, il = this.length; equalCommands && i < il; i++) { - equalCommands = this[i][0] === pathArray.value[i][0] + equalCommands = this[i][0] === pathArray[i][0] } return equalCommands - } + }, // Make path array morphable morph (pathArray) { @@ -200,7 +197,7 @@ export default class PathArray extends SVGArray { } return this - } + }, // Get morphed path array at given position at (pos) { @@ -234,12 +231,12 @@ export default class PathArray extends SVGArray { // Directly modify the value of a path array, this is done this way for performance pathArray.value = array return pathArray - } + }, // Absolutize and parse path to array - parse (array) { + parse (array = [['M', 0, 0]]) { // if it's already a patharray, no need to parse it - if (array instanceof PathArray) return array.valueOf() + if (array instanceof PathArray) return array // prepare for parsing var s @@ -285,11 +282,228 @@ export default class PathArray extends SVGArray { } while (len > index) return result - } + }, // Get bounding box of path bbox () { parser().path.setAttribute('d', this.toString()) return parser.nodes.path.getBBox() } -} +}) + +// export default class PathArray extends SVGArray { +// constructor (array, fallback = [['M', 0, 0]]) { +// super(array, fallback) +// } +// +// // Convert array to string +// toString () { +// return arrayToString(this) +// } +// +// toArray () { +// return this.reduce(function (prev, curr) { +// return [].concat.call(prev, curr) +// }, []) +// } +// +// // Move path string +// move (x, y) { +// // get bounding box of current situation +// var box = this.bbox() +// +// // get relative offset +// x -= box.x +// y -= box.y +// +// if (!isNaN(x) && !isNaN(y)) { +// // move every point +// for (var l, i = this.length - 1; i >= 0; i--) { +// l = this[i][0] +// +// if (l === 'M' || l === 'L' || l === 'T') { +// this[i][1] += x +// this[i][2] += y +// } else if (l === 'H') { +// this[i][1] += x +// } else if (l === 'V') { +// this[i][1] += y +// } else if (l === 'C' || l === 'S' || l === 'Q') { +// this[i][1] += x +// this[i][2] += y +// this[i][3] += x +// this[i][4] += y +// +// if (l === 'C') { +// this[i][5] += x +// this[i][6] += y +// } +// } else if (l === 'A') { +// this[i][6] += x +// this[i][7] += y +// } +// } +// } +// +// return this +// } +// +// // Resize path string +// size (width, height) { +// // get bounding box of current situation +// var box = this.bbox() +// var i, l +// +// // recalculate position of all points according to new size +// for (i = this.length - 1; i >= 0; i--) { +// l = this[i][0] +// +// if (l === 'M' || l === 'L' || l === 'T') { +// this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x +// this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y +// } else if (l === 'H') { +// this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x +// } else if (l === 'V') { +// this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y +// } else if (l === 'C' || l === 'S' || l === 'Q') { +// this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x +// this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y +// this[i][3] = ((this[i][3] - box.x) * width) / box.width + box.x +// this[i][4] = ((this[i][4] - box.y) * height) / box.height + box.y +// +// if (l === 'C') { +// this[i][5] = ((this[i][5] - box.x) * width) / box.width + box.x +// this[i][6] = ((this[i][6] - box.y) * height) / box.height + box.y +// } +// } else if (l === 'A') { +// // resize radii +// this[i][1] = (this[i][1] * width) / box.width +// this[i][2] = (this[i][2] * height) / box.height +// +// // move position values +// this[i][6] = ((this[i][6] - box.x) * width) / box.width + box.x +// this[i][7] = ((this[i][7] - box.y) * height) / box.height + box.y +// } +// } +// +// return this +// } +// +// // Test if the passed path array use the same path data commands as this path array +// equalCommands (pathArray) { +// var i, il, equalCommands +// +// pathArray = new PathArray(pathArray) +// +// equalCommands = this.length === pathArray.value.length +// for (i = 0, il = this.length; equalCommands && i < il; i++) { +// equalCommands = this[i][0] === pathArray.value[i][0] +// } +// +// return equalCommands +// } +// +// // Make path array morphable +// morph (pathArray) { +// pathArray = new PathArray(pathArray) +// +// if (this.equalCommands(pathArray)) { +// this.destination = pathArray +// } else { +// this.destination = null +// } +// +// return this +// } +// +// // Get morphed path array at given position +// at (pos) { +// // make sure a destination is defined +// if (!this.destination) return this +// +// var sourceArray = this +// var destinationArray = this.destination.value +// var array = [] +// var pathArray = new PathArray() +// var i, il, j, jl +// +// // Animate has specified in the SVG spec +// // See: https://www.w3.org/TR/SVG11/paths.html#PathElement +// for (i = 0, il = sourceArray.length; i < il; i++) { +// array[i] = [sourceArray[i][0]] +// for (j = 1, jl = sourceArray[i].length; j < jl; j++) { +// array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos +// } +// // For the two flags of the elliptical arc command, the SVG spec say: +// // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true +// // Elliptical arc command as an array followed by corresponding indexes: +// // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] +// // 0 1 2 3 4 5 6 7 +// if (array[i][0] === 'A') { +// array[i][4] = +(array[i][4] !== 0) +// array[i][5] = +(array[i][5] !== 0) +// } +// } +// +// // Directly modify the value of a path array, this is done this way for performance +// pathArray.value = array +// return pathArray +// } +// +// // Absolutize and parse path to array +// parse (array) { +// // if it's already a patharray, no need to parse it +// if (array instanceof PathArray) return array.valueOf() +// +// // prepare for parsing +// var s +// var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 } +// +// if (typeof array === 'string') { +// array = array +// .replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 +// .replace(pathLetters, ' $& ') // put some room between letters and numbers +// .replace(hyphen, '$1 -') // add space before hyphen +// .trim() // trim +// .split(delimiter) // split into array +// } else { +// array = array.reduce(function (prev, curr) { +// return [].concat.call(prev, curr) +// }, []) +// } +// +// // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] +// var result = [] +// var p = new Point() +// var p0 = new Point() +// var index = 0 +// var len = array.length +// +// do { +// // Test if we have a path letter +// if (isPathLetter.test(array[index])) { +// s = array[index] +// ++index +// // If last letter was a move command and we got no new, it defaults to [L]ine +// } else if (s === 'M') { +// s = 'L' +// } else if (s === 'm') { +// s = 'l' +// } +// +// result.push(pathHandlers[s].call(null, +// array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), +// p, p0 +// ) +// ) +// } while (len > index) +// +// return result +// } +// +// // Get bounding box of path +// bbox () { +// parser().path.setAttribute('d', this.toString()) +// return parser.nodes.path.getBBox() +// } +// } diff --git a/src/Pattern.js b/src/Pattern.js index eca2355..2c61baf 100644 --- a/src/Pattern.js +++ b/src/Pattern.js @@ -7,7 +7,7 @@ import {registerMethods} from './methods.js' export default class Pattern extends Base { // Initialize node constructor (node) { - super(nodeOrNew('pattern', node)) + super(nodeOrNew('pattern', node), Pattern) } // Return the fill id diff --git a/src/PointArray.js b/src/PointArray.js index cadff80..a291054 100644 --- a/src/PointArray.js +++ b/src/PointArray.js @@ -1,36 +1,32 @@ import SVGArray from './SVGArray.js' import {delimiter} from './regex.js' +import {subClassArray} from './ArrayPolyfill.js' +import {extend2} from './tools.js' -export default class PointArray extends SVGArray { - constructor (array, fallback = [[0, 0]]) { - super(array, fallback) - } +const PointArray = subClassArray('PointArray', SVGArray) + +export default PointArray +extend2(PointArray, { // Convert array to string toString () { // convert to a poly point string - for (var i = 0, il = this.value.length, array = []; i < il; i++) { - array.push(this.value[i].join(',')) + for (var i = 0, il = this.length, array = []; i < il; i++) { + array.push(this[i].join(',')) } return array.join(' ') - } - - toArray () { - return this.value.reduce(function (prev, curr) { - return [].concat.call(prev, curr) - }, []) - } + }, // Convert array to line object toLine () { return { - x1: this.value[0][0], - y1: this.value[0][1], - x2: this.value[1][0], - y2: this.value[1][1] + x1: this[0][0], + y1: this[0][1], + x2: this[1][0], + y2: this[1][1] } - } + }, // Get morphed array at given position at (pos) { @@ -38,26 +34,24 @@ export default class PointArray extends SVGArray { if (!this.destination) return this // generate morphed point string - for (var i = 0, il = this.value.length, array = []; i < il; i++) { + for (var i = 0, il = this.length, array = []; i < il; i++) { array.push([ - this.value[i][0] + (this.destination[i][0] - this.value[i][0]) * pos, - this.value[i][1] + (this.destination[i][1] - this.value[i][1]) * pos + this[i][0] + (this.destination[i][0] - this[i][0]) * pos, + this[i][1] + (this.destination[i][1] - this[i][1]) * pos ]) } return new PointArray(array) - } + }, // Parse point string and flat array - parse (array) { + parse (array = [[0, 0]]) { var points = [] - array = array.valueOf() - // if it is an array - if (Array.isArray(array)) { + if (array instanceof Array) { // and it is not flat, there is no need to parse it - if (Array.isArray(array[0])) { + if (array[0] instanceof Array) { return array } } else { // Else, it is considered as a string @@ -75,7 +69,7 @@ export default class PointArray extends SVGArray { } return points - } + }, // Move point string move (x, y) { @@ -87,13 +81,13 @@ export default class PointArray extends SVGArray { // move every point if (!isNaN(x) && !isNaN(y)) { - for (var i = this.value.length - 1; i >= 0; i--) { - this.value[i] = [this.value[i][0] + x, this.value[i][1] + y] + for (var i = this.length - 1; i >= 0; i--) { + this[i] = [this[i][0] + x, this[i][1] + y] } } return this - } + }, // Resize poly string size (width, height) { @@ -101,13 +95,13 @@ export default class PointArray extends SVGArray { var box = this.bbox() // recalculate position of all points according to new size - for (i = this.value.length - 1; i >= 0; i--) { - if (box.width) this.value[i][0] = ((this.value[i][0] - box.x) * width) / box.width + box.x - if (box.height) this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y + for (i = this.length - 1; i >= 0; i--) { + if (box.width) this[i][0] = ((this[i][0] - box.x) * width) / box.width + box.x + if (box.height) this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y } return this - } + }, // Get bounding box of points bbox () { @@ -115,7 +109,7 @@ export default class PointArray extends SVGArray { var maxY = -Infinity var minX = Infinity var minY = Infinity - this.value.forEach(function (el) { + this.forEach(function (el) { maxX = Math.max(el[0], maxX) maxY = Math.max(el[1], maxY) minX = Math.min(el[0], minX) @@ -123,4 +117,128 @@ export default class PointArray extends SVGArray { }) return {x: minX, y: minY, width: maxX - minX, height: maxY - minY} } -} +}) + +// export default class PointArray extends SVGArray { +// constructor (array, fallback = [[0, 0]]) { +// super(array, fallback) +// } +// +// // Convert array to string +// toString () { +// // convert to a poly point string +// for (var i = 0, il = this.length, array = []; i < il; i++) { +// array.push(this[i].join(',')) +// } +// +// return array.join(' ') +// } +// +// // toArray () { +// // return this.reduce(function (prev, curr) { +// // return [].concat.call(prev, curr) +// // }, []) +// // } +// +// // Convert array to line object +// toLine () { +// return { +// x1: this[0][0], +// y1: this[0][1], +// x2: this[1][0], +// y2: this[1][1] +// } +// } +// +// // Get morphed array at given position +// at (pos) { +// // make sure a destination is defined +// if (!this.destination) return this +// +// // generate morphed point string +// for (var i = 0, il = this.length, array = []; i < il; i++) { +// array.push([ +// this[i][0] + (this.destination[i][0] - this[i][0]) * pos, +// this[i][1] + (this.destination[i][1] - this[i][1]) * pos +// ]) +// } +// +// return new PointArray(array) +// } +// +// // Parse point string and flat array +// parse (array) { +// var points = [] +// +// array = array.valueOf() +// +// // if it is an array +// if (Array.isArray(array)) { +// // and it is not flat, there is no need to parse it +// if (Array.isArray(array[0])) { +// return array +// } +// } else { // Else, it is considered as a string +// // parse points +// array = array.trim().split(delimiter).map(parseFloat) +// } +// +// // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints +// // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. +// if (array.length % 2 !== 0) array.pop() +// +// // wrap points in two-tuples and parse points as floats +// for (var i = 0, len = array.length; i < len; i = i + 2) { +// points.push([ array[i], array[i + 1] ]) +// } +// +// return points +// } +// +// // Move point string +// move (x, y) { +// var box = this.bbox() +// +// // get relative offset +// x -= box.x +// y -= box.y +// +// // move every point +// if (!isNaN(x) && !isNaN(y)) { +// for (var i = this.length - 1; i >= 0; i--) { +// this[i] = [this[i][0] + x, this[i][1] + y] +// } +// } +// +// return this +// } +// +// // Resize poly string +// size (width, height) { +// var i +// var box = this.bbox() +// +// // recalculate position of all points according to new size +// for (i = this.length - 1; i >= 0; i--) { +// if (box.width) this[i][0] = ((this[i][0] - box.x) * width) / box.width + box.x +// if (box.height) this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y +// } +// +// return this +// } +// +// // Get bounding box of points +// bbox () { +// var maxX = -Infinity +// var maxY = -Infinity +// var minX = Infinity +// var minY = Infinity +// this.forEach(function (el) { +// maxX = Math.max(el[0], maxX) +// maxY = Math.max(el[1], maxY) +// minX = Math.min(el[0], minX) +// minY = Math.min(el[1], minY) +// }) +// return {x: minX, y: minY, width: maxX - minX, height: maxY - minY} +// } +// } diff --git a/src/Polygon.js b/src/Polygon.js index 208adca..69337e3 100644 --- a/src/Polygon.js +++ b/src/Polygon.js @@ -15,7 +15,7 @@ export default class Polygon extends Base { } registerMethods({ - Parent: { + Container: { // Create a wrapped polygon element polygon (p) { // make sure plot is called as a setter diff --git a/src/Polyline.js b/src/Polyline.js index a4c7a23..4fad379 100644 --- a/src/Polyline.js +++ b/src/Polyline.js @@ -14,7 +14,7 @@ export default class Polyline extends Base { } registerMethods({ - Parent: { + Container: { // Create a wrapped polygon element polyline (p) { // make sure plot is called as a setter diff --git a/src/Runner.js b/src/Runner.js index 04b2a9c..52731e0 100644 --- a/src/Runner.js +++ b/src/Runner.js @@ -1,6 +1,6 @@ import {isMatrixLike, getOrigin} from './helpers.js' import Matrix from './Matrix.js' -import Morphable from './Morphable.js' +import {default as Morphable, TransformBag} from './Morphable.js' import SVGNumber from './SVGNumber.js' import Timeline from './Timeline.js' import {Controller, Ease, Stepper} from './Controller.js' @@ -674,7 +674,7 @@ extend(Runner, { // Create a morepher and set its type const morpher = new Morphable() - .type(affine ? Morphable.TransformBag : Matrix) + .type(affine ? TransformBag : Matrix) .stepper(this._stepper) let origin diff --git a/src/SVGArray.js b/src/SVGArray.js index 9789dfe..bb98aad 100644 --- a/src/SVGArray.js +++ b/src/SVGArray.js @@ -1,55 +1,95 @@ /* global arrayClone */ import {delimiter} from './regex.js' -import ArrayPolyfill from './ArrayPolyfill.js' - -let BaseArray = (function() { - try { - let b = class extends Array {} - return Array - } catch (e) { - return ArrayPolyfill - } -})() - -export default class SVGArray extends BaseArray { - constructor (...args) { - super() - this.init(...args) - } - - init (array, fallback) { +import {subClassArray} from './ArrayPolyfill.js' +import {extend2} from './tools.js' + +const SVGArray = subClassArray('SVGArray', Array, function (...args) { + this.init(...args) +}) + +export default SVGArray + +extend2(SVGArray, { + init (...args) { //this.splice(0, this.length) this.length = 0 - this.push(...this.parse(array || fallback)) - } + this.push(...this.parse(...args)) + }, toArray () { - return Array.prototype.slice(this) - } + const ret = [] + ret.push(...this) + //Array.prototype.push.apply(ret, this) + return ret + //return Array.prototype.concat.apply([], this) + }, toString () { - this.join(' ') - } + return this.join(' ') + }, valueOf () { return this.toArray() - } + }, // Parse whitespace separated string - parse (array) { - array = array.valueOf() + parse (array = []) { + //array = array.valueOf() - // if already is an array, no need to parse it - if (Array.isArray(array)) return array + // If already is an array, no need to parse it + if (array instanceof Array) return array return array.trim().split(delimiter).map(parseFloat) - } + }, clone () { return new this.constructor(this) - } + }, toSet () { return new Set(this) - } -} + }, +}) + +// export default class SVGArray extends BaseArray { +// constructor (...args) { +// super() +// this.init(...args) +// } +// +// init (array, fallback = []) { +// //this.splice(0, this.length) +// this.length = 0 +// this.push(...this.parse(array || fallback)) +// } +// +// toArray () { +// return [].concat(this) +// } +// +// toString () { +// return this.join(' ') +// } +// +// valueOf () { +// return this.toArray() +// } +// +// // Parse whitespace separated string +// parse (array) { +// array = array.valueOf() +// +// // if already is an array, no need to parse it +// if (Array.isArray(array)) return array +// +// return array.trim().split(delimiter).map(parseFloat) +// } +// +// clone () { +// return new this.constructor(this) +// } +// +// toSet () { +// return new Set(this) +// } +// } diff --git a/src/TextPath.js b/src/TextPath.js index ac9b9b6..afe29ce 100644 --- a/src/TextPath.js +++ b/src/TextPath.js @@ -9,7 +9,7 @@ import {registerMethods} from './methods.js' export default class TextPath extends Text { // Initialize node constructor (node) { - super(nodeOrNew('textPath', node)) + super(nodeOrNew('textPath', node), TextPath) } // return the array of the path track element diff --git a/src/Tspan.js b/src/Tspan.js index aa05269..e2e14e3 100644 --- a/src/Tspan.js +++ b/src/Tspan.js @@ -3,6 +3,7 @@ import {nodeOrNew, extend} from './tools.js' import * as textable from './textable.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' +import Text from './Text.js' export default class Tspan extends Base { // Initialize node diff --git a/src/Use.js b/src/Use.js index d01db5a..697ed03 100644 --- a/src/Use.js +++ b/src/Use.js @@ -2,6 +2,7 @@ import Base from './Base.js' import {xlink} from './namespaces.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' +import {nodeOrNew} from './tools.js' export default class Use extends Base { constructor (node) { diff --git a/src/adopter.js b/src/adopter.js index 8b25718..61b1e83 100644 --- a/src/adopter.js +++ b/src/adopter.js @@ -23,7 +23,9 @@ export function makeInstance (element) { var node = makeNode('svg') node.innerHTML = element - element = adopt(node.firstElementChild) + // We can use firstChild here because we know, + // that the first char is < and thus an element + element = adopt(node.firstChild) return element } diff --git a/src/arrange.js b/src/arrange.js index 3668f87..4d4ec1c 100644 --- a/src/arrange.js +++ b/src/arrange.js @@ -1,4 +1,5 @@ // ### This module adds backward / forward functionality to elements. +import {registerMethods} from './methods.js' // Get all siblings, including myself export function siblings () { @@ -55,7 +56,7 @@ export function front () { p.node.appendChild(this.node) // Make sure defs node is always at the top - if (p instanceof Doc) { + if (typeof p.isRoot == 'function' && p.isRoot()) { p.node.appendChild(p.defs().node) } @@ -92,3 +93,7 @@ export function after (element) { return this } + +registerMethods('Element', { + siblings, position, next, prev, forward, backward, front, back, before, after +}) diff --git a/src/attr.js b/src/attr.js index 912bb07..9ec9eb0 100644 --- a/src/attr.js +++ b/src/attr.js @@ -54,8 +54,8 @@ export default function attr (attr, val, ns) { } else if (Color.isColor(val)) { // ensure full hex color val = new Color(val) - } else if (Array.isArray(val)) { - // parse array values + } else if (val.constructor === Array) { + // Check for plain arrays and parse array values val = new SVGArray(val) } diff --git a/src/containers.js b/src/containers.js index 56287de..675c307 100644 --- a/src/containers.js +++ b/src/containers.js @@ -9,3 +9,7 @@ export {default as Marker} from './Marker.js' export {default as Mask} from './Mask.js' export {default as Pattern} from './Pattern.js' export {default as Symbol} from './Symbol.js' + +export {default as Text} from './Text.js' +export {default as Tspan} from './Tspan.js' +export {default as TextPath} from './TextPath.js' diff --git a/src/elements.js b/src/elements.js index 4709c96..c251f25 100644 --- a/src/elements.js +++ b/src/elements.js @@ -21,4 +21,5 @@ export {default as Stop} from './Stop.js' export {default as Symbol} from './Symbol.js' export {default as Text} from './Text.js' export {default as TextPath} from './TextPath.js' +export {default as Tspan} from './Tspan.js' export {default as Use} from './Use.js' diff --git a/src/elemnts-svg.js b/src/elemnts-svg.js index 39fb22b..5e51034 100644 --- a/src/elemnts-svg.js +++ b/src/elemnts-svg.js @@ -45,7 +45,7 @@ // Act as setter if we got a string // Make sure we are on a current when trying to import - if(!(this instanceof SVG.current)) + if(!(this instanceof SVG.Parent)) throw Error('Cannot import svg into non-current element') // Create temporary holder diff --git a/src/event.js b/src/event.js index 8d8737a..dd782c6 100644 --- a/src/event.js +++ b/src/event.js @@ -1,3 +1,4 @@ +import Base from './Base.js' import {delimiter} from './regex.js' import {registerMethods} from './methods.js' diff --git a/src/helpers.js b/src/helpers.js index 0ad1777..2248ea9 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -162,6 +162,7 @@ export function closeEnough (a, b, threshold) { return Math.abs(b - a) < (threshold || 1e-6) } +// move this to static matrix method export function isMatrixLike (o) { return ( o.a != null || diff --git a/src/memory.js b/src/memory.js index def5969..9850881 100644 --- a/src/memory.js +++ b/src/memory.js @@ -37,7 +37,7 @@ export function forget () { return this } - // Initialize or return local memory object + // return local memory object export function memory () { return this._memory } diff --git a/src/poly.js b/src/poly.js index e8edbed..19643ef 100644 --- a/src/poly.js +++ b/src/poly.js @@ -1,4 +1,5 @@ // Add polygon-specific functions +import PointArray from './PointArray.js' // Get array export function array () { diff --git a/src/regex.js b/src/regex.js index 5477b81..1056554 100644 --- a/src/regex.js +++ b/src/regex.js @@ -8,7 +8,7 @@ export let hex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i export let rgb = /rgb\((\d+),(\d+),(\d+)\)/ // Parse reference id -export let reference = /#([a-z0-9\-_]+)/i +export let reference = /(#[a-z0-9\-_]+)/i // splits a transformation chain export let transforms = /\)\s*,?\s*/ diff --git a/src/selector.js b/src/selector.js index 7d6901a..fcd7363 100644 --- a/src/selector.js +++ b/src/selector.js @@ -27,7 +27,7 @@ import {registerMethods} from './methods.js' // } export default function baseFind (query, parent) { - return utils.map((parent || document).querySelectorAll(query), function (node) { + return map((parent || document).querySelectorAll(query), function (node) { return adopt(node) }) } diff --git a/src/sugar.js b/src/sugar.js index 75f0e00..3751f31 100644 --- a/src/sugar.js +++ b/src/sugar.js @@ -1,6 +1,9 @@ import Color from './Color.js' +import Runner from './Runner.js' +import SVGNumber from './SVGNumber.js' import {registerMethods} from './methods.js' + // Define list of available attributes for stroke and fill var sugar = { stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], @@ -136,7 +139,7 @@ registerMethods('Path', { } }) -registerMethods(['Container', 'Runner'], { +registerMethods(['Parent', 'Runner'], { // Set font font: function (a, v) { if (typeof a === 'object') { diff --git a/src/svg.js b/src/svg.js index bc5dd3b..de24923 100644 --- a/src/svg.js +++ b/src/svg.js @@ -12,12 +12,13 @@ import * as containers from './containers.js' import * as elements from './elements.js' import './attr.js' import './arrange.js' -import './selector.js' +import find from './selector.js' import './css.js' import './transform.js' import './memory.js' import './sugar.js' import {getMethodsFor, getConstructor} from './methods.js' +import {registerMorphableType, makeMorphable} from './Morphable.js' const extend = tools.extend import './EventTarget.js' @@ -63,13 +64,27 @@ for (let i in containers) { } const elementMethods = getMethodsFor('Element') +const eventTargetMethods = getMethodsFor('EventTarget') for (let i in elements) { extend(elements[i], elementMethods) + extend(elements[i], eventTargetMethods) extend(elements[i], getConstructor('EventTarget')) extend(elements[i], getConstructor('Element')) extend(elements[i], getConstructor('Memory')) } +registerMorphableType([ + Classes.SVGNumber, + Classes.Color, + Classes.Box, + Classes.Matrix, + Classes.SVGArray, + Classes.PointArray, + Classes.PathArray +]) + +makeMorphable() + // The main wrapping element export default function SVG (element) { return makeInstance(element) @@ -78,3 +93,20 @@ export default function SVG (element) { Object.assign(SVG, Classes) Object.assign(SVG, tools) Object.assign(SVG, adopter) + +import * as utils from './utils.js' +SVG.utils = utils + +import * as regex from './regex.js' +SVG.regex = regex + + + + +// satisfy tests, fix later +import * as ns from './namespaces' +SVG.get = SVG +SVG.select = find +Object.assign(SVG, ns) +import Base from './Base.js' +SVG.Element = SVG.Parent = SVG.Shape = SVG.Container = Base diff --git a/src/tools.js b/src/tools.js index 7e58865..4dc381e 100644 --- a/src/tools.js +++ b/src/tools.js @@ -15,13 +15,6 @@ export function makeNode (name) { export function extend (modules, methods) { var key, i - if (Array.isArray(methods)) { - methods.forEach((method) => { - extend(modules, method) - }) - return - } - modules = Array.isArray(modules) ? modules : [modules] for (i = modules.length - 1; i >= 0; i--) { @@ -35,6 +28,18 @@ export function extend (modules, methods) { } } +export function extend2 (modules, methods) { + var key, i + + modules = Array.isArray(modules) ? modules : [modules] + + for (i = modules.length - 1; i >= 0; i--) { + for (key in methods) { + modules[i].prototype[key] = methods[key] + } + } +} + // FIXME: enhanced constructors here export function addFactory (modules, methods) { extend(modules, methods) -- cgit v1.2.3 From d22dce113a4a61d76b3c0e7c7fb77231f575c6fd Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Sun, 4 Nov 2018 17:04:11 +0100 Subject: fix even more tests --- dist/svg.js | 266 ++++++++++++++++++++++++++++---------------------- dist/svg.min.js | 2 +- spec/spec/element.js | 136 +++++++++++++------------- spec/spec/fx.js | 22 ++--- spec/spec/morphing.js | 60 ++++++------ spec/spec/number.js | 84 ++++------------ spec/spec/point.js | 56 ----------- spec/spec/selector.js | 26 ++--- spec/spec/sugar.js | 12 +-- spec/spec/text.js | 4 +- src/Controller.js | 2 +- src/Element.js | 5 +- src/Marker.js | 1 + src/Matrix.js | 2 +- src/Parent.js | 1 + src/Point.js | 2 +- src/Text.js | 3 +- src/TextPath.js | 2 +- src/attr.js | 2 +- src/css.js | 2 +- src/event.js | 55 ++++++----- src/poly.js | 1 + src/sugar.js | 5 +- src/svg.js | 13 ++- 24 files changed, 353 insertions(+), 411 deletions(-) (limited to 'src') diff --git a/dist/svg.js b/dist/svg.js index d8edd95..82efb01 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -301,6 +301,10 @@ var SVG = (function () { return c + d.replace(dots, ' .'); } // creates deep clone of array + function matcher(el, selector) { + return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector); + } // Convert dash-separated-string to camelCase + function camelCase(s) { return s.toLowerCase().replace(/-(.)/g, function (m, g) { return g.toUpperCase(); @@ -320,7 +324,7 @@ var SVG = (function () { return hex$$1.length === 1 ? '0' + hex$$1 : hex$$1; } // Calculate proportional width and height values when necessary - function proportionalSize$1(element, width, height) { + function proportionalSize(element, width, height) { if (width == null || height == null) { var box = element.bbox(); @@ -446,25 +450,25 @@ var SVG = (function () { } // Default namespaces - var ns$1 = 'http://www.w3.org/2000/svg'; + var ns = 'http://www.w3.org/2000/svg'; var xmlns = 'http://www.w3.org/2000/xmlns/'; var xlink = 'http://www.w3.org/1999/xlink'; var svgjs = 'http://svgjs.com/svgjs'; - var ns$2 = /*#__PURE__*/Object.freeze({ - ns: ns$1, + var ns$1 = /*#__PURE__*/Object.freeze({ + ns: ns, xmlns: xmlns, xlink: xlink, svgjs: svgjs }); - function nodeOrNew$1(name, node) { + function nodeOrNew(name, node) { return node || makeNode(name); } // Method for element creation function makeNode(name) { // create element - return document.createElementNS(ns$1, name); + return document.createElementNS(ns, name); } // Method for extending objects function extend(modules, methods) { @@ -522,7 +526,7 @@ var SVG = (function () { } var tools = /*#__PURE__*/Object.freeze({ - nodeOrNew: nodeOrNew$1, + nodeOrNew: nodeOrNew, makeNode: makeNode, extend: extend, extend2: extend2, @@ -536,7 +540,7 @@ var SVG = (function () { if (element instanceof Base) return element; if (_typeof(element) === 'object') { - return adopt$1(element); + return adopt(element); } if (element == null) { @@ -544,18 +548,18 @@ var SVG = (function () { } if (typeof element === 'string' && element.charAt(0) !== '<') { - return adopt$1(document.querySelector(element)); + return adopt(document.querySelector(element)); } var node = makeNode('svg'); node.innerHTML = element; // We can use firstChild here because we know, // that the first char is < and thus an element - element = adopt$1(node.firstChild); + element = adopt(node.firstChild); return element; } // Adopt existing svg elements - function adopt$1(node) { + function adopt(node) { // check for presence of node if (!node) return null; // make sure a node isn't already adopted @@ -604,16 +608,16 @@ var SVG = (function () { } if (node.id) { - return adopt$1(node).id(eid(node.nodeName)); + return adopt(node).id(eid(node.nodeName)); } - return adopt$1(node); + return adopt(node); } var adopter = /*#__PURE__*/Object.freeze({ root: root, makeInstance: makeInstance, - adopt: adopt$1, + adopt: adopt, register: register, getClass: getClass, eid: eid, @@ -671,7 +675,7 @@ var SVG = (function () { function Defs(node) { _classCallCheck(this, Defs); - return _possibleConstructorReturn(this, _getPrototypeOf(Defs).call(this, nodeOrNew$1('defs', node), Defs)); + return _possibleConstructorReturn(this, _getPrototypeOf(Defs).call(this, nodeOrNew('defs', node), Defs)); } _createClass(Defs, [{ @@ -849,6 +853,7 @@ var SVG = (function () { }(); var Doc = getClass(root); + var HtmlNode$1 = getClass('HtmlNode'); function setup(node) { // initialize data object this.dom = {}; // create circular reference @@ -896,7 +901,7 @@ var SVG = (function () { } // Set element size to given width and height function size(width, height) { - var p = proportionalSize$1(this, width, height); + var p = proportionalSize(this, width, height); return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height)); } // Clone element @@ -993,12 +998,12 @@ var SVG = (function () { if (!parent.node.parentNode) return null; // get parent element - parent = adopt$1(parent.node.parentNode); + parent = adopt(parent.node.parentNode); if (!type) return parent; // loop trough ancestors if type is given while (parent && parent.node instanceof window.SVGElement) { if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent; - parent = adopt$1(parent.node.parentNode); + parent = adopt(parent.node.parentNode); } } // Get parent document @@ -1017,7 +1022,7 @@ var SVG = (function () { do { parent = parent.parent(type); - if (!parent || !parent.node) break; + if (!parent || parent instanceof HtmlNode$1) break; parents.push(parent); } while (parent.parent); @@ -1025,7 +1030,7 @@ var SVG = (function () { } // matches the element vs a css selector function matches(selector) { - return matches(this.node, selector); + return matcher(this.node, selector); } // Returns the svg node to call native svg methods on it function native() { @@ -1103,7 +1108,7 @@ var SVG = (function () { _classCallCheck(this, Doc); - _this = _possibleConstructorReturn(this, _getPrototypeOf(Doc).call(this, nodeOrNew$1('svg', node), Doc)); + _this = _possibleConstructorReturn(this, _getPrototypeOf(Doc).call(this, nodeOrNew('svg', node), Doc)); _this.namespace(); @@ -1129,7 +1134,7 @@ var SVG = (function () { value: function namespace() { if (!this.isRoot()) return this.doc().namespace(); return this.attr({ - xmlns: ns$1, + xmlns: ns, version: '1.1' }).attr('xmlns:xlink', xlink, xmlns).attr('xmlns:svgjs', svgjs, xmlns); } // Creates and returns defs element @@ -1138,14 +1143,14 @@ var SVG = (function () { key: "defs", value: function defs$$1() { if (!this.isRoot()) return this.doc().defs(); - return adopt$1(this.node.getElementsByTagName('defs')[0]) || this.put(new Defs()); + return adopt(this.node.getElementsByTagName('defs')[0]) || this.put(new Defs()); } // custom parent method }, { key: "parent", value: function parent$$1(type) { if (this.isRoot()) { - return this.node.parentNode.nodeName === '#document' ? null : adopt$1(this.node.parentNode); + return this.node.parentNode.nodeName === '#document' ? null : adopt(this.node.parentNode); } return parent.call(this, type); @@ -1196,7 +1201,7 @@ var SVG = (function () { function G(node) { _classCallCheck(this, G); - return _possibleConstructorReturn(this, _getPrototypeOf(G).call(this, nodeOrNew$1('g', node), G)); + return _possibleConstructorReturn(this, _getPrototypeOf(G).call(this, nodeOrNew('g', node), G)); } return G; @@ -1373,7 +1378,7 @@ var SVG = (function () { _classCallCheck(this, Bare); - return _possibleConstructorReturn(this, _getPrototypeOf(Bare).call(this, nodeOrNew$1(node, typeof node === 'string' ? null : node), Bare)); //extend(this, inherit) + return _possibleConstructorReturn(this, _getPrototypeOf(Bare).call(this, nodeOrNew(node, typeof node === 'string' ? null : node), Bare)); //extend(this, inherit) } _createClass(Bare, [{ @@ -1435,7 +1440,7 @@ var SVG = (function () { } // Custom size function function size$1(width, height) { - var p = proportionalSize$1(this, width, height); + var p = proportionalSize(this, width, height); return this.rx(new SVGNumber(p.width).divide(2)).ry(new SVGNumber(p.height).divide(2)); } @@ -1459,7 +1464,7 @@ var SVG = (function () { function Circle(node) { _classCallCheck(this, Circle); - return _possibleConstructorReturn(this, _getPrototypeOf(Circle).call(this, nodeOrNew$1('circle', node), Circle)); + return _possibleConstructorReturn(this, _getPrototypeOf(Circle).call(this, nodeOrNew('circle', node), Circle)); } _createClass(Circle, [{ @@ -1574,7 +1579,7 @@ var SVG = (function () { function baseFind(query, parent) { return map((parent || document).querySelectorAll(query), function (node) { - return adopt$1(node); + return adopt(node); }); } // Scoped find method @@ -1593,7 +1598,7 @@ var SVG = (function () { function ClipPath(node) { _classCallCheck(this, ClipPath); - return _possibleConstructorReturn(this, _getPrototypeOf(ClipPath).call(this, nodeOrNew$1('clipPath', node), ClipPath)); + return _possibleConstructorReturn(this, _getPrototypeOf(ClipPath).call(this, nodeOrNew('clipPath', node), ClipPath)); } // Unclip all clipped elements and remove itself @@ -1650,7 +1655,7 @@ var SVG = (function () { function A(node) { _classCallCheck(this, A); - return _possibleConstructorReturn(this, _getPrototypeOf(A).call(this, nodeOrNew$1('a', node), A)); + return _possibleConstructorReturn(this, _getPrototypeOf(A).call(this, nodeOrNew('a', node), A)); } // Link url @@ -1701,7 +1706,7 @@ var SVG = (function () { function Ellipse(node) { _classCallCheck(this, Ellipse); - return _possibleConstructorReturn(this, _getPrototypeOf(Ellipse).call(this, nodeOrNew$1('ellipse', node), Ellipse)); + return _possibleConstructorReturn(this, _getPrototypeOf(Ellipse).call(this, nodeOrNew('ellipse', node), Ellipse)); } return Ellipse; @@ -1723,7 +1728,7 @@ var SVG = (function () { function Stop(node) { _classCallCheck(this, Stop); - return _possibleConstructorReturn(this, _getPrototypeOf(Stop).call(this, nodeOrNew$1('stop', node), Stop)); + return _possibleConstructorReturn(this, _getPrototypeOf(Stop).call(this, nodeOrNew('stop', node), Stop)); } // add color stops @@ -2033,7 +2038,7 @@ var SVG = (function () { try { for (var _iterator = val[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var node = _step.value; - attr[node.nodeName] = isNumer.test(node.nodeValue) ? parseFloat(node.nodeValue) : node.nodeValue; + attr[node.nodeName] = isNumber.test(node.nodeValue) ? parseFloat(node.nodeValue) : node.nodeValue; } } catch (err) { _didIteratorError = true; @@ -2120,7 +2125,7 @@ var SVG = (function () { function Gradient(type) { _classCallCheck(this, Gradient); - return _possibleConstructorReturn(this, _getPrototypeOf(Gradient).call(this, nodeOrNew$1(type + 'Gradient', typeof type === 'string' ? null : type), Gradient)); + return _possibleConstructorReturn(this, _getPrototypeOf(Gradient).call(this, nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type), Gradient)); } // Add a color stop @@ -2196,7 +2201,7 @@ var SVG = (function () { function Pattern(node) { _classCallCheck(this, Pattern); - return _possibleConstructorReturn(this, _getPrototypeOf(Pattern).call(this, nodeOrNew$1('pattern', node), Pattern)); + return _possibleConstructorReturn(this, _getPrototypeOf(Pattern).call(this, nodeOrNew('pattern', node), Pattern)); } // Return the fill id @@ -2261,31 +2266,22 @@ var SVG = (function () { }); register(Pattern); - // ;[ 'click', - // 'dblclick', - // 'mousedown', - // 'mouseup', - // 'mouseover', - // 'mouseout', - // 'mousemove', - // 'mouseenter', - // 'mouseleave', - // 'touchstart', - // 'touchmove', - // 'touchleave', - // 'touchend', - // 'touchcancel' ].forEach(function (event) { - // // add event to Element - // Element.prototype[event] = function (f) { - // if (f === null) { - // off(this, event) - // } else { - // on(this, event, f) - // } - // return this - // } - // }) + var methods$1 = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove', 'mouseenter', 'mouseleave', 'touchstart', 'touchmove', 'touchleave', 'touchend', 'touchcancel'].reduce(function (last, event) { + // add event to Element + var fn = function fn(f) { + if (f === null) { + off(this, event); + } else { + on(this, event, f); + } + + return this; + }; + last[event] = fn; + return last; + }, {}); + registerMethods('Element', methods$1); var listenerId = 0; function getEventTarget$1(node) { @@ -2401,6 +2397,12 @@ var SVG = (function () { return event; } + var events = /*#__PURE__*/Object.freeze({ + on: on, + off: off, + dispatch: dispatch + }); + var Image = /*#__PURE__*/ function (_Base) { @@ -2409,7 +2411,7 @@ var SVG = (function () { function Image(node) { _classCallCheck(this, Image); - return _possibleConstructorReturn(this, _getPrototypeOf(Image).call(this, nodeOrNew$1('image', node), Image)); + return _possibleConstructorReturn(this, _getPrototypeOf(Image).call(this, nodeOrNew('image', node), Image)); } // (re)load image @@ -2706,7 +2708,7 @@ var SVG = (function () { function Line(node) { _classCallCheck(this, Line); - return _possibleConstructorReturn(this, _getPrototypeOf(Line).call(this, nodeOrNew$1('line', node), Line)); + return _possibleConstructorReturn(this, _getPrototypeOf(Line).call(this, nodeOrNew('line', node), Line)); } // Get array @@ -2744,7 +2746,7 @@ var SVG = (function () { }, { key: "size", value: function size(width, height) { - var p = proportionalSize$1(this, width, height); + var p = proportionalSize(this, width, height); return this.attr(this.array().size(p.width, p.height).toLine()); } }]); @@ -2858,7 +2860,7 @@ var SVG = (function () { function Mask(node) { _classCallCheck(this, Mask); - return _possibleConstructorReturn(this, _getPrototypeOf(Mask).call(this, nodeOrNew$1('mask', node), Mask)); + return _possibleConstructorReturn(this, _getPrototypeOf(Mask).call(this, nodeOrNew('mask', node), Mask)); } // Unmask all masked elements and remove itself @@ -2931,7 +2933,7 @@ var SVG = (function () { return parser.nodes; } - var Point$1 = + var Point = /*#__PURE__*/ function () { // Initialize @@ -2970,7 +2972,7 @@ var SVG = (function () { key: "native", value: function native() { // create new point - var point = parser().svg.createSVGPoint(); // update with current values + var point = parser().svg.node.createSVGPoint(); // update with current values point.x = this.x; point.y = this.y; @@ -2994,7 +2996,7 @@ var SVG = (function () { Element: { // Get point point: function point(x, y) { - return new Point$1(x, y).transform(this.screenCTM().inverse()); + return new Point(x, y).transform(this.screenCTM().inverse()); } } }); @@ -3241,8 +3243,8 @@ var SVG = (function () { var result = []; - var p = new Point$1(); - var p0 = new Point$1(); + var p = new Point(); + var p0 = new Point(); var index = 0; var len = array.length; @@ -3493,7 +3495,7 @@ var SVG = (function () { function Path(node) { _classCallCheck(this, Path); - return _possibleConstructorReturn(this, _getPrototypeOf(Path).call(this, nodeOrNew$1('path', node), Path)); + return _possibleConstructorReturn(this, _getPrototypeOf(Path).call(this, nodeOrNew('path', node), Path)); } // Get array @@ -3537,7 +3539,7 @@ var SVG = (function () { }, { key: "size", value: function size(width, height) { - var p = proportionalSize$1(this, width, height); + var p = proportionalSize(this, width, height); return this.attr('d', this.array().size(p.width, p.height)); } // Set width of element @@ -3643,7 +3645,7 @@ var SVG = (function () { function Polygon(node) { _classCallCheck(this, Polygon); - return _possibleConstructorReturn(this, _getPrototypeOf(Polygon).call(this, nodeOrNew$1('polygon', node), Polygon)); + return _possibleConstructorReturn(this, _getPrototypeOf(Polygon).call(this, nodeOrNew('polygon', node), Polygon)); } return Polygon; @@ -3670,7 +3672,7 @@ var SVG = (function () { function Polyline(node) { _classCallCheck(this, Polyline); - return _possibleConstructorReturn(this, _getPrototypeOf(Polyline).call(this, nodeOrNew$1('polyline', node), Polyline)); + return _possibleConstructorReturn(this, _getPrototypeOf(Polyline).call(this, nodeOrNew('polyline', node), Polyline)); } return Polyline; @@ -3697,7 +3699,7 @@ var SVG = (function () { function Rect(node) { _classCallCheck(this, Rect); - return _possibleConstructorReturn(this, _getPrototypeOf(Rect).call(this, nodeOrNew$1('rect', node), Rect)); + return _possibleConstructorReturn(this, _getPrototypeOf(Rect).call(this, nodeOrNew('rect', node), Rect)); } return Rect; @@ -3721,7 +3723,7 @@ var SVG = (function () { function _Symbol(node) { _classCallCheck(this, _Symbol); - return _possibleConstructorReturn(this, _getPrototypeOf(_Symbol).call(this, nodeOrNew$1('symbol', node), _Symbol)); + return _possibleConstructorReturn(this, _getPrototypeOf(_Symbol).call(this, nodeOrNew('symbol', node), _Symbol)); } return _Symbol; @@ -3768,7 +3770,7 @@ var SVG = (function () { _classCallCheck(this, Text); - _this = _possibleConstructorReturn(this, _getPrototypeOf(Text).call(this, nodeOrNew$1('text', node), Text)); + _this = _possibleConstructorReturn(this, _getPrototypeOf(Text).call(this, nodeOrNew('text', node), Text)); _this.dom.leading = new SVGNumber(1.3); // store leading value for rebuilding _this._rebuild = true; // enable automatic updating of dy values @@ -3823,6 +3825,7 @@ var SVG = (function () { value: function text(_text) { // act as getter if (_text === undefined) { + // FIXME use children() or each() var children = this.node.childNodes; var firstLine = 0; _text = ''; @@ -3951,7 +3954,7 @@ var SVG = (function () { function TextPath(node) { _classCallCheck(this, TextPath); - return _possibleConstructorReturn(this, _getPrototypeOf(TextPath).call(this, nodeOrNew$1('textPath', node), TextPath)); + return _possibleConstructorReturn(this, _getPrototypeOf(TextPath).call(this, nodeOrNew('textPath', node), TextPath)); } // return the array of the path track element @@ -4008,7 +4011,7 @@ var SVG = (function () { // FIXME: make this plural? // Get the textPath children textPath: function textPath() { - return this.select('textPath'); + return this.find('textPath'); } }, Path: { @@ -4037,7 +4040,7 @@ var SVG = (function () { function Tspan(node) { _classCallCheck(this, Tspan); - return _possibleConstructorReturn(this, _getPrototypeOf(Tspan).call(this, nodeOrNew$1('tspan', node), Tspan)); + return _possibleConstructorReturn(this, _getPrototypeOf(Tspan).call(this, nodeOrNew('tspan', node), Tspan)); } // Set text content @@ -4101,7 +4104,7 @@ var SVG = (function () { function Use(node) { _classCallCheck(this, Use); - return _possibleConstructorReturn(this, _getPrototypeOf(Use).call(this, nodeOrNew$1('use', node), Use)); + return _possibleConstructorReturn(this, _getPrototypeOf(Use).call(this, nodeOrNew('use', node), Use)); } // Use element as a reference @@ -4125,7 +4128,7 @@ var SVG = (function () { }); register(Use); - var Matrix$1 = + var Matrix = /*#__PURE__*/ function () { function Matrix() { @@ -4169,7 +4172,7 @@ var SVG = (function () { var t = Matrix.formatTransforms(o); var current = this; - var _transform = new Point$1(t.ox, t.oy).transform(current), + var _transform = new Point(t.ox, t.oy).transform(current), ox = _transform.x, oy = _transform.y; // Construct the resulting matrix @@ -4177,7 +4180,7 @@ var SVG = (function () { var transformer = new Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy); // If we want the origin at a particular place, we force it there if (isFinite(t.px) || isFinite(t.py)) { - var origin = new Point$1(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px) + var origin = new Point(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px) var dx = t.px ? t.px - origin.x : 0; var dy = t.py ? t.py - origin.y : 0; @@ -4513,7 +4516,7 @@ var SVG = (function () { key: "native", value: function native() { // create new matrix - var matrix = parser().node.createSVGMatrix(); // update with current values + var matrix = parser().svg.node.createSVGMatrix(); // update with current values for (var i = abcdef.length - 1; i >= 0; i--) { matrix[abcdef[i]] = this[abcdef[i]]; @@ -4565,16 +4568,16 @@ var SVG = (function () { var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY; var shear = o.shear || 0; var theta = o.rotate || o.theta || 0; - var origin = new Point$1(o.origin || o.around || o.ox || o.originX, o.oy || o.originY); + var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY); var ox = origin.x; var oy = origin.y; - var position = new Point$1(o.position || o.px || o.positionX, o.py || o.positionY); + var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY); var px = position.x; var py = position.y; - var translate = new Point$1(o.translate || o.tx || o.translateX, o.ty || o.translateY); + var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY); var tx = translate.x; var ty = translate.y; - var relative = new Point$1(o.relative || o.rx || o.relativeX, o.ry || o.relativeY); + var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY); var rx = relative.x; var ry = relative.y; // Populate all of the values @@ -4623,7 +4626,7 @@ var SVG = (function () { Element: { // Get current matrix ctm: function ctm() { - return new Matrix$1(this.node.getCTM()); + return new Matrix(this.node.getCTM()); }, // Get current screen matrix screenCTM: function screenCTM() { @@ -4635,10 +4638,10 @@ var SVG = (function () { var rect = this.rect(1, 1); var m = rect.node.getScreenCTM(); rect.remove(); - return new Matrix$1(m); + return new Matrix(m); } - return new Matrix$1(this.node.getScreenCTM()); + return new Matrix(this.node.getScreenCTM()); } } }); @@ -4681,7 +4684,7 @@ var SVG = (function () { var xMax = -Infinity; var yMin = Infinity; var yMax = -Infinity; - var pts = [new Point$1(this.x, this.y), new Point$1(this.x2, this.y), new Point$1(this.x, this.y2), new Point$1(this.x2, this.y2)]; + var pts = [new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2)]; pts.forEach(function (p) { p = p.transform(m); xMin = Math.min(xMin, p.x); @@ -5572,7 +5575,7 @@ var SVG = (function () { this._time = 0; this._last = 0; // Save transforms applied to this runner - this.transforms = new Matrix$1(); + this.transforms = new Matrix(); this.transformId = 1; // Looping variables this._haveReversed = false; @@ -5813,7 +5816,7 @@ var SVG = (function () { this._initialise(running); // clear the transforms on this runner so they dont get added again and again - this.transforms = new Matrix$1(); + this.transforms = new Matrix(); var converged = this._run(declarative ? dt : position); // this.fire('step', this) @@ -5947,7 +5950,7 @@ var SVG = (function () { }, { key: "clearTransform", value: function clearTransform() { - this.transforms = new Matrix$1(); + this.transforms = new Matrix(); return this; } }], [{ @@ -5986,7 +5989,7 @@ var SVG = (function () { Runner.id = 0; var FakeRunner = function FakeRunner() { - var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix$1(); + var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix(); var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; var done = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; @@ -6014,7 +6017,7 @@ var SVG = (function () { function mergeTransforms() { // Find the matrix to apply to the element and apply it var runners = this._transformationRunners.runners; - var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix$1()); + var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix()); this.transform(netTransform); this._transformationRunners.merge(); @@ -6128,7 +6131,7 @@ var SVG = (function () { // taken into account .filter(function (runner) { return runner.id <= current.id; - }).map(getRunnerTransform).reduce(lmultiply, new Matrix$1()); + }).map(getRunnerTransform).reduce(lmultiply, new Matrix()); }, addRunner: function addRunner(runner) { this._transformationRunners.add(runner); @@ -6137,7 +6140,7 @@ var SVG = (function () { }, _prepareRunner: function _prepareRunner() { if (this._frameId == null) { - this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix$1(this))); + this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix(this))); this._frameId = frameId++; } } @@ -6206,7 +6209,7 @@ var SVG = (function () { var isMatrix = isMatrixLike(transforms); affine = transforms.affine != null ? transforms.affine : affine != null ? affine : !isMatrix; // Create a morepher and set its type - var morpher = new Morphable().type(affine ? TransformBag : Matrix$1).stepper(this._stepper); + var morpher = new Morphable().type(affine ? TransformBag : Matrix).stepper(this._stepper); var origin; var element; var current; @@ -6217,7 +6220,7 @@ var SVG = (function () { // make sure element and origin is defined element = element || this.element(); origin = origin || getOrigin(transforms, element); - startTransform = new Matrix$1(relative ? undefined : element); // add the runner to the element so it can merge transformations + startTransform = new Matrix(relative ? undefined : element); // add the runner to the element so it can merge transformations element.addRunner(this); // Deactivate all transforms that have run so far if we are absolute @@ -6231,11 +6234,11 @@ var SVG = (function () { // on this runner. We are absolute. We dont need these! if (!relative) this.clearTransform(); - var _transform = new Point$1(origin).transform(element._currentTransform(this)), + var _transform = new Point(origin).transform(element._currentTransform(this)), x = _transform.x, y = _transform.y; - var target = new Matrix$1(_objectSpread({}, transforms, { + var target = new Matrix(_objectSpread({}, transforms, { origin: [x, y] })); var start = this._isDeclarative && current ? current : startTransform; @@ -6272,7 +6275,7 @@ var SVG = (function () { morpher.to(target); var affineParameters = morpher.at(pos); currentAngle = affineParameters.rotate; - current = new Matrix$1(affineParameters); + current = new Matrix(affineParameters); this.addTransform(current); return morpher.done(); } @@ -6506,8 +6509,8 @@ var SVG = (function () { SVGArray: SVGArray, PathArray: PathArray, PointArray: PointArray, - Matrix: Matrix$1, - Point: Point$1, + Matrix: Matrix, + Point: Point, Box: Box$1, Color: Color, Morphable: Morphable, @@ -6656,6 +6659,27 @@ var SVG = (function () { after: after }); + function data(a, v, r) { + if (_typeof(a) === 'object') { + for (v in a) { + this.data(v, a[v]); + } + } else if (arguments.length < 2) { + try { + return JSON.parse(this.attr('data-' + a)); + } catch (e) { + return this.attr('data-' + a); + } + } else { + this.attr('data-' + a, v === null ? null : r === true || typeof v === 'string' || typeof v === 'number' ? v : JSON.stringify(v)); + } + + return this; + } + registerMethods('Element', { + data: data + }); + // Dynamic style generator function css(style, val) { @@ -6683,7 +6707,7 @@ var SVG = (function () { for (var _iterator = style[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var _name = _step.value; var cased = camelCase(_name); - ret[cased] = this.node.style(cased); + ret[cased] = this.node.style[cased]; } } catch (err) { _didIteratorError = true; @@ -6762,7 +6786,7 @@ var SVG = (function () { } return matrix[transform[0]].apply(matrix, transform[1]); - }, new Matrix$1()); + }, new Matrix()); return matrix; } // add an element to another parent without changing the visual representation on the screen @@ -6781,7 +6805,7 @@ var SVG = (function () { function transform(o, relative) { // Act as a getter if no object was passed if (o == null || typeof o === 'string') { - var decomposed = new Matrix$1(this).decompose(); + var decomposed = new Matrix(this).decompose(); return decomposed[o] || decomposed; } @@ -6794,7 +6818,7 @@ var SVG = (function () { var cleanRelative = relative === true ? this : relative || false; - var result = new Matrix$1(cleanRelative).transform(o); + var result = new Matrix(cleanRelative).transform(o); return this.attr('transform', result); } registerMethods('Element', { @@ -6986,7 +7010,7 @@ var SVG = (function () { return new Point(this.node.getPointAtLength(length)); } }); - registerMethods(['Parent', 'Runner'], { + registerMethods(['Container', 'Runner'], { // Set font font: function font(a, v) { if (_typeof(a) === 'object') { @@ -7033,7 +7057,7 @@ var SVG = (function () { function children() { return map(this.node.children, function (node) { - return adopt$1(node); + return adopt(node); }); } // Add given element at a position @@ -7063,15 +7087,15 @@ var SVG = (function () { } // Get a element at the given index function get(i) { - return adopt$1(this.node.childNodes[i]); + return adopt(this.node.childNodes[i]); } // Get first child function first() { - return adopt$1(this.node.firstChild); + return adopt(this.node.firstChild); } // Get the last child function last() { - return adopt$1(this.node.lastChild); + return adopt(this.node.lastChild); } // Iterates over all children and invokes a given block function each(block, deep) { @@ -7204,7 +7228,7 @@ var SVG = (function () { extend$1(elements$1[_i], getConstructor('Memory')); } - registerMorphableType([SVGNumber, Color, Box$1, Matrix$1, SVGArray, PointArray, PathArray]); + registerMorphableType([SVGNumber, Color, Box$1, Matrix, SVGArray, PointArray, PathArray]); makeMorphable(); // The main wrapping element function SVG(element) { @@ -7216,9 +7240,15 @@ var SVG = (function () { SVG.utils = utils; SVG.regex = regex$1; // satisfy tests, fix later SVG.get = SVG; - SVG.select = baseFind; - Object.assign(SVG, ns$2); + SVG.find = baseFind; + Object.assign(SVG, ns$1); SVG.Element = SVG.Parent = SVG.Shape = SVG.Container = Base; + SVG.easing = easing; + Object.assign(SVG, events); + SVG.TransformBag = TransformBag; + SVG.ObjectBag = ObjectBag; + SVG.NonMorphable = NonMorphable; + SVG.parser = parser; return SVG; diff --git a/dist/svg.min.js b/dist/svg.min.js index c2bd909..81337c2 100644 --- a/dist/svg.min.js +++ b/dist/svg.min.js @@ -1 +1 @@ -var SVG=function(){"use strict";function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function c(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;nn.x&&e>n.y&&t=e.time?e.run():_t.timeouts.push(e),e!==n););for(var i=null,r=_t.frames.last();i!==r&&(i=_t.frames.shift());)i.run();_t.transforms.forEach(function(t){t()}),_t.nextDraw=_t.timeouts.first()||_t.frames.first()?window.requestAnimationFrame(_t._draw):null}},kt=function(t){function e(t){return c(this,e),a(this,u(e).call(this,B(t,"string"==typeof t?null:t),e))}return r(e,s),o(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function Ot(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function At(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function Ct(t){return null==t?this.attr("cx"):this.attr("cx",t)}function Mt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function jt(t){return null==t?2*this.rx():this.rx(new vt(t).divide(2))}function Tt(t){return null==t?2*this.ry():this.ry(new vt(t).divide(2))}function St(t,e){var n=D(this,t,e);return this.rx(new vt(n.width).divide(2)).ry(new vt(n.height).divide(2))}tt(kt),lt("Container",{element:function(t,e){return this.put(new kt(t,e))}});var Et=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:Ot,y:At,cx:Ct,cy:Mt,width:jt,height:Tt,size:St}),Nt=function(t){function e(t){return c(this,e),a(this,u(e).call(this,B("circle",t),e))}return r(e,s),o(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Pt(t,e){var n,i=t.length,r=[];for(n=0;n",Bt=0,Vt={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},Ut=function(){function t(){c(this,t),this.init.apply(this,arguments)}return o(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?g.test(t)?(i=v.exec(t.replace(p,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):m.test(t)&&(i=d.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+P(Math.round(this.r))+P(Math.round(this.g))+P(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",m.test(t)||g.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}(),Qt=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Pe=function(){function t(){c(this,t)}return o(t,[{key:"done",value:function(){return!1}}]),t}(),De=function(t){function n(t){var e;return c(this,n),(e=a(this,u(n).call(this))).ease=Ne[t||Ht]||t,e}return r(n,Pe),o(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),ze=function(t){function n(t){var e;return c(this,n),(e=a(this,u(n).call(this))).stepper=t,e}return r(n,Pe),o(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Re(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var qe=function(t){function i(t,e){var n;return c(this,i),(n=a(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,ze),o(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i);this._lastTime=this._time;var s=this._isDeclarative;if(this.done=!s&&!r&&this._time>=i,n||s){this._initialise(n),this.transforms=new je;var u=this._run(s?t:e)}return this.done=this.done||u&&s,this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new De(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;en.x&&e>n.y&&t=e.time?e.run():kt.timeouts.push(e),e!==n););for(var i=null,r=kt.frames.last();i!==r&&(i=kt.frames.shift());)i.run();kt.transforms.forEach(function(t){t()}),kt.nextDraw=kt.timeouts.first()||kt.frames.first()?window.requestAnimationFrame(kt._draw):null}},Ot=function(t){function e(t){return c(this,e),a(this,u(e).call(this,H(t,"string"==typeof t?null:t),e))}return r(e,s),o(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function At(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function Ct(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function Mt(t){return null==t?this.attr("cx"):this.attr("cx",t)}function jt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function Tt(t){return null==t?2*this.rx():this.rx(new vt(t).divide(2))}function St(t){return null==t?2*this.ry():this.ry(new vt(t).divide(2))}function Et(t,e){var n=D(this,t,e);return this.rx(new vt(n.width).divide(2)).ry(new vt(n.height).divide(2))}tt(Ot),lt("Container",{element:function(t,e){return this.put(new Ot(t,e))}});var Nt=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:At,y:Ct,cx:Mt,cy:jt,width:Tt,height:St,size:Et}),Pt=function(t){function e(t){return c(this,e),a(this,u(e).call(this,H("circle",t),e))}return r(e,s),o(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Dt(t,e){var n,i=t.length,r=[];for(n=0;n",Vt=0,Ut={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},Qt=function(){function t(){c(this,t),this.init.apply(this,arguments)}return o(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?g.test(t)?(i=v.exec(t.replace(p,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):m.test(t)&&(i=d.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+P(Math.round(this.r))+P(Math.round(this.g))+P(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",m.test(t)||g.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}(),$t=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Re=function(){function t(){c(this,t)}return o(t,[{key:"done",value:function(){return!1}}]),t}(),qe=function(t){function n(t){var e;return c(this,n),(e=a(this,u(n).call(this))).ease=ze[t||Ht]||t,e}return r(n,Re),o(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),Le=function(t){function n(t){var e;return c(this,n),(e=a(this,u(n).call(this))).stepper=t,e}return r(n,Re),o(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Ie(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var Fe=function(t){function i(t,e){var n;return c(this,i),(n=a(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,Le),o(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i);this._lastTime=this._time;var s=this._isDeclarative;if(this.done=!s&&!r&&this._time>=i,n||s){this._initialise(n),this.transforms=new Ee;var u=this._run(s?t:e)}return this.done=this.done||u&&s,this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new qe(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, diff --git a/src/Element.js b/src/Element.js index 0494965..e8352a8 100644 --- a/src/Element.js +++ b/src/Element.js @@ -7,6 +7,7 @@ import {registerMethods} from './methods.js' import {registerConstructor} from './methods.js' const Doc = getClass(root) +const HtmlNode = getClass('HtmlNode') export const name = 'Element' @@ -223,7 +224,7 @@ export function parents (type) { do { parent = parent.parent(type) - if (!parent || !parent.node) break + if (!parent || parent instanceof HtmlNode) break parents.push(parent) } while (parent.parent) @@ -233,7 +234,7 @@ export function parents (type) { // matches the element vs a css selector export function matches (selector) { - return matches(this.node, selector) + return matcher(this.node, selector) } // Returns the svg node to call native svg methods on it diff --git a/src/Marker.js b/src/Marker.js index bf2b854..403a387 100644 --- a/src/Marker.js +++ b/src/Marker.js @@ -1,6 +1,7 @@ import Base from './Base.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' +import {nodeOrNew} from './tools.js' export default class Marker extends Base { // Initialize node diff --git a/src/Matrix.js b/src/Matrix.js index 7f3afe5..b0a6c48 100644 --- a/src/Matrix.js +++ b/src/Matrix.js @@ -375,7 +375,7 @@ export default class Matrix { // Convert to native SVGMatrix native () { // create new matrix - var matrix = parser().node.createSVGMatrix() + var matrix = parser().svg.node.createSVGMatrix() // update with current values for (var i = abcdef.length - 1; i >= 0; i--) { diff --git a/src/Parent.js b/src/Parent.js index 769cd49..a52b000 100644 --- a/src/Parent.js +++ b/src/Parent.js @@ -2,6 +2,7 @@ import {makeInstance, adopt} from './adopter.js' import {map} from './utils.js' import {registerMethods} from './methods.js' import Base from './Base.js' +import {ns} from './namespaces.js' // Returns all child elements export function children () { diff --git a/src/Point.js b/src/Point.js index 7919d02..7f8e2c3 100644 --- a/src/Point.js +++ b/src/Point.js @@ -25,7 +25,7 @@ export default class Point { // Convert to native SVGPoint native () { // create new point - var point = parser().svg.createSVGPoint() + var point = parser().svg.node.createSVGPoint() // update with current values point.x = this.x diff --git a/src/Text.js b/src/Text.js index fabdbe5..02a601b 100644 --- a/src/Text.js +++ b/src/Text.js @@ -3,7 +3,7 @@ import SVGNumber from './SVGNumber.js' import {nodeOrNew, extend} from './tools.js' import {attrs} from './defaults.js' import * as textable from './textable.js' -import {register} from './adopter.js' +import {register, adopt} from './adopter.js' import {registerMethods} from './methods.js' export default class Text extends Base { @@ -56,6 +56,7 @@ export default class Text extends Base { text (text) { // act as getter if (text === undefined) { + // FIXME use children() or each() var children = this.node.childNodes var firstLine = 0 text = '' diff --git a/src/TextPath.js b/src/TextPath.js index afe29ce..df5b690 100644 --- a/src/TextPath.js +++ b/src/TextPath.js @@ -64,7 +64,7 @@ registerMethods({ // FIXME: make this plural? // Get the textPath children textPath: function () { - return this.select('textPath') + return this.find('textPath') } }, Path: { diff --git a/src/attr.js b/src/attr.js index 9ec9eb0..23baf51 100644 --- a/src/attr.js +++ b/src/attr.js @@ -14,7 +14,7 @@ export default function attr (attr, val, ns) { val = this.node.attributes for (let node of val) { - attr[node.nodeName] = isNumer.test(node.nodeValue) + attr[node.nodeName] = isNumber.test(node.nodeValue) ? parseFloat(node.nodeValue) : node.nodeValue } diff --git a/src/css.js b/src/css.js index 7a3bfbe..795be71 100644 --- a/src/css.js +++ b/src/css.js @@ -24,7 +24,7 @@ export function css (style, val) { if (Array.isArray(style)) { for (let name of style) { let cased = camelCase(name) - ret[cased] = this.node.style(cased) + ret[cased] = this.node.style[cased] } return ret } diff --git a/src/event.js b/src/event.js index dd782c6..9fa99e1 100644 --- a/src/event.js +++ b/src/event.js @@ -2,31 +2,36 @@ import Base from './Base.js' import {delimiter} from './regex.js' import {registerMethods} from './methods.js' -// // Add events to elements -// ;[ 'click', -// 'dblclick', -// 'mousedown', -// 'mouseup', -// 'mouseover', -// 'mouseout', -// 'mousemove', -// 'mouseenter', -// 'mouseleave', -// 'touchstart', -// 'touchmove', -// 'touchleave', -// 'touchend', -// 'touchcancel' ].forEach(function (event) { -// // add event to Element -// Element.prototype[event] = function (f) { -// if (f === null) { -// off(this, event) -// } else { -// on(this, event, f) -// } -// return this -// } -// }) +// Add events to elements +const methods = [ 'click', + 'dblclick', + 'mousedown', + 'mouseup', + 'mouseover', + 'mouseout', + 'mousemove', + 'mouseenter', + 'mouseleave', + 'touchstart', + 'touchmove', + 'touchleave', + 'touchend', + 'touchcancel' ].reduce(function (last, event) { + // add event to Element + const fn = function (f) { + if (f === null) { + off(this, event) + } else { + on(this, event, f) + } + return this + } + + last[event] = fn + return last + }, {}) + +registerMethods('Element', methods) let listenerId = 0 diff --git a/src/poly.js b/src/poly.js index 19643ef..937247a 100644 --- a/src/poly.js +++ b/src/poly.js @@ -1,5 +1,6 @@ // Add polygon-specific functions import PointArray from './PointArray.js' +import {proportionalSize} from './helpers.js' // Get array export function array () { diff --git a/src/sugar.js b/src/sugar.js index 3751f31..9a075a0 100644 --- a/src/sugar.js +++ b/src/sugar.js @@ -1,9 +1,10 @@ import Color from './Color.js' import Runner from './Runner.js' import SVGNumber from './SVGNumber.js' +import Matrix from './Matrix.js' +import Point from './Point.js' import {registerMethods} from './methods.js' - // Define list of available attributes for stroke and fill var sugar = { stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], @@ -139,7 +140,7 @@ registerMethods('Path', { } }) -registerMethods(['Parent', 'Runner'], { +registerMethods(['Container', 'Runner'], { // Set font font: function (a, v) { if (typeof a === 'object') { diff --git a/src/svg.js b/src/svg.js index de24923..10135b1 100644 --- a/src/svg.js +++ b/src/svg.js @@ -12,6 +12,7 @@ import * as containers from './containers.js' import * as elements from './elements.js' import './attr.js' import './arrange.js' +import './data.js' import find from './selector.js' import './css.js' import './transform.js' @@ -106,7 +107,17 @@ SVG.regex = regex // satisfy tests, fix later import * as ns from './namespaces' SVG.get = SVG -SVG.select = find +SVG.find = find Object.assign(SVG, ns) import Base from './Base.js' SVG.Element = SVG.Parent = SVG.Shape = SVG.Container = Base +import {easing} from './Controller.js' +SVG.easing = easing +import * as events from './event.js' +Object.assign(SVG, events) +import {TransformBag, ObjectBag, NonMorphable} from './Morphable.js' +SVG.TransformBag = TransformBag +SVG.ObjectBag = ObjectBag +SVG.NonMorphable = NonMorphable +import parser from './parser.js' +SVG.parser = parser -- cgit v1.2.3 From d654ab010adf42aab757529b6c09f27215740b27 Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Sun, 4 Nov 2018 21:46:33 +0100 Subject: Revert back to classes, fix remaining tests --- dist/svg.js | 3918 ++++++++++++++++++++++++++------------------------ dist/svg.min.js | 2 +- spec/SpecRunner.html | 1 - spec/spec/array.js | 4 +- spec/spec/bare.js | 8 +- spec/spec/element.js | 10 - spec/spec/event.js | 67 +- spec/spec/runner.js | 31 +- spec/spec/svg.js | 36 +- src/A.js | 4 +- src/ArrayPolyfill.js | 1 - src/Bare.js | 8 +- src/Base.js | 14 +- src/Box.js | 1 - src/Circle.js | 4 +- src/ClipPath.js | 9 +- src/Container.js | 2 + src/Defs.js | 4 +- src/Doc.js | 34 +- src/Element.js | 362 ++--- src/Ellipse.js | 4 +- src/EventTarget.js | 86 +- src/G.js | 4 +- src/Gradient.js | 14 +- src/HtmlNode.js | 9 +- src/Image.js | 4 +- src/Line.js | 10 +- src/Marker.js | 4 +- src/Mask.js | 9 +- src/Matrix.js | 4 +- src/Morphable.js | 7 +- src/Parent.js | 243 ++-- src/Path.js | 4 +- src/Pattern.js | 14 +- src/Polygon.js | 4 +- src/Polyline.js | 4 +- src/Rect.js | 15 +- src/SVGArray.js | 15 +- src/Shape.js | 2 + src/Stop.js | 4 +- src/Symbol.js | 4 +- src/Text.js | 4 +- src/Tspan.js | 4 +- src/Use.js | 4 +- src/classes.js | 5 + src/event.js | 34 +- src/pointed.js | 2 +- src/selector.js | 2 +- src/sugar.js | 4 +- src/svg.js | 30 +- src/tools.js | 4 - 51 files changed, 2609 insertions(+), 2468 deletions(-) create mode 100644 src/Container.js create mode 100644 src/Shape.js (limited to 'src') diff --git a/dist/svg.js b/dist/svg.js index 82efb01..fe8c329 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -118,6 +118,36 @@ var SVG = (function () { return _assertThisInitialized(self); } + function _superPropBase(object, property) { + while (!Object.prototype.hasOwnProperty.call(object, property)) { + object = _getPrototypeOf(object); + if (object === null) break; + } + + return object; + } + + function _get(target, property, receiver) { + if (typeof Reflect !== "undefined" && Reflect.get) { + _get = Reflect.get; + } else { + _get = function _get(target, property, receiver) { + var base = _superPropBase(target, property); + + if (!base) return; + var desc = Object.getOwnPropertyDescriptor(base, property); + + if (desc.get) { + return desc.get.call(receiver); + } + + return desc.value; + }; + } + + return _get(target, property, receiver || target); + } + function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } @@ -179,37 +209,16 @@ var SVG = (function () { var Base = /*#__PURE__*/ function () { - function Base(node, _ref) { - var _ref$extensions = _ref.extensions, - extensions = _ref$extensions === void 0 ? [] : _ref$extensions; + function Base(node + /*, {extensions = []}*/ + ) {// this.tags = [] + // + // for (let extension of extensions) { + // extension.setup.call(this, node) + // this.tags.push(extension.name) + // } _classCallCheck(this, Base); - - this.tags = []; - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = extensions[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var extension = _step.value; - extension.setup.call(this, node); - this.tags.push(extension.name); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } } _createClass(Base, [{ @@ -262,7 +271,7 @@ var SVG = (function () { var dots = /\./g; - var regex$1 = /*#__PURE__*/Object.freeze({ + var regex = /*#__PURE__*/Object.freeze({ numberAndUnit: numberAndUnit, hex: hex, rgb: rgb, @@ -476,12 +485,7 @@ var SVG = (function () { modules = Array.isArray(modules) ? modules : [modules]; for (i = modules.length - 1; i >= 0; i--) { - if (methods.name) { - modules[i].extensions = (modules[i].extensions || []).concat(methods); - } - for (key in methods) { - if (modules[i].prototype[key] || key == 'name' || key == 'setup') continue; modules[i].prototype[key] = methods[key]; } } @@ -624,76 +628,6 @@ var SVG = (function () { assignNewId: assignNewId }); - var HtmlNode = - /*#__PURE__*/ - function (_Base) { - _inherits(HtmlNode, _Base); - - function HtmlNode(element) { - var _this; - - _classCallCheck(this, HtmlNode); - - _this = _possibleConstructorReturn(this, _getPrototypeOf(HtmlNode).call(this, element, HtmlNode)); - _this.node = element; - return _this; - } - - _createClass(HtmlNode, [{ - key: "add", - value: function add(element, i) { - element = makeInstance(element); - - if (element.node !== this.node.children[i]) { - this.node.insertBefore(element.node, this.node.children[i] || null); - } - - return this; - } - }, { - key: "put", - value: function put(element, i) { - this.add(element, i); - return element; - } - }, { - key: "getEventTarget", - value: function getEventTarget() { - return this.node; - } - }]); - - return HtmlNode; - }(Base); - register(HtmlNode); - - var Defs = - /*#__PURE__*/ - function (_Base) { - _inherits(Defs, _Base); - - function Defs(node) { - _classCallCheck(this, Defs); - - return _possibleConstructorReturn(this, _getPrototypeOf(Defs).call(this, nodeOrNew('defs', node), Defs)); - } - - _createClass(Defs, [{ - key: "flatten", - value: function flatten() { - return this; - } - }, { - key: "ungroup", - value: function ungroup() { - return this; - } - }]); - - return Defs; - }(Base); - register(Defs); - var methods = {}; var constructors = {}; function registerMethods(name, m) { @@ -754,758 +688,587 @@ var SVG = (function () { } : {}; } - var SVGNumber = - /*#__PURE__*/ - function () { - // Initialize - function SVGNumber() { - _classCallCheck(this, SVGNumber); - - this.init.apply(this, arguments); - } - - _createClass(SVGNumber, [{ - key: "init", - value: function init(value, unit) { - unit = Array.isArray(value) ? value[1] : unit; - value = Array.isArray(value) ? value[0] : value; // initialize defaults - - this.value = 0; - this.unit = unit || ''; // parse value - - if (typeof value === 'number') { - // ensure a valid numeric value - this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; - } else if (typeof value === 'string') { - unit = value.match(numberAndUnit); - - if (unit) { - // make value numeric - this.value = parseFloat(unit[1]); // normalize - - if (unit[5] === '%') { - this.value /= 100; - } else if (unit[5] === 's') { - this.value *= 1000; - } // store unit - - - this.unit = unit[5]; - } - } else { - if (value instanceof SVGNumber) { - this.value = value.valueOf(); - this.unit = value.unit; - } - } - } - }, { - key: "toString", - value: function toString() { - return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; - } - }, { - key: "toJSON", - value: function toJSON() { - return this.toString(); - } - }, { - key: "toArray", - value: function toArray() { - return [this.value, this.unit]; - } - }, { - key: "valueOf", - value: function valueOf() { - return this.value; - } // Add number - - }, { - key: "plus", - value: function plus(number) { - number = new SVGNumber(number); - return new SVGNumber(this + number, this.unit || number.unit); - } // Subtract number + var listenerId = 0; - }, { - key: "minus", - value: function minus(number) { - number = new SVGNumber(number); - return new SVGNumber(this - number, this.unit || number.unit); - } // Multiply number + function getEventTarget(node) { + return typeof node.getEventTarget === 'function' ? node.getEventTarget() : node; + } // Add event binder in the SVG namespace - }, { - key: "times", - value: function times(number) { - number = new SVGNumber(number); - return new SVGNumber(this * number, this.unit || number.unit); - } // Divide number - }, { - key: "divide", - value: function divide(number) { - number = new SVGNumber(number); - return new SVGNumber(this / number, this.unit || number.unit); - } - }]); + function on(node, events, listener, binding, options) { + var l = listener.bind(binding || node); + var n = getEventTarget(node); // events can be an array of events or a string of events - return SVGNumber; - }(); + events = Array.isArray(events) ? events : events.split(delimiter); // ensure instance object for nodes which are not adopted - var Doc = getClass(root); - var HtmlNode$1 = getClass('HtmlNode'); - function setup(node) { - // initialize data object - this.dom = {}; // create circular reference + n.instance = n.instance || { + events: {} // pull event handlers from the element - this.node = node; - this.type = node.nodeName; - this.node.instance = this; + }; + var bag = n.instance.events; // add id to listener - 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')) || {}); + if (!listener._svgjsListenerId) { + listener._svgjsListenerId = ++listenerId; } - } // Move over x-axis - - function x(x) { - return this.attr('x', x); - } // Move over y-axis - - function y(y) { - return this.attr('y', y); - } // Move by center over x-axis - - function cx(x) { - return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2); - } // Move by center over y-axis - - function cy(y) { - return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2); - } // Move element to given x and y values - - function move(x, y) { - return this.x(x).y(y); - } // Move element by its center - - function center(x, y) { - return this.cx(x).cy(y); - } // Set width of element - function width(width) { - return this.attr('width', width); - } // Set height of element - - function height(height) { - return this.attr('height', height); - } // Set element size to given width and height - - function size(width, height) { - var p = proportionalSize(this, width, height); - return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height)); - } // Clone element + events.forEach(function (event) { + var ev = event.split('.')[0]; + var ns = event.split('.')[1] || '*'; // ensure valid object - function clone(parent) { - // write dom data to the dom so the clone can pickup the data - this.writeDataToDom(); // clone element and assign new id + bag[ev] = bag[ev] || {}; + bag[ev][ns] = bag[ev][ns] || {}; // reference listener - var clone = assignNewId(this.node.cloneNode(true)); // insert the clone in the given parent or after myself + bag[ev][ns][listener._svgjsListenerId] = l; // add listener - if (parent) parent.add(clone);else this.after(clone); - return clone; - } // Remove element + n.addEventListener(ev, l, options || false); + }); + } // Add event unbinder in the SVG namespace - function remove() { - if (this.parent()) { - this.parent().removeElement(this); - } + function off(node, events, listener, options) { + var n = getEventTarget(node); // we cannot remove an event if its not an svg.js instance - return this; - } // Replace element + if (!n.instance) return; // listener can be a function or a number - function replace(element) { - this.after(element).remove(); - return element; - } // Add element to given container and return self + if (typeof listener === 'function') { + listener = listener._svgjsListenerId; + if (!listener) return; + } // pull event handlers from the element - function addTo(parent) { - return makeInstance(parent).put(this); - } // Add element to given container and return container - function putIn(parent) { - return makeInstance(parent).add(this); - } // Get / set id + var bag = n.instance.events; // events can be an array of events or a string or undefined - function id$1(id) { - // generate new id if no id set - 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 + events = Array.isArray(events) ? events : (events || '').split(delimiter); + events.forEach(function (event) { + var ev = event && event.split('.')[0]; + var ns = event && event.split('.')[1]; + var namespace, l; + if (listener) { + // remove listener reference + if (bag[ev] && bag[ev][ns || '*']) { + // removeListener + n.removeEventListener(ev, bag[ev][ns || '*'][listener], options || false); + delete bag[ev][ns || '*'][listener]; + } + } else if (ev && ns) { + // remove all listeners for a namespaced event + if (bag[ev] && bag[ev][ns]) { + for (l in bag[ev][ns]) { + off(n, [ev, ns].join('.'), l); + } - return this.attr('id', id); - } // Checks whether the given point inside the bounding box of the element - - function inside(x, y) { - var box = this.bbox(); - return x > box.x && y > box.y && x < box.x + box.width && y < box.y + box.height; - } // Return id on string conversion - - function toString() { - return this.id(); - } // Return array of classes on the node - - function classes() { - var attr = this.attr('class'); - return attr == null ? [] : attr.trim().split(delimiter); - } // Return true if class exists on the node, false otherwise - - function hasClass(name) { - return this.classes().indexOf(name) !== -1; - } // Add class to the node - - function addClass(name) { - if (!this.hasClass(name)) { - var array = this.classes(); - array.push(name); - this.attr('class', array.join(' ')); - } - - return this; - } // Remove class from the node - - function removeClass(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 - - function toggleClass(name) { - return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); - } // Get referenced element form attribute value - - function reference$1(attr) { - var id = idFromReference(this.attr(attr)); - return id ? makeInstance(id) : null; - } // Returns the parent element instance - - function parent(type) { - var parent = this; // check for parent + delete bag[ev][ns]; + } + } else if (ns) { + // remove all listeners for a specific namespace + for (event in bag) { + for (namespace in bag[event]) { + if (ns === namespace) { + off(n, [event, ns].join('.')); + } + } + } + } else if (ev) { + // remove all listeners for the event + if (bag[ev]) { + for (namespace in bag[ev]) { + off(n, [ev, namespace].join('.')); + } - if (!parent.node.parentNode) return null; // get parent element + delete bag[ev]; + } + } else { + // remove all listeners on a given node + for (event in bag) { + off(n, event); + } - parent = adopt(parent.node.parentNode); - if (!type) return parent; // loop trough ancestors if type is given + n.instance.events = {}; + } + }); + } + function dispatch(node, event, data) { + var n = getEventTarget(node); // Dispatch event - while (parent && parent.node instanceof window.SVGElement) { - if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent; - parent = adopt(parent.node.parentNode); - } - } // Get parent document - - function doc() { - var p = this.parent(Doc); - return p && p.doc(); - } // Get defs - - function defs() { - return this.doc().defs(); - } // return array of all ancestors of given type up to the root svg - - function parents(type) { - var parents = []; - var parent = this; - - do { - parent = parent.parent(type); - if (!parent || parent instanceof HtmlNode$1) break; - parents.push(parent); - } while (parent.parent); - - return parents; - } // matches the element vs a css selector - - function matches(selector) { - return matcher(this.node, selector); - } // Returns the svg node to call native svg methods on it - - function native() { - return this.node; - } // Import raw svg - - function svg() { - // write svgjs data to the dom - this.writeDataToDom(); - return this.node.outerHTML; - } // write svgjs data to the dom - - function 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 + if (event instanceof window.Event) { + n.dispatchEvent(event); + } else { + event = new window.CustomEvent(event, { + detail: data, + cancelable: true + }); + n.dispatchEvent(event); } - return this; - } // set given data to the elements data property - - function setData(o) { - this.dom = o; - return this; - } - function getEventTarget() { - return this.node; + return event; } - registerMethods('Element', { - x: x, - y: y, - cx: cx, - cy: cy, - move: move, - center: center, - width: width, - height: height, - size: size, - clone: clone, - remove: remove, - replace: replace, - addTo: addTo, - putIn: putIn, - id: id$1, - inside: inside, - toString: toString, - classes: classes, - hasClass: hasClass, - addClass: addClass, - removeClass: removeClass, - toggleClass: toggleClass, - reference: reference$1, - doc: doc, - defs: defs, - parent: parent, - parents: parents, - matches: matches, - native: native, - svg: svg, - writeDataToDom: writeDataToDom, - setData: setData, - getEventTarget: getEventTarget + + var events = /*#__PURE__*/Object.freeze({ + on: on, + off: off, + dispatch: dispatch }); - registerConstructor('Element', setup); - var Doc$1 = + var EventTarget = /*#__PURE__*/ function (_Base) { - _inherits(Doc, _Base); + _inherits(EventTarget, _Base); - function Doc(node) { + function EventTarget() { var _this; - _classCallCheck(this, Doc); - - _this = _possibleConstructorReturn(this, _getPrototypeOf(Doc).call(this, nodeOrNew('svg', node), Doc)); + var node = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - _this.namespace(); + _classCallCheck(this, EventTarget); + _this = _possibleConstructorReturn(this, _getPrototypeOf(EventTarget).call(this)); + _this.events = node.events || {}; return _this; - } - - _createClass(Doc, [{ - key: "isRoot", - value: function isRoot() { - return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document'; - } // Check if this is a root svg - // If not, call docs from this element - - }, { - key: "doc", - value: function doc$$1() { - if (this.isRoot()) return this; - return doc.call(this); - } // Add namespaces - - }, { - key: "namespace", - value: function namespace() { - if (!this.isRoot()) return this.doc().namespace(); - return this.attr({ - xmlns: ns, - version: '1.1' - }).attr('xmlns:xlink', xlink, xmlns).attr('xmlns:svgjs', svgjs, xmlns); - } // Creates and returns defs element + } // Bind given event to listener - }, { - key: "defs", - value: function defs$$1() { - if (!this.isRoot()) return this.doc().defs(); - return adopt(this.node.getElementsByTagName('defs')[0]) || this.put(new Defs()); - } // custom parent method - }, { - key: "parent", - value: function parent$$1(type) { - if (this.isRoot()) { - return this.node.parentNode.nodeName === '#document' ? null : adopt(this.node.parentNode); - } + _createClass(EventTarget, [{ + key: "on", + value: function on$$1(event, listener, binding, options) { + on(this, event, listener, binding, options); - return parent.call(this, type); - } // Removes the doc from the DOM + return this; + } // Unbind event from listener }, { - key: "remove", - value: function remove$$1() { - if (!this.isRoot()) { - return remove.call(this); - } - - if (this.parent()) { - this.parent().removeChild(this.node); - } + key: "off", + value: function off$$1(event, listener) { + off(this, event, listener); return this; } }, { - key: "clear", - value: function clear() { - // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild); - } + key: "dispatch", + value: function dispatch$$1(event, data) { + return dispatch(this, event, data); + } // Fire given event + }, { + key: "fire", + value: function fire(event, data) { + this.dispatch(event, data); return this; } }]); - return Doc; - }(Base); - registerMethods({ - Container: { - // Create nested svg document - nested: function nested() { - return this.put(new Doc$1()); + return EventTarget; + }(Base); // Add events to elements + var methods$1 = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove', 'mouseenter', 'mouseleave', 'touchstart', 'touchmove', 'touchleave', 'touchend', 'touchcancel'].reduce(function (last, event) { + // add event to Element + var fn = function fn(f) { + if (f === null) { + off(this, event); + } else { + on(this, event, f); } - } - }); - register(Doc$1, 'Doc', true); - - var G = - /*#__PURE__*/ - function (_Base) { - _inherits(G, _Base); - - function G(node) { - _classCallCheck(this, G); - return _possibleConstructorReturn(this, _getPrototypeOf(G).call(this, nodeOrNew('g', node), G)); - } + return this; + }; - return G; - }(Base); - registerMethods({ - Element: { - // Create a group element - group: function group() { - return this.put(new G()); - } - } - }); - register(G); + last[event] = fn; + return last; + }, {}); + extend(EventTarget, methods$1); // registerMethods('EventTarget', { + // on, off, dispatch, fire + // }) + // + // registerConstructor('EventTarget', setup) - var Queue = + var SVGNumber = /*#__PURE__*/ function () { - function Queue() { - _classCallCheck(this, Queue); + // Initialize + function SVGNumber() { + _classCallCheck(this, SVGNumber); - this._first = null; - this._last = null; + this.init.apply(this, arguments); } - _createClass(Queue, [{ - key: "push", - value: function push(value) { - // An item stores an id and the provided value - var item = value.next ? value : { - value: value, - next: null, - prev: null // Deal with the queue being empty or populated + _createClass(SVGNumber, [{ + key: "init", + value: function init(value, unit) { + unit = Array.isArray(value) ? value[1] : unit; + value = Array.isArray(value) ? value[0] : value; // initialize defaults - }; + this.value = 0; + this.unit = unit || ''; // parse value - if (this._last) { - item.prev = this._last; - this._last.next = item; - this._last = item; - } else { - this._last = item; - this._first = item; - } // Update the length and return the current item + if (typeof value === 'number') { + // ensure a valid numeric value + this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; + } else if (typeof value === 'string') { + unit = value.match(numberAndUnit); + if (unit) { + // make value numeric + this.value = parseFloat(unit[1]); // normalize - return item; - } - }, { - key: "shift", - value: function shift() { - // Check if we have a value - var remove = this._first; - if (!remove) return null; // If we do, remove it and relink things + if (unit[5] === '%') { + this.value /= 100; + } else if (unit[5] === 's') { + this.value *= 1000; + } // store unit - this._first = remove.next; - if (this._first) this._first.prev = null; - this._last = this._first ? this._last : null; - return remove.value; - } // Shows us the first item in the list + this.unit = unit[5]; + } + } else { + if (value instanceof SVGNumber) { + this.value = value.valueOf(); + this.unit = value.unit; + } + } + } }, { - key: "first", - value: function first() { - return this._first && this._first.value; - } // Shows us the last item in the list - + key: "toString", + value: function toString() { + return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; + } }, { - key: "last", - value: function last() { - return this._last && this._last.value; - } // Removes the item that was returned from the push + key: "toJSON", + value: function toJSON() { + return this.toString(); + } + }, { + key: "toArray", + value: function toArray() { + return [this.value, this.unit]; + } + }, { + key: "valueOf", + value: function valueOf() { + return this.value; + } // Add number }, { - key: "remove", - value: function remove(item) { - // Relink the previous item - if (item.prev) item.prev.next = item.next; - if (item.next) item.next.prev = item.prev; - if (item === this._last) this._last = item.prev; - if (item === this._first) this._first = item.next; // Invalidate item + key: "plus", + value: function plus(number) { + number = new SVGNumber(number); + return new SVGNumber(this + number, this.unit || number.unit); + } // Subtract number - item.prev = null; - item.next = null; + }, { + key: "minus", + value: function minus(number) { + number = new SVGNumber(number); + return new SVGNumber(this - number, this.unit || number.unit); + } // Multiply number + + }, { + key: "times", + value: function times(number) { + number = new SVGNumber(number); + return new SVGNumber(this * number, this.unit || number.unit); + } // Divide number + + }, { + key: "divide", + value: function divide(number) { + number = new SVGNumber(number); + return new SVGNumber(this / number, this.unit || number.unit); } }]); - return Queue; + return SVGNumber; }(); - var Animator = { - nextDraw: null, - frames: new Queue(), - timeouts: new Queue(), - timer: window.performance || window.Date, - transforms: [], - frame: function frame(fn) { - // Store the node - var node = Animator.frames.push({ - run: fn - }); // Request an animation frame if we don't have one + var Doc = getClass(root); //export const name = 'Element' - if (Animator.nextDraw === null) { - Animator.nextDraw = window.requestAnimationFrame(Animator._draw); - } // Return the node so we can remove it easily + var Element = + /*#__PURE__*/ + function (_EventTarget) { + _inherits(Element, _EventTarget); + function Element(node) { + var _this; - return node; - }, - transform_frame: function transform_frame(fn, id) { - Animator.transforms[id] = fn; - }, - timeout: function timeout(fn, delay) { - delay = delay || 0; // Work out when the event should fire + _classCallCheck(this, Element); - var time = Animator.timer.now() + delay; // Add the timeout to the end of the queue + _this = _possibleConstructorReturn(this, _getPrototypeOf(Element).call(this)); // initialize data object - var node = Animator.timeouts.push({ - run: fn, - time: time - }); // Request another animation frame if we need one + _this.dom = {}; // create circular reference - if (Animator.nextDraw === null) { - Animator.nextDraw = window.requestAnimationFrame(Animator._draw); + _this.node = node; + _this.type = node.nodeName; + _this.node.instance = _assertThisInitialized(_assertThisInitialized(_this)); + + 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')) || {}); } - return node; - }, - cancelFrame: function cancelFrame(node) { - Animator.frames.remove(node); - }, - clearTimeout: function clearTimeout(node) { - Animator.timeouts.remove(node); - }, - _draw: function _draw(now) { - // Run all the timeouts we can run, if they are not ready yet, add them - // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) - var nextTimeout = null; - var lastTimeout = Animator.timeouts.last(); + return _this; + } // Move over x-axis - while (nextTimeout = Animator.timeouts.shift()) { - // Run the timeout if its time, or push it to the end - if (now >= nextTimeout.time) { - nextTimeout.run(); - } else { - Animator.timeouts.push(nextTimeout); - } // If we hit the last item, we should stop shifting out more items + _createClass(Element, [{ + key: "x", + value: function x(_x) { + return this.attr('x', _x); + } // Move over y-axis - if (nextTimeout === lastTimeout) break; - } // Run all of the animation frames + }, { + key: "y", + value: function y(_y) { + return this.attr('y', _y); + } // Move by center over x-axis + }, { + key: "cx", + value: function cx(x) { + return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2); + } // Move by center over y-axis - var nextFrame = null; - var lastFrame = Animator.frames.last(); + }, { + key: "cy", + value: function cy(y) { + return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2); + } // Move element to given x and y values - while (nextFrame !== lastFrame && (nextFrame = Animator.frames.shift())) { - nextFrame.run(); - } + }, { + key: "move", + value: function move(x, y) { + return this.x(x).y(y); + } // Move element by its center - Animator.transforms.forEach(function (el) { - el(); - }); // If we have remaining timeouts or frames, draw until we don't anymore + }, { + key: "center", + value: function center(x, y) { + return this.cx(x).cy(y); + } // Set width of element - Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() ? window.requestAnimationFrame(Animator._draw) : null; - } - }; + }, { + key: "width", + value: function width(_width) { + return this.attr('width', _width); + } // Set height of element - var Bare = - /*#__PURE__*/ - function (_Base) { - _inherits(Bare, _Base); + }, { + key: "height", + value: function height(_height) { + return this.attr('height', _height); + } // Set element size to given width and height - function Bare(node) { + }, { + key: "size", + value: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height)); + } // Clone element - _classCallCheck(this, Bare); + }, { + key: "clone", + value: function clone(parent) { + // write dom data to the dom so the clone can pickup the data + this.writeDataToDom(); // clone element and assign new id - return _possibleConstructorReturn(this, _getPrototypeOf(Bare).call(this, nodeOrNew(node, typeof node === 'string' ? null : node), Bare)); //extend(this, inherit) - } + var clone = assignNewId(this.node.cloneNode(true)); // insert the clone in the given parent or after myself - _createClass(Bare, [{ - key: "words", - value: function words(text) { - // remove contents - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild); - } // create text node + if (parent) parent.add(clone);else this.after(clone); + return clone; + } // Remove element + }, { + key: "remove", + value: function remove() { + if (this.parent()) { + this.parent().removeElement(this); + } - this.node.appendChild(document.createTextNode(text)); return this; - } - }]); - - return Bare; - }(Base); - register(Bare); - registerMethods('Container', { - // Create an element that is not described by SVG.js - element: function element(node, inherit) { - return this.put(new Bare(node, inherit)); - } - }); + } // Replace element - // FIXME: import this to runner + }, { + key: "replace", + value: function replace(element) { + this.after(element).remove(); + return element; + } // Add element to given container and return self - function rx(rx) { - return this.attr('rx', rx); - } // Radius y value + }, { + key: "addTo", + value: function addTo(parent) { + return makeInstance(parent).put(this); + } // Add element to given container and return container - function ry(ry) { - return this.attr('ry', ry); - } // Move over x-axis + }, { + key: "putIn", + value: function putIn(parent) { + return makeInstance(parent).add(this); + } // Get / set id - function x$1(x) { - return x == null ? this.cx() - this.rx() : this.cx(x + this.rx()); - } // Move over y-axis + }, { + key: "id", + value: function id(_id) { + // generate new id if no id set + 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 - function y$1(y) { - return y == null ? this.cy() - this.ry() : this.cy(y + this.ry()); - } // Move by center over x-axis - function cx$1(x) { - return x == null ? this.attr('cx') : this.attr('cx', x); - } // Move by center over y-axis + return this.attr('id', _id); + } // Checks whether the given point inside the bounding box of the element - function cy$1(y) { - return y == null ? this.attr('cy') : this.attr('cy', y); - } // Set width of element + }, { + key: "inside", + value: function inside(x, y) { + var box = this.bbox(); + return x > box.x && y > box.y && x < box.x + box.width && y < box.y + box.height; + } // Return id on string conversion - function width$1(width) { - return width == null ? this.rx() * 2 : this.rx(new SVGNumber(width).divide(2)); - } // Set height of element + }, { + key: "toString", + value: function toString() { + return this.id(); + } // Return array of classes on the node - function height$1(height) { - return height == null ? this.ry() * 2 : this.ry(new SVGNumber(height).divide(2)); - } // Custom size function + }, { + key: "classes", + value: function classes() { + var attr = this.attr('class'); + return attr == null ? [] : attr.trim().split(delimiter); + } // Return true if class exists on the node, false otherwise - function size$1(width, height) { - var p = proportionalSize(this, width, height); - return this.rx(new SVGNumber(p.width).divide(2)).ry(new SVGNumber(p.height).divide(2)); - } + }, { + key: "hasClass", + value: function hasClass(name) { + return this.classes().indexOf(name) !== -1; + } // Add class to the node - var circled = /*#__PURE__*/Object.freeze({ - rx: rx, - ry: ry, - x: x$1, - y: y$1, - cx: cx$1, - cy: cy$1, - width: width$1, - height: height$1, - size: size$1 - }); + }, { + key: "addClass", + value: function addClass(name) { + if (!this.hasClass(name)) { + var array = this.classes(); + array.push(name); + this.attr('class', array.join(' ')); + } - var Circle = - /*#__PURE__*/ - function (_Base) { - _inherits(Circle, _Base); + return this; + } // Remove class from the node - function Circle(node) { - _classCallCheck(this, Circle); + }, { + key: "removeClass", + value: function removeClass(name) { + if (this.hasClass(name)) { + this.attr('class', this.classes().filter(function (c) { + return c !== name; + }).join(' ')); + } - return _possibleConstructorReturn(this, _getPrototypeOf(Circle).call(this, nodeOrNew('circle', node), Circle)); - } + return this; + } // Toggle the presence of a class on the node - _createClass(Circle, [{ - key: "radius", - value: function radius(r) { - return this.attr('r', r); - } // Radius x value + }, { + key: "toggleClass", + value: function toggleClass(name) { + return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); + } // Get referenced element form attribute value }, { - key: "rx", - value: function rx$$1(_rx) { - return this.attr('r', _rx); - } // Alias radius x value + key: "reference", + value: function reference$$1(attr) { + var id = idFromReference(this.attr(attr)); + return id ? makeInstance(id) : null; + } // Returns the parent element instance }, { - key: "ry", - value: function ry$$1(_ry) { - return this.rx(_ry); - } - }]); + key: "parent", + value: function parent(type) { + var parent = this; // check for parent - return Circle; - }(Base); - extend(Circle, { - x: x$1, - y: y$1, - cx: cx$1, - cy: cy$1, - width: width$1, - height: height$1, - size: size$1 - }); - registerMethods({ - Element: { - // Create circle element - circle: function circle(size) { - return this.put(new Circle()).radius(new SVGNumber(size).divide(2)).move(0, 0); + if (!parent.node.parentNode) return null; // get parent element + + parent = adopt(parent.node.parentNode); + if (!type) return parent; // loop trough ancestors if type is given + + while (parent && parent.node instanceof window.SVGElement) { + if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent; + parent = adopt(parent.node.parentNode); + } + } // Get parent document + + }, { + key: "doc", + value: function doc() { + var p = this.parent(Doc); + return p && p.doc(); + } // Get defs + + }, { + key: "defs", + value: function defs() { + return this.doc().defs(); + } // return array of all ancestors of given type up to the root svg + + }, { + key: "parents", + value: function parents(type) { + var parents = []; + var parent = this; + + do { + parent = parent.parent(type); + if (!parent || parent instanceof getClass('HtmlNode')) break; + parents.push(parent); + } while (parent.parent); + + return parents; + } // matches the element vs a css selector + + }, { + key: "matches", + value: function matches(selector) { + return matcher(this.node, selector); + } // Returns the svg node to call native svg methods on it + + }, { + key: "native", + value: function native() { + return this.node; + } // Import raw svg + + }, { + key: "svg", + value: function svg() { + // write svgjs data to the dom + this.writeDataToDom(); + return this.node.outerHTML; + } // write svgjs data to the dom + + }, { + key: "writeDataToDom", + value: function 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 + + }, { + key: "setData", + value: function setData(o) { + this.dom = o; + return this; } - } - }); - register(Circle); + }, { + key: "getEventTarget", + value: function getEventTarget() { + return this.node; + } + }]); + + return Element; + }(EventTarget); // registerMethods('Element', { // Map function function map(array, block) { @@ -1555,572 +1318,1133 @@ var SVG = (function () { filterSVGElements: filterSVGElements }); - // SVG.get = function (id) { - // var node = document.getElementById(idFromReference(id) || id) - // 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.$$ = function (query, parent) { - // return SVG.utils.map((parent || document).querySelectorAll(query), function (node) { - // return SVG.adopt(node) - // }) - // } - // - // SVG.$ = function (query, parent) { - // return SVG.adopt((parent || document).querySelector(query)) - // } + var Parent = + /*#__PURE__*/ + function (_Element) { + _inherits(Parent, _Element); - function baseFind(query, parent) { - return map((parent || document).querySelectorAll(query), function (node) { - return adopt(node); - }); - } // Scoped find method + function Parent() { + _classCallCheck(this, Parent); - function find$1(query) { - return baseFind(query, this.node); - } - registerMethods('Container', { - find: find$1 - }); + return _possibleConstructorReturn(this, _getPrototypeOf(Parent).apply(this, arguments)); + } - var ClipPath = - /*#__PURE__*/ - function (_Base) { - _inherits(ClipPath, _Base); + _createClass(Parent, [{ + key: "children", + // Returns all child elements + value: function children() { + return map(this.node.children, function (node) { + return adopt(node); + }); + } // Add given element at a position - function ClipPath(node) { - _classCallCheck(this, ClipPath); + }, { + key: "add", + value: function add(element, i) { + element = makeInstance(element); - return _possibleConstructorReturn(this, _getPrototypeOf(ClipPath).call(this, nodeOrNew('clipPath', node), ClipPath)); - } // Unclip all clipped elements and remove itself + 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; + } // Basically does the same as `add()` but returns the added element instead - _createClass(ClipPath, [{ - key: "remove", - value: function remove$$1() { - // unclip all targets - this.targets().forEach(function (el) { - el.unclip(); - }); // remove clipPath from parent + }, { + key: "put", + value: function put(element, i) { + this.add(element, i); + return element.instance || element; + } // Checks if the given element is a child - return remove.call(this); - } }, { - key: "targets", - value: function targets() { - return baseFind('svg [clip-path*="' + this.id() + '"]'); - } - }]); + key: "has", + value: function has(element) { + return this.index(element) >= 0; + } // Gets index of given element - return ClipPath; - }(Base); - registerMethods({ - Container: { - // Create clipping element - clip: function clip() { - return this.defs().put(new ClipPath()); - } - }, - Element: { - // Distribute clipPath to svg element - clipWith: function clipWith(element) { - // use given clip or create a new one - var clipper = element instanceof ClipPath ? element : this.parent().clip().add(element); // apply mask + }, { + key: "index", + value: function index(element) { + return [].slice.call(this.node.childNodes).indexOf(element.node); + } // Get a element at the given index - return this.attr('clip-path', 'url("#' + clipper.id() + '")'); - }, - // Unclip element - unclip: function unclip() { - return this.attr('clip-path', null); - }, - clipper: function clipper() { - return this.reference('clip-path'); - } - } - }); - register(ClipPath); + }, { + key: "get", + value: function get(i) { + return adopt(this.node.childNodes[i]); + } // Get first child - var A = - /*#__PURE__*/ - function (_Base) { - _inherits(A, _Base); + }, { + key: "first", + value: function first() { + return adopt(this.node.firstChild); + } // Get the last child - function A(node) { - _classCallCheck(this, A); + }, { + key: "last", + value: function last() { + return adopt(this.node.lastChild); + } // Iterates over all children and invokes a given block - return _possibleConstructorReturn(this, _getPrototypeOf(A).call(this, nodeOrNew('a', node), A)); - } // Link url + }, { + key: "each", + value: function each(block, deep) { + var children = this.children(); + var i, il; + for (i = 0, il = children.length; i < il; i++) { + if (children[i] instanceof Element) { + block.apply(children[i], [i, children]); + } - _createClass(A, [{ - key: "to", - value: function to(url) { - return this.attr('href', url, xlink); - } // Link target attribute + if (deep && children[i] instanceof Parent) { + children[i].each(block, deep); + } + } + + return this; + } // Remove a given child }, { - key: "target", - value: function target(_target) { - return this.attr('target', _target); - } - }]); + key: "removeElement", + value: function removeElement(element) { + this.node.removeChild(element.node); + return this; + } // Remove all elements in this container - return A; - }(Base); - registerMethods({ - Container: { - // Create a hyperlink element - link: function link(url) { - return this.put(new A()).to(url); - } - }, - Element: { - // Create a hyperlink element - linkTo: function linkTo(url) { - var link = new A(); + }, { + key: "clear", + value: function clear() { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } // remove defs reference - if (typeof url === 'function') { - url.call(link, link); - } else { - link.to(url); - } - return this.parent().put(link).put(this); - } - } - }); - register(A); + delete this._defs; + return this; + } // Import raw svg - var Ellipse = - /*#__PURE__*/ - function (_Base) { - _inherits(Ellipse, _Base); + }, { + key: "svg", + value: function svg(_svg) { + var well, len; // act as a setter if svg is given - function Ellipse(node) { - _classCallCheck(this, Ellipse); + if (_svg) { + // create temporary holder + well = document.createElementNS(ns, 'svg'); // dump raw svg - return _possibleConstructorReturn(this, _getPrototypeOf(Ellipse).call(this, nodeOrNew('ellipse', node), Ellipse)); - } + well.innerHTML = _svg; // transplant nodes - return Ellipse; - }(Base); - extend(Ellipse, circled); - registerMethods('Container', { - // Create an ellipse - ellipse: function ellipse(width, height) { - return this.put(new Ellipse()).size(width, height).move(0, 0); - } - }); - register(Ellipse); + for (len = well.children.length; len--;) { + this.node.appendChild(well.firstElementChild); + } // otherwise act as a getter - var Stop = - /*#__PURE__*/ - function (_Base) { - _inherits(Stop, _Base); + } else { + // write svgjs data to the dom + this.writeDataToDom(); + return this.node.outerHTML; + } - function Stop(node) { - _classCallCheck(this, Stop); + return this; + } // write svgjs data to the dom - return _possibleConstructorReturn(this, _getPrototypeOf(Stop).call(this, nodeOrNew('stop', node), Stop)); - } // add color stops + }, { + key: "writeDataToDom", + value: function writeDataToDom() { + // dump variables recursively + this.each(function () { + this.writeDataToDom(); + }); // remove previously set data + this.node.removeAttribute('svgjs:data'); - _createClass(Stop, [{ - key: "update", - value: function update(o) { - if (typeof o === 'number' || o instanceof SVGNumber) { - o = { - offset: arguments[0], - color: arguments[1], - opacity: arguments[2] - }; - } // set attributes + if (Object.keys(this.dom).length) { + this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)); // see #428 + } + return this; + } + }, { + key: "flatten", + value: function flatten(parent) { + this.each(function () { + if (this instanceof Parent) return this.flatten(parent).ungroup(parent); + return this.toParent(parent); + }); // we need this so that Doc does not get removed - 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)); + this.node.firstElementChild || this.remove(); + return this; + } + }, { + key: "ungroup", + value: function ungroup(parent) { + parent = parent || this.parent(); + this.each(function () { + return this.toParent(parent); + }); + this.remove(); return this; } }]); - return Stop; - }(Base); - register(Stop); + return Parent; + }(Element); // registerMethods('Container', { - // FIXME: add to runner - function from(x, y) { - return (this._element || this).type === 'radialGradient' ? this.attr({ - fx: new SVGNumber(x), - fy: new SVGNumber(y) - }) : this.attr({ - x1: new SVGNumber(x), - y1: new SVGNumber(y) - }); - } - function to(x, y) { - return (this._element || this).type === 'radialGradient' ? this.attr({ - cx: new SVGNumber(x), - cy: new SVGNumber(y) - }) : this.attr({ - x2: new SVGNumber(x), - y2: new SVGNumber(y) - }); - } - - var gradiented = /*#__PURE__*/Object.freeze({ - from: from, - to: to - }); + var Shape = + /*#__PURE__*/ + function (_Parent) { + _inherits(Shape, _Parent); - function noop() {} // Default animation values + function Shape() { + _classCallCheck(this, Shape); - var timeline = { - duration: 400, - ease: '>', - delay: 0 // Default attribute values + return _possibleConstructorReturn(this, _getPrototypeOf(Shape).apply(this, arguments)); + } - }; - var attrs = { - // fill and stroke - 'fill-opacity': 1, - 'stroke-opacity': 1, - 'stroke-width': 0, - 'stroke-linejoin': 'miter', - 'stroke-linecap': 'butt', - fill: '#000000', - stroke: '#000000', - opacity: 1, - // position - x: 0, - y: 0, - cx: 0, - cy: 0, - // size - width: 0, - height: 0, - // radius - r: 0, - rx: 0, - ry: 0, - // gradient - offset: 0, - 'stop-opacity': 1, - 'stop-color': '#000000', - // text - 'font-size': 16, - 'font-family': 'Helvetica, Arial, sans-serif', - 'text-anchor': 'start' - }; + return Shape; + }(Parent); - var Color = + var Container$1 = /*#__PURE__*/ - function () { - function Color() { - _classCallCheck(this, Color); + function (_Parent) { + _inherits(Container, _Parent); - this.init.apply(this, arguments); + function Container() { + _classCallCheck(this, Container); + + return _possibleConstructorReturn(this, _getPrototypeOf(Container).apply(this, arguments)); } - _createClass(Color, [{ - key: "init", - value: function init(color, g, b) { - var match; // initialize defaults + return Container; + }(Parent); - this.r = 0; - this.g = 0; - this.b = 0; - if (!color) return; // parse color + var HtmlNode = + /*#__PURE__*/ + function (_Parent) { + _inherits(HtmlNode, _Parent); - if (typeof color === 'string') { - if (isRgb.test(color)) { - // get rgb values - match = rgb.exec(color.replace(whitespace, '')); // parse numeric values + function HtmlNode(element) { + var _this; - this.r = parseInt(match[1]); - this.g = parseInt(match[2]); - this.b = parseInt(match[3]); - } else if (isHex.test(color)) { - // get hex values - match = hex.exec(fullHex(color)); // parse numeric values + _classCallCheck(this, HtmlNode); - this.r = parseInt(match[1], 16); - this.g = parseInt(match[2], 16); - this.b = parseInt(match[3], 16); - } - } else if (Array.isArray(color)) { - this.r = color[0]; - this.g = color[1]; - this.b = color[2]; - } else if (_typeof(color) === 'object') { - this.r = color.r; - this.g = color.g; - this.b = color.b; - } else if (arguments.length === 3) { - this.r = color; - this.g = g; - this.b = b; + _this = _possibleConstructorReturn(this, _getPrototypeOf(HtmlNode).call(this, element, HtmlNode)); + _this.node = element; + return _this; + } + + _createClass(HtmlNode, [{ + key: "add", + value: function add(element, i) { + element = makeInstance(element); + + if (element.node !== this.node.children[i]) { + this.node.insertBefore(element.node, this.node.children[i] || null); } - } // Default to hex conversion + return this; + } }, { - key: "toString", - value: function toString() { - return this.toHex(); + key: "put", + value: function put(element, i) { + this.add(element, i); + return element; } }, { - key: "toArray", - value: function toArray() { - return [this.r, this.g, this.b]; - } // Build hex value - + key: "removeElement", + value: function removeElement(element) { + this.node.removeChild(element.node); + return this; + } }, { - key: "toHex", - value: function toHex() { - return '#' + compToHex(Math.round(this.r)) + compToHex(Math.round(this.g)) + compToHex(Math.round(this.b)); - } // Build rgb value + key: "getEventTarget", + value: function getEventTarget() { + return this.node; + } + }]); - }, { - key: "toRgb", - value: function toRgb() { - return 'rgb(' + [this.r, this.g, this.b].join() + ')'; - } // Calculate true brightness + return HtmlNode; + }(Parent); + register(HtmlNode); - }, { - key: "brightness", - value: function brightness() { - return this.r / 255 * 0.30 + this.g / 255 * 0.59 + this.b / 255 * 0.11; - } // Testers - // Test if given value is a color string + var Defs = + /*#__PURE__*/ + function (_Container) { + _inherits(Defs, _Container); - }], [{ - key: "test", - value: function test(color) { - color += ''; - return isHex.test(color) || isRgb.test(color); - } // Test if given value is a rgb object + function Defs(node) { + _classCallCheck(this, Defs); - }, { - key: "isRgb", - value: function isRgb$$1(color) { - return color && typeof color.r === 'number' && typeof color.g === 'number' && typeof color.b === 'number'; - } // Test if given value is a color + return _possibleConstructorReturn(this, _getPrototypeOf(Defs).call(this, nodeOrNew('defs', node), Defs)); + } + _createClass(Defs, [{ + key: "flatten", + value: function flatten() { + return this; + } }, { - key: "isColor", - value: function isColor(color) { - return this.isRgb(color) || this.test(color); + key: "ungroup", + value: function ungroup() { + return this; } }]); - return Color; - }(); + return Defs; + }(Container$1); + register(Defs); - var subClassArray = function () { - try { - //throw 'asdad' - // try es6 subclassing - return Function('name', 'baseClass', '_constructor', ['baseClass = baseClass || Array', 'return {', '[name]: class extends baseClass {', 'constructor (...args) {', 'super(...args)', '_constructor && _constructor.apply(this, args)', '}', '}', '}[name]'].join('\n')); - } catch (e) { - // Use es5 approach - return function (name) { - var baseClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Array; + var Doc$1 = + /*#__PURE__*/ + function (_Container) { + _inherits(Doc, _Container); - var _constructor = arguments.length > 2 ? arguments[2] : undefined; + function Doc(node) { + var _this; - var Arr = function Arr() { - baseClass.apply(this, arguments); - _constructor && _constructor.apply(this, arguments); - }; + _classCallCheck(this, Doc); - Arr.prototype = Object.create(baseClass.prototype); - Arr.prototype.constructor = Arr; - return Arr; - }; - } - }(); + _this = _possibleConstructorReturn(this, _getPrototypeOf(Doc).call(this, nodeOrNew('svg', node), Doc)); - var SVGArray = subClassArray('SVGArray', Array, function () { - this.init.apply(this, arguments); - }); - extend2(SVGArray, { - init: function init() { - //this.splice(0, this.length) - this.length = 0; - this.push.apply(this, _toConsumableArray(this.parse.apply(this, arguments))); - }, - toArray: function toArray() { - var ret = []; - ret.push.apply(ret, _toConsumableArray(this)); //Array.prototype.push.apply(ret, this) + _this.namespace(); - return ret; //return Array.prototype.concat.apply([], this) - }, - toString: function toString() { - return this.join(' '); - }, - valueOf: function valueOf() { - return this.toArray(); - }, - // Parse whitespace separated string - parse: function parse() { - var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - //array = array.valueOf() - // If already is an array, no need to parse it - if (array instanceof Array) return array; - return array.trim().split(delimiter).map(parseFloat); - }, - clone: function clone() { - return new this.constructor(this); - }, - toSet: function toSet() { - return new Set(this); + return _this; } - }); // export default class SVGArray extends BaseArray { - // constructor (...args) { - // super() - // this.init(...args) - // } - // - // init (array, fallback = []) { - // //this.splice(0, this.length) - // this.length = 0 - // this.push(...this.parse(array || fallback)) - // } - // - // toArray () { - // return [].concat(this) - // } - // - // toString () { - // return this.join(' ') - // } - // - // valueOf () { - // return this.toArray() - // } - // - // // Parse whitespace separated string - // parse (array) { - // array = array.valueOf() - // - // // if already is an array, no need to parse it - // if (Array.isArray(array)) return array - // - // return array.trim().split(delimiter).map(parseFloat) - // } - // - // clone () { - // return new this.constructor(this) - // } - // - // toSet () { - // return new Set(this) - // } - // } - function attr(attr, val, ns) { - // act as full getter - if (attr == null) { - // get an object of attributes - attr = {}; - val = this.node.attributes; - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; + _createClass(Doc, [{ + key: "isRoot", + value: function isRoot() { + return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document'; + } // Check if this is a root svg + // If not, call docs from this element - try { - for (var _iterator = val[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var node = _step.value; - attr[node.nodeName] = isNumber.test(node.nodeValue) ? parseFloat(node.nodeValue) : node.nodeValue; + }, { + key: "doc", + value: function doc() { + if (this.isRoot()) return this; + return _get(_getPrototypeOf(Doc.prototype), "doc", this).call(this); //return doc.call(this) + } // Add namespaces + + }, { + key: "namespace", + value: function namespace() { + if (!this.isRoot()) return this.doc().namespace(); + return this.attr({ + xmlns: ns, + version: '1.1' + }).attr('xmlns:xlink', xlink, xmlns).attr('xmlns:svgjs', svgjs, xmlns); + } // Creates and returns defs element + + }, { + key: "defs", + value: function defs() { + if (!this.isRoot()) return this.doc().defs(); + return adopt(this.node.getElementsByTagName('defs')[0]) || this.put(new Defs()); + } // custom parent method + + }, { + key: "parent", + value: function parent(type) { + if (this.isRoot()) { + return this.node.parentNode.nodeName === '#document' ? null : adopt(this.node.parentNode); } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } + + return _get(_getPrototypeOf(Doc.prototype), "parent", this).call(this, type); //return parent.call(this, type) + } // Removes the doc from the DOM + // remove() { + // if (!this.isRoot()) { + // return super.remove() + // } + // + // if (this.parent()) { + // this.parent().remove(this) + // } + // + // return this + // } + + }, { + key: "clear", + value: function clear() { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); } + + return this; } + }]); - return attr; - } else if (Array.isArray(attr)) ; else if (_typeof(attr) === 'object') { - // apply every attribute individually if an object is passed - for (val in attr) { - this.attr(val, attr[val]); + return Doc; + }(Container$1); + registerMethods({ + Container: { + // Create nested svg document + nested: function nested() { + return this.put(new Doc$1()); } - } else if (val === null) { - // remove value - this.node.removeAttribute(attr); - } else if (val == null) { - // act as a getter if the first and only argument is not an object - val = this.node.getAttribute(attr); - return val == null ? attrs[attr] // FIXME: do we need to return defaults? - : isNumber.test(val) ? parseFloat(val) : val; - } else { - // convert image fill and stroke to patterns - if (attr === 'fill' || attr === 'stroke') { - if (isImage.test(val)) { - val = this.doc().defs().image(val); - } - } // FIXME: This is fine, but what about the lines above? - // How does attr know about image()? + } + }); + register(Doc$1, 'Doc', true); + + var G = + /*#__PURE__*/ + function (_Container) { + _inherits(G, _Container); + + function G(node) { + _classCallCheck(this, G); + + return _possibleConstructorReturn(this, _getPrototypeOf(G).call(this, nodeOrNew('g', node), G)); + } + + return G; + }(Container$1); + registerMethods({ + Element: { + // Create a group element + group: function group() { + return this.put(new G()); + } + } + }); + register(G); + + var Queue = + /*#__PURE__*/ + function () { + function Queue() { + _classCallCheck(this, Queue); + + this._first = null; + this._last = null; + } + + _createClass(Queue, [{ + key: "push", + value: function push(value) { + // An item stores an id and the provided value + var item = value.next ? value : { + value: value, + next: null, + prev: null // Deal with the queue being empty or populated + + }; + + if (this._last) { + item.prev = this._last; + this._last.next = item; + this._last = item; + } else { + this._last = item; + this._first = item; + } // Update the length and return the current item + + + return item; + } + }, { + key: "shift", + value: function shift() { + // Check if we have a value + var remove = this._first; + if (!remove) return null; // If we do, remove it and relink things + + this._first = remove.next; + if (this._first) this._first.prev = null; + this._last = this._first ? this._last : null; + return remove.value; + } // Shows us the first item in the list + + }, { + key: "first", + value: function first() { + return this._first && this._first.value; + } // Shows us the last item in the list + + }, { + key: "last", + value: function last() { + return this._last && this._last.value; + } // Removes the item that was returned from the push + + }, { + key: "remove", + value: function remove(item) { + // Relink the previous item + if (item.prev) item.prev.next = item.next; + if (item.next) item.next.prev = item.prev; + if (item === this._last) this._last = item.prev; + if (item === this._first) this._first = item.next; // Invalidate item + + item.prev = null; + item.next = null; + } + }]); + + return Queue; + }(); + + var Animator = { + nextDraw: null, + frames: new Queue(), + timeouts: new Queue(), + timer: window.performance || window.Date, + transforms: [], + frame: function frame(fn) { + // Store the node + var node = Animator.frames.push({ + run: fn + }); // Request an animation frame if we don't have one + + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw); + } // Return the node so we can remove it easily + + + return node; + }, + transform_frame: function transform_frame(fn, id) { + Animator.transforms[id] = fn; + }, + timeout: function timeout(fn, delay) { + delay = delay || 0; // Work out when the event should fire + + var time = Animator.timer.now() + delay; // Add the timeout to the end of the queue + + var node = Animator.timeouts.push({ + run: fn, + time: time + }); // Request another animation frame if we need one + + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw); + } + + return node; + }, + cancelFrame: function cancelFrame(node) { + Animator.frames.remove(node); + }, + clearTimeout: function clearTimeout(node) { + Animator.timeouts.remove(node); + }, + _draw: function _draw(now) { + // Run all the timeouts we can run, if they are not ready yet, add them + // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) + var nextTimeout = null; + var lastTimeout = Animator.timeouts.last(); + + while (nextTimeout = Animator.timeouts.shift()) { + // Run the timeout if its time, or push it to the end + if (now >= nextTimeout.time) { + nextTimeout.run(); + } else { + Animator.timeouts.push(nextTimeout); + } // If we hit the last item, we should stop shifting out more items + + + if (nextTimeout === lastTimeout) break; + } // Run all of the animation frames + + + var nextFrame = null; + var lastFrame = Animator.frames.last(); + + while (nextFrame !== lastFrame && (nextFrame = Animator.frames.shift())) { + nextFrame.run(); + } + + Animator.transforms.forEach(function (el) { + el(); + }); // If we have remaining timeouts or frames, draw until we don't anymore + + Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() ? window.requestAnimationFrame(Animator._draw) : null; + } + }; + + var Bare = + /*#__PURE__*/ + function (_Parent) { + _inherits(Bare, _Parent); + + function Bare(node) { + _classCallCheck(this, Bare); + + return _possibleConstructorReturn(this, _getPrototypeOf(Bare).call(this, nodeOrNew(node, typeof node === 'string' ? null : node), Bare)); + } + + _createClass(Bare, [{ + key: "words", + value: function words(text) { + // remove contents + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } // create text node + + + this.node.appendChild(document.createTextNode(text)); + return this; + } + }]); + + return Bare; + }(Parent); + register(Bare); + registerMethods('Container', { + // Create an element that is not described by SVG.js + element: function element(node, inherit) { + return this.put(new Bare(node, inherit)); + } + }); + + // FIXME: import this to runner + + function rx(rx) { + return this.attr('rx', rx); + } // Radius y value + + function ry(ry) { + return this.attr('ry', ry); + } // Move over x-axis + + function x(x) { + return x == null ? this.cx() - this.rx() : this.cx(x + this.rx()); + } // Move over y-axis + + function y(y) { + return y == null ? this.cy() - this.ry() : this.cy(y + this.ry()); + } // Move by center over x-axis + + function cx(x) { + return x == null ? this.attr('cx') : this.attr('cx', x); + } // Move by center over y-axis + + function cy(y) { + return y == null ? this.attr('cy') : this.attr('cy', y); + } // Set width of element + + function width(width) { + return width == null ? this.rx() * 2 : this.rx(new SVGNumber(width).divide(2)); + } // Set height of element + + function height(height) { + return height == null ? this.ry() * 2 : this.ry(new SVGNumber(height).divide(2)); + } // Custom size function + + function 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)); + } + + var circled = /*#__PURE__*/Object.freeze({ + rx: rx, + ry: ry, + x: x, + y: y, + cx: cx, + cy: cy, + width: width, + height: height, + size: size + }); + + var Circle = + /*#__PURE__*/ + function (_Shape) { + _inherits(Circle, _Shape); + + function Circle(node) { + _classCallCheck(this, Circle); + + return _possibleConstructorReturn(this, _getPrototypeOf(Circle).call(this, nodeOrNew('circle', node), Circle)); + } + + _createClass(Circle, [{ + key: "radius", + value: function radius(r) { + return this.attr('r', r); + } // Radius x value + + }, { + key: "rx", + value: function rx$$1(_rx) { + return this.attr('r', _rx); + } // Alias radius x value + + }, { + key: "ry", + value: function ry$$1(_ry) { + return this.rx(_ry); + } + }]); + + return Circle; + }(Shape); + extend(Circle, { + x: x, + y: y, + cx: cx, + cy: cy, + width: width, + height: height, + size: size + }); + registerMethods({ + Element: { + // Create circle element + circle: function circle(size$$1) { + return this.put(new Circle()).radius(new SVGNumber(size$$1).divide(2)).move(0, 0); + } + } + }); + register(Circle); + + // SVG.get = function (id) { + // var node = document.getElementById(idFromReference(id) || id) + // 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.$$ = function (query, parent) { + // return SVG.utils.map((parent || document).querySelectorAll(query), function (node) { + // return SVG.adopt(node) + // }) + // } + // + // SVG.$ = function (query, parent) { + // return SVG.adopt((parent || document).querySelector(query)) + // } + + function baseFind(query, parent) { + return map((parent || document).querySelectorAll(query), function (node) { + return adopt(node); + }); + } // Scoped find method + + function find$1(query) { + return baseFind(query, this.node); + } + registerMethods('Element', { + find: find$1 + }); + + var ClipPath = + /*#__PURE__*/ + function (_Container) { + _inherits(ClipPath, _Container); + + function ClipPath(node) { + _classCallCheck(this, ClipPath); + + return _possibleConstructorReturn(this, _getPrototypeOf(ClipPath).call(this, nodeOrNew('clipPath', node), ClipPath)); + } // Unclip all clipped elements and remove itself + + + _createClass(ClipPath, [{ + key: "remove", + value: function remove() { + // unclip all targets + this.targets().forEach(function (el) { + el.unclip(); + }); // remove clipPath from parent + + return _get(_getPrototypeOf(ClipPath.prototype), "remove", this).call(this); //return remove.call(this) + } + }, { + key: "targets", + value: function targets() { + return baseFind('svg [clip-path*="' + this.id() + '"]'); + } + }]); + + return ClipPath; + }(Container$1); + registerMethods({ + Container: { + // Create clipping element + clip: function clip() { + return this.defs().put(new ClipPath()); + } + }, + Element: { + // Distribute clipPath to svg element + clipWith: function clipWith(element) { + // use given clip or create a new one + var clipper = element instanceof ClipPath ? element : this.parent().clip().add(element); // apply mask + + return this.attr('clip-path', 'url("#' + clipper.id() + '")'); + }, + // Unclip element + unclip: function unclip() { + return this.attr('clip-path', null); + }, + clipper: function clipper() { + return this.reference('clip-path'); + } + } + }); + register(ClipPath); + + var A = + /*#__PURE__*/ + function (_Container) { + _inherits(A, _Container); + + function A(node) { + _classCallCheck(this, A); + + return _possibleConstructorReturn(this, _getPrototypeOf(A).call(this, nodeOrNew('a', node), A)); + } // Link url + + + _createClass(A, [{ + key: "to", + value: function to(url) { + return this.attr('href', url, xlink); + } // Link target attribute + + }, { + key: "target", + value: function target(_target) { + return this.attr('target', _target); + } + }]); + + return A; + }(Container$1); + registerMethods({ + Container: { + // Create a hyperlink element + link: function link(url) { + return this.put(new A()).to(url); + } + }, + Element: { + // Create a hyperlink element + linkTo: function linkTo(url) { + var link = new A(); + + if (typeof url === 'function') { + url.call(link, link); + } else { + link.to(url); + } + + return this.parent().put(link).put(this); + } + } + }); + register(A); + + var Ellipse = + /*#__PURE__*/ + function (_Shape) { + _inherits(Ellipse, _Shape); + + function Ellipse(node) { + _classCallCheck(this, Ellipse); + + return _possibleConstructorReturn(this, _getPrototypeOf(Ellipse).call(this, nodeOrNew('ellipse', node), Ellipse)); + } + + return Ellipse; + }(Shape); + extend(Ellipse, circled); + registerMethods('Container', { + // Create an ellipse + ellipse: function ellipse(width$$1, height$$1) { + return this.put(new Ellipse()).size(width$$1, height$$1).move(0, 0); + } + }); + register(Ellipse); + + var Stop = + /*#__PURE__*/ + function (_Element) { + _inherits(Stop, _Element); + + function Stop(node) { + _classCallCheck(this, Stop); + + return _possibleConstructorReturn(this, _getPrototypeOf(Stop).call(this, nodeOrNew('stop', node), Stop)); + } // add color stops + + + _createClass(Stop, [{ + key: "update", + value: function 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)); + return this; + } + }]); + + return Stop; + }(Element); + register(Stop); + + // FIXME: add to runner + function from(x, y) { + return (this._element || this).type === 'radialGradient' ? this.attr({ + fx: new SVGNumber(x), + fy: new SVGNumber(y) + }) : this.attr({ + x1: new SVGNumber(x), + y1: new SVGNumber(y) + }); + } + function to(x, y) { + return (this._element || this).type === 'radialGradient' ? this.attr({ + cx: new SVGNumber(x), + cy: new SVGNumber(y) + }) : this.attr({ + x2: new SVGNumber(x), + y2: new SVGNumber(y) + }); + } + + var gradiented = /*#__PURE__*/Object.freeze({ + from: from, + to: to + }); + + function parser() { + // Reuse cached element if possible + if (!parser.nodes) { + var svg = new Doc$1().size(2, 0).css({ + opacity: 0, + position: 'absolute', + left: '-100%', + top: '-100%', + overflow: 'hidden' + }); + var path = svg.path().node; + parser.nodes = { + svg: svg, + path: path + }; + } + + if (!parser.nodes.svg.node.parentNode) { + var b = document.body || document.documentElement; + parser.nodes.svg.addTo(b); + } + + return parser.nodes; + } + + var Point = + /*#__PURE__*/ + function () { + // Initialize + function Point(x, y, base) { + _classCallCheck(this, Point); + + var source; + base = base || { + x: 0, + y: 0 // ensure source as object + + }; + source = Array.isArray(x) ? { + x: x[0], + y: x[1] + } : _typeof(x) === 'object' ? { + x: x.x, + y: x.y + } : { + x: x, + y: y // merge source + + }; + this.x = source.x == null ? base.x : source.x; + this.y = source.y == null ? base.y : source.y; + } // Clone point + + + _createClass(Point, [{ + key: "clone", + value: function clone() { + return new Point(this); + } // Convert to native SVGPoint + + }, { + key: "native", + value: function native() { + // create new point + var point = parser().svg.node.createSVGPoint(); // update with current values + + point.x = this.x; + point.y = this.y; + return point; + } // transform point with matrix + + }, { + key: "transform", + value: function transform(m) { + // Perform the matrix multiplication + var x = m.a * this.x + m.c * this.y + m.e; + var y = m.b * this.x + m.d * this.y + m.f; // Return the required point + + return new Point(x, y); + } + }]); + + return Point; + }(); + registerMethods({ + Element: { + // Get point + point: function point(x, y) { + return new Point(x, y).transform(this.screenCTM().inverse()); + } + } + }); + var Box$1 = + /*#__PURE__*/ + function () { + function Box() { + _classCallCheck(this, Box); - while (typeof val.attrHook == 'function') { - val = val.attrHook(this, attr); - } // ensure correct numeric values (also accepts NaN and Infinity) + this.init.apply(this, arguments); + } + + _createClass(Box, [{ + key: "init", + value: function init(source) { + var base = [0, 0, 0, 0]; + source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) : Array.isArray(source) ? source : _typeof(source) === 'object' ? [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] : arguments.length === 4 ? [].slice.call(arguments) : base; + this.x = source[0]; + this.y = source[1]; + this.width = source[2]; + this.height = source[3]; // add center, right, bottom... + fullBox(this); + } // Merge rect box with another, return a new instance - if (typeof val === 'number') { - val = new SVGNumber(val); - } else if (Color.isColor(val)) { - // ensure full hex color - val = new Color(val); - } else if (val.constructor === Array) { - // Check for plain arrays and parse array values - val = new SVGArray(val); - } // if the passed attribute is leading... + }, { + key: "merge", + value: function merge(box) { + var x = Math.min(this.x, box.x); + var y = Math.min(this.y, box.y); + var width = Math.max(this.x + this.width, box.x + box.width) - x; + var height = Math.max(this.y + this.height, box.y + box.height) - y; + return new Box(x, y, width, height); + } + }, { + key: "transform", + value: function transform(m) { + var xMin = Infinity; + var xMax = -Infinity; + var yMin = Infinity; + var yMax = -Infinity; + var pts = [new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2)]; + pts.forEach(function (p) { + p = p.transform(m); + xMin = Math.min(xMin, p.x); + xMax = Math.max(xMax, p.x); + yMin = Math.min(yMin, p.y); + yMax = Math.max(yMax, p.y); + }); + return new Box(xMin, yMin, xMax - xMin, yMax - yMin); + } + }, { + key: "addOffset", + value: function addOffset() { + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset; + this.y += window.pageYOffset; + return this; + } + }, { + key: "toString", + value: function toString() { + return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height; + } + }, { + key: "toArray", + value: function toArray() { + return [this.x, this.y, this.width, this.height]; + } + }]); + return Box; + }(); - if (attr === 'leading') { - // ... call the leading method instead - if (this.leading) { - this.leading(val); - } - } else { - // set given attribute on node - typeof ns === 'string' ? this.node.setAttributeNS(ns, attr, val.toString()) : this.node.setAttribute(attr, val.toString()); - } // rebuild if required + function getBox(cb) { + var box; + try { + box = cb(this.node); - if (this.rebuild && (attr === 'font-size' || attr === 'x')) { - this.rebuild(); + if (isNulledBox(box) && !domContains(this.node)) { + throw new Error('Element not in the dom'); + } + } catch (e) { + try { + var clone = this.clone(parser().svg).show(); + box = cb(clone.node); + clone.remove(); + } catch (e) { + console.warn('Getting a bounding box of this element is not possible'); } } - return this; + return box; } - registerMethods('Element', { - attr: attr + + registerMethods({ + Element: { + // Get bounding box + bbox: function bbox() { + return new Box$1(getBox.call(this, function (node) { + return node.getBBox(); + })); + }, + rbox: function rbox(el) { + var box = new Box$1(getBox.call(this, function (node) { + return node.getBoundingClientRect(); + })); + if (el) return box.transform(el.screenCTM().inverse()); + return box.addOffset(); + } + }, + viewbox: { + viewbox: function viewbox(x, y, width, height) { + // act as getter + if (x == null) return new Box$1(this.attr('viewBox')); // act as setter + + return this.attr('viewBox', new Box$1(x, y, width, height)); + } + } }); var Gradient = /*#__PURE__*/ - function (_Base) { - _inherits(Gradient, _Base); + function (_Container) { + _inherits(Gradient, _Container); function Gradient(type) { _classCallCheck(this, Gradient); @@ -2162,19 +2486,24 @@ var SVG = (function () { }, { key: "attr", - value: function attr$$1(a, b, c) { + value: function attr(a, b, c) { if (a === 'transform') a = 'gradientTransform'; - return attr.call(this, a, b, c); + return _get(_getPrototypeOf(Gradient.prototype), "attr", this).call(this, a, b, c); //return attr.call(this, a, b, c) } }, { key: "targets", value: function targets() { return find('svg [fill*="' + this.id() + '"]'); } + }, { + key: "bbox", + value: function bbox() { + return new Box$1(); + } }]); return Gradient; - }(Base); + }(Container$1); extend(Gradient, gradiented); registerMethods({ Container: { @@ -2194,8 +2523,8 @@ var SVG = (function () { var Pattern = /*#__PURE__*/ - function (_Base) { - _inherits(Pattern, _Base); + function (_Container) { + _inherits(Pattern, _Container); // Initialize node function Pattern(node) { @@ -2232,19 +2561,24 @@ var SVG = (function () { }, { key: "attr", - value: function attr$$1(a, b, c) { + value: function attr(a, b, c) { if (a === 'transform') a = 'patternTransform'; - return attr.call(this, a, b, c); + return _get(_getPrototypeOf(Pattern.prototype), "attr", this).call(this, a, b, c); //return attr.call(this, a, b, c) } }, { key: "targets", value: function targets() { return find('svg [fill*="' + this.id() + '"]'); } + }, { + key: "bbox", + value: function bbox() { + return new Box$1(); + } }]); return Pattern; - }(Base); + }(Container$1); registerMethods({ Container: { // Create pattern element in defs @@ -2256,157 +2590,20 @@ var SVG = (function () { pattern: function pattern(width, height, block) { return this.put(new Pattern()).update(block).attr({ x: 0, - y: 0, - width: width, - height: height, - patternUnits: 'userSpaceOnUse' - }); - } - } - }); - register(Pattern); - - var methods$1 = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove', 'mouseenter', 'mouseleave', 'touchstart', 'touchmove', 'touchleave', 'touchend', 'touchcancel'].reduce(function (last, event) { - // add event to Element - var fn = function fn(f) { - if (f === null) { - off(this, event); - } else { - on(this, event, f); - } - - return this; - }; - - last[event] = fn; - return last; - }, {}); - registerMethods('Element', methods$1); - var listenerId = 0; - - function getEventTarget$1(node) { - return node instanceof Base && node.is('EventTarget') ? node.getEventTarget() : node; - } // Add event binder in the SVG namespace - - - function on(node, events, listener, binding, options) { - var l = listener.bind(binding || node); - var n = getEventTarget$1(node); // events can be an array of events or a string of events - - events = Array.isArray(events) ? events : events.split(delimiter); // ensure instance object for nodes which are not adopted - - n.instance = n.instance || { - events: {} // pull event handlers from the element - - }; - var bag = n.instance.events; // add id to listener - - if (!listener._svgjsListenerId) { - listener._svgjsListenerId = ++listenerId; - } - - events.forEach(function (event) { - var ev = event.split('.')[0]; - var ns = event.split('.')[1] || '*'; // ensure valid object - - bag[ev] = bag[ev] || {}; - bag[ev][ns] = bag[ev][ns] || {}; // reference listener - - bag[ev][ns][listener._svgjsListenerId] = l; // add listener - - n.addEventListener(ev, l, options || false); - }); - } // Add event unbinder in the SVG namespace - - function off(node, events, listener, options) { - var n = getEventTarget$1(node); // we cannot remove an event if its not an svg.js instance - - if (!n.instance) return; // listener can be a function or a number - - if (typeof listener === 'function') { - listener = listener._svgjsListenerId; - if (!listener) return; - } // pull event handlers from the element - - - var bag = n.instance.events; // events can be an array of events or a string or undefined - - events = Array.isArray(events) ? events : (events || '').split(delimiter); - events.forEach(function (event) { - var ev = event && event.split('.')[0]; - var ns = event && event.split('.')[1]; - var namespace, l; - - if (listener) { - // remove listener reference - if (bag[ev] && bag[ev][ns || '*']) { - // removeListener - n.removeEventListener(ev, bag[ev][ns || '*'][listener], options || false); - delete bag[ev][ns || '*'][listener]; - } - } else if (ev && ns) { - // remove all listeners for a namespaced event - if (bag[ev] && bag[ev][ns]) { - for (l in bag[ev][ns]) { - off(n, [ev, ns].join('.'), l); - } - - delete bag[ev][ns]; - } - } else if (ns) { - // remove all listeners for a specific namespace - for (event in bag) { - for (namespace in bag[event]) { - if (ns === namespace) { - off(n, [event, ns].join('.')); - } - } - } - } else if (ev) { - // remove all listeners for the event - if (bag[ev]) { - for (namespace in bag[ev]) { - off(n, [ev, namespace].join('.')); - } - - delete bag[ev]; - } - } else { - // remove all listeners on a given node - for (event in bag) { - off(n, event); - } - - n.instance.events = {}; + y: 0, + width: width, + height: height, + patternUnits: 'userSpaceOnUse' + }); } - }); - } - function dispatch(node, event, data) { - var n = getEventTarget$1(node); // Dispatch event - - if (event instanceof window.Event) { - n.dispatchEvent(event); - } else { - event = new window.CustomEvent(event, { - detail: data, - cancelable: true - }); - n.dispatchEvent(event); } - - return event; - } - - var events = /*#__PURE__*/Object.freeze({ - on: on, - off: off, - dispatch: dispatch }); + register(Pattern); var Image = /*#__PURE__*/ - function (_Base) { - _inherits(Image, _Base); + function (_Shape) { + _inherits(Image, _Shape); function Image(node) { _classCallCheck(this, Image); @@ -2461,7 +2658,7 @@ var SVG = (function () { }]); return Image; - }(Base); + }(Shape); registerMethods({ Container: { // create image element, load image and set its size @@ -2472,6 +2669,110 @@ var SVG = (function () { }); register(Image); + var subClassArray = function () { + try { + // try es6 subclassing + return Function('name', 'baseClass', '_constructor', ['baseClass = baseClass || Array', 'return {', '[name]: class extends baseClass {', 'constructor (...args) {', 'super(...args)', '_constructor && _constructor.apply(this, args)', '}', '}', '}[name]'].join('\n')); + } catch (e) { + // Use es5 approach + return function (name) { + var baseClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Array; + + var _constructor = arguments.length > 2 ? arguments[2] : undefined; + + var Arr = function Arr() { + baseClass.apply(this, arguments); + _constructor && _constructor.apply(this, arguments); + }; + + Arr.prototype = Object.create(baseClass.prototype); + Arr.prototype.constructor = Arr; + return Arr; + }; + } + }(); + + var SVGArray = subClassArray('SVGArray', Array, function () { + this.init.apply(this, arguments); + }); + extend2(SVGArray, { + init: function init() { + //this.splice(0, this.length) + this.length = 0; + this.push.apply(this, _toConsumableArray(this.parse.apply(this, arguments))); + }, + toArray: function toArray() { + // const ret = [] + // ret.push(...this) + // return ret + return Array.prototype.concat.apply([], this); + }, + toString: function toString() { + return this.join(' '); + }, + // Flattens the array if needed + valueOf: function valueOf() { + var ret = []; + ret.push.apply(ret, _toConsumableArray(this)); + return ret; // return this.toArray() + }, + // Parse whitespace separated string + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + //array = array.valueOf() + // If already is an array, no need to parse it + if (array instanceof Array) return array; + return array.trim().split(delimiter).map(parseFloat); + }, + clone: function clone() { + return new this.constructor(this); + }, + toSet: function toSet() { + return new Set(this); + } + }); // export default class SVGArray extends BaseArray { + // constructor (...args) { + // super() + // this.init(...args) + // } + // + // init (array, fallback = []) { + // //this.splice(0, this.length) + // this.length = 0 + // this.push(...this.parse(array || fallback)) + // } + // + // toArray () { + // return [].concat(this) + // } + // + // toString () { + // return this.join(' ') + // } + // + // valueOf () { + // return this.toArray() + // } + // + // // Parse whitespace separated string + // parse (array) { + // array = array.valueOf() + // + // // if already is an array, no need to parse it + // if (Array.isArray(array)) return array + // + // return array.trim().split(delimiter).map(parseFloat) + // } + // + // clone () { + // return new this.constructor(this) + // } + // + // toSet () { + // return new Set(this) + // } + // } + var PointArray = subClassArray('PointArray', SVGArray); extend2(PointArray, { // Convert array to string @@ -2699,10 +3000,38 @@ var SVG = (function () { // } // } + var MorphArray = PointArray; // Move by left top corner over x-axis + + function x$1(x) { + return x == null ? this.bbox().x : this.move(x, this.bbox().y); + } // Move by left top corner over y-axis + + function y$1(y) { + return y == null ? this.bbox().y : this.move(this.bbox().x, y); + } // Set width of element + + function width$1(width) { + var b = this.bbox(); + return width == null ? b.width : this.size(width, b.height); + } // Set height of element + + function height$1(height) { + var b = this.bbox(); + return height == null ? b.height : this.size(b.width, height); + } + + var pointed = /*#__PURE__*/Object.freeze({ + MorphArray: MorphArray, + x: x$1, + y: y$1, + width: width$1, + height: height$1 + }); + var Line = /*#__PURE__*/ - function (_Base) { - _inherits(Line, _Base); + function (_Shape) { + _inherits(Line, _Shape); // Initialize node function Line(node) { @@ -2752,7 +3081,8 @@ var SVG = (function () { }]); return Line; - }(Base); + }(Shape); + extend(Line, pointed); registerMethods({ Container: { // Create a line element @@ -2771,8 +3101,8 @@ var SVG = (function () { var Marker = /*#__PURE__*/ - function (_Base) { - _inherits(Marker, _Base); + function (_Container) { + _inherits(Marker, _Container); // Initialize node function Marker(node) { @@ -2821,7 +3151,7 @@ var SVG = (function () { }]); return Marker; - }(Base); + }(Container$1); registerMethods({ Container: { marker: function marker(width, height, block) { @@ -2853,153 +3183,60 @@ var SVG = (function () { var Mask = /*#__PURE__*/ - function (_Base) { - _inherits(Mask, _Base); - - // Initialize node - function Mask(node) { - _classCallCheck(this, Mask); - - return _possibleConstructorReturn(this, _getPrototypeOf(Mask).call(this, nodeOrNew('mask', node), Mask)); - } // Unmask all masked elements and remove itself - - - _createClass(Mask, [{ - key: "remove", - value: function remove$$1() { - // unmask all targets - this.targets().forEach(function (el) { - el.unmask(); - }); // remove mask from parent - - return remove.call(this); - } - }, { - key: "targets", - value: function targets() { - return baseFind('svg [mask*="' + this.id() + '"]'); - } - }]); - - return Mask; - }(Base); - registerMethods({ - Container: { - mask: function mask() { - return this.defs().put(new Mask()); - } - }, - Element: { - // Distribute mask to svg element - maskWith: function maskWith(element) { - // use given mask or create a new one - var masker = element instanceof Mask ? element : this.parent().mask().add(element); // apply mask - - return this.attr('mask', 'url("#' + masker.id() + '")'); - }, - // Unmask element - unmask: function unmask() { - return this.attr('mask', null); - }, - masker: function masker() { - return this.reference('mask'); - } - } - }); - register(Mask); - - function parser() { - // Reuse cached element if possible - if (!parser.nodes) { - var svg = new Doc$1().size(2, 0).css({ - opacity: 0, - position: 'absolute', - left: '-100%', - top: '-100%', - overflow: 'hidden' - }); - var path = svg.path().node; - parser.nodes = { - svg: svg, - path: path - }; - } - - if (!parser.nodes.svg.node.parentNode) { - var b = document.body || document.documentElement; - parser.nodes.svg.addTo(b); - } - - return parser.nodes; - } - - var Point = - /*#__PURE__*/ - function () { - // Initialize - function Point(x, y, base) { - _classCallCheck(this, Point); - - var source; - base = base || { - x: 0, - y: 0 // ensure source as object - - }; - source = Array.isArray(x) ? { - x: x[0], - y: x[1] - } : _typeof(x) === 'object' ? { - x: x.x, - y: x.y - } : { - x: x, - y: y // merge source - - }; - this.x = source.x == null ? base.x : source.x; - this.y = source.y == null ? base.y : source.y; - } // Clone point + function (_Container) { + _inherits(Mask, _Container); + // Initialize node + function Mask(node) { + _classCallCheck(this, Mask); - _createClass(Point, [{ - key: "clone", - value: function clone() { - return new Point(this); - } // Convert to native SVGPoint + return _possibleConstructorReturn(this, _getPrototypeOf(Mask).call(this, nodeOrNew('mask', node), Mask)); + } // Unmask all masked elements and remove itself - }, { - key: "native", - value: function native() { - // create new point - var point = parser().svg.node.createSVGPoint(); // update with current values - point.x = this.x; - point.y = this.y; - return point; - } // transform point with matrix + _createClass(Mask, [{ + key: "remove", + value: function remove() { + // unmask all targets + this.targets().forEach(function (el) { + el.unmask(); + }); // remove mask from parent + return _get(_getPrototypeOf(Mask.prototype), "remove", this).call(this); //return remove.call(this) + } }, { - key: "transform", - value: function transform(m) { - // Perform the matrix multiplication - var x = m.a * this.x + m.c * this.y + m.e; - var y = m.b * this.x + m.d * this.y + m.f; // Return the required point - - return new Point(x, y); + key: "targets", + value: function targets() { + return baseFind('svg [mask*="' + this.id() + '"]'); } }]); - return Point; - }(); + return Mask; + }(Container$1); registerMethods({ + Container: { + mask: function mask() { + return this.defs().put(new Mask()); + } + }, Element: { - // Get point - point: function point(x, y) { - return new Point(x, y).transform(this.screenCTM().inverse()); + // Distribute mask to svg element + maskWith: function maskWith(element) { + // use given mask or create a new one + var masker = element instanceof Mask ? element : this.parent().mask().add(element); // apply mask + + return this.attr('mask', 'url("#' + masker.id() + '")'); + }, + // Unmask element + unmask: function unmask() { + return this.attr('mask', null); + }, + masker: function masker() { + return this.reference('mask'); } } }); + register(Mask); var PathArray = subClassArray('PathArray', SVGArray); var pathHandlers = { @@ -3488,8 +3725,8 @@ var SVG = (function () { var Path = /*#__PURE__*/ - function (_Base) { - _inherits(Path, _Base); + function (_Shape) { + _inherits(Path, _Shape); // Initialize node function Path(node) { @@ -3562,7 +3799,7 @@ var SVG = (function () { }]); return Path; - }(Base); // Define morphable array + }(Shape); // Define morphable array Path.prototype.MorphArray = PathArray; // Add parent method registerMethods({ @@ -3576,34 +3813,6 @@ var SVG = (function () { }); register(Path); - var MorphArray = PointArray; // Move by left top corner over x-axis - - function x$2(x) { - return x == null ? this.bbox().x : this.move(x, this.bbox().y); - } // Move by left top corner over y-axis - - function y$2(y) { - return y == null ? this.bbox().y : this.move(this.bbox().x, y); - } // Set width of element - - function width$2(width) { - var b = this.bbox(); - return width == null ? b.width : this.size(width, b.height); - } // Set height of element - - function height$2(height) { - var b = this.bbox(); - return height == null ? b.height : this.size(b.width, height); - } - - var pointed = /*#__PURE__*/Object.freeze({ - MorphArray: MorphArray, - x: x$2, - y: y$2, - width: width$2, - height: height$2 - }); - // Add polygon-specific functions function array() { @@ -3619,11 +3828,11 @@ var SVG = (function () { return this; } // Move by left top corner - function move$1(x, y) { + function move(x, y) { return this.attr('points', this.array().move(x, y)); } // Set element size to given width and height - function size$2(width, height) { + function size$1(width, height) { var p = proportionalSize(this, width, height); return this.attr('points', this.array().size(p.width, p.height)); } @@ -3632,14 +3841,14 @@ var SVG = (function () { array: array, plot: plot, clear: clear, - move: move$1, - size: size$2 + move: move, + size: size$1 }); var Polygon = /*#__PURE__*/ - function (_Base) { - _inherits(Polygon, _Base); + function (_Shape) { + _inherits(Polygon, _Shape); // Initialize node function Polygon(node) { @@ -3649,7 +3858,7 @@ var SVG = (function () { } return Polygon; - }(Base); + }(Shape); registerMethods({ Container: { // Create a wrapped polygon element @@ -3665,8 +3874,8 @@ var SVG = (function () { var Polyline = /*#__PURE__*/ - function (_Base) { - _inherits(Polyline, _Base); + function (_Shape) { + _inherits(Polyline, _Shape); // Initialize node function Polyline(node) { @@ -3676,7 +3885,7 @@ var SVG = (function () { } return Polyline; - }(Base); + }(Shape); registerMethods({ Container: { // Create a wrapped polygon element @@ -3692,18 +3901,33 @@ var SVG = (function () { var Rect = /*#__PURE__*/ - function (_Base) { - _inherits(Rect, _Base); + function (_Shape) { + _inherits(Rect, _Shape); // Initialize node function Rect(node) { _classCallCheck(this, Rect); return _possibleConstructorReturn(this, _getPrototypeOf(Rect).call(this, nodeOrNew('rect', node), Rect)); - } + } // FIXME: unify with circle + // Radius x value + + + _createClass(Rect, [{ + key: "rx", + value: function rx(_rx) { + return this.attr('rx', _rx); + } // Radius y value + + }, { + key: "ry", + value: function ry(_ry) { + return this.attr('ry', _ry); + } + }]); return Rect; - }(Base); + }(Shape); registerMethods({ Container: { // Create a rect element @@ -3716,8 +3940,8 @@ var SVG = (function () { var _Symbol = /*#__PURE__*/ - function (_Base) { - _inherits(_Symbol, _Base); + function (_Container) { + _inherits(_Symbol, _Container); // Initialize node function _Symbol(node) { @@ -3727,7 +3951,7 @@ var SVG = (function () { } return _Symbol; - }(Base); + }(Container$1); registerMethods({ Container: { symbol: function symbol() { @@ -3737,6 +3961,52 @@ var SVG = (function () { }); register(_Symbol); + function noop() {} // Default animation values + + var timeline = { + duration: 400, + ease: '>', + delay: 0 // Default attribute values + + }; + var attrs = { + // fill and stroke + 'fill-opacity': 1, + 'stroke-opacity': 1, + 'stroke-width': 0, + 'stroke-linejoin': 'miter', + 'stroke-linecap': 'butt', + fill: '#000000', + stroke: '#000000', + opacity: 1, + // position + x: 0, + y: 0, + cx: 0, + cy: 0, + // size + width: 0, + height: 0, + // radius + r: 0, + rx: 0, + ry: 0, + // gradient + offset: 0, + 'stop-opacity': 1, + 'stop-color': '#000000', + // text + 'font-size': 16, + 'font-family': 'Helvetica, Arial, sans-serif', + 'text-anchor': 'start' + }; + + var defaults = /*#__PURE__*/Object.freeze({ + noop: noop, + timeline: timeline, + attrs: attrs + }); + // Create plain text node function plain(text) { // clear if build mode is disabled @@ -3761,8 +4031,8 @@ var SVG = (function () { var Text = /*#__PURE__*/ - function (_Base) { - _inherits(Text, _Base); + function (_Parent) { + _inherits(Text, _Parent); // Initialize node function Text(node) { @@ -3929,7 +4199,7 @@ var SVG = (function () { }]); return Text; - }(Base); + }(Parent); extend(Text, textable); registerMethods({ Container: { @@ -4033,8 +4303,8 @@ var SVG = (function () { var Tspan = /*#__PURE__*/ - function (_Base) { - _inherits(Tspan, _Base); + function (_Parent) { + _inherits(Tspan, _Parent); // Initialize node function Tspan(node) { @@ -4077,7 +4347,7 @@ var SVG = (function () { }]); return Tspan; - }(Base); + }(Parent); extend(Tspan, textable); registerMethods({ Tspan: { @@ -4098,8 +4368,8 @@ var SVG = (function () { var Use = /*#__PURE__*/ - function (_Base) { - _inherits(Use, _Base); + function (_Shape) { + _inherits(Use, _Shape); function Use(node) { _classCallCheck(this, Use); @@ -4117,7 +4387,7 @@ var SVG = (function () { }]); return Use; - }(Base); + }(Shape); registerMethods({ Container: { // Create a use element @@ -4143,7 +4413,7 @@ var SVG = (function () { value: function init(source) { var base = arrayToMatrix([1, 0, 0, 1, 0, 0]); // ensure source as object - source = source instanceof Base && source.is('Element') ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? arrayToMatrix(source) : _typeof(source) === 'object' && isMatrixLike(source) ? source : _typeof(source) === 'object' ? new Matrix().transform(source) : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) : base; // Merge the source matrix with the base matrix + source = source instanceof Element ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? arrayToMatrix(source) : _typeof(source) === 'object' && isMatrixLike(source) ? source : _typeof(source) === 'object' ? new Matrix().transform(source) : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) : base; // Merge the source matrix with the base matrix this.a = source.a != null ? source.a : base.a; this.b = source.b != null ? source.b : base.b; @@ -4646,125 +4916,108 @@ var SVG = (function () { } }); - var Box$1 = + var Color = /*#__PURE__*/ function () { - function Box() { - _classCallCheck(this, Box); + function Color() { + _classCallCheck(this, Color); this.init.apply(this, arguments); } - _createClass(Box, [{ + _createClass(Color, [{ key: "init", - value: function init(source) { - var base = [0, 0, 0, 0]; - source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) : Array.isArray(source) ? source : _typeof(source) === 'object' ? [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] : arguments.length === 4 ? [].slice.call(arguments) : base; - this.x = source[0]; - this.y = source[1]; - this.width = source[2]; - this.height = source[3]; // add center, right, bottom... + value: function init(color, g, b) { + var match; // initialize defaults - fullBox(this); - } // Merge rect box with another, return a new instance + this.r = 0; + this.g = 0; + this.b = 0; + if (!color) return; // parse color + + if (typeof color === 'string') { + if (isRgb.test(color)) { + // get rgb values + match = rgb.exec(color.replace(whitespace, '')); // parse numeric values + + this.r = parseInt(match[1]); + this.g = parseInt(match[2]); + this.b = parseInt(match[3]); + } else if (isHex.test(color)) { + // get hex values + match = hex.exec(fullHex(color)); // parse numeric values + + this.r = parseInt(match[1], 16); + this.g = parseInt(match[2], 16); + this.b = parseInt(match[3], 16); + } + } else if (Array.isArray(color)) { + this.r = color[0]; + this.g = color[1]; + this.b = color[2]; + } else if (_typeof(color) === 'object') { + this.r = color.r; + this.g = color.g; + this.b = color.b; + } else if (arguments.length === 3) { + this.r = color; + this.g = g; + this.b = b; + } + } // Default to hex conversion - }, { - key: "merge", - value: function merge(box) { - var x = Math.min(this.x, box.x); - var y = Math.min(this.y, box.y); - var width = Math.max(this.x + this.width, box.x + box.width) - x; - var height = Math.max(this.y + this.height, box.y + box.height) - y; - return new Box(x, y, width, height); - } - }, { - key: "transform", - value: function transform(m) { - var xMin = Infinity; - var xMax = -Infinity; - var yMin = Infinity; - var yMax = -Infinity; - var pts = [new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2)]; - pts.forEach(function (p) { - p = p.transform(m); - xMin = Math.min(xMin, p.x); - xMax = Math.max(xMax, p.x); - yMin = Math.min(yMin, p.y); - yMax = Math.max(yMax, p.y); - }); - return new Box(xMin, yMin, xMax - xMin, yMax - yMin); - } - }, { - key: "addOffset", - value: function addOffset() { - // offset by window scroll position, because getBoundingClientRect changes when window is scrolled - this.x += window.pageXOffset; - this.y += window.pageYOffset; - return this; - } }, { key: "toString", value: function toString() { - return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height; + return this.toHex(); } }, { key: "toArray", value: function toArray() { - return [this.x, this.y, this.width, this.height]; - } - }]); - - return Box; - }(); + return [this.r, this.g, this.b]; + } // Build hex value - function getBox(cb) { - var box; + }, { + key: "toHex", + value: function toHex() { + return '#' + compToHex(Math.round(this.r)) + compToHex(Math.round(this.g)) + compToHex(Math.round(this.b)); + } // Build rgb value - try { - box = cb(this.node); + }, { + key: "toRgb", + value: function toRgb() { + return 'rgb(' + [this.r, this.g, this.b].join() + ')'; + } // Calculate true brightness - if (isNulledBox(box) && !domContains(this.node)) { - throw new Error('Element not in the dom'); - } - } catch (e) { - try { - var clone = this.clone(parser().svg).show(); - box = cb(clone.node); - clone.remove(); - } catch (e) { - throw e; - console.warn('Getting a bounding box of this element is not possible'); - } - } + }, { + key: "brightness", + value: function brightness() { + return this.r / 255 * 0.30 + this.g / 255 * 0.59 + this.b / 255 * 0.11; + } // Testers + // Test if given value is a color string - return box; - } + }], [{ + key: "test", + value: function test(color) { + color += ''; + return isHex.test(color) || isRgb.test(color); + } // Test if given value is a rgb object - registerMethods({ - Element: { - // Get bounding box - bbox: function bbox() { - return new Box$1(getBox.call(this, function (node) { - return node.getBBox(); - })); - }, - rbox: function rbox(el) { - var box = new Box$1(getBox.call(this, function (node) { - return node.getBoundingClientRect(); - })); - if (el) return box.transform(el.screenCTM().inverse()); - return box.addOffset(); - } - }, - viewbox: { - viewbox: function viewbox(x, y, width, height) { - // act as getter - if (x == null) return new Box$1(this.attr('viewBox')); // act as setter + }, { + key: "isRgb", + value: function isRgb$$1(color) { + return color && typeof color.r === 'number' && typeof color.g === 'number' && typeof color.b === 'number'; + } // Test if given value is a color - return this.attr('viewBox', new Box$1(x, y, width, height)); + }, { + key: "isColor", + value: function isColor(color) { + return this.isRgb(color) || this.test(color); } - } - }); + }]); + + return Color; + }(); /*** Base Class @@ -5054,9 +5307,9 @@ var SVG = (function () { } else if (type === 'string') { if (Color.isColor(value)) { this.type(Color); - } else if (regex.delimiter.test(value)) { - this.type(regex.pathLetters.test(value) ? PathArray : SVGArray); - } else if (regex.numberAndUnit.test(value)) { + } else if (delimiter.test(value)) { + this.type(pathLetters.test(value) ? PathArray : SVGArray); + } else if (numberAndUnit.test(value)) { this.type(SVGNumber); } else { this.type(NonMorphable); @@ -6479,6 +6732,11 @@ var SVG = (function () { // export {default as Use} from './Use.js' var Classes = /*#__PURE__*/Object.freeze({ + EventTarget: EventTarget, + Element: Element, + Shape: Shape, + Parent: Parent, + Container: Container$1, HtmlNode: HtmlNode, Doc: Doc$1, Defs: Defs, @@ -6523,53 +6781,96 @@ var SVG = (function () { Spring: Spring }); + function attr(attr, val, ns) { + // act as full getter + if (attr == null) { + // get an object of attributes + attr = {}; + val = this.node.attributes; + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = val[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var node = _step.value; + attr[node.nodeName] = isNumber.test(node.nodeValue) ? parseFloat(node.nodeValue) : node.nodeValue; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + return attr; + } else if (Array.isArray(attr)) ; else if (_typeof(attr) === 'object') { + // apply every attribute individually if an object is passed + for (val in attr) { + this.attr(val, attr[val]); + } + } else if (val === null) { + // remove value + this.node.removeAttribute(attr); + } else if (val == null) { + // act as a getter if the first and only argument is not an object + val = this.node.getAttribute(attr); + return val == null ? attrs[attr] // FIXME: do we need to return defaults? + : isNumber.test(val) ? parseFloat(val) : val; + } else { + // convert image fill and stroke to patterns + if (attr === 'fill' || attr === 'stroke') { + if (isImage.test(val)) { + val = this.doc().defs().image(val); + } + } // FIXME: This is fine, but what about the lines above? + // How does attr know about image()? - var containers = /*#__PURE__*/Object.freeze({ - Bare: Bare, - ClipPath: ClipPath, - Defs: Defs, - Doc: Doc$1, - Gradient: Gradient, - G: G, - A: A, - Marker: Marker, - Mask: Mask, - Pattern: Pattern, - Symbol: _Symbol, - Text: Text, - Tspan: Tspan, - TextPath: TextPath - }); + while (typeof val.attrHook == 'function') { + val = val.attrHook(this, attr); + } // ensure correct numeric values (also accepts NaN and Infinity) + if (typeof val === 'number') { + val = new SVGNumber(val); + } else if (Color.isColor(val)) { + // ensure full hex color + val = new Color(val); + } else if (val.constructor === Array) { + // Check for plain arrays and parse array values + val = new SVGArray(val); + } // if the passed attribute is leading... - var elements$1 = /*#__PURE__*/Object.freeze({ - Bare: Bare, - Circle: Circle, - ClipPath: ClipPath, - Defs: Defs, - Doc: Doc$1, - Ellipse: Ellipse, - Gradient: Gradient, - G: G, - HtmlNode: HtmlNode, - A: A, - Image: Image, - Line: Line, - Marker: Marker, - Mask: Mask, - Path: Path, - Pattern: Pattern, - Polygon: Polygon, - Polyline: Polyline, - Rect: Rect, - Stop: Stop, - Symbol: _Symbol, - Text: Text, - TextPath: TextPath, - Tspan: Tspan, - Use: Use + + if (attr === 'leading') { + // ... call the leading method instead + if (this.leading) { + this.leading(val); + } + } else { + // set given attribute on node + typeof ns === 'string' ? this.node.setAttributeNS(ns, attr, val.toString()) : this.node.setAttribute(attr, val.toString()); + } // rebuild if required + + + if (this.rebuild && (attr === 'font-size' || attr === 'x')) { + this.rebuild(); + } + } + + return this; + } + registerMethods('Element', { + attr: attr }); // ### This module adds backward / forward functionality to elements. @@ -6829,7 +7130,7 @@ var SVG = (function () { transform: transform }); - function setup$1(node) { + function setup(node) { this._memory = {}; } // Remember arbitrary data @@ -6870,7 +7171,7 @@ var SVG = (function () { forget: forget, memory: memory }); - registerConstructor('Memory', setup$1); + registerConstructor('Memory', setup); var sugar = { stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], @@ -6996,7 +7297,7 @@ var SVG = (function () { registerMethods('radius', { // Add x and y radius radius: function radius(x, y) { - var type = (this._target || this).type; + var type = (this._element || this).type; return type === 'radialGradient' || type === 'radialGradient' ? this.attr('r', new SVGNumber(x)) : this.rx(x).ry(y == null ? x : y); } }); @@ -7010,7 +7311,7 @@ var SVG = (function () { return new Point(this.node.getPointAtLength(length)); } }); - registerMethods(['Container', 'Runner'], { + registerMethods(['Parent', 'Runner'], { // Set font font: function font(a, v) { if (_typeof(a) === 'object') { @@ -7023,185 +7324,6 @@ var SVG = (function () { } }); - function setup$2() { - var node = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - this.events = node.events || {}; - } // Bind given event to listener - - function on$1(event, listener, binding, options) { - on(this, event, listener, binding, options); - - return this; - } // Unbind event from listener - - function off$1(event, listener) { - off(this, event, listener); - - return this; - } - function dispatch$1(event, data) { - return dispatch(this, event, data); - } // Fire given event - - function fire(event, data) { - this.dispatch(event, data); - return this; - } - registerMethods('EventTarget', { - on: on$1, - off: off$1, - dispatch: dispatch$1, - fire: fire - }); - registerConstructor('EventTarget', setup$2); - - function children() { - return map(this.node.children, function (node) { - return adopt(node); - }); - } // Add given element at a position - - function 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]); - } - - return this; - } // Basically does the same as `add()` but returns the added element instead - - function put(element, i) { - this.add(element, i); - return element.instance || element; - } // Checks if the given element is a child - - function has(element) { - return this.index(element) >= 0; - } // Gets index of given element - - function index(element) { - return [].slice.call(this.node.childNodes).indexOf(element.node); - } // Get a element at the given index - - function get(i) { - return adopt(this.node.childNodes[i]); - } // Get first child - - function first() { - return adopt(this.node.firstChild); - } // Get the last child - - function last() { - return adopt(this.node.lastChild); - } // Iterates over all children and invokes a given block - - function each(block, deep) { - var children = this.children(); - var i, il; - - for (i = 0, il = children.length; i < il; i++) { - if (children[i] instanceof Base) { - block.apply(children[i], [i, children]); - } - - if (deep && children[i] instanceof Base && children[i].is('Parent')) { - children[i].each(block, deep); - } - } - - return this; - } // Remove a given child - - function removeElement(element) { - this.node.removeChild(element.node); - return this; - } // Remove all elements in this container - - function clear$1() { - // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild); - } // remove defs reference - - - delete this._defs; - return this; - } // Import raw svg - - function svg$1(svg) { - var well, len; // act as a setter if svg is given - - if (svg) { - // create temporary holder - well = document.createElementNS(ns, 'svg'); // dump raw svg - - well.innerHTML = svg; // transplant nodes - - for (len = well.children.length; len--;) { - this.node.appendChild(well.firstElementChild); - } // otherwise act as a getter - - } else { - // write svgjs data to the dom - this.writeDataToDom(); - return this.node.outerHTML; - } - - return this; - } // write svgjs data to the dom - - function writeDataToDom$1() { - // dump variables recursively - this.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; - } - function flatten(parent) { - this.each(function () { - if (this.is('Parent')) return this.flatten(parent).ungroup(parent); - return this.toParent(parent); - }); // we need this so that Doc does not get removed - - this.node.firstElementChild || this.remove(); - return this; - } - function ungroup(parent) { - parent = parent || this.parent(); - this.each(function () { - return this.toParent(parent); - }); - this.remove(); - return this; - } - registerMethods('Container', { - children: children, - add: add, - put: put, - has: has, - index: index, - get: get, - first: first, - last: last, - each: each, - removeElement: removeElement, - clear: clear$1, - svg: svg$1, - writeDataToDom: writeDataToDom$1, - flatten: flatten, - ungroup: ungroup - }); - // import {extend} from './tools.js' var extend$1 = extend; extend$1([Doc$1, _Symbol, Image, Pattern, Marker], getMethodsFor('viewbox')); @@ -7211,23 +7333,11 @@ var SVG = (function () { extend$1(Defs, getMethodsFor('Defs')); extend$1([Text, Tspan], getMethodsFor('Tspan')); extend$1([Rect, Ellipse, Circle, Gradient], getMethodsFor('radius')); - var containerMethods = getMethodsFor('Container'); // FIXME: We need a container array - - for (var i$1 in containers) { - extend$1(containers[i$1], containerMethods); - } - - var elementMethods = getMethodsFor('Element'); - var eventTargetMethods = getMethodsFor('EventTarget'); - - for (var _i in elements$1) { - extend$1(elements$1[_i], elementMethods); - extend$1(elements$1[_i], eventTargetMethods); - extend$1(elements$1[_i], getConstructor('EventTarget')); - extend$1(elements$1[_i], getConstructor('Element')); - extend$1(elements$1[_i], getConstructor('Memory')); - } - + extend$1(EventTarget, getMethodsFor('EventTarget')); + extend$1(Element, getMethodsFor('Element')); + extend$1(Element, getMethodsFor('Parent')); + extend$1(Element, getConstructor('Memory')); + extend$1(Container$1, getMethodsFor('Container')); registerMorphableType([SVGNumber, Color, Box$1, Matrix, SVGArray, PointArray, PathArray]); makeMorphable(); // The main wrapping element @@ -7238,17 +7348,17 @@ var SVG = (function () { Object.assign(SVG, tools); Object.assign(SVG, adopter); SVG.utils = utils; - SVG.regex = regex$1; // satisfy tests, fix later + SVG.regex = regex; // satisfy tests, fix later SVG.get = SVG; SVG.find = baseFind; - Object.assign(SVG, ns$1); - SVG.Element = SVG.Parent = SVG.Shape = SVG.Container = Base; + Object.assign(SVG, ns$1); // import Base from './Base.js' SVG.easing = easing; Object.assign(SVG, events); SVG.TransformBag = TransformBag; SVG.ObjectBag = ObjectBag; SVG.NonMorphable = NonMorphable; SVG.parser = parser; + SVG.defaults = defaults; return SVG; diff --git a/dist/svg.min.js b/dist/svg.min.js index 81337c2..386a99a 100644 --- a/dist/svg.min.js +++ b/dist/svg.min.js @@ -1 +1 @@ -var SVG=function(){"use strict";function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function c(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;nn.x&&e>n.y&&t=e.time?e.run():kt.timeouts.push(e),e!==n););for(var i=null,r=kt.frames.last();i!==r&&(i=kt.frames.shift());)i.run();kt.transforms.forEach(function(t){t()}),kt.nextDraw=kt.timeouts.first()||kt.frames.first()?window.requestAnimationFrame(kt._draw):null}},Ot=function(t){function e(t){return c(this,e),a(this,u(e).call(this,H(t,"string"==typeof t?null:t),e))}return r(e,s),o(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function At(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function Ct(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function Mt(t){return null==t?this.attr("cx"):this.attr("cx",t)}function jt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function Tt(t){return null==t?2*this.rx():this.rx(new vt(t).divide(2))}function St(t){return null==t?2*this.ry():this.ry(new vt(t).divide(2))}function Et(t,e){var n=D(this,t,e);return this.rx(new vt(n.width).divide(2)).ry(new vt(n.height).divide(2))}tt(Ot),lt("Container",{element:function(t,e){return this.put(new Ot(t,e))}});var Nt=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:At,y:Ct,cx:Mt,cy:jt,width:Tt,height:St,size:Et}),Pt=function(t){function e(t){return c(this,e),a(this,u(e).call(this,H("circle",t),e))}return r(e,s),o(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Dt(t,e){var n,i=t.length,r=[];for(n=0;n",Vt=0,Ut={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},Qt=function(){function t(){c(this,t),this.init.apply(this,arguments)}return o(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?g.test(t)?(i=v.exec(t.replace(p,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):m.test(t)&&(i=d.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+P(Math.round(this.r))+P(Math.round(this.g))+P(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",m.test(t)||g.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}(),$t=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Re=function(){function t(){c(this,t)}return o(t,[{key:"done",value:function(){return!1}}]),t}(),qe=function(t){function n(t){var e;return c(this,n),(e=a(this,u(n).call(this))).ease=ze[t||Ht]||t,e}return r(n,Re),o(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),Le=function(t){function n(t){var e;return c(this,n),(e=a(this,u(n).call(this))).stepper=t,e}return r(n,Re),o(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Ie(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var Fe=function(t){function i(t,e){var n;return c(this,i),(n=a(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,Le),o(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i);this._lastTime=this._time;var s=this._isDeclarative;if(this.done=!s&&!r&&this._time>=i,n||s){this._initialise(n),this.transforms=new Ee;var u=this._run(s?t:e)}return this.done=this.done||u&&s,this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new qe(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;en.x&&e>n.y&&t=e.time?e.run():Pt.timeouts.push(e),e!==n););for(var i=null,r=Pt.frames.last();i!==r&&(i=Pt.frames.shift());)i.run();Pt.transforms.forEach(function(t){t()}),Pt.nextDraw=Pt.timeouts.first()||Pt.frames.first()?window.requestAnimationFrame(Pt._draw):null}},Dt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q(t,"string"==typeof t?null:t),e))}return r(e,At),a(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function zt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function Rt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function qt(t){return null==t?this.attr("cx"):this.attr("cx",t)}function Lt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function Ft(t){return null==t?2*this.rx():this.rx(new wt(t).divide(2))}function It(t){return null==t?2*this.ry():this.ry(new wt(t).divide(2))}function Xt(t,e){var n=R(this,t,e);return this.rx(new wt(n.width).divide(2)).ry(new wt(n.height).divide(2))}nt(Dt),lt("Container",{element:function(t,e){return this.put(new Dt(t,e))}});var Yt=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:zt,y:Rt,cx:qt,cy:Lt,width:Ft,height:It,size:Xt}),Ht=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("circle",t),e))}return r(e,jt),a(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Bt(t,e){return xt((e||document).querySelectorAll(t),function(t){return et(t)})}$(Ht,{x:zt,y:Rt,cx:qt,cy:Lt,width:Ft,height:It,size:Xt}),lt({Element:{circle:function(t){return this.put(new Ht).radius(new wt(t).divide(2)).move(0,0)}}}),nt(Ht),lt("Element",{find:function(t){return Bt(t,this.node)}});var Gt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("clipPath",t),e))}return r(e,Ct),a(e,[{key:"remove",value:function(){return this.targets().forEach(function(t){t.unclip()}),c(u(e.prototype),"remove",this).call(this)}},{key:"targets",value:function(){return Bt('svg [clip-path*="'+this.id()+'"]')}}]),e}();lt({Container:{clip:function(){return this.defs().put(new Gt)}},Element:{clipWith:function(t){var e=t instanceof Gt?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.id()+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}}),nt(Gt);var Vt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("a",t),e))}return r(e,Ct),a(e,[{key:"to",value:function(t){return this.attr("href",t,B)}},{key:"target",value:function(t){return this.attr("target",t)}}]),e}();lt({Container:{link:function(t){return this.put(new Vt).to(t)}},Element:{linkTo:function(t){var e=new Vt;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}}),nt(Vt);var Qt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("ellipse",t),e))}return r(e,jt),e}();$(Qt,Yt),lt("Container",{ellipse:function(t,e){return this.put(new Qt).size(t,e).move(0,0)}}),nt(Qt);var Ut=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("stop",t),e))}return r(e,bt),a(e,[{key:"update",value:function(t){return("number"==typeof t||t instanceof wt)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new wt(t.offset)),this}}]),e}();nt(Ut);var $t=Object.freeze({from:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({fx:new wt(t),fy:new wt(e)}):this.attr({x1:new wt(t),y1:new wt(e)})},to:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({cx:new wt(t),cy:new wt(e)}):this.attr({x2:new wt(t),y2:new wt(e)})}});function Jt(){if(!Jt.nodes){var t=(new Tt).size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"}),e=t.path().node;Jt.nodes={svg:t,path:e}}if(!Jt.nodes.svg.node.parentNode){var n=document.body||document.documentElement;Jt.nodes.svg.addTo(n)}return Jt.nodes}var Wt=function(){function r(t,e,n){var i;o(this,r),n=n||{x:0,y:0},i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"===l(t)?{x:t.x,y:t.y}:{x:t,y:e},this.x=null==i.x?n.x:i.x,this.y=null==i.y?n.y:i.y}return a(r,[{key:"clone",value:function(){return new r(this)}},{key:"native",value:function(){var t=Jt().svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t}},{key:"transform",value:function(t){return new r(t.a*this.x+t.c*this.y+t.e,t.b*this.x+t.d*this.y+t.f)}}]),r}();lt({Element:{point:function(t,e){return new Wt(t,e).transform(this.screenCTM().inverse())}}});var Zt=function(){function u(){o(this,u),this.init.apply(this,arguments)}return a(u,[{key:"init",value:function(t){var e;t="string"==typeof t?t.split(j).map(parseFloat):Array.isArray(t)?t:"object"===l(t)?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):[0,0,0,0],this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],null==(e=this).x&&(e.x=0,e.y=0,e.width=0,e.height=0),e.w=e.width,e.h=e.height,e.x2=e.x+e.width,e.y2=e.y+e.height,e.cx=e.x+e.width/2,e.cy=e.y+e.height/2}},{key:"merge",value:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new u(e,n,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-n)}},{key:"transform",value:function(e){var n=1/0,i=-1/0,r=1/0,s=-1/0;return[new Wt(this.x,this.y),new Wt(this.x2,this.y),new Wt(this.x,this.y2),new Wt(this.x2,this.y2)].forEach(function(t){t=t.transform(e),n=Math.min(n,t.x),i=Math.max(i,t.x),r=Math.min(r,t.y),s=Math.max(s,t.y)}),new u(n,r,i-n,s-r)}},{key:"addOffset",value:function(){return this.x+=window.pageXOffset,this.y+=window.pageYOffset,this}},{key:"toString",value:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}},{key:"toArray",value:function(){return[this.x,this.y,this.width,this.height]}}]),u}();function Kt(e){var n,t,i;try{if(n=e(this.node),!((i=n).w||i.h||i.x||i.y||(t=this.node,(document.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===document}).call(document.documentElement,t))))throw new Error("Element not in the dom")}catch(t){try{var r=this.clone(Jt().svg).show();n=e(r.node),r.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return n}lt({Element:{bbox:function(){return new Zt(Kt.call(this,function(t){return t.getBBox()}))},rbox:function(t){var e=new Zt(Kt.call(this,function(t){return t.getBoundingClientRect()}));return t?e.transform(t.screenCTM().inverse()):e.addOffset()}},viewbox:{viewbox:function(t,e,n,i){return null==t?new Zt(this.attr("viewBox")):this.attr("viewBox",new Zt(t,e,n,i))}}});var te=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q(t+"Gradient","string"==typeof t?null:t),i))}return r(i,Ct),a(i,[{key:"stop",value:function(t,e,n){return this.put(new Ut).update(t,e,n)}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="gradientTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new Zt}}]),i}();$(te,$t),lt({Container:{gradient:function(t,e){return this.defs().gradient(t,e)}},Defs:{gradient:function(t,e){return this.put(new te(t)).update(e)}}}),nt(te);var ee=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q("pattern",t),i))}return r(i,Ct),a(i,[{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="patternTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new Zt}}]),i}();lt({Container:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}},Defs:{pattern:function(t,e,n){return this.put(new ee).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}}),nt(ee);var ne=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("image",t),e))}return r(e,jt),a(e,[{key:"load",value:function(n,i){if(!n)return this;var r=new window.Image;return yt(r,"load",function(t){var e=this.parent(ee);0===this.width()&&0===this.height()&&this.size(r.width,r.height),e instanceof ee&&0===e.width()&&0===e.height()&&e.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:r.width,height:r.height,ratio:r.width/r.height,url:n})},this),yt(r,"load error",function(){vt(r)}),this.attr("href",r.src=n,B)}},{key:"attrHook",value:function(t){var e=this;return t.doc().defs().pattern(0,0,function(t){t.add(e)})}}]),e}();lt({Container:{image:function(t,e){return this.put(new ne).size(0,0).load(t,e)}}}),nt(ne);var ie=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1",delay:0},Oe={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},Ae=Object.freeze({noop:xe,timeline:_e,attrs:Oe});var je=Object.freeze({plain:function(t){return!1===this._build&&this.clear(),this.node.appendChild(document.createTextNode(t)),this},length:function(){return this.node.getComputedTextLength()}}),Ce=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this,Q("text",t),n))).dom.leading=new wt(1.3),e._rebuild=!0,e._build=!1,e.attr("font-family",Oe["font-family"]),e}return r(n,At),a(n,[{key:"x",value:function(t){return null==t?this.attr("x"):this.attr("x",t)}},{key:"y",value:function(t){var e=this.attr("y"),n="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-n:e:this.attr("y","number"==typeof t?t+n:t)}},{key:"cx",value:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)}},{key:"cy",value:function(t){return null==t?this.bbox().cy:this.y(t-this.bbox().height/2)}},{key:"text",value:function(t){if(void 0===t){var e=this.node.childNodes,n=0;t="";for(var i=0,r=e.length;i":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},ze=function(){function t(){o(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),Re=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).ease=De[t||_e.ease]||t,e}return r(n,ze),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),qe=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).stepper=t,e}return r(n,ze),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Le(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var Fe=function(t){function i(t,e){var n;return o(this,i),(n=h(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,qe),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i);this._lastTime=this._time;var s=this._isDeclarative;if(this.done=!s&&!r&&this._time>=i,n||s){this._initialise(n),this.transforms=new Ee;var u=this._run(s?t:e)}return this.done=this.done||u&&s,this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new Re(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e - diff --git a/spec/spec/array.js b/spec/spec/array.js index 2ec69dd..eeccdca 100644 --- a/spec/spec/array.js +++ b/spec/spec/array.js @@ -225,9 +225,9 @@ describe('PathArray', function () { var toBeTested = p3.size(600,200) - for(var i = toBeTested.legth; --i;) { + for(var i = toBeTested.length; i--;) { expect(toBeTested[i].shift().toUpperCase()).toBe(expected[i].shift().toUpperCase()) - for(var j = toBeTested[i].length; --j;) { + for(var j = toBeTested[i].length; j--;) { expect(toBeTested[i][j]).toBeCloseTo(expected[i][j]) } } diff --git a/spec/spec/bare.js b/spec/spec/bare.js index 0488bbd..5601a37 100644 --- a/spec/spec/bare.js +++ b/spec/spec/bare.js @@ -13,10 +13,10 @@ describe('Bare', function() { it('creates element in called parent', function() { expect(element.parent()).toBe(draw) }) - it('inherits from given parent', function() { - expect(draw.element('g', SVG.Container).rect).toBeTruthy() - expect(draw.element('g', SVG.Container).group).toBeTruthy() - }) + // it('inherits from given parent', function() { + // expect(draw.element('g', SVG.Container).rect).toBeTruthy() + // expect(draw.element('g', SVG.Container).group).toBeTruthy() + // }) }) describe('words()', function() { diff --git a/spec/spec/element.js b/spec/spec/element.js index f9b1ff0..7922946 100644 --- a/spec/spec/element.js +++ b/spec/spec/element.js @@ -883,16 +883,6 @@ describe('Element', function() { expect(draw.get(0+parserInDoc).get(1).type).toBe('circle') expect(draw.get(0+parserInDoc).get(1).attr('fill')).toBe('#ff0066') }) - it('does not import on single elements, even with an argument it acts as a getter', function() { - var rect = draw.rect(100,100).id(null) - , result = rect.svg('') - - expect( - result === '' - || result === '' - || result === '' - ).toBeTruthy() - }) }) }) diff --git a/spec/spec/event.js b/spec/spec/event.js index 6329151..83d173a 100644 --- a/spec/spec/event.js +++ b/spec/spec/event.js @@ -18,39 +18,40 @@ describe('Event', function() { toast = context = null }) - if (!this.isTouchDevice) { - [ 'click' - , 'dblclick' - , 'mousedown' - , 'mouseup' - , 'mouseover' - , 'mouseout' - , 'mousemove' - , 'mouseenter' - , 'mouseleave' - ].forEach(function(event) { - describe(event+'()', function() { - it('calls `on()` with '+event+' as event', function() { - rect[event](action) - expect(SVG.on).toHaveBeenCalledWith(rect, event, action) - }) - }) - }) - } else { - [ 'touchstart' - , 'touchmove' - , 'touchleave' - , 'touchend' - , 'touchcancel' - ].forEach(function(event) { - describe(event+'()', function() { - it('calls `on()` with '+event+' as event', function() { - rect[event](action) - expect(SVG.on).toHaveBeenCalledWith(rect, event, action) - }) - }) - }) - } + // FIXME: cannot be spied like that with es6 modules + // if (!this.isTouchDevice) { + // [ 'click' + // , 'dblclick' + // , 'mousedown' + // , 'mouseup' + // , 'mouseover' + // , 'mouseout' + // , 'mousemove' + // , 'mouseenter' + // , 'mouseleave' + // ].forEach(function(event) { + // describe(event+'()', function() { + // it('calls `on()` with '+event+' as event', function() { + // rect[event](action) + // expect(SVG.on).toHaveBeenCalledWith(rect, event, action) + // }) + // }) + // }) + // } else { + // [ 'touchstart' + // , 'touchmove' + // , 'touchleave' + // , 'touchend' + // , 'touchcancel' + // ].forEach(function(event) { + // describe(event+'()', function() { + // it('calls `on()` with '+event+' as event', function() { + // rect[event](action) + // expect(SVG.on).toHaveBeenCalledWith(rect, event, action) + // }) + // }) + // }) + // } describe('on()', function() { diff --git a/spec/spec/runner.js b/spec/spec/runner.js index c824eff..0f231a3 100644 --- a/spec/spec/runner.js +++ b/spec/spec/runner.js @@ -92,21 +92,22 @@ describe('SVG.Runner', function () { }) describe('constructors', function () { - describe('animate()', function () { - it('creates a runner with the element set and schedules it on the timeline', function () { - var orginalRunner = SVG.Runner - spyOn(SVG, 'Runner').and.callFake(function() { - return new orginalRunner() - }) - - var element = SVG('') - var runner = element.animate() - expect(SVG.Runner).toHaveBeenCalled(); - expect(runner instanceof SVG.Runner) - expect(runner.element()).toBe(element) - expect(runner.timeline()).toBe(element.timeline()) - }) - }) + // FIXME: Not possible to spy like this in es6 + // describe('animate()', function () { + // it('creates a runner with the element set and schedules it on the timeline', function () { + // var orginalRunner = SVG.Runner + // spyOn(SVG, 'Runner').and.callFake(function() { + // return new orginalRunner() + // }) + // + // var element = SVG('') + // var runner = element.animate() + // expect(SVG.Runner).toHaveBeenCalled(); + // expect(runner instanceof SVG.Runner) + // expect(runner.element()).toBe(element) + // expect(runner.timeline()).toBe(element.timeline()) + // }) + // }) describe('delay()', function () { it('calls animate with correct parameters', function () { diff --git a/spec/spec/svg.js b/spec/spec/svg.js index ea51703..6acbda4 100644 --- a/spec/spec/svg.js +++ b/spec/spec/svg.js @@ -28,7 +28,7 @@ describe('SVG', function() { expect(el instanceof SVG.HtmlNode).toBe(true) expect(el.node).toBe(wrapperHTML) }) - + it('creates new SVG.HtmlNode when called with css selector pointing to html node', function() { var el = SVG('#testDiv') expect(el instanceof SVG.HtmlNode).toBe(true) @@ -40,13 +40,13 @@ describe('SVG', function() { expect(doc instanceof SVG.Doc).toBe(true) expect(doc.node).toBe(wrapper) }) - + it('creates new SVG.Doc when called with css selector pointing to svg node', function() { var doc = SVG('#testSvg') expect(doc instanceof SVG.Doc).toBe(true) expect(doc.node).toBe(wrapper) }) - + it('adopts any SVGElement', function() { expect(SVG(rect) instanceof SVG.Rect).toBe(true) expect(SVG(rect).node).toBe(rect) @@ -64,11 +64,11 @@ describe('SVG', function() { it('creates SVG.Shape from any shape string', function() { var rect = SVG('') , circle = SVG('') - + expect(rect instanceof SVG.Rect).toBe(true) expect(rect.node.nodeName).toBe('rect') expect(rect.width()).toBe(200) - + expect(circle instanceof SVG.Circle).toBe(true) expect(circle.node.nodeName).toBe('circle') expect(circle.attr('r')).toBe(200) @@ -80,9 +80,9 @@ describe('SVG', function() { }) }) - describe('create()', function() { + describe('makeNode()', function() { it('creates an element with given node name and return it', function() { - var element = SVG.create('rect') + var element = SVG.makeNode('rect') expect(element.nodeName).toBe('rect') }) @@ -113,16 +113,16 @@ describe('SVG', function() { expect(typeof SVG.Path.prototype.soft).toBe('function') expect(draw.path().soft().attr('opacity')).toBe(0.5) }) - it('ignores non existant objects', function() { - SVG.extend([SVG.Rect, SVG.Bogus], { - soft: function() { - return this.opacity(0.3) - } - }) - - expect(typeof SVG.Rect.prototype.soft).toBe('function') - expect(draw.rect(100,100).soft().attr('opacity')).toBe(0.3) - expect(typeof SVG.Bogus).toBe('undefined') - }) + // it('ignores non existant objects', function() { + // SVG.extend([SVG.Rect, SVG.Bogus], { + // soft: function() { + // return this.opacity(0.3) + // } + // }) + // + // expect(typeof SVG.Rect.prototype.soft).toBe('function') + // expect(draw.rect(100,100).soft().attr('opacity')).toBe(0.3) + // expect(typeof SVG.Bogus).toBe('undefined') + // }) }) }) diff --git a/src/A.js b/src/A.js index eff76d2..02a4e0b 100644 --- a/src/A.js +++ b/src/A.js @@ -1,10 +1,10 @@ -import Base from './Base.js' +import Container from './Container.js' import {nodeOrNew} from './tools.js' import {xlink} from './namespaces.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class A extends Base{ +export default class A extends Container { constructor (node) { super(nodeOrNew('a', node), A) } diff --git a/src/ArrayPolyfill.js b/src/ArrayPolyfill.js index 9c3ee61..19c1ede 100644 --- a/src/ArrayPolyfill.js +++ b/src/ArrayPolyfill.js @@ -1,6 +1,5 @@ export const subClassArray = (function () { try { - //throw 'asdad' // try es6 subclassing return Function('name', 'baseClass', '_constructor', [ 'baseClass = baseClass || Array', diff --git a/src/Bare.js b/src/Bare.js index e0d8cdd..76aa3bf 100644 --- a/src/Bare.js +++ b/src/Bare.js @@ -1,14 +1,12 @@ import {nodeOrNew} from './tools.js' import {register} from './adopter.js' -import Base from './Base.js' +import Parent from './Parent.js' import {registerMethods} from './methods.js' import {extend} from './tools.js' - -export default class Bare extends Base { - constructor (node, inherit = {}) { +export default class Bare extends Parent { + constructor (node) { super(nodeOrNew(node, typeof node === 'string' ? null : node), Bare) - //extend(this, inherit) } words (text) { diff --git a/src/Base.js b/src/Base.js index 6b1242b..1e76bb4 100644 --- a/src/Base.js +++ b/src/Base.js @@ -1,11 +1,11 @@ export default class Base { - constructor (node, {extensions = []}) { - this.tags = [] - - for (let extension of extensions) { - extension.setup.call(this, node) - this.tags.push(extension.name) - } + constructor (node/*, {extensions = []}*/) { + // this.tags = [] + // + // for (let extension of extensions) { + // extension.setup.call(this, node) + // this.tags.push(extension.name) + // } } is (ability) { diff --git a/src/Box.js b/src/Box.js index 1cb46b0..0bf738e 100644 --- a/src/Box.js +++ b/src/Box.js @@ -98,7 +98,6 @@ function getBox(cb) { box = cb(clone.node) clone.remove() } catch (e) { - throw (e) console.warn('Getting a bounding box of this element is not possible') } } diff --git a/src/Circle.js b/src/Circle.js index d19b759..9d0c4db 100644 --- a/src/Circle.js +++ b/src/Circle.js @@ -1,11 +1,11 @@ -import Base from './Base.js' +import Shape from './Shape.js' import {nodeOrNew, extend} from './tools.js' import {x, y, cx, cy, width, height, size} from './circled.js' import SVGNumber from './SVGNumber.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class Circle extends Base { +export default class Circle extends Shape { constructor (node) { super(nodeOrNew('circle', node), Circle) } diff --git a/src/ClipPath.js b/src/ClipPath.js index 4989d6d..1801c67 100644 --- a/src/ClipPath.js +++ b/src/ClipPath.js @@ -1,11 +1,11 @@ -import Base from './Base.js' +import Container from './Container.js' import {nodeOrNew, extend} from './tools.js' import find from './selector.js' -import {remove} from './Element.js' +//import {remove} from './Element.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class ClipPath extends Base { +export default class ClipPath extends Container { constructor (node) { super(nodeOrNew('clipPath', node), ClipPath) } @@ -18,7 +18,8 @@ export default class ClipPath extends Base { }) // remove clipPath from parent - return remove.call(this) + return super.remove() + //return remove.call(this) } targets () { diff --git a/src/Container.js b/src/Container.js new file mode 100644 index 0000000..5d6dc43 --- /dev/null +++ b/src/Container.js @@ -0,0 +1,2 @@ +import Parent from './Parent.js' +export default class Container extends Parent {} diff --git a/src/Defs.js b/src/Defs.js index 68c5755..8cafb49 100644 --- a/src/Defs.js +++ b/src/Defs.js @@ -1,8 +1,8 @@ -import Base from './Base.js' +import Container from './Container.js' import {nodeOrNew} from './tools.js' import {register} from './adopter.js' -export default class Defs extends Base { +export default class Defs extends Container { constructor (node) { super(nodeOrNew('defs', node), Defs) } diff --git a/src/Doc.js b/src/Doc.js index b5e4ffd..3d8c18c 100644 --- a/src/Doc.js +++ b/src/Doc.js @@ -1,12 +1,12 @@ -import Base from './Base.js' +import Container from './Container.js' import Defs from './Defs.js' import { extend, nodeOrNew } from './tools.js' import { ns, xlink, xmlns, svgjs } from './namespaces.js' import {adopt, register} from './adopter.js' import {registerMethods} from './methods.js' -import {remove, parent, doc} from './Element.js' +//import {remove, parent, doc} from './Element.js' -export default class Doc extends Base { +export default class Doc extends Container { constructor(node) { super(nodeOrNew('svg', node), Doc) this.namespace() @@ -22,7 +22,8 @@ export default class Doc extends Base { // If not, call docs from this element doc() { if (this.isRoot()) return this - return doc.call(this) + return super.doc() + //return doc.call(this) } // Add namespaces @@ -50,21 +51,22 @@ export default class Doc extends Base { : adopt(this.node.parentNode) } - return parent.call(this, type) + return super.parent(type) + //return parent.call(this, type) } // Removes the doc from the DOM - remove() { - if (!this.isRoot()) { - return remove.call(this) - } - - if (this.parent()) { - this.parent().removeChild(this.node) - } - - return this - } + // remove() { + // if (!this.isRoot()) { + // return super.remove() + // } + // + // if (this.parent()) { + // this.parent().remove(this) + // } + // + // return this + // } clear() { // remove children diff --git a/src/Element.js b/src/Element.js index e8352a8..5e798ff 100644 --- a/src/Element.js +++ b/src/Element.js @@ -5,277 +5,283 @@ import {ns} from './namespaces.js' import SVGNumber from './SVGNumber.js' import {registerMethods} from './methods.js' import {registerConstructor} from './methods.js' +import EventTarget from './EventTarget.js' const Doc = getClass(root) -const HtmlNode = getClass('HtmlNode') -export const name = 'Element' +//export const name = 'Element' + +export default class Element extends EventTarget { + constructor (node) { + super() -export function setup (node) { // initialize data object - this.dom = {} + this.dom = {} // create circular reference - this.node = node + this.node = node - this.type = node.nodeName - this.node.instance = this + this.type = node.nodeName + this.node.instance = this - 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')) || {}) + 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')) || {}) + } } -} // Move over x-axis -export function x (x) { - return this.attr('x', x) -} + x (x) { + return this.attr('x', x) + } // Move over y-axis -export function y (y) { - return this.attr('y', y) -} + y (y) { + return this.attr('y', y) + } // Move by center over x-axis -export function 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 -export function cy (y) { - return y == null - ? this.y() + this.height() / 2 - : this.y(y - this.height() / 2) -} + cy (y) { + return y == null + ? this.y() + this.height() / 2 + : this.y(y - this.height() / 2) + } // Move element to given x and y values -export function move (x, y) { - return this.x(x).y(y) -} + move (x, y) { + return this.x(x).y(y) + } // Move element by its center -export function center (x, y) { - return this.cx(x).cy(y) -} + center (x, y) { + return this.cx(x).cy(y) + } // Set width of element -export function width (width) { - return this.attr('width', width) -} + width (width) { + return this.attr('width', width) + } // Set height of element -export function height (height) { - return this.attr('height', height) -} + height (height) { + return this.attr('height', height) + } // Set element size to given width and height -export function 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)) -} + return this + .width(new SVGNumber(p.width)) + .height(new SVGNumber(p.height)) + } // Clone element -export function clone (parent) { - // write dom data to the dom so the clone can pickup the data - this.writeDataToDom() + clone (parent) { + // write dom data to the dom so the clone can pickup the data + this.writeDataToDom() - // clone element and assign new id - let clone = assignNewId(this.node.cloneNode(true)) + // clone element and assign new id + let 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) + // insert the clone in the given parent or after myself + if (parent) parent.add(clone) + else this.after(clone) - return clone -} + return clone + } // Remove element -export function remove () { - if (this.parent()) { this.parent().removeElement(this) } + remove () { + if (this.parent()) { this.parent().removeElement(this) } - return this -} + return this + } // Replace element -export function replace (element) { - this.after(element).remove() + replace (element) { + this.after(element).remove() - return element -} + return element + } // Add element to given container and return self -export function addTo (parent) { - return makeInstance(parent).put(this) -} + addTo (parent) { + return makeInstance(parent).put(this) + } // Add element to given container and return container -export function putIn (parent) { - return makeInstance(parent).add(this) -} + putIn (parent) { + return makeInstance(parent).add(this) + } // Get / set id -export function id (id) { - // generate new id if no id set - if (typeof id === 'undefined' && !this.node.id) { - this.node.id = eid(this.type) + id (id) { + // generate new id if no id set + 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) } - // dont't set directly width this.node.id to make `null` work correctly - return this.attr('id', id) -} - // Checks whether the given point inside the bounding box of the element -export function inside (x, y) { - let box = this.bbox() + 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 + } // Return id on string conversion -export function toString () { - return this.id() -} + toString () { + return this.id() + } // Return array of classes on the node -export function classes () { - var attr = this.attr('class') - return attr == null ? [] : attr.trim().split(delimiter) -} + classes () { + var attr = this.attr('class') + return attr == null ? [] : attr.trim().split(delimiter) + } // Return true if class exists on the node, false otherwise -export function hasClass (name) { - return this.classes().indexOf(name) !== -1 -} + hasClass (name) { + return this.classes().indexOf(name) !== -1 + } // Add class to the node -export function addClass (name) { - if (!this.hasClass(name)) { - var array = this.classes() - array.push(name) - this.attr('class', array.join(' ')) + addClass (name) { + if (!this.hasClass(name)) { + var array = this.classes() + array.push(name) + this.attr('class', array.join(' ')) + } + + return this } - return this -} - // Remove class from the node -export function removeClass (name) { - if (this.hasClass(name)) { - this.attr('class', this.classes().filter(function (c) { - return c !== name - }).join(' ')) + removeClass (name) { + if (this.hasClass(name)) { + this.attr('class', this.classes().filter(function (c) { + return c !== name + }).join(' ')) + } + + return this } - return this -} - // Toggle the presence of a class on the node -export function toggleClass (name) { - return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) -} + toggleClass (name) { + return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) + } -// Get referenced element form attribute value -export function reference (attr) { - let id = idFromReference(this.attr(attr)) - return id ? makeInstance(id) : null -} + // Get referenced element form attribute value + reference (attr) { + let id = idFromReference(this.attr(attr)) + return id ? makeInstance(id) : null + } // Returns the parent element instance -export function parent (type) { - var parent = this + parent (type) { + var parent = this - // check for parent - if (!parent.node.parentNode) return null + // check for parent + if (!parent.node.parentNode) return null - // get parent element - parent = adopt(parent.node.parentNode) + // get parent element + 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 window.SVGElement) { - if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent - parent = adopt(parent.node.parentNode) + // loop trough ancestors if type is given + while (parent && parent.node instanceof window.SVGElement) { + if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent + parent = adopt(parent.node.parentNode) + } } -} -// Get parent document -export function doc () { - let p = this.parent(Doc) - return p && p.doc() -} + // Get parent document + doc () { + let p = this.parent(Doc) + return p && p.doc() + } // Get defs -export function defs () { - return this.doc().defs() -} + defs () { + return this.doc().defs() + } // return array of all ancestors of given type up to the root svg -export function parents (type) { - let parents = [] - let parent = this + parents (type) { + let parents = [] + let parent = this - do { - parent = parent.parent(type) - if (!parent || parent instanceof HtmlNode) break + do { + parent = parent.parent(type) + if (!parent || parent instanceof getClass('HtmlNode')) break - parents.push(parent) - } while (parent.parent) + parents.push(parent) + } while (parent.parent) - return parents -} + return parents + } // matches the element vs a css selector -export function matches (selector) { - return matcher(this.node, selector) -} + matches (selector) { + return matcher(this.node, selector) + } // Returns the svg node to call native svg methods on it -export function native () { - return this.node -} + native () { + return this.node + } // Import raw svg -export function svg () { - // write svgjs data to the dom - this.writeDataToDom() + svg () { + // write svgjs data to the dom + this.writeDataToDom() - return this.node.outerHTML -} + return this.node.outerHTML + } // write svgjs data to the dom -export function 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 + 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 } - return this -} // set given data to the elements data property -export function setData (o) { - this.dom = o - return this -} + setData (o) { + this.dom = o + return this + } -export function getEventTarget () { - return this.node + getEventTarget () { + return this.node + } } -registerMethods('Element', { - x, y, cx, cy, move, center, width, height, size, clone, remove, replace, - addTo, putIn, id, inside, toString, classes, hasClass, addClass, removeClass, - toggleClass, reference, doc, defs, parent, parents, matches, native, svg, - writeDataToDom, setData, getEventTarget -}) -registerConstructor('Element', setup) + +// registerMethods('Element', { +// x, y, cx, cy, move, center, width, height, size, clone, remove, replace, +// addTo, putIn, id, inside, toString, classes, hasClass, addClass, removeClass, +// toggleClass, reference, doc, defs, parent, parents, matches, native, svg, +// writeDataToDom, setData, getEventTarget +// }) +// +// registerConstructor('Element', setup) diff --git a/src/Ellipse.js b/src/Ellipse.js index b5bd436..21a1018 100644 --- a/src/Ellipse.js +++ b/src/Ellipse.js @@ -1,10 +1,10 @@ -import Base from './Base.js' +import Shape from './Shape.js' import * as circled from './circled.js' import {extend, nodeOrNew} from './tools.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class Ellipse extends Base { +export default class Ellipse extends Shape { constructor (node) { super(nodeOrNew('ellipse', node), Ellipse) } diff --git a/src/EventTarget.js b/src/EventTarget.js index 8702894..a72cafd 100644 --- a/src/EventTarget.js +++ b/src/EventTarget.js @@ -1,37 +1,71 @@ -import {on as _on, off as _off, dispatch as _dispatch} from './event.js' -import {registerMethods} from './methods.js' -import {registerConstructor} from './methods.js' +import Base from './Base.js' +import {on, off, dispatch} from './event.js' +import {extend} from './tools.js' -export const name = 'EventTarget' - -export function setup (node = {}) { - this.events = node.events || {} -} +export default class EventTarget extends Base{ + constructor (node = {}) { + super() + this.events = node.events || {} + } // Bind given event to listener -export function on (event, listener, binding, options) { - _on(this, event, listener, binding, options) - return this -} + on (event, listener, binding, options) { + on(this, event, listener, binding, options) + return this + } // Unbind event from listener -export function off (event, listener) { - _off(this, event, listener) - return this -} + off (event, listener) { + off(this, event, listener) + return this + } -export function dispatch (event, data) { - return _dispatch(this, event, data) -} + dispatch (event, data) { + return dispatch(this, event, data) + } // Fire given event -export function fire (event, data) { - this.dispatch(event, data) - return this + fire (event, data) { + this.dispatch(event, data) + return this + } } -registerMethods('EventTarget', { - on, off, dispatch, fire -}) -registerConstructor('EventTarget', setup) +// Add events to elements +const methods = [ 'click', + 'dblclick', + 'mousedown', + 'mouseup', + 'mouseover', + 'mouseout', + 'mousemove', + 'mouseenter', + 'mouseleave', + 'touchstart', + 'touchmove', + 'touchleave', + 'touchend', + 'touchcancel' ].reduce(function (last, event) { + // add event to Element + const fn = function (f) { + if (f === null) { + off(this, event) + } else { + on(this, event, f) + } + return this + } + + last[event] = fn + return last + }, {}) + +extend(EventTarget, methods) + + +// registerMethods('EventTarget', { +// on, off, dispatch, fire +// }) +// +// registerConstructor('EventTarget', setup) diff --git a/src/G.js b/src/G.js index 58962e0..d20aba2 100644 --- a/src/G.js +++ b/src/G.js @@ -1,9 +1,9 @@ -import Base from './Base.js' +import Container from './Container.js' import {nodeOrNew} from './tools.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class G extends Base { +export default class G extends Container { constructor (node) { super(nodeOrNew('g', node), G) } diff --git a/src/Gradient.js b/src/Gradient.js index e6aa362..0f20173 100644 --- a/src/Gradient.js +++ b/src/Gradient.js @@ -1,12 +1,13 @@ import Stop from './Stop.js' -import Base from './Base.js' +import Container from './Container.js' import * as gradiented from './gradiented.js' import {nodeOrNew, extend} from './tools.js' -import attr from './attr.js' +//import attr from './attr.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' +import Box from './Box.js' -export default class Gradient extends Base { +export default class Gradient extends Container { constructor (type) { super( nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type), @@ -45,12 +46,17 @@ export default class Gradient extends Base { // custom attr to handle transform attr (a, b, c) { if (a === 'transform') a = 'gradientTransform' - return attr.call(this, a, b, c) + return super.attr(a, b, c) + //return attr.call(this, a, b, c) } targets () { return find('svg [fill*="' + this.id() + '"]') } + + bbox () { + return new Box() + } } extend(Gradient, gradiented) diff --git a/src/HtmlNode.js b/src/HtmlNode.js index 8488edf..258c0ec 100644 --- a/src/HtmlNode.js +++ b/src/HtmlNode.js @@ -1,8 +1,8 @@ import {makeInstance} from './adopter.js' -import Base from './Base.js' +import Parent from './Parent.js' import {register} from './adopter.js' -export default class HtmlNode extends Base { +export default class HtmlNode extends Parent { constructor (element) { super(element, HtmlNode) this.node = element @@ -23,6 +23,11 @@ export default class HtmlNode extends Base { return element } + removeElement (element) { + this.node.removeChild(element.node) + return this + } + getEventTarget () { return this.node } diff --git a/src/Image.js b/src/Image.js index 69eede5..ea46a57 100644 --- a/src/Image.js +++ b/src/Image.js @@ -1,4 +1,4 @@ -import Base from './Base.js' +import Shape from './Shape.js' import Pattern from './Pattern.js' import {on, off} from './event.js' import {nodeOrNew} from './tools.js' @@ -6,7 +6,7 @@ import {xlink} from './namespaces.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class Image extends Base { +export default class Image extends Shape { constructor (node) { super(nodeOrNew('image', node), Image) } diff --git a/src/Line.js b/src/Line.js index 550c0de..660b4f5 100644 --- a/src/Line.js +++ b/src/Line.js @@ -1,11 +1,12 @@ import {proportionalSize} from './helpers.js' -import {nodeOrNew} from './tools.js' +import {nodeOrNew, extend} from './tools.js' import PointArray from './PointArray.js' -import Base from './Base.js' +import Shape from './Shape.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' +import * as pointed from './pointed.js' -export default class Line extends Base { +export default class Line extends Shape { // Initialize node constructor (node) { super(nodeOrNew('line', node), Line) @@ -42,9 +43,10 @@ export default class Line extends Base { var p = proportionalSize(this, width, height) return this.attr(this.array().size(p.width, p.height).toLine()) } - } +extend(Line, pointed) + registerMethods({ Container: { // Create a line element diff --git a/src/Marker.js b/src/Marker.js index 403a387..df19f20 100644 --- a/src/Marker.js +++ b/src/Marker.js @@ -1,9 +1,9 @@ -import Base from './Base.js' +import Container from './Container.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' import {nodeOrNew} from './tools.js' -export default class Marker extends Base { +export default class Marker extends Container { // Initialize node constructor (node) { super(nodeOrNew('marker', node), Marker) diff --git a/src/Mask.js b/src/Mask.js index b61c336..40ebce7 100644 --- a/src/Mask.js +++ b/src/Mask.js @@ -1,11 +1,11 @@ -import Base from './Base.js' +import Container from './Container.js' import {nodeOrNew} from './tools.js' import find from './selector.js' -import {remove} from './Element.js' +//import {remove} from './Element.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class Mask extends Base { +export default class Mask extends Container { // Initialize node constructor (node) { super(nodeOrNew('mask', node), Mask) @@ -19,7 +19,8 @@ export default class Mask extends Base { }) // remove mask from parent - return remove.call(this) + return super.remove() + //return remove.call(this) } targets () { diff --git a/src/Matrix.js b/src/Matrix.js index b0a6c48..e6d3da0 100644 --- a/src/Matrix.js +++ b/src/Matrix.js @@ -3,7 +3,7 @@ import Point from './Point.js' import {delimiter} from './regex.js' import {radians} from './utils.js' import parser from './parser.js' -import Base from './Base.js' +import Element from './Element.js' import {registerMethods} from './methods.js' export default class Matrix { @@ -16,7 +16,7 @@ export default class Matrix { var base = arrayToMatrix([1, 0, 0, 1, 0, 0]) // ensure source as object - source = source instanceof Base && source.is('Element') ? source.matrixify() + source = source instanceof Element ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? arrayToMatrix(source) : (typeof source === 'object' && isMatrixLike(source)) ? source diff --git a/src/Morphable.js b/src/Morphable.js index d927733..18f5a3b 100644 --- a/src/Morphable.js +++ b/src/Morphable.js @@ -7,6 +7,7 @@ import PointArray from './PointArray.js' import PathArray from './PathArray.js' import Box from './Box.js' import Matrix from './Matrix.js' +import {delimiter, pathLetters, numberAndUnit} from './regex.js' export default class Morphable { constructor (stepper) { @@ -58,12 +59,12 @@ export default class Morphable { } else if (type === 'string') { if (Color.isColor(value)) { this.type(Color) - } else if (regex.delimiter.test(value)) { - this.type(regex.pathLetters.test(value) + } else if (delimiter.test(value)) { + this.type(pathLetters.test(value) ? PathArray : SVGArray ) - } else if (regex.numberAndUnit.test(value)) { + } else if (numberAndUnit.test(value)) { this.type(SVGNumber) } else { this.type(NonMorphable) diff --git a/src/Parent.js b/src/Parent.js index a52b000..6786329 100644 --- a/src/Parent.js +++ b/src/Parent.js @@ -1,166 +1,169 @@ import {makeInstance, adopt} from './adopter.js' import {map} from './utils.js' import {registerMethods} from './methods.js' -import Base from './Base.js' +import Element from './Element.js' import {ns} from './namespaces.js' -// Returns all child elements -export function children () { - return map(this.node.children, function (node) { - return adopt(node) - }) -} +export default class Parent extends Element { + // Returns all child elements + children () { + return map(this.node.children, function (node) { + return adopt(node) + }) + } -// Add given element at a position -export function add (element, i) { - element = makeInstance(element) + // Add given element at a position + 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 } - return this -} + // Basically does the same as `add()` but returns the added element instead + put (element, i) { + this.add(element, i) + return element.instance || element + } -// Basically does the same as `add()` but returns the added element instead -export function put (element, i) { - this.add(element, i) - return element.instance || element -} + // Checks if the given element is a child + has (element) { + return this.index(element) >= 0 + } -// Checks if the given element is a child -export function has (element) { - return this.index(element) >= 0 -} + // Gets index of given element + index (element) { + return [].slice.call(this.node.childNodes).indexOf(element.node) + } -// Gets index of given element -export function index (element) { - return [].slice.call(this.node.childNodes).indexOf(element.node) -} + // Get a element at the given index + get (i) { + return adopt(this.node.childNodes[i]) + } -// Get a element at the given index -export function get (i) { - return adopt(this.node.childNodes[i]) -} + // Get first child + first () { + return adopt(this.node.firstChild) + } -// Get first child -export function first () { - return adopt(this.node.firstChild) -} + // Get the last child + last () { + return adopt(this.node.lastChild) + } -// Get the last child -export function last () { - return adopt(this.node.lastChild) -} + // Iterates over all children and invokes a given block + each (block, deep) { + var children = this.children() + var i, il -// Iterates over all children and invokes a given block -export function each (block, deep) { - var children = this.children() - var i, il + for (i = 0, il = children.length; i < il; i++) { + if (children[i] instanceof Element) { + block.apply(children[i], [i, children]) + } - for (i = 0, il = children.length; i < il; i++) { - if (children[i] instanceof Base) { - block.apply(children[i], [i, children]) + if (deep && (children[i] instanceof Parent)) { + children[i].each(block, deep) + } } - if (deep && (children[i] instanceof Base && children[i].is('Parent'))) { - children[i].each(block, deep) - } + return this } - return this -} + // Remove a given child + removeElement (element) { + this.node.removeChild(element.node) -// Remove a given child -export function removeElement (element) { - this.node.removeChild(element.node) + return this + } - return this -} + // Remove all elements in this container + clear () { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild) + } + + // remove defs reference + delete this._defs -// Remove all elements in this container -export function clear () { - // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) + return this } - // remove defs reference - delete this._defs + // Import raw svg + svg (svg) { + var well, len - return this -} + // act as a setter if svg is given + if (svg) { + // create temporary holder + well = document.createElementNS(ns, 'svg') + // dump raw svg + well.innerHTML = svg -// Import raw svg -export function svg (svg) { - var well, len + // transplant nodes + for (len = well.children.length; len--;) { + this.node.appendChild(well.firstElementChild) + } - // act as a setter if svg is given - if (svg) { - // create temporary holder - well = document.createElementNS(ns, 'svg') - // dump raw svg - well.innerHTML = svg + // otherwise act as a getter + } else { + // write svgjs data to the dom + this.writeDataToDom() - // transplant nodes - for (len = well.children.length; len--;) { - this.node.appendChild(well.firstElementChild) + return this.node.outerHTML } - // otherwise act as a getter - } else { - // write svgjs data to the dom - this.writeDataToDom() - - return this.node.outerHTML + return this } - return this -} - -// write svgjs data to the dom -export function writeDataToDom () { - // dump variables recursively - this.each(function () { - this.writeDataToDom() - }) + // write svgjs data to the dom + writeDataToDom () { + // dump variables recursively + this.each(function () { + this.writeDataToDom() + }) - // remove previously set data - this.node.removeAttribute('svgjs:data') + // 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 + if (Object.keys(this.dom).length) { + this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)) // see #428 + } + return this } - return this -} -export function flatten (parent) { - this.each(function () { - if (this.is('Parent')) return this.flatten(parent).ungroup(parent) - return this.toParent(parent) - }) + flatten (parent) { + this.each(function () { + if (this instanceof Parent) return this.flatten(parent).ungroup(parent) + return this.toParent(parent) + }) - // we need this so that Doc does not get removed - this.node.firstElementChild || this.remove() + // we need this so that Doc does not get removed + this.node.firstElementChild || this.remove() - return this -} + return this + } -export function ungroup (parent) { - parent = parent || this.parent() + ungroup (parent) { + parent = parent || this.parent() - this.each(function () { - return this.toParent(parent) - }) + this.each(function () { + return this.toParent(parent) + }) - this.remove() + this.remove() - return this + return this + } } -registerMethods('Container', { - children, add, put, has, index, get, first, last, each, - removeElement, clear, svg, writeDataToDom, flatten, ungroup -}) + +// registerMethods('Container', { +// children, add, put, has, index, get, first, last, each, +// removeElement, clear, svg, writeDataToDom, flatten, ungroup +// }) diff --git a/src/Path.js b/src/Path.js index 7ed3c13..42ab411 100644 --- a/src/Path.js +++ b/src/Path.js @@ -1,12 +1,12 @@ import {proportionalSize} from './helpers.js' import {nodeOrNew} from './tools.js' -import Base from './Base.js' +import Shape from './Shape.js' import PathArray from './PathArray.js' import find from './selector.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class Path extends Base { +export default class Path extends Shape { // Initialize node constructor (node) { super(nodeOrNew('path', node), Path) diff --git a/src/Pattern.js b/src/Pattern.js index 2c61baf..0c26d79 100644 --- a/src/Pattern.js +++ b/src/Pattern.js @@ -1,10 +1,11 @@ -import Base from './Base.js' +import Container from './Container.js' import {nodeOrNew} from './tools.js' -import attr from './attr.js' +//import attr from './attr.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' +import Box from './Box.js' -export default class Pattern extends Base { +export default class Pattern extends Container { // Initialize node constructor (node) { super(nodeOrNew('pattern', node), Pattern) @@ -36,12 +37,17 @@ export default class Pattern extends Base { // custom attr to handle transform attr (a, b, c) { if (a === 'transform') a = 'patternTransform' - return attr.call(this, a, b, c) + return super.attr(a, b, c) + //return attr.call(this, a, b, c) } targets () { return find('svg [fill*="' + this.id() + '"]') } + + bbox () { + return new Box() + } } registerMethods({ diff --git a/src/Polygon.js b/src/Polygon.js index 69337e3..1272e44 100644 --- a/src/Polygon.js +++ b/src/Polygon.js @@ -1,5 +1,5 @@ import {proportionalSize} from './helpers.js' -import Base from './Base.js' +import Shape from './Shape.js' import {nodeOrNew, extend} from './tools.js' import * as pointed from './pointed.js' import * as poly from './poly.js' @@ -7,7 +7,7 @@ import PointArray from './PointArray.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class Polygon extends Base { +export default class Polygon extends Shape { // Initialize node constructor (node) { super(nodeOrNew('polygon', node), Polygon) diff --git a/src/Polyline.js b/src/Polyline.js index 4fad379..d651abd 100644 --- a/src/Polyline.js +++ b/src/Polyline.js @@ -1,4 +1,4 @@ -import Base from './Base.js' +import Shape from './Shape.js' import {nodeOrNew, extend} from './tools.js' import PointArray from './PointArray.js' import * as pointed from './pointed.js' @@ -6,7 +6,7 @@ import * as poly from './poly.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class Polyline extends Base { +export default class Polyline extends Shape { // Initialize node constructor (node) { super(nodeOrNew('polyline', node), Polyline) diff --git a/src/Rect.js b/src/Rect.js index 037064c..232f591 100644 --- a/src/Rect.js +++ b/src/Rect.js @@ -1,13 +1,24 @@ -import Base from './Base.js' +import Shape from './Shape.js' import {nodeOrNew, extend} from './tools.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class Rect extends Base { +export default class Rect extends Shape { // Initialize node constructor (node) { super(nodeOrNew('rect', node), Rect) } + + // FIXME: unify with circle + // Radius x value + rx (rx) { + return this.attr('rx', rx) + } + + // Radius y value + ry (ry) { + return this.attr('ry', ry) + } } registerMethods({ diff --git a/src/SVGArray.js b/src/SVGArray.js index bb98aad..5927945 100644 --- a/src/SVGArray.js +++ b/src/SVGArray.js @@ -17,19 +17,22 @@ extend2(SVGArray, { }, toArray () { - const ret = [] - ret.push(...this) - //Array.prototype.push.apply(ret, this) - return ret - //return Array.prototype.concat.apply([], this) + // const ret = [] + // ret.push(...this) + // return ret + return Array.prototype.concat.apply([], this) }, toString () { return this.join(' ') }, + // Flattens the array if needed valueOf () { - return this.toArray() + const ret = [] + ret.push(...this) + return ret + // return this.toArray() }, // Parse whitespace separated string diff --git a/src/Shape.js b/src/Shape.js new file mode 100644 index 0000000..bf4ae8f --- /dev/null +++ b/src/Shape.js @@ -0,0 +1,2 @@ +import Parent from './Parent.js' +export default class Shape extends Parent {} diff --git a/src/Stop.js b/src/Stop.js index 0cd21e6..7db6027 100644 --- a/src/Stop.js +++ b/src/Stop.js @@ -1,9 +1,9 @@ -import Base from './Base.js' +import Element from './Element.js' import SVGNumber from './SVGNumber.js' import {nodeOrNew} from './tools.js' import {register} from './adopter.js' -export default class Stop extends Base { +export default class Stop extends Element { constructor (node) { super(nodeOrNew('stop', node), Stop) } diff --git a/src/Symbol.js b/src/Symbol.js index fbd4f3b..22d85da 100644 --- a/src/Symbol.js +++ b/src/Symbol.js @@ -1,9 +1,9 @@ -import Base from './Base.js' +import Container from './Container.js' import {nodeOrNew} from './tools.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -export default class Symbol extends Base { +export default class Symbol extends Container { // Initialize node constructor (node) { super(nodeOrNew('symbol', node), Symbol) diff --git a/src/Text.js b/src/Text.js index 02a601b..239b429 100644 --- a/src/Text.js +++ b/src/Text.js @@ -1,4 +1,4 @@ -import Base from './Base.js' +import Parent from './Parent.js' import SVGNumber from './SVGNumber.js' import {nodeOrNew, extend} from './tools.js' import {attrs} from './defaults.js' @@ -6,7 +6,7 @@ import * as textable from './textable.js' import {register, adopt} from './adopter.js' import {registerMethods} from './methods.js' -export default class Text extends Base { +export default class Text extends Parent { // Initialize node constructor (node) { super(nodeOrNew('text', node), Text) diff --git a/src/Tspan.js b/src/Tspan.js index e2e14e3..677adf4 100644 --- a/src/Tspan.js +++ b/src/Tspan.js @@ -1,11 +1,11 @@ -import Base from './Base.js' +import Parent from './Parent.js' import {nodeOrNew, extend} from './tools.js' import * as textable from './textable.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' import Text from './Text.js' -export default class Tspan extends Base { +export default class Tspan extends Parent { // Initialize node constructor (node) { super(nodeOrNew('tspan', node), Tspan) diff --git a/src/Use.js b/src/Use.js index 697ed03..7769929 100644 --- a/src/Use.js +++ b/src/Use.js @@ -1,10 +1,10 @@ -import Base from './Base.js' +import Shape from './Shape.js' import {xlink} from './namespaces.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' import {nodeOrNew} from './tools.js' -export default class Use extends Base { +export default class Use extends Shape { constructor (node) { super(nodeOrNew('use', node), Use) } diff --git a/src/classes.js b/src/classes.js index 7241d90..8385c20 100644 --- a/src/classes.js +++ b/src/classes.js @@ -1,3 +1,8 @@ +export {default as EventTarget} from './EventTarget.js' +export {default as Element} from './Element.js' +export {default as Shape} from './Shape.js' +export {default as Parent} from './Parent.js' +export {default as Container} from './Container.js' export {default as HtmlNode} from './HtmlNode.js' export {default as Doc} from './Doc.js' export {default as Defs} from './Defs.js' diff --git a/src/event.js b/src/event.js index 9fa99e1..acc4dd6 100644 --- a/src/event.js +++ b/src/event.js @@ -1,42 +1,10 @@ -import Base from './Base.js' import {delimiter} from './regex.js' import {registerMethods} from './methods.js' -// Add events to elements -const methods = [ 'click', - 'dblclick', - 'mousedown', - 'mouseup', - 'mouseover', - 'mouseout', - 'mousemove', - 'mouseenter', - 'mouseleave', - 'touchstart', - 'touchmove', - 'touchleave', - 'touchend', - 'touchcancel' ].reduce(function (last, event) { - // add event to Element - const fn = function (f) { - if (f === null) { - off(this, event) - } else { - on(this, event, f) - } - return this - } - - last[event] = fn - return last - }, {}) - -registerMethods('Element', methods) - let listenerId = 0 function getEventTarget (node) { - return node instanceof Base && node.is('EventTarget') + return typeof node.getEventTarget === 'function' ? node.getEventTarget() : node } diff --git a/src/pointed.js b/src/pointed.js index 11df4f3..d5deaf1 100644 --- a/src/pointed.js +++ b/src/pointed.js @@ -1,6 +1,6 @@ import PointArray from './PointArray.js' -export let MorphArray = PointArray +export let MorphArray = PointArray // Move by left top corner over x-axis export function x (x) { diff --git a/src/selector.js b/src/selector.js index fcd7363..973787d 100644 --- a/src/selector.js +++ b/src/selector.js @@ -37,4 +37,4 @@ export function find (query) { return baseFind(query, this.node) } -registerMethods('Container', {find}) +registerMethods('Element', {find}) diff --git a/src/sugar.js b/src/sugar.js index 9a075a0..e5d6b61 100644 --- a/src/sugar.js +++ b/src/sugar.js @@ -122,7 +122,7 @@ registerMethods(['Element', 'Runner'], { registerMethods('radius', { // Add x and y radius radius: function (x, y) { - var type = (this._target || this).type + var type = (this._element || this).type return type === 'radialGradient' || type === 'radialGradient' ? this.attr('r', new SVGNumber(x)) : this.rx(x).ry(y == null ? x : y) @@ -140,7 +140,7 @@ registerMethods('Path', { } }) -registerMethods(['Container', 'Runner'], { +registerMethods(['Parent', 'Runner'], { // Set font font: function (a, v) { if (typeof a === 'object') { diff --git a/src/svg.js b/src/svg.js index 10135b1..1d72d64 100644 --- a/src/svg.js +++ b/src/svg.js @@ -58,21 +58,11 @@ extend([ Classes.Gradient ], getMethodsFor('radius')) -const containerMethods = getMethodsFor('Container') -// FIXME: We need a container array -for (let i in containers) { - extend(containers[i], containerMethods) -} - -const elementMethods = getMethodsFor('Element') -const eventTargetMethods = getMethodsFor('EventTarget') -for (let i in elements) { - extend(elements[i], elementMethods) - extend(elements[i], eventTargetMethods) - extend(elements[i], getConstructor('EventTarget')) - extend(elements[i], getConstructor('Element')) - extend(elements[i], getConstructor('Memory')) -} +extend(Classes.EventTarget, getMethodsFor('EventTarget')) +extend(Classes.Element, getMethodsFor('Element')) +extend(Classes.Element, getMethodsFor('Parent')) +extend(Classes.Element, getConstructor('Memory')) +extend(Classes.Container, getMethodsFor('Container')) registerMorphableType([ Classes.SVGNumber, @@ -102,15 +92,13 @@ import * as regex from './regex.js' SVG.regex = regex - - // satisfy tests, fix later -import * as ns from './namespaces' +import * as ns from './namespaces.js' SVG.get = SVG SVG.find = find Object.assign(SVG, ns) -import Base from './Base.js' -SVG.Element = SVG.Parent = SVG.Shape = SVG.Container = Base +// import Base from './Base.js' +// SVG.Element = SVG.Parent = SVG.Shape = SVG.Container = Base import {easing} from './Controller.js' SVG.easing = easing import * as events from './event.js' @@ -121,3 +109,5 @@ SVG.ObjectBag = ObjectBag SVG.NonMorphable = NonMorphable import parser from './parser.js' SVG.parser = parser +import * as defaults from './defaults.js' +SVG.defaults = defaults diff --git a/src/tools.js b/src/tools.js index 4dc381e..d33566a 100644 --- a/src/tools.js +++ b/src/tools.js @@ -18,11 +18,7 @@ export function extend (modules, methods) { modules = Array.isArray(modules) ? modules : [modules] for (i = modules.length - 1; i >= 0; i--) { - if (methods.name) { - modules[i].extensions = (modules[i].extensions || []).concat(methods) - } for (key in methods) { - if (modules[i].prototype[key] || key == 'name' || key == 'setup') continue modules[i].prototype[key] = methods[key] } } -- cgit v1.2.3 From edc9454ddf9a0fc29a81713b98e15ddfded04bf4 Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Sun, 4 Nov 2018 22:04:54 +0100 Subject: forgot about memory tests --- dist/svg.js | 44 ++++++++++++-------------------------------- dist/svg.min.js | 2 +- spec/SpecRunner.html | 1 + src/PathArray.js | 4 ++-- src/PointArray.js | 4 ++-- src/SVGArray.js | 4 ++-- src/memory.js | 14 +++++++------- src/svg.js | 2 +- src/tools.js | 12 ------------ 9 files changed, 28 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/dist/svg.js b/dist/svg.js index fe8c329..ba5a1d8 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -484,16 +484,6 @@ var SVG = (function () { var key, i; modules = Array.isArray(modules) ? modules : [modules]; - for (i = modules.length - 1; i >= 0; i--) { - for (key in methods) { - modules[i].prototype[key] = methods[key]; - } - } - } - function extend2(modules, methods) { - var key, i; - modules = Array.isArray(modules) ? modules : [modules]; - for (i = modules.length - 1; i >= 0; i--) { for (key in methods) { modules[i].prototype[key] = methods[key]; @@ -533,7 +523,6 @@ var SVG = (function () { nodeOrNew: nodeOrNew, makeNode: makeNode, extend: extend, - extend2: extend2, addFactory: addFactory, invent: invent }); @@ -629,7 +618,6 @@ var SVG = (function () { }); var methods = {}; - var constructors = {}; function registerMethods(name, m) { if (Array.isArray(name)) { var _iteratorNormalCompletion = true; @@ -678,15 +666,6 @@ var SVG = (function () { function getMethodsFor(name) { return methods[name] || {}; } // FIXME: save memory? - function registerConstructor(name, setup) { - constructors[name] = setup; - } - function getConstructor(name) { - return constructors[name] ? { - setup: constructors[name], - name: name - } : {}; - } var listenerId = 0; @@ -2695,7 +2674,7 @@ var SVG = (function () { var SVGArray = subClassArray('SVGArray', Array, function () { this.init.apply(this, arguments); }); - extend2(SVGArray, { + extend(SVGArray, { init: function init() { //this.splice(0, this.length) this.length = 0; @@ -2774,7 +2753,7 @@ var SVG = (function () { // } var PointArray = subClassArray('PointArray', SVGArray); - extend2(PointArray, { + extend(PointArray, { // Convert array to string toString: function toString() { // convert to a poly point string @@ -3307,7 +3286,7 @@ var SVG = (function () { }(mlhvqtcsaz[i].toUpperCase()); } - extend2(PathArray, { + extend(PathArray, { // Convert array to string toString: function toString() { return arrayToString(this); @@ -7130,9 +7109,11 @@ var SVG = (function () { transform: transform }); - function setup(node) { - this._memory = {}; - } // Remember arbitrary data + // + // export function setup (node) { + // this._memory = {} + // } + // Remember arbitrary data function remember(k, v) { // remember every item in an object individually @@ -7164,14 +7145,13 @@ var SVG = (function () { } // return local memory object function memory() { - return this._memory; + return this._memory = this._memory || {}; } registerMethods('Element', { remember: remember, forget: forget, memory: memory - }); - registerConstructor('Memory', setup); + }); //registerConstructor('Memory', setup) var sugar = { stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], @@ -7335,8 +7315,8 @@ var SVG = (function () { extend$1([Rect, Ellipse, Circle, Gradient], getMethodsFor('radius')); extend$1(EventTarget, getMethodsFor('EventTarget')); extend$1(Element, getMethodsFor('Element')); - extend$1(Element, getMethodsFor('Parent')); - extend$1(Element, getConstructor('Memory')); + extend$1(Element, getMethodsFor('Parent')); //extend(Classes.Element, getConstructor('Memory')) + extend$1(Container$1, getMethodsFor('Container')); registerMorphableType([SVGNumber, Color, Box$1, Matrix, SVGArray, PointArray, PathArray]); makeMorphable(); // The main wrapping element diff --git a/dist/svg.min.js b/dist/svg.min.js index 386a99a..27a2e20 100644 --- a/dist/svg.min.js +++ b/dist/svg.min.js @@ -1 +1 @@ -var SVG=function(){"use strict";function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;nn.x&&e>n.y&&t=e.time?e.run():Pt.timeouts.push(e),e!==n););for(var i=null,r=Pt.frames.last();i!==r&&(i=Pt.frames.shift());)i.run();Pt.transforms.forEach(function(t){t()}),Pt.nextDraw=Pt.timeouts.first()||Pt.frames.first()?window.requestAnimationFrame(Pt._draw):null}},Dt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q(t,"string"==typeof t?null:t),e))}return r(e,At),a(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function zt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function Rt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function qt(t){return null==t?this.attr("cx"):this.attr("cx",t)}function Lt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function Ft(t){return null==t?2*this.rx():this.rx(new wt(t).divide(2))}function It(t){return null==t?2*this.ry():this.ry(new wt(t).divide(2))}function Xt(t,e){var n=R(this,t,e);return this.rx(new wt(n.width).divide(2)).ry(new wt(n.height).divide(2))}nt(Dt),lt("Container",{element:function(t,e){return this.put(new Dt(t,e))}});var Yt=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:zt,y:Rt,cx:qt,cy:Lt,width:Ft,height:It,size:Xt}),Ht=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("circle",t),e))}return r(e,jt),a(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Bt(t,e){return xt((e||document).querySelectorAll(t),function(t){return et(t)})}$(Ht,{x:zt,y:Rt,cx:qt,cy:Lt,width:Ft,height:It,size:Xt}),lt({Element:{circle:function(t){return this.put(new Ht).radius(new wt(t).divide(2)).move(0,0)}}}),nt(Ht),lt("Element",{find:function(t){return Bt(t,this.node)}});var Gt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("clipPath",t),e))}return r(e,Ct),a(e,[{key:"remove",value:function(){return this.targets().forEach(function(t){t.unclip()}),c(u(e.prototype),"remove",this).call(this)}},{key:"targets",value:function(){return Bt('svg [clip-path*="'+this.id()+'"]')}}]),e}();lt({Container:{clip:function(){return this.defs().put(new Gt)}},Element:{clipWith:function(t){var e=t instanceof Gt?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.id()+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}}),nt(Gt);var Vt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("a",t),e))}return r(e,Ct),a(e,[{key:"to",value:function(t){return this.attr("href",t,B)}},{key:"target",value:function(t){return this.attr("target",t)}}]),e}();lt({Container:{link:function(t){return this.put(new Vt).to(t)}},Element:{linkTo:function(t){var e=new Vt;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}}),nt(Vt);var Qt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("ellipse",t),e))}return r(e,jt),e}();$(Qt,Yt),lt("Container",{ellipse:function(t,e){return this.put(new Qt).size(t,e).move(0,0)}}),nt(Qt);var Ut=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("stop",t),e))}return r(e,bt),a(e,[{key:"update",value:function(t){return("number"==typeof t||t instanceof wt)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new wt(t.offset)),this}}]),e}();nt(Ut);var $t=Object.freeze({from:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({fx:new wt(t),fy:new wt(e)}):this.attr({x1:new wt(t),y1:new wt(e)})},to:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({cx:new wt(t),cy:new wt(e)}):this.attr({x2:new wt(t),y2:new wt(e)})}});function Jt(){if(!Jt.nodes){var t=(new Tt).size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"}),e=t.path().node;Jt.nodes={svg:t,path:e}}if(!Jt.nodes.svg.node.parentNode){var n=document.body||document.documentElement;Jt.nodes.svg.addTo(n)}return Jt.nodes}var Wt=function(){function r(t,e,n){var i;o(this,r),n=n||{x:0,y:0},i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"===l(t)?{x:t.x,y:t.y}:{x:t,y:e},this.x=null==i.x?n.x:i.x,this.y=null==i.y?n.y:i.y}return a(r,[{key:"clone",value:function(){return new r(this)}},{key:"native",value:function(){var t=Jt().svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t}},{key:"transform",value:function(t){return new r(t.a*this.x+t.c*this.y+t.e,t.b*this.x+t.d*this.y+t.f)}}]),r}();lt({Element:{point:function(t,e){return new Wt(t,e).transform(this.screenCTM().inverse())}}});var Zt=function(){function u(){o(this,u),this.init.apply(this,arguments)}return a(u,[{key:"init",value:function(t){var e;t="string"==typeof t?t.split(j).map(parseFloat):Array.isArray(t)?t:"object"===l(t)?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):[0,0,0,0],this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],null==(e=this).x&&(e.x=0,e.y=0,e.width=0,e.height=0),e.w=e.width,e.h=e.height,e.x2=e.x+e.width,e.y2=e.y+e.height,e.cx=e.x+e.width/2,e.cy=e.y+e.height/2}},{key:"merge",value:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new u(e,n,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-n)}},{key:"transform",value:function(e){var n=1/0,i=-1/0,r=1/0,s=-1/0;return[new Wt(this.x,this.y),new Wt(this.x2,this.y),new Wt(this.x,this.y2),new Wt(this.x2,this.y2)].forEach(function(t){t=t.transform(e),n=Math.min(n,t.x),i=Math.max(i,t.x),r=Math.min(r,t.y),s=Math.max(s,t.y)}),new u(n,r,i-n,s-r)}},{key:"addOffset",value:function(){return this.x+=window.pageXOffset,this.y+=window.pageYOffset,this}},{key:"toString",value:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}},{key:"toArray",value:function(){return[this.x,this.y,this.width,this.height]}}]),u}();function Kt(e){var n,t,i;try{if(n=e(this.node),!((i=n).w||i.h||i.x||i.y||(t=this.node,(document.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===document}).call(document.documentElement,t))))throw new Error("Element not in the dom")}catch(t){try{var r=this.clone(Jt().svg).show();n=e(r.node),r.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return n}lt({Element:{bbox:function(){return new Zt(Kt.call(this,function(t){return t.getBBox()}))},rbox:function(t){var e=new Zt(Kt.call(this,function(t){return t.getBoundingClientRect()}));return t?e.transform(t.screenCTM().inverse()):e.addOffset()}},viewbox:{viewbox:function(t,e,n,i){return null==t?new Zt(this.attr("viewBox")):this.attr("viewBox",new Zt(t,e,n,i))}}});var te=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q(t+"Gradient","string"==typeof t?null:t),i))}return r(i,Ct),a(i,[{key:"stop",value:function(t,e,n){return this.put(new Ut).update(t,e,n)}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="gradientTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new Zt}}]),i}();$(te,$t),lt({Container:{gradient:function(t,e){return this.defs().gradient(t,e)}},Defs:{gradient:function(t,e){return this.put(new te(t)).update(e)}}}),nt(te);var ee=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q("pattern",t),i))}return r(i,Ct),a(i,[{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="patternTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new Zt}}]),i}();lt({Container:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}},Defs:{pattern:function(t,e,n){return this.put(new ee).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}}),nt(ee);var ne=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("image",t),e))}return r(e,jt),a(e,[{key:"load",value:function(n,i){if(!n)return this;var r=new window.Image;return yt(r,"load",function(t){var e=this.parent(ee);0===this.width()&&0===this.height()&&this.size(r.width,r.height),e instanceof ee&&0===e.width()&&0===e.height()&&e.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:r.width,height:r.height,ratio:r.width/r.height,url:n})},this),yt(r,"load error",function(){vt(r)}),this.attr("href",r.src=n,B)}},{key:"attrHook",value:function(t){var e=this;return t.doc().defs().pattern(0,0,function(t){t.add(e)})}}]),e}();lt({Container:{image:function(t,e){return this.put(new ne).size(0,0).load(t,e)}}}),nt(ne);var ie=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1",delay:0},Oe={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},Ae=Object.freeze({noop:xe,timeline:_e,attrs:Oe});var je=Object.freeze({plain:function(t){return!1===this._build&&this.clear(),this.node.appendChild(document.createTextNode(t)),this},length:function(){return this.node.getComputedTextLength()}}),Ce=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this,Q("text",t),n))).dom.leading=new wt(1.3),e._rebuild=!0,e._build=!1,e.attr("font-family",Oe["font-family"]),e}return r(n,At),a(n,[{key:"x",value:function(t){return null==t?this.attr("x"):this.attr("x",t)}},{key:"y",value:function(t){var e=this.attr("y"),n="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-n:e:this.attr("y","number"==typeof t?t+n:t)}},{key:"cx",value:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)}},{key:"cy",value:function(t){return null==t?this.bbox().cy:this.y(t-this.bbox().height/2)}},{key:"text",value:function(t){if(void 0===t){var e=this.node.childNodes,n=0;t="";for(var i=0,r=e.length;i":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},ze=function(){function t(){o(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),Re=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).ease=De[t||_e.ease]||t,e}return r(n,ze),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),qe=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).stepper=t,e}return r(n,ze),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Le(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var Fe=function(t){function i(t,e){var n;return o(this,i),(n=h(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,qe),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i);this._lastTime=this._time;var s=this._isDeclarative;if(this.done=!s&&!r&&this._time>=i,n||s){this._initialise(n),this.transforms=new Ee;var u=this._run(s?t:e)}return this.done=this.done||u&&s,this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new Re(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;en.x&&e>n.y&&t=e.time?e.run():Et.timeouts.push(e),e!==n););for(var i=null,r=Et.frames.last();i!==r&&(i=Et.frames.shift());)i.run();Et.transforms.forEach(function(t){t()}),Et.nextDraw=Et.timeouts.first()||Et.frames.first()?window.requestAnimationFrame(Et._draw):null}},Nt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q(t,"string"==typeof t?null:t),e))}return r(e,_t),a(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function Pt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function Dt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function zt(t){return null==t?this.attr("cx"):this.attr("cx",t)}function Rt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function qt(t){return null==t?2*this.rx():this.rx(new mt(t).divide(2))}function Lt(t){return null==t?2*this.ry():this.ry(new mt(t).divide(2))}function Ft(t,e){var n=R(this,t,e);return this.rx(new mt(n.width).divide(2)).ry(new mt(n.height).divide(2))}et(Nt),at("Container",{element:function(t,e){return this.put(new Nt(t,e))}});var It=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:Pt,y:Dt,cx:zt,cy:Rt,width:qt,height:Lt,size:Ft}),Xt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("circle",t),e))}return r(e,Ot),a(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Yt(t,e){return kt((e||document).querySelectorAll(t),function(t){return tt(t)})}$(Xt,{x:Pt,y:Dt,cx:zt,cy:Rt,width:qt,height:Lt,size:Ft}),at({Element:{circle:function(t){return this.put(new Xt).radius(new mt(t).divide(2)).move(0,0)}}}),et(Xt),at("Element",{find:function(t){return Yt(t,this.node)}});var Ht=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("clipPath",t),e))}return r(e,At),a(e,[{key:"remove",value:function(){return this.targets().forEach(function(t){t.unclip()}),c(u(e.prototype),"remove",this).call(this)}},{key:"targets",value:function(){return Yt('svg [clip-path*="'+this.id()+'"]')}}]),e}();at({Container:{clip:function(){return this.defs().put(new Ht)}},Element:{clipWith:function(t){var e=t instanceof Ht?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.id()+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}}),et(Ht);var Bt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("a",t),e))}return r(e,At),a(e,[{key:"to",value:function(t){return this.attr("href",t,B)}},{key:"target",value:function(t){return this.attr("target",t)}}]),e}();at({Container:{link:function(t){return this.put(new Bt).to(t)}},Element:{linkTo:function(t){var e=new Bt;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}}),et(Bt);var Gt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("ellipse",t),e))}return r(e,Ot),e}();$(Gt,It),at("Container",{ellipse:function(t,e){return this.put(new Gt).size(t,e).move(0,0)}}),et(Gt);var Vt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("stop",t),e))}return r(e,wt),a(e,[{key:"update",value:function(t){return("number"==typeof t||t instanceof mt)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new mt(t.offset)),this}}]),e}();et(Vt);var Qt=Object.freeze({from:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({fx:new mt(t),fy:new mt(e)}):this.attr({x1:new mt(t),y1:new mt(e)})},to:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({cx:new mt(t),cy:new mt(e)}):this.attr({x2:new mt(t),y2:new mt(e)})}});function Ut(){if(!Ut.nodes){var t=(new Mt).size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"}),e=t.path().node;Ut.nodes={svg:t,path:e}}if(!Ut.nodes.svg.node.parentNode){var n=document.body||document.documentElement;Ut.nodes.svg.addTo(n)}return Ut.nodes}var $t=function(){function r(t,e,n){var i;o(this,r),n=n||{x:0,y:0},i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"===l(t)?{x:t.x,y:t.y}:{x:t,y:e},this.x=null==i.x?n.x:i.x,this.y=null==i.y?n.y:i.y}return a(r,[{key:"clone",value:function(){return new r(this)}},{key:"native",value:function(){var t=Ut().svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t}},{key:"transform",value:function(t){return new r(t.a*this.x+t.c*this.y+t.e,t.b*this.x+t.d*this.y+t.f)}}]),r}();at({Element:{point:function(t,e){return new $t(t,e).transform(this.screenCTM().inverse())}}});var Jt=function(){function u(){o(this,u),this.init.apply(this,arguments)}return a(u,[{key:"init",value:function(t){var e;t="string"==typeof t?t.split(j).map(parseFloat):Array.isArray(t)?t:"object"===l(t)?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):[0,0,0,0],this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],null==(e=this).x&&(e.x=0,e.y=0,e.width=0,e.height=0),e.w=e.width,e.h=e.height,e.x2=e.x+e.width,e.y2=e.y+e.height,e.cx=e.x+e.width/2,e.cy=e.y+e.height/2}},{key:"merge",value:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new u(e,n,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-n)}},{key:"transform",value:function(e){var n=1/0,i=-1/0,r=1/0,s=-1/0;return[new $t(this.x,this.y),new $t(this.x2,this.y),new $t(this.x,this.y2),new $t(this.x2,this.y2)].forEach(function(t){t=t.transform(e),n=Math.min(n,t.x),i=Math.max(i,t.x),r=Math.min(r,t.y),s=Math.max(s,t.y)}),new u(n,r,i-n,s-r)}},{key:"addOffset",value:function(){return this.x+=window.pageXOffset,this.y+=window.pageYOffset,this}},{key:"toString",value:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}},{key:"toArray",value:function(){return[this.x,this.y,this.width,this.height]}}]),u}();function Wt(e){var n,t,i;try{if(n=e(this.node),!((i=n).w||i.h||i.x||i.y||(t=this.node,(document.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===document}).call(document.documentElement,t))))throw new Error("Element not in the dom")}catch(t){try{var r=this.clone(Ut().svg).show();n=e(r.node),r.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return n}at({Element:{bbox:function(){return new Jt(Wt.call(this,function(t){return t.getBBox()}))},rbox:function(t){var e=new Jt(Wt.call(this,function(t){return t.getBoundingClientRect()}));return t?e.transform(t.screenCTM().inverse()):e.addOffset()}},viewbox:{viewbox:function(t,e,n,i){return null==t?new Jt(this.attr("viewBox")):this.attr("viewBox",new Jt(t,e,n,i))}}});var Zt=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q(t+"Gradient","string"==typeof t?null:t),i))}return r(i,At),a(i,[{key:"stop",value:function(t,e,n){return this.put(new Vt).update(t,e,n)}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="gradientTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new Jt}}]),i}();$(Zt,Qt),at({Container:{gradient:function(t,e){return this.defs().gradient(t,e)}},Defs:{gradient:function(t,e){return this.put(new Zt(t)).update(e)}}}),et(Zt);var Kt=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q("pattern",t),i))}return r(i,At),a(i,[{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="patternTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new Jt}}]),i}();at({Container:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}},Defs:{pattern:function(t,e,n){return this.put(new Kt).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}}),et(Kt);var te=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("image",t),e))}return r(e,Ot),a(e,[{key:"load",value:function(n,i){if(!n)return this;var r=new window.Image;return ft(r,"load",function(t){var e=this.parent(Kt);0===this.width()&&0===this.height()&&this.size(r.width,r.height),e instanceof Kt&&0===e.width()&&0===e.height()&&e.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:r.width,height:r.height,ratio:r.width/r.height,url:n})},this),ft(r,"load error",function(){dt(r)}),this.attr("href",r.src=n,B)}},{key:"attrHook",value:function(t){var e=this;return t.doc().defs().pattern(0,0,function(t){t.add(e)})}}]),e}();at({Container:{image:function(t,e){return this.put(new te).size(0,0).load(t,e)}}}),et(te);var ee=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1",delay:0},xe={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},_e=Object.freeze({noop:ke,timeline:be,attrs:xe});var Oe=Object.freeze({plain:function(t){return!1===this._build&&this.clear(),this.node.appendChild(document.createTextNode(t)),this},length:function(){return this.node.getComputedTextLength()}}),Ae=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this,Q("text",t),n))).dom.leading=new mt(1.3),e._rebuild=!0,e._build=!1,e.attr("font-family",xe["font-family"]),e}return r(n,_t),a(n,[{key:"x",value:function(t){return null==t?this.attr("x"):this.attr("x",t)}},{key:"y",value:function(t){var e=this.attr("y"),n="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-n:e:this.attr("y","number"==typeof t?t+n:t)}},{key:"cx",value:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)}},{key:"cy",value:function(t){return null==t?this.bbox().cy:this.y(t-this.bbox().height/2)}},{key:"text",value:function(t){if(void 0===t){var e=this.node.childNodes,n=0;t="";for(var i=0,r=e.length;i":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Pe=function(){function t(){o(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),De=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).ease=Ne[t||be.ease]||t,e}return r(n,Pe),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),ze=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).stepper=t,e}return r(n,Pe),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Re(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var qe=function(t){function i(t,e){var n;return o(this,i),(n=h(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,ze),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i);this._lastTime=this._time;var s=this._isDeclarative;if(this.done=!s&&!r&&this._time>=i,n||s){this._initialise(n),this.transforms=new Se;var u=this._run(s?t:e)}return this.done=this.done||u&&s,this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new De(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e + diff --git a/src/PathArray.js b/src/PathArray.js index b05bd92..8529bf9 100644 --- a/src/PathArray.js +++ b/src/PathArray.js @@ -4,7 +4,7 @@ import {numbersWithDots, pathLetters, hyphen, delimiter, isPathLetter} from './r import Point from './Point.js' import SVGArray from './SVGArray.js' import {subClassArray} from './ArrayPolyfill.js' -import {extend2} from './tools.js' +import {extend} from './tools.js' const PathArray = subClassArray('PathArray', SVGArray) @@ -84,7 +84,7 @@ for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { } -extend2(PathArray, { +extend(PathArray, { // Convert array to string toString () { return arrayToString(this) diff --git a/src/PointArray.js b/src/PointArray.js index a291054..1bf5460 100644 --- a/src/PointArray.js +++ b/src/PointArray.js @@ -1,13 +1,13 @@ import SVGArray from './SVGArray.js' import {delimiter} from './regex.js' import {subClassArray} from './ArrayPolyfill.js' -import {extend2} from './tools.js' +import {extend} from './tools.js' const PointArray = subClassArray('PointArray', SVGArray) export default PointArray -extend2(PointArray, { +extend(PointArray, { // Convert array to string toString () { // convert to a poly point string diff --git a/src/SVGArray.js b/src/SVGArray.js index 5927945..a442aad 100644 --- a/src/SVGArray.js +++ b/src/SVGArray.js @@ -1,7 +1,7 @@ /* global arrayClone */ import {delimiter} from './regex.js' import {subClassArray} from './ArrayPolyfill.js' -import {extend2} from './tools.js' +import {extend} from './tools.js' const SVGArray = subClassArray('SVGArray', Array, function (...args) { this.init(...args) @@ -9,7 +9,7 @@ const SVGArray = subClassArray('SVGArray', Array, function (...args) { export default SVGArray -extend2(SVGArray, { +extend(SVGArray, { init (...args) { //this.splice(0, this.length) this.length = 0 diff --git a/src/memory.js b/src/memory.js index 9850881..77d3518 100644 --- a/src/memory.js +++ b/src/memory.js @@ -1,11 +1,11 @@ import {registerMethods} from './methods.js' import {registerConstructor} from './methods.js' -export const name = 'Memory' - -export function setup (node) { - this._memory = {} -} +// export const name = 'Memory' +// +// export function setup (node) { +// this._memory = {} +// } // Remember arbitrary data export function remember (k, v) { @@ -39,8 +39,8 @@ export function forget () { // return local memory object export function memory () { - return this._memory + return (this._memory = this._memory || {}) } registerMethods('Element', {remember, forget, memory}) -registerConstructor('Memory', setup) +//registerConstructor('Memory', setup) diff --git a/src/svg.js b/src/svg.js index 1d72d64..4206060 100644 --- a/src/svg.js +++ b/src/svg.js @@ -61,7 +61,7 @@ extend([ extend(Classes.EventTarget, getMethodsFor('EventTarget')) extend(Classes.Element, getMethodsFor('Element')) extend(Classes.Element, getMethodsFor('Parent')) -extend(Classes.Element, getConstructor('Memory')) +//extend(Classes.Element, getConstructor('Memory')) extend(Classes.Container, getMethodsFor('Container')) registerMorphableType([ diff --git a/src/tools.js b/src/tools.js index d33566a..898f016 100644 --- a/src/tools.js +++ b/src/tools.js @@ -24,18 +24,6 @@ export function extend (modules, methods) { } } -export function extend2 (modules, methods) { - var key, i - - modules = Array.isArray(modules) ? modules : [modules] - - for (i = modules.length - 1; i >= 0; i--) { - for (key in methods) { - modules[i].prototype[key] = methods[key] - } - } -} - // FIXME: enhanced constructors here export function addFactory (modules, methods) { extend(modules, methods) -- cgit v1.2.3 From 4049e2e6361d5ed9120f1edd02ef96ecc138fa6d Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Mon, 5 Nov 2018 15:12:58 +0100 Subject: rework of classes, make events on every object possible --- dirty.html | 3 + dist/svg.js | 1857 ++++++++++++++++++++++++------------------------ dist/svg.min.js | 2 +- spec/spec/container.js | 6 +- src/Bare.js | 4 +- src/Box.js | 1 - src/Container.js | 28 +- src/Dom.js | 237 ++++++ src/Element.js | 232 ++---- src/EventTarget.js | 31 +- src/HtmlNode.js | 34 +- src/Parent.js | 169 ----- src/Runner.js | 15 +- src/Shape.js | 4 +- src/Text.js | 4 +- src/Tspan.js | 5 +- src/arrange.js | 2 +- src/attr.js | 4 +- src/classHandling.js | 44 ++ src/classes.js | 3 +- src/css.js | 2 +- src/data.js | 2 +- src/elemnts-svg.js | 4 - src/event.js | 28 +- src/memory.js | 2 +- src/selector.js | 2 +- src/sugar.js | 7 +- src/svg.js | 13 +- 28 files changed, 1388 insertions(+), 1357 deletions(-) create mode 100644 src/Dom.js delete mode 100644 src/Parent.js create mode 100644 src/classHandling.js (limited to 'src') diff --git a/dirty.html b/dirty.html index 9792d5e..23b2d6d 100644 --- a/dirty.html +++ b/dirty.html @@ -267,6 +267,9 @@ let moon = canvas.circle(50).center(1200, 300).attr({fill: '#ffa'}) earth.animate(10000).loop().ease('-') .transform({rotate: 360, origin: [500, 300]}, true) .transform({rotate: 720, origin: 'center'}, true) + .on('step', (e) => { + // console.log(e) + }) moon.animate(10000).loop().ease('-') .transform({rotate: 360, origin: [500, 300]}, true) diff --git a/dist/svg.js b/dist/svg.js index ba5a1d8..1d465b9 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -669,22 +669,32 @@ var SVG = (function () { var listenerId = 0; + function getEvents(node) { + var n = makeInstance(node).getEventHolder(); + if (!n.events) n.events = {}; + return n.events; + } + function getEventTarget(node) { - return typeof node.getEventTarget === 'function' ? node.getEventTarget() : node; + return makeInstance(node).getEventTarget(); + } + + function clearEvents(node) { + var n = makeInstance(node).getEventHolder(); + if (n.events) n.events = {}; } // Add event binder in the SVG namespace function on(node, events, listener, binding, options) { var l = listener.bind(binding || node); + var bag = getEvents(node); var n = getEventTarget(node); // events can be an array of events or a string of events events = Array.isArray(events) ? events : events.split(delimiter); // ensure instance object for nodes which are not adopted - - n.instance = n.instance || { - events: {} // pull event handlers from the element - - }; - var bag = n.instance.events; // add id to listener + // n.instance = n.instance || {events: {}} + // pull event handlers from the element + // var bag = n.instance.events + // add id to listener if (!listener._svgjsListenerId) { listener._svgjsListenerId = ++listenerId; @@ -704,18 +714,19 @@ var SVG = (function () { } // Add event unbinder in the SVG namespace function off(node, events, listener, options) { + var bag = getEvents(node); var n = getEventTarget(node); // we cannot remove an event if its not an svg.js instance - - if (!n.instance) return; // listener can be a function or a number + // if (!n.instance) return + // listener can be a function or a number if (typeof listener === 'function') { listener = listener._svgjsListenerId; if (!listener) return; } // pull event handlers from the element + // var bag = n.instance.events + // events can be an array of events or a string or undefined - var bag = n.instance.events; // events can be an array of events or a string or undefined - events = Array.isArray(events) ? events : (events || '').split(delimiter); events.forEach(function (event) { var ev = event && event.split('.')[0]; @@ -762,7 +773,7 @@ var SVG = (function () { off(n, event); } - n.instance.events = {}; + clearEvents(node); } }); } @@ -796,17 +807,22 @@ var SVG = (function () { function EventTarget() { var _this; - var node = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + _ref$events = _ref.events, + events = _ref$events === void 0 ? {} : _ref$events; _classCallCheck(this, EventTarget); _this = _possibleConstructorReturn(this, _getPrototypeOf(EventTarget).call(this)); - _this.events = node.events || {}; + _this.events = events; return _this; - } // Bind given event to listener - + } _createClass(EventTarget, [{ + key: "addEventListener", + value: function addEventListener() {} // Bind given event to listener + + }, { key: "on", value: function on$$1(event, listener, binding, options) { on(this, event, listener, binding, options); @@ -825,6 +841,21 @@ var SVG = (function () { key: "dispatch", value: function dispatch$$1(event, data) { return dispatch(this, event, data); + } + }, { + key: "dispatchEvent", + value: function dispatchEvent(event) { + var bag = this.getEventHolder().events; + if (!bag) return true; + var events = bag[event.type]; + + for (var i in events) { + for (var j in events[i]) { + events[i][j](event); + } + } + + return !event.defaultPrevented; } // Fire given event }, { @@ -833,6 +864,19 @@ var SVG = (function () { this.dispatch(event, data); return this; } + }, { + key: "getEventHolder", + value: function getEventHolder() { + return this; + } + }, { + key: "getEventTarget", + value: function getEventTarget() { + return this; + } + }, { + key: "removeEventListener", + value: function removeEventListener() {} }]); return EventTarget; @@ -858,530 +902,682 @@ var SVG = (function () { // // registerConstructor('EventTarget', setup) - var SVGNumber = + // Map function + function map(array, block) { + var i; + var il = array.length; + var result = []; + + for (i = 0; i < il; i++) { + result.push(block(array[i])); + } + + return result; + } // Filter function + + function filter(array, block) { + var i; + var il = array.length; + var result = []; + + for (i = 0; i < il; i++) { + if (block(array[i])) { + result.push(array[i]); + } + } + + return result; + } // Degrees to radians + + function radians(d) { + return d % 360 * Math.PI / 180; + } // Radians to degrees + + function degrees(r) { + return r * 180 / Math.PI % 360; + } + function filterSVGElements(nodes) { + return this.filter(nodes, function (el) { + return el instanceof window.SVGElement; + }); + } + + var utils = /*#__PURE__*/Object.freeze({ + map: map, + filter: filter, + radians: radians, + degrees: degrees, + filterSVGElements: filterSVGElements + }); + + function noop() {} // Default animation values + + var timeline = { + duration: 400, + ease: '>', + delay: 0 // Default attribute values + + }; + var attrs = { + // fill and stroke + 'fill-opacity': 1, + 'stroke-opacity': 1, + 'stroke-width': 0, + 'stroke-linejoin': 'miter', + 'stroke-linecap': 'butt', + fill: '#000000', + stroke: '#000000', + opacity: 1, + // position + x: 0, + y: 0, + cx: 0, + cy: 0, + // size + width: 0, + height: 0, + // radius + r: 0, + rx: 0, + ry: 0, + // gradient + offset: 0, + 'stop-opacity': 1, + 'stop-color': '#000000', + // text + 'font-size': 16, + 'font-family': 'Helvetica, Arial, sans-serif', + 'text-anchor': 'start' + }; + + var defaults = /*#__PURE__*/Object.freeze({ + noop: noop, + timeline: timeline, + attrs: attrs + }); + + var Color = /*#__PURE__*/ function () { - // Initialize - function SVGNumber() { - _classCallCheck(this, SVGNumber); + function Color() { + _classCallCheck(this, Color); this.init.apply(this, arguments); } - _createClass(SVGNumber, [{ + _createClass(Color, [{ key: "init", - value: function init(value, unit) { - unit = Array.isArray(value) ? value[1] : unit; - value = Array.isArray(value) ? value[0] : value; // initialize defaults - - this.value = 0; - this.unit = unit || ''; // parse value - - if (typeof value === 'number') { - // ensure a valid numeric value - this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; - } else if (typeof value === 'string') { - unit = value.match(numberAndUnit); + value: function init(color, g, b) { + var match; // initialize defaults - if (unit) { - // make value numeric - this.value = parseFloat(unit[1]); // normalize + this.r = 0; + this.g = 0; + this.b = 0; + if (!color) return; // parse color - if (unit[5] === '%') { - this.value /= 100; - } else if (unit[5] === 's') { - this.value *= 1000; - } // store unit + if (typeof color === 'string') { + if (isRgb.test(color)) { + // get rgb values + match = rgb.exec(color.replace(whitespace, '')); // parse numeric values + this.r = parseInt(match[1]); + this.g = parseInt(match[2]); + this.b = parseInt(match[3]); + } else if (isHex.test(color)) { + // get hex values + match = hex.exec(fullHex(color)); // parse numeric values - this.unit = unit[5]; - } - } else { - if (value instanceof SVGNumber) { - this.value = value.valueOf(); - this.unit = value.unit; + this.r = parseInt(match[1], 16); + this.g = parseInt(match[2], 16); + this.b = parseInt(match[3], 16); } + } else if (Array.isArray(color)) { + this.r = color[0]; + this.g = color[1]; + this.b = color[2]; + } else if (_typeof(color) === 'object') { + this.r = color.r; + this.g = color.g; + this.b = color.b; + } else if (arguments.length === 3) { + this.r = color; + this.g = g; + this.b = b; } - } + } // Default to hex conversion + }, { key: "toString", value: function toString() { - return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; - } - }, { - key: "toJSON", - value: function toJSON() { - return this.toString(); + return this.toHex(); } }, { key: "toArray", value: function toArray() { - return [this.value, this.unit]; - } + return [this.r, this.g, this.b]; + } // Build hex value + }, { - key: "valueOf", - value: function valueOf() { - return this.value; - } // Add number + key: "toHex", + value: function toHex() { + return '#' + compToHex(Math.round(this.r)) + compToHex(Math.round(this.g)) + compToHex(Math.round(this.b)); + } // Build rgb value }, { - key: "plus", - value: function plus(number) { - number = new SVGNumber(number); - return new SVGNumber(this + number, this.unit || number.unit); - } // Subtract number + key: "toRgb", + value: function toRgb() { + return 'rgb(' + [this.r, this.g, this.b].join() + ')'; + } // Calculate true brightness }, { - key: "minus", - value: function minus(number) { - number = new SVGNumber(number); - return new SVGNumber(this - number, this.unit || number.unit); - } // Multiply number + key: "brightness", + value: function brightness() { + return this.r / 255 * 0.30 + this.g / 255 * 0.59 + this.b / 255 * 0.11; + } // Testers + // Test if given value is a color string + + }], [{ + key: "test", + value: function test(color) { + color += ''; + return isHex.test(color) || isRgb.test(color); + } // Test if given value is a rgb object }, { - key: "times", - value: function times(number) { - number = new SVGNumber(number); - return new SVGNumber(this * number, this.unit || number.unit); - } // Divide number + key: "isRgb", + value: function isRgb$$1(color) { + return color && typeof color.r === 'number' && typeof color.g === 'number' && typeof color.b === 'number'; + } // Test if given value is a color }, { - key: "divide", - value: function divide(number) { - number = new SVGNumber(number); - return new SVGNumber(this / number, this.unit || number.unit); + key: "isColor", + value: function isColor(color) { + return this.isRgb(color) || this.test(color); } }]); - return SVGNumber; + return Color; }(); - var Doc = getClass(root); //export const name = 'Element' - - var Element = - /*#__PURE__*/ - function (_EventTarget) { - _inherits(Element, _EventTarget); - - function Element(node) { - var _this; - - _classCallCheck(this, Element); - - _this = _possibleConstructorReturn(this, _getPrototypeOf(Element).call(this)); // initialize data object - - _this.dom = {}; // create circular reference - - _this.node = node; - _this.type = node.nodeName; - _this.node.instance = _assertThisInitialized(_assertThisInitialized(_this)); - - 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')) || {}); - } - - return _this; - } // Move over x-axis - + var subClassArray = function () { + try { + // try es6 subclassing + return Function('name', 'baseClass', '_constructor', ['baseClass = baseClass || Array', 'return {', '[name]: class extends baseClass {', 'constructor (...args) {', 'super(...args)', '_constructor && _constructor.apply(this, args)', '}', '}', '}[name]'].join('\n')); + } catch (e) { + // Use es5 approach + return function (name) { + var baseClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Array; - _createClass(Element, [{ - key: "x", - value: function x(_x) { - return this.attr('x', _x); - } // Move over y-axis + var _constructor = arguments.length > 2 ? arguments[2] : undefined; - }, { - key: "y", - value: function y(_y) { - return this.attr('y', _y); - } // Move by center over x-axis + var Arr = function Arr() { + baseClass.apply(this, arguments); + _constructor && _constructor.apply(this, arguments); + }; - }, { - key: "cx", - value: function cx(x) { - return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2); - } // Move by center over y-axis + Arr.prototype = Object.create(baseClass.prototype); + Arr.prototype.constructor = Arr; + return Arr; + }; + } + }(); - }, { - key: "cy", - value: function cy(y) { - return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2); - } // Move element to given x and y values + var SVGArray = subClassArray('SVGArray', Array, function () { + this.init.apply(this, arguments); + }); + extend(SVGArray, { + init: function init() { + //this.splice(0, this.length) + this.length = 0; + this.push.apply(this, _toConsumableArray(this.parse.apply(this, arguments))); + }, + toArray: function toArray() { + // const ret = [] + // ret.push(...this) + // return ret + return Array.prototype.concat.apply([], this); + }, + toString: function toString() { + return this.join(' '); + }, + // Flattens the array if needed + valueOf: function valueOf() { + var ret = []; + ret.push.apply(ret, _toConsumableArray(this)); + return ret; // return this.toArray() + }, + // Parse whitespace separated string + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + //array = array.valueOf() + // If already is an array, no need to parse it + if (array instanceof Array) return array; + return array.trim().split(delimiter).map(parseFloat); + }, + clone: function clone() { + return new this.constructor(this); + }, + toSet: function toSet() { + return new Set(this); + } + }); // export default class SVGArray extends BaseArray { + // constructor (...args) { + // super() + // this.init(...args) + // } + // + // init (array, fallback = []) { + // //this.splice(0, this.length) + // this.length = 0 + // this.push(...this.parse(array || fallback)) + // } + // + // toArray () { + // return [].concat(this) + // } + // + // toString () { + // return this.join(' ') + // } + // + // valueOf () { + // return this.toArray() + // } + // + // // Parse whitespace separated string + // parse (array) { + // array = array.valueOf() + // + // // if already is an array, no need to parse it + // if (Array.isArray(array)) return array + // + // return array.trim().split(delimiter).map(parseFloat) + // } + // + // clone () { + // return new this.constructor(this) + // } + // + // toSet () { + // return new Set(this) + // } + // } - }, { - key: "move", - value: function move(x, y) { - return this.x(x).y(y); - } // Move element by its center + var SVGNumber = + /*#__PURE__*/ + function () { + // Initialize + function SVGNumber() { + _classCallCheck(this, SVGNumber); - }, { - key: "center", - value: function center(x, y) { - return this.cx(x).cy(y); - } // Set width of element + this.init.apply(this, arguments); + } - }, { - key: "width", - value: function width(_width) { - return this.attr('width', _width); - } // Set height of element + _createClass(SVGNumber, [{ + key: "init", + value: function init(value, unit) { + unit = Array.isArray(value) ? value[1] : unit; + value = Array.isArray(value) ? value[0] : value; // initialize defaults - }, { - key: "height", - value: function height(_height) { - return this.attr('height', _height); - } // Set element size to given width and height + this.value = 0; + this.unit = unit || ''; // parse value - }, { - key: "size", - value: function size(width, height) { - var p = proportionalSize(this, width, height); - return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height)); - } // Clone element + if (typeof value === 'number') { + // ensure a valid numeric value + this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; + } else if (typeof value === 'string') { + unit = value.match(numberAndUnit); - }, { - key: "clone", - value: function clone(parent) { - // write dom data to the dom so the clone can pickup the data - this.writeDataToDom(); // clone element and assign new id + if (unit) { + // make value numeric + this.value = parseFloat(unit[1]); // normalize - var clone = assignNewId(this.node.cloneNode(true)); // insert the clone in the given parent or after myself + if (unit[5] === '%') { + this.value /= 100; + } else if (unit[5] === 's') { + this.value *= 1000; + } // store unit - if (parent) parent.add(clone);else this.after(clone); - return clone; - } // Remove element - }, { - key: "remove", - value: function remove() { - if (this.parent()) { - this.parent().removeElement(this); + this.unit = unit[5]; + } + } else { + if (value instanceof SVGNumber) { + this.value = value.valueOf(); + this.unit = value.unit; + } } - - return this; - } // Replace element - - }, { - key: "replace", - value: function replace(element) { - this.after(element).remove(); - return element; - } // Add element to given container and return self - - }, { - key: "addTo", - value: function addTo(parent) { - return makeInstance(parent).put(this); - } // Add element to given container and return container - - }, { - key: "putIn", - value: function putIn(parent) { - return makeInstance(parent).add(this); - } // Get / set id - - }, { - key: "id", - value: function id(_id) { - // generate new id if no id set - 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); - } // Checks whether the given point inside the bounding box of the element - - }, { - key: "inside", - value: function inside(x, y) { - var box = this.bbox(); - return x > box.x && y > box.y && x < box.x + box.width && y < box.y + box.height; - } // Return id on string conversion - + } }, { key: "toString", value: function toString() { - return this.id(); - } // Return array of classes on the node - - }, { - key: "classes", - value: function classes() { - var attr = this.attr('class'); - return attr == null ? [] : attr.trim().split(delimiter); - } // Return true if class exists on the node, false otherwise - - }, { - key: "hasClass", - value: function hasClass(name) { - return this.classes().indexOf(name) !== -1; - } // Add class to the node - - }, { - key: "addClass", - value: function addClass(name) { - if (!this.hasClass(name)) { - var array = this.classes(); - array.push(name); - this.attr('class', array.join(' ')); - } - - return this; - } // Remove class from the node - - }, { - key: "removeClass", - value: function removeClass(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 - - }, { - key: "toggleClass", - value: function toggleClass(name) { - return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); - } // Get referenced element form attribute value - - }, { - key: "reference", - value: function reference$$1(attr) { - var id = idFromReference(this.attr(attr)); - return id ? makeInstance(id) : null; - } // Returns the parent element instance - + return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; + } }, { - key: "parent", - value: function parent(type) { - var parent = this; // check for parent - - if (!parent.node.parentNode) return null; // get parent element - - parent = adopt(parent.node.parentNode); - if (!type) return parent; // loop trough ancestors if type is given - - while (parent && parent.node instanceof window.SVGElement) { - if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent; - parent = adopt(parent.node.parentNode); - } - } // Get parent document - + key: "toJSON", + value: function toJSON() { + return this.toString(); + } }, { - key: "doc", - value: function doc() { - var p = this.parent(Doc); - return p && p.doc(); - } // Get defs - + key: "toArray", + value: function toArray() { + return [this.value, this.unit]; + } }, { - key: "defs", - value: function defs() { - return this.doc().defs(); - } // return array of all ancestors of given type up to the root svg + key: "valueOf", + value: function valueOf() { + return this.value; + } // Add number }, { - key: "parents", - value: function parents(type) { - var parents = []; - var parent = this; - - do { - parent = parent.parent(type); - if (!parent || parent instanceof getClass('HtmlNode')) break; - parents.push(parent); - } while (parent.parent); - - return parents; - } // matches the element vs a css selector + key: "plus", + value: function plus(number) { + number = new SVGNumber(number); + return new SVGNumber(this + number, this.unit || number.unit); + } // Subtract number }, { - key: "matches", - value: function matches(selector) { - return matcher(this.node, selector); - } // Returns the svg node to call native svg methods on it + key: "minus", + value: function minus(number) { + number = new SVGNumber(number); + return new SVGNumber(this - number, this.unit || number.unit); + } // Multiply number }, { - key: "native", - value: function native() { - return this.node; - } // Import raw svg + key: "times", + value: function times(number) { + number = new SVGNumber(number); + return new SVGNumber(this * number, this.unit || number.unit); + } // Divide number }, { - key: "svg", - value: function svg() { - // write svgjs data to the dom - this.writeDataToDom(); - return this.node.outerHTML; - } // write svgjs data to the dom + key: "divide", + value: function divide(number) { + number = new SVGNumber(number); + return new SVGNumber(this / number, this.unit || number.unit); + } + }]); - }, { - key: "writeDataToDom", - value: function writeDataToDom() { - // remove previously set data - this.node.removeAttribute('svgjs:data'); + return SVGNumber; + }(); - if (Object.keys(this.dom).length) { - this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)); // see #428 - } + // Set svg element attribute - return this; - } // set given data to the elements data property + function attr(attr, val, ns) { + // act as full getter + if (attr == null) { + // get an object of attributes + attr = {}; + val = this.node.attributes; + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; - }, { - key: "setData", - value: function setData(o) { - this.dom = o; - return this; + try { + for (var _iterator = val[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var node = _step.value; + attr[node.nodeName] = isNumber.test(node.nodeValue) ? parseFloat(node.nodeValue) : node.nodeValue; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } } - }, { - key: "getEventTarget", - value: function getEventTarget() { - return this.node; + + return attr; + } else if (Array.isArray(attr)) ; else if (_typeof(attr) === 'object') { + // apply every attribute individually if an object is passed + for (val in attr) { + this.attr(val, attr[val]); } - }]); + } else if (val === null) { + // remove value + this.node.removeAttribute(attr); + } else if (val == null) { + // act as a getter if the first and only argument is not an object + val = this.node.getAttribute(attr); + return val == null ? attrs[attr] // FIXME: do we need to return defaults? + : isNumber.test(val) ? parseFloat(val) : val; + } else { + // convert image fill and stroke to patterns + if (attr === 'fill' || attr === 'stroke') { + if (isImage.test(val)) { + val = this.doc().defs().image(val); + } + } // FIXME: This is fine, but what about the lines above? + // How does attr know about image()? - return Element; - }(EventTarget); // registerMethods('Element', { - // Map function - function map(array, block) { - var i; - var il = array.length; - var result = []; + while (typeof val.attrHook == 'function') { + val = val.attrHook(this, attr); + } // ensure correct numeric values (also accepts NaN and Infinity) - for (i = 0; i < il; i++) { - result.push(block(array[i])); - } - return result; - } // Filter function + if (typeof val === 'number') { + val = new SVGNumber(val); + } else if (Color.isColor(val)) { + // ensure full hex color + val = new Color(val); + } else if (val.constructor === Array) { + // Check for plain arrays and parse array values + val = new SVGArray(val); + } // if the passed attribute is leading... - function filter(array, block) { - var i; - var il = array.length; - var result = []; - for (i = 0; i < il; i++) { - if (block(array[i])) { - result.push(array[i]); + if (attr === 'leading') { + // ... call the leading method instead + if (this.leading) { + this.leading(val); + } + } else { + // set given attribute on node + typeof ns === 'string' ? this.node.setAttributeNS(ns, attr, val.toString()) : this.node.setAttribute(attr, val.toString()); + } // rebuild if required + + + if (this.rebuild && (attr === 'font-size' || attr === 'x')) { + this.rebuild(); } } - return result; - } // Degrees to radians + return this; + } //registerMethods('Element', {attr}) - function radians(d) { - return d % 360 * Math.PI / 180; - } // Radians to degrees + var Dom = + /*#__PURE__*/ + function (_EventTarget) { + _inherits(Dom, _EventTarget); - function degrees(r) { - return r * 180 / Math.PI % 360; - } - function filterSVGElements(nodes) { - return this.filter(nodes, function (el) { - return el instanceof window.SVGElement; - }); - } + function Dom(node) { + var _this; - var utils = /*#__PURE__*/Object.freeze({ - map: map, - filter: filter, - radians: radians, - degrees: degrees, - filterSVGElements: filterSVGElements - }); + _classCallCheck(this, Dom); - var Parent = - /*#__PURE__*/ - function (_Element) { - _inherits(Parent, _Element); + _this = _possibleConstructorReturn(this, _getPrototypeOf(Dom).call(this, node)); + _this.node = node; + _this.type = node.nodeName; + return _this; + } // Add given element at a position - function Parent() { - _classCallCheck(this, Parent); - return _possibleConstructorReturn(this, _getPrototypeOf(Parent).apply(this, arguments)); - } + _createClass(Dom, [{ + key: "add", + value: function 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]); + } + + return this; + } // Add element to given container and return self + + }, { + key: "addTo", + value: function addTo(parent) { + return makeInstance(parent).put(this); + } // Returns all child elements - _createClass(Parent, [{ + }, { key: "children", - // Returns all child elements value: function children() { return map(this.node.children, function (node) { return adopt(node); }); - } // Add given element at a position + } // Remove all elements in this container }, { - key: "add", - value: function add(element, i) { - element = makeInstance(element); + key: "clear", + value: function clear() { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } // remove defs reference + + + delete this._defs; + return this; + } // Clone element + + }, { + key: "clone", + value: function clone(parent) { + // write dom data to the dom so the clone can pickup the data + this.writeDataToDom(); // 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); // FIXME: after might not be available here + else this.after(clone); + return clone; + } // Iterates over all children and invokes a given block + + }, { + key: "each", + value: function each(block, deep) { + var children = this.children(); + var i, il; - 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]); + for (i = 0, il = children.length; i < il; i++) { + block.apply(children[i], [i, children]); + + if (deep) { + children[i].each(block, deep); + } } return this; - } // Basically does the same as `add()` but returns the added element instead + } // Get first child }, { - key: "put", - value: function put(element, i) { - this.add(element, i); - return element.instance || element; + key: "first", + value: function first() { + return adopt(this.node.firstChild); + } // Get a element at the given index + + }, { + key: "get", + value: function get(i) { + return adopt(this.node.childNodes[i]); + } + }, { + key: "getEventHolder", + value: function getEventHolder() { + return this.node; + } + }, { + key: "getEventTarget", + value: function getEventTarget() { + return this.node; } // Checks if the given element is a child }, { key: "has", value: function has(element) { return this.index(element) >= 0; + } // Get / set id + + }, { + key: "id", + value: function id(_id) { + // generate new id if no id set + 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); } // Gets index of given element }, { key: "index", value: function index(element) { return [].slice.call(this.node.childNodes).indexOf(element.node); - } // Get a element at the given index - - }, { - key: "get", - value: function get(i) { - return adopt(this.node.childNodes[i]); - } // Get first child - - }, { - key: "first", - value: function first() { - return adopt(this.node.firstChild); } // Get the last child }, { key: "last", value: function last() { return adopt(this.node.lastChild); - } // Iterates over all children and invokes a given block + } // matches the element vs a css selector }, { - key: "each", - value: function each(block, deep) { - var children = this.children(); - var i, il; + key: "matches", + value: function matches(selector) { + return matcher(this.node, selector); + } // Returns the svg node to call native svg methods on it - for (i = 0, il = children.length; i < il; i++) { - if (children[i] instanceof Element) { - block.apply(children[i], [i, children]); - } + }, { + key: "native", + value: function native() { + return this.node; + } // Returns the parent element instance - if (deep && children[i] instanceof Parent) { - children[i].each(block, deep); - } + }, { + key: "parent", + value: function parent(type) { + var parent = this; // check for parent + + if (!parent.node.parentNode) return null; // get parent element + + parent = adopt(parent.node.parentNode); + if (!type) return parent; // loop trough ancestors if type is given + + while (parent && parent.node instanceof window.SVGElement) { + 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 + + }, { + key: "put", + value: function put(element, i) { + this.add(element, i); + return element; + } // Add element to given container and return container + + }, { + key: "putIn", + value: function putIn(parent) { + return makeInstance(parent).add(this); + } // Remove element + + }, { + key: "remove", + value: function remove() { + if (this.parent()) { + this.parent().removeElement(this); } return this; @@ -1392,19 +1588,20 @@ var SVG = (function () { value: function removeElement(element) { this.node.removeChild(element.node); return this; - } // Remove all elements in this container + } // Replace element }, { - key: "clear", - value: function clear() { - // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild); - } // remove defs reference - + key: "replace", + value: function replace(element) { + // FIXME: after might not be available here + this.after(element).remove(); + return element; + } // Return id on string conversion - delete this._defs; - return this; + }, { + key: "toString", + value: function toString() { + return this.id(); } // Import raw svg }, { @@ -1434,49 +1631,177 @@ var SVG = (function () { }, { key: "writeDataToDom", value: function writeDataToDom() { - // dump variables recursively - this.each(function () { - this.writeDataToDom(); - }); // remove previously set data - + // dump variables recursively + this.each(function () { + this.writeDataToDom(); + }); + return this; + } + }]); + + return Dom; + }(EventTarget); + extend(Dom, { + attr: attr + }); + + var Doc = getClass(root); + + var Element = + /*#__PURE__*/ + function (_Dom) { + _inherits(Element, _Dom); + + function Element(node) { + var _this; + + _classCallCheck(this, Element); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Element).call(this, node)); // initialize data object + + _this.dom = {}; // create circular reference + + _this.node.instance = _assertThisInitialized(_assertThisInitialized(_this)); + + 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')) || {}); + } + + return _this; + } // Move element by its center + + + _createClass(Element, [{ + key: "center", + value: function center(x, y) { + return this.cx(x).cy(y); + } // Move by center over x-axis + + }, { + key: "cx", + value: function cx(x) { + return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2); + } // Move by center over y-axis + + }, { + key: "cy", + value: function cy(y) { + return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2); + } // Get defs + + }, { + key: "defs", + value: function defs() { + return this.doc().defs(); + } // Get parent document + + }, { + key: "doc", + value: function doc() { + var p = this.parent(Doc); + return p && p.doc(); + } + }, { + key: "getEventHolder", + value: function getEventHolder() { + return this; + } // Set height of element + + }, { + key: "height", + value: function height(_height) { + return this.attr('height', _height); + } // Checks whether the given point inside the bounding box of the element + + }, { + key: "inside", + value: function inside(x, y) { + var box = this.bbox(); + 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 + + }, { + key: "move", + value: function move(x, y) { + return this.x(x).y(y); + } // return array of all ancestors of given type up to the root svg + + }, { + key: "parents", + value: function parents(type) { + var parents = []; + var parent = this; + + do { + parent = parent.parent(type); + if (!parent || parent instanceof getClass('HtmlNode')) break; + parents.push(parent); + } while (parent.parent); + + return parents; + } // Get referenced element form attribute value + + }, { + key: "reference", + value: function reference$$1(attr) { + var id = idFromReference(this.attr(attr)); + return id ? makeInstance(id) : null; + } // set given data to the elements data property + + }, { + key: "setData", + value: function setData(o) { + this.dom = o; + return this; + } // Set element size to given width and height + + }, { + key: "size", + value: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height)); + } // Set width of element + + }, { + key: "width", + value: function width(_width) { + return this.attr('width', _width); + } // write svgjs data to the dom + + }, { + key: "writeDataToDom", + value: function 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; - } + return _get(_getPrototypeOf(Element.prototype), "writeDataToDom", this).call(this); + } // Move over x-axis + }, { - key: "flatten", - value: function flatten(parent) { - this.each(function () { - if (this instanceof Parent) return this.flatten(parent).ungroup(parent); - return this.toParent(parent); - }); // we need this so that Doc does not get removed + key: "x", + value: function x(_x) { + return this.attr('x', _x); + } // Move over y-axis - this.node.firstElementChild || this.remove(); - return this; - } }, { - key: "ungroup", - value: function ungroup(parent) { - parent = parent || this.parent(); - this.each(function () { - return this.toParent(parent); - }); - this.remove(); - return this; + key: "y", + value: function y(_y) { + return this.attr('y', _y); } }]); - return Parent; - }(Element); // registerMethods('Container', { + return Element; + }(Dom); // registerMethods('Element', { var Shape = /*#__PURE__*/ - function (_Parent) { - _inherits(Shape, _Parent); + function (_Element) { + _inherits(Shape, _Element); function Shape() { _classCallCheck(this, Shape); @@ -1485,12 +1810,12 @@ var SVG = (function () { } return Shape; - }(Parent); + }(Element); var Container$1 = /*#__PURE__*/ - function (_Parent) { - _inherits(Container, _Parent); + function (_Element) { + _inherits(Container, _Element); function Container() { _classCallCheck(this, Container); @@ -1498,56 +1823,45 @@ var SVG = (function () { return _possibleConstructorReturn(this, _getPrototypeOf(Container).apply(this, arguments)); } + _createClass(Container, [{ + key: "flatten", + value: function flatten(parent) { + this.each(function () { + if (this instanceof Container) return this.flatten(parent).ungroup(parent); + return this.toParent(parent); + }); // we need this so that Doc does not get removed + + this.node.firstElementChild || this.remove(); + return this; + } + }, { + key: "ungroup", + value: function ungroup(parent) { + parent = parent || this.parent(); + this.each(function () { + return this.toParent(parent); + }); + this.remove(); + return this; + } + }]); + return Container; - }(Parent); + }(Element); var HtmlNode = /*#__PURE__*/ - function (_Parent) { - _inherits(HtmlNode, _Parent); - - function HtmlNode(element) { - var _this; + function (_Dom) { + _inherits(HtmlNode, _Dom); + function HtmlNode(node) { _classCallCheck(this, HtmlNode); - _this = _possibleConstructorReturn(this, _getPrototypeOf(HtmlNode).call(this, element, HtmlNode)); - _this.node = element; - return _this; + return _possibleConstructorReturn(this, _getPrototypeOf(HtmlNode).call(this, node, HtmlNode)); } - _createClass(HtmlNode, [{ - key: "add", - value: function add(element, i) { - element = makeInstance(element); - - if (element.node !== this.node.children[i]) { - this.node.insertBefore(element.node, this.node.children[i] || null); - } - - return this; - } - }, { - key: "put", - value: function put(element, i) { - this.add(element, i); - return element; - } - }, { - key: "removeElement", - value: function removeElement(element) { - this.node.removeChild(element.node); - return this; - } - }, { - key: "getEventTarget", - value: function getEventTarget() { - return this.node; - } - }]); - return HtmlNode; - }(Parent); + }(Dom); register(HtmlNode); var Defs = @@ -1848,8 +2162,8 @@ var SVG = (function () { var Bare = /*#__PURE__*/ - function (_Parent) { - _inherits(Bare, _Parent); + function (_Container) { + _inherits(Bare, _Container); function Bare(node) { _classCallCheck(this, Bare); @@ -1872,7 +2186,7 @@ var SVG = (function () { }]); return Bare; - }(Parent); + }(Container$1); register(Bare); registerMethods('Container', { // Create an element that is not described by SVG.js @@ -2014,7 +2328,7 @@ var SVG = (function () { function find$1(query) { return baseFind(query, this.node); } - registerMethods('Element', { + registerMethods('Dom', { find: find$1 }); @@ -2648,110 +2962,6 @@ var SVG = (function () { }); register(Image); - var subClassArray = function () { - try { - // try es6 subclassing - return Function('name', 'baseClass', '_constructor', ['baseClass = baseClass || Array', 'return {', '[name]: class extends baseClass {', 'constructor (...args) {', 'super(...args)', '_constructor && _constructor.apply(this, args)', '}', '}', '}[name]'].join('\n')); - } catch (e) { - // Use es5 approach - return function (name) { - var baseClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Array; - - var _constructor = arguments.length > 2 ? arguments[2] : undefined; - - var Arr = function Arr() { - baseClass.apply(this, arguments); - _constructor && _constructor.apply(this, arguments); - }; - - Arr.prototype = Object.create(baseClass.prototype); - Arr.prototype.constructor = Arr; - return Arr; - }; - } - }(); - - var SVGArray = subClassArray('SVGArray', Array, function () { - this.init.apply(this, arguments); - }); - extend(SVGArray, { - init: function init() { - //this.splice(0, this.length) - this.length = 0; - this.push.apply(this, _toConsumableArray(this.parse.apply(this, arguments))); - }, - toArray: function toArray() { - // const ret = [] - // ret.push(...this) - // return ret - return Array.prototype.concat.apply([], this); - }, - toString: function toString() { - return this.join(' '); - }, - // Flattens the array if needed - valueOf: function valueOf() { - var ret = []; - ret.push.apply(ret, _toConsumableArray(this)); - return ret; // return this.toArray() - }, - // Parse whitespace separated string - parse: function parse() { - var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - //array = array.valueOf() - // If already is an array, no need to parse it - if (array instanceof Array) return array; - return array.trim().split(delimiter).map(parseFloat); - }, - clone: function clone() { - return new this.constructor(this); - }, - toSet: function toSet() { - return new Set(this); - } - }); // export default class SVGArray extends BaseArray { - // constructor (...args) { - // super() - // this.init(...args) - // } - // - // init (array, fallback = []) { - // //this.splice(0, this.length) - // this.length = 0 - // this.push(...this.parse(array || fallback)) - // } - // - // toArray () { - // return [].concat(this) - // } - // - // toString () { - // return this.join(' ') - // } - // - // valueOf () { - // return this.toArray() - // } - // - // // Parse whitespace separated string - // parse (array) { - // array = array.valueOf() - // - // // if already is an array, no need to parse it - // if (Array.isArray(array)) return array - // - // return array.trim().split(delimiter).map(parseFloat) - // } - // - // clone () { - // return new this.constructor(this) - // } - // - // toSet () { - // return new Set(this) - // } - // } - var PointArray = subClassArray('PointArray', SVGArray); extend(PointArray, { // Convert array to string @@ -3922,69 +4132,23 @@ var SVG = (function () { function (_Container) { _inherits(_Symbol, _Container); - // Initialize node - function _Symbol(node) { - _classCallCheck(this, _Symbol); - - return _possibleConstructorReturn(this, _getPrototypeOf(_Symbol).call(this, nodeOrNew('symbol', node), _Symbol)); - } - - return _Symbol; - }(Container$1); - registerMethods({ - Container: { - symbol: function symbol() { - return this.put(new _Symbol()); - } - } - }); - register(_Symbol); - - function noop() {} // Default animation values - - var timeline = { - duration: 400, - ease: '>', - delay: 0 // Default attribute values - - }; - var attrs = { - // fill and stroke - 'fill-opacity': 1, - 'stroke-opacity': 1, - 'stroke-width': 0, - 'stroke-linejoin': 'miter', - 'stroke-linecap': 'butt', - fill: '#000000', - stroke: '#000000', - opacity: 1, - // position - x: 0, - y: 0, - cx: 0, - cy: 0, - // size - width: 0, - height: 0, - // radius - r: 0, - rx: 0, - ry: 0, - // gradient - offset: 0, - 'stop-opacity': 1, - 'stop-color': '#000000', - // text - 'font-size': 16, - 'font-family': 'Helvetica, Arial, sans-serif', - 'text-anchor': 'start' - }; - - var defaults = /*#__PURE__*/Object.freeze({ - noop: noop, - timeline: timeline, - attrs: attrs + // Initialize node + function _Symbol(node) { + _classCallCheck(this, _Symbol); + + return _possibleConstructorReturn(this, _getPrototypeOf(_Symbol).call(this, nodeOrNew('symbol', node), _Symbol)); + } + + return _Symbol; + }(Container$1); + registerMethods({ + Container: { + symbol: function symbol() { + return this.put(new _Symbol()); + } + } }); + register(_Symbol); // Create plain text node function plain(text) { @@ -4010,8 +4174,8 @@ var SVG = (function () { var Text = /*#__PURE__*/ - function (_Parent) { - _inherits(Text, _Parent); + function (_Shape) { + _inherits(Text, _Shape); // Initialize node function Text(node) { @@ -4178,7 +4342,7 @@ var SVG = (function () { }]); return Text; - }(Parent); + }(Shape); extend(Text, textable); registerMethods({ Container: { @@ -4282,8 +4446,8 @@ var SVG = (function () { var Tspan = /*#__PURE__*/ - function (_Parent) { - _inherits(Tspan, _Parent); + function (_Text) { + _inherits(Tspan, _Text); // Initialize node function Tspan(node) { @@ -4326,7 +4490,7 @@ var SVG = (function () { }]); return Tspan; - }(Parent); + }(Text); extend(Tspan, textable); registerMethods({ Tspan: { @@ -4895,109 +5059,6 @@ var SVG = (function () { } }); - var Color = - /*#__PURE__*/ - function () { - function Color() { - _classCallCheck(this, Color); - - this.init.apply(this, arguments); - } - - _createClass(Color, [{ - key: "init", - value: function init(color, g, b) { - var match; // initialize defaults - - this.r = 0; - this.g = 0; - this.b = 0; - if (!color) return; // parse color - - if (typeof color === 'string') { - if (isRgb.test(color)) { - // get rgb values - match = rgb.exec(color.replace(whitespace, '')); // parse numeric values - - this.r = parseInt(match[1]); - this.g = parseInt(match[2]); - this.b = parseInt(match[3]); - } else if (isHex.test(color)) { - // get hex values - match = hex.exec(fullHex(color)); // parse numeric values - - this.r = parseInt(match[1], 16); - this.g = parseInt(match[2], 16); - this.b = parseInt(match[3], 16); - } - } else if (Array.isArray(color)) { - this.r = color[0]; - this.g = color[1]; - this.b = color[2]; - } else if (_typeof(color) === 'object') { - this.r = color.r; - this.g = color.g; - this.b = color.b; - } else if (arguments.length === 3) { - this.r = color; - this.g = g; - this.b = b; - } - } // Default to hex conversion - - }, { - key: "toString", - value: function toString() { - return this.toHex(); - } - }, { - key: "toArray", - value: function toArray() { - return [this.r, this.g, this.b]; - } // Build hex value - - }, { - key: "toHex", - value: function toHex() { - return '#' + compToHex(Math.round(this.r)) + compToHex(Math.round(this.g)) + compToHex(Math.round(this.b)); - } // Build rgb value - - }, { - key: "toRgb", - value: function toRgb() { - return 'rgb(' + [this.r, this.g, this.b].join() + ')'; - } // Calculate true brightness - - }, { - key: "brightness", - value: function brightness() { - return this.r / 255 * 0.30 + this.g / 255 * 0.59 + this.b / 255 * 0.11; - } // Testers - // Test if given value is a color string - - }], [{ - key: "test", - value: function test(color) { - color += ''; - return isHex.test(color) || isRgb.test(color); - } // Test if given value is a rgb object - - }, { - key: "isRgb", - value: function isRgb$$1(color) { - return color && typeof color.r === 'number' && typeof color.g === 'number' && typeof color.b === 'number'; - } // Test if given value is a color - - }, { - key: "isColor", - value: function isColor(color) { - return this.isRgb(color) || this.test(color); - } - }]); - - return Color; - }(); - /*** Base Class ========== @@ -5781,41 +5842,47 @@ var SVG = (function () { var Runner = /*#__PURE__*/ - function () { + function (_EventTarget) { + _inherits(Runner, _EventTarget); + function Runner(options) { + var _this; + _classCallCheck(this, Runner); - // Store a unique id on the runner, so that we can identify it later - this.id = Runner.id++; // Ensure a default value + _this = _possibleConstructorReturn(this, _getPrototypeOf(Runner).call(this)); // Store a unique id on the runner, so that we can identify it later + + _this.id = Runner.id++; // Ensure a default value options = options == null ? timeline.duration : options; // Ensure that we get a controller options = typeof options === 'function' ? new Controller(options) : options; // Declare all of the variables - this._element = null; - this._timeline = null; - this.done = false; - this._queue = []; // Work out the stepper and the duration + _this._element = null; + _this._timeline = null; + _this.done = false; + _this._queue = []; // Work out the stepper and the duration - this._duration = typeof options === 'number' && options; - this._isDeclarative = options instanceof Controller; - this._stepper = this._isDeclarative ? options : new Ease(); // We copy the current values from the timeline because they can change + _this._duration = typeof options === 'number' && options; + _this._isDeclarative = options instanceof Controller; + _this._stepper = _this._isDeclarative ? options : new Ease(); // We copy the current values from the timeline because they can change - this._history = {}; // Store the state of the runner + _this._history = {}; // Store the state of the runner - this.enabled = true; - this._time = 0; - this._last = 0; // Save transforms applied to this runner + _this.enabled = true; + _this._time = 0; + _this._last = 0; // Save transforms applied to this runner - this.transforms = new Matrix(); - this.transformId = 1; // Looping variables + _this.transforms = new Matrix(); + _this.transformId = 1; // Looping variables - this._haveReversed = false; - this._reverse = false; - this._loopsDone = 0; - this._swing = false; - this._wait = 0; - this._times = 1; + _this._haveReversed = false; + _this._reverse = false; + _this._loopsDone = 0; + _this._swing = false; + _this._wait = 0; + _this._times = 1; + return _this; } /* Runner Definitions @@ -6036,7 +6103,10 @@ var SVG = (function () { var justStarted = this._lastTime < 0 && this._time > 0; var justFinished = this._lastTime < this._time && this.time > duration; this._lastTime = this._time; - // Work out if the runner is finished set the done flag here so animations + + if (justStarted) { + this.fire('start', this); + } // Work out if the runner is finished set the done flag here so animations // know, that they are running in the last step (this is good for // transformations which can be merged) @@ -6050,15 +6120,18 @@ var SVG = (function () { this.transforms = new Matrix(); - var converged = this._run(declarative ? dt : position); // this.fire('step', this) + var converged = this._run(declarative ? dt : position); + this.fire('step', this); } // correct the done flag here // declaritive animations itself know when they converged - this.done = this.done || converged && declarative; // if (this.done) { - // this.fire('finish', this) - // } + this.done = this.done || converged && declarative; + + if (this.done) { + this.fire('finish', this); + } return this; } @@ -6217,7 +6290,7 @@ var SVG = (function () { }]); return Runner; - }(); + }(EventTarget); Runner.id = 0; var FakeRunner = function FakeRunner() { @@ -6299,14 +6372,14 @@ var SVG = (function () { }, { key: "merge", value: function merge() { - var _this = this; + var _this2 = this; var lastRunner = null; this.runners.forEach(function (runner, i) { if (lastRunner && runner.done && lastRunner.done) { - _this.remove(runner.id); + _this2.remove(runner.id); - _this.edit(lastRunner.id, runner.mergeWith(lastRunner)); + _this2.edit(lastRunner.id, runner.mergeWith(lastRunner)); } lastRunner = runner; @@ -6691,7 +6764,6 @@ var SVG = (function () { // export {default as Matrix} from './Matrix.js' // export {default as Morphable} from './Morphable.js' // export {default as SVGNumber} from './SVGNumber.js' - // export {default as Parent} from './Parent.js' // export {default as Path} from './Path.js' // export {default as PathArray} from './PathArray.js' // export {default as Pattern} from './Pattern.js' @@ -6712,9 +6784,9 @@ var SVG = (function () { var Classes = /*#__PURE__*/Object.freeze({ EventTarget: EventTarget, + Dom: Dom, Element: Element, Shape: Shape, - Parent: Parent, Container: Container$1, HtmlNode: HtmlNode, Doc: Doc$1, @@ -6760,98 +6832,6 @@ var SVG = (function () { Spring: Spring }); - function attr(attr, val, ns) { - // act as full getter - if (attr == null) { - // get an object of attributes - attr = {}; - val = this.node.attributes; - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = val[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var node = _step.value; - attr[node.nodeName] = isNumber.test(node.nodeValue) ? parseFloat(node.nodeValue) : node.nodeValue; - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - return attr; - } else if (Array.isArray(attr)) ; else if (_typeof(attr) === 'object') { - // apply every attribute individually if an object is passed - for (val in attr) { - this.attr(val, attr[val]); - } - } else if (val === null) { - // remove value - this.node.removeAttribute(attr); - } else if (val == null) { - // act as a getter if the first and only argument is not an object - val = this.node.getAttribute(attr); - return val == null ? attrs[attr] // FIXME: do we need to return defaults? - : isNumber.test(val) ? parseFloat(val) : val; - } else { - // convert image fill and stroke to patterns - if (attr === 'fill' || attr === 'stroke') { - if (isImage.test(val)) { - val = this.doc().defs().image(val); - } - } // FIXME: This is fine, but what about the lines above? - // How does attr know about image()? - - - while (typeof val.attrHook == 'function') { - val = val.attrHook(this, attr); - } // ensure correct numeric values (also accepts NaN and Infinity) - - - if (typeof val === 'number') { - val = new SVGNumber(val); - } else if (Color.isColor(val)) { - // ensure full hex color - val = new Color(val); - } else if (val.constructor === Array) { - // Check for plain arrays and parse array values - val = new SVGArray(val); - } // if the passed attribute is leading... - - - if (attr === 'leading') { - // ... call the leading method instead - if (this.leading) { - this.leading(val); - } - } else { - // set given attribute on node - typeof ns === 'string' ? this.node.setAttributeNS(ns, attr, val.toString()) : this.node.setAttribute(attr, val.toString()); - } // rebuild if required - - - if (this.rebuild && (attr === 'font-size' || attr === 'x')) { - this.rebuild(); - } - } - - return this; - } - registerMethods('Element', { - attr: attr - }); - // ### This module adds backward / forward functionality to elements. function siblings() { @@ -6926,7 +6906,7 @@ var SVG = (function () { this.parent().add(element, i + 1); return this; } - registerMethods('Element', { + registerMethods('Dom', { siblings: siblings, position: position, next: next, @@ -6956,10 +6936,55 @@ var SVG = (function () { return this; } - registerMethods('Element', { + registerMethods('Dom', { data: data }); + function classes() { + var attr = this.attr('class'); + return attr == null ? [] : attr.trim().split(delimiter); + } // Return true if class exists on the node, false otherwise + + + function hasClass(name) { + return this.classes().indexOf(name) !== -1; + } // Add class to the node + + + function addClass(name) { + if (!this.hasClass(name)) { + var array = this.classes(); + array.push(name); + this.attr('class', array.join(' ')); + } + + return this; + } // Remove class from the node + + + function removeClass(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 + + + function toggleClass(name) { + return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); + } + + registerMethods('Dom', { + classes: classes, + hasClass: hasClass, + addClass: addClass, + removeClass: removeClass, + toggleClass: toggleClass + }); + // Dynamic style generator function css(style, val) { @@ -7040,7 +7065,7 @@ var SVG = (function () { function visible() { return this.css('display') !== 'none'; } - registerMethods('Element', { + registerMethods('Dom', { css: css, show: show, hide: hide, @@ -7147,7 +7172,7 @@ var SVG = (function () { function memory() { return this._memory = this._memory || {}; } - registerMethods('Element', { + registerMethods('Dom', { remember: remember, forget: forget, memory: memory @@ -7170,7 +7195,7 @@ var SVG = (function () { return this; } - if (typeof o === 'string' || Color.isRgb(o) || o && typeof o.fill === 'function') { + if (typeof o === 'string' || Color.isRgb(o) || o instanceof Element) { this.attr(m, o); } else { // set all attributes from sugar.fill and sugar.stroke list @@ -7184,7 +7209,7 @@ var SVG = (function () { return this; }; - registerMethods(['Element', 'Runner'], extension); + registerMethods(['Shape', 'Runner'], extension); }); registerMethods(['Element', 'Runner'], { // Let the user set the matrix directly @@ -7291,7 +7316,7 @@ var SVG = (function () { return new Point(this.node.getPointAtLength(length)); } }); - registerMethods(['Parent', 'Runner'], { + registerMethods(['Element', 'Runner'], { // Set font font: function font(a, v) { if (_typeof(a) === 'object') { @@ -7304,7 +7329,6 @@ var SVG = (function () { } }); - // import {extend} from './tools.js' var extend$1 = extend; extend$1([Doc$1, _Symbol, Image, Pattern, Marker], getMethodsFor('viewbox')); extend$1([Line, Polyline, Polygon, Path], getMethodsFor('marker')); @@ -7314,8 +7338,9 @@ var SVG = (function () { extend$1([Text, Tspan], getMethodsFor('Tspan')); extend$1([Rect, Ellipse, Circle, Gradient], getMethodsFor('radius')); extend$1(EventTarget, getMethodsFor('EventTarget')); + extend$1(Dom, getMethodsFor('Dom')); extend$1(Element, getMethodsFor('Element')); - extend$1(Element, getMethodsFor('Parent')); //extend(Classes.Element, getConstructor('Memory')) + extend$1(Shape, getMethodsFor('Shape')); //extend(Classes.Element, getConstructor('Memory')) extend$1(Container$1, getMethodsFor('Container')); registerMorphableType([SVGNumber, Color, Box$1, Matrix, SVGArray, PointArray, PathArray]); @@ -7331,7 +7356,7 @@ var SVG = (function () { SVG.regex = regex; // satisfy tests, fix later SVG.get = SVG; SVG.find = baseFind; - Object.assign(SVG, ns$1); // import Base from './Base.js' + Object.assign(SVG, ns$1); SVG.easing = easing; Object.assign(SVG, events); SVG.TransformBag = TransformBag; diff --git a/dist/svg.min.js b/dist/svg.min.js index 27a2e20..ed14bb2 100644 --- a/dist/svg.min.js +++ b/dist/svg.min.js @@ -1 +1 @@ -var SVG=function(){"use strict";function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;nn.x&&e>n.y&&t=e.time?e.run():Et.timeouts.push(e),e!==n););for(var i=null,r=Et.frames.last();i!==r&&(i=Et.frames.shift());)i.run();Et.transforms.forEach(function(t){t()}),Et.nextDraw=Et.timeouts.first()||Et.frames.first()?window.requestAnimationFrame(Et._draw):null}},Nt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q(t,"string"==typeof t?null:t),e))}return r(e,_t),a(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function Pt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function Dt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function zt(t){return null==t?this.attr("cx"):this.attr("cx",t)}function Rt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function qt(t){return null==t?2*this.rx():this.rx(new mt(t).divide(2))}function Lt(t){return null==t?2*this.ry():this.ry(new mt(t).divide(2))}function Ft(t,e){var n=R(this,t,e);return this.rx(new mt(n.width).divide(2)).ry(new mt(n.height).divide(2))}et(Nt),at("Container",{element:function(t,e){return this.put(new Nt(t,e))}});var It=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:Pt,y:Dt,cx:zt,cy:Rt,width:qt,height:Lt,size:Ft}),Xt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("circle",t),e))}return r(e,Ot),a(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Yt(t,e){return kt((e||document).querySelectorAll(t),function(t){return tt(t)})}$(Xt,{x:Pt,y:Dt,cx:zt,cy:Rt,width:qt,height:Lt,size:Ft}),at({Element:{circle:function(t){return this.put(new Xt).radius(new mt(t).divide(2)).move(0,0)}}}),et(Xt),at("Element",{find:function(t){return Yt(t,this.node)}});var Ht=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("clipPath",t),e))}return r(e,At),a(e,[{key:"remove",value:function(){return this.targets().forEach(function(t){t.unclip()}),c(u(e.prototype),"remove",this).call(this)}},{key:"targets",value:function(){return Yt('svg [clip-path*="'+this.id()+'"]')}}]),e}();at({Container:{clip:function(){return this.defs().put(new Ht)}},Element:{clipWith:function(t){var e=t instanceof Ht?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.id()+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}}),et(Ht);var Bt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("a",t),e))}return r(e,At),a(e,[{key:"to",value:function(t){return this.attr("href",t,B)}},{key:"target",value:function(t){return this.attr("target",t)}}]),e}();at({Container:{link:function(t){return this.put(new Bt).to(t)}},Element:{linkTo:function(t){var e=new Bt;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}}),et(Bt);var Gt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("ellipse",t),e))}return r(e,Ot),e}();$(Gt,It),at("Container",{ellipse:function(t,e){return this.put(new Gt).size(t,e).move(0,0)}}),et(Gt);var Vt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("stop",t),e))}return r(e,wt),a(e,[{key:"update",value:function(t){return("number"==typeof t||t instanceof mt)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new mt(t.offset)),this}}]),e}();et(Vt);var Qt=Object.freeze({from:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({fx:new mt(t),fy:new mt(e)}):this.attr({x1:new mt(t),y1:new mt(e)})},to:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({cx:new mt(t),cy:new mt(e)}):this.attr({x2:new mt(t),y2:new mt(e)})}});function Ut(){if(!Ut.nodes){var t=(new Mt).size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"}),e=t.path().node;Ut.nodes={svg:t,path:e}}if(!Ut.nodes.svg.node.parentNode){var n=document.body||document.documentElement;Ut.nodes.svg.addTo(n)}return Ut.nodes}var $t=function(){function r(t,e,n){var i;o(this,r),n=n||{x:0,y:0},i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"===l(t)?{x:t.x,y:t.y}:{x:t,y:e},this.x=null==i.x?n.x:i.x,this.y=null==i.y?n.y:i.y}return a(r,[{key:"clone",value:function(){return new r(this)}},{key:"native",value:function(){var t=Ut().svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t}},{key:"transform",value:function(t){return new r(t.a*this.x+t.c*this.y+t.e,t.b*this.x+t.d*this.y+t.f)}}]),r}();at({Element:{point:function(t,e){return new $t(t,e).transform(this.screenCTM().inverse())}}});var Jt=function(){function u(){o(this,u),this.init.apply(this,arguments)}return a(u,[{key:"init",value:function(t){var e;t="string"==typeof t?t.split(j).map(parseFloat):Array.isArray(t)?t:"object"===l(t)?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):[0,0,0,0],this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],null==(e=this).x&&(e.x=0,e.y=0,e.width=0,e.height=0),e.w=e.width,e.h=e.height,e.x2=e.x+e.width,e.y2=e.y+e.height,e.cx=e.x+e.width/2,e.cy=e.y+e.height/2}},{key:"merge",value:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new u(e,n,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-n)}},{key:"transform",value:function(e){var n=1/0,i=-1/0,r=1/0,s=-1/0;return[new $t(this.x,this.y),new $t(this.x2,this.y),new $t(this.x,this.y2),new $t(this.x2,this.y2)].forEach(function(t){t=t.transform(e),n=Math.min(n,t.x),i=Math.max(i,t.x),r=Math.min(r,t.y),s=Math.max(s,t.y)}),new u(n,r,i-n,s-r)}},{key:"addOffset",value:function(){return this.x+=window.pageXOffset,this.y+=window.pageYOffset,this}},{key:"toString",value:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}},{key:"toArray",value:function(){return[this.x,this.y,this.width,this.height]}}]),u}();function Wt(e){var n,t,i;try{if(n=e(this.node),!((i=n).w||i.h||i.x||i.y||(t=this.node,(document.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===document}).call(document.documentElement,t))))throw new Error("Element not in the dom")}catch(t){try{var r=this.clone(Ut().svg).show();n=e(r.node),r.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return n}at({Element:{bbox:function(){return new Jt(Wt.call(this,function(t){return t.getBBox()}))},rbox:function(t){var e=new Jt(Wt.call(this,function(t){return t.getBoundingClientRect()}));return t?e.transform(t.screenCTM().inverse()):e.addOffset()}},viewbox:{viewbox:function(t,e,n,i){return null==t?new Jt(this.attr("viewBox")):this.attr("viewBox",new Jt(t,e,n,i))}}});var Zt=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q(t+"Gradient","string"==typeof t?null:t),i))}return r(i,At),a(i,[{key:"stop",value:function(t,e,n){return this.put(new Vt).update(t,e,n)}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="gradientTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new Jt}}]),i}();$(Zt,Qt),at({Container:{gradient:function(t,e){return this.defs().gradient(t,e)}},Defs:{gradient:function(t,e){return this.put(new Zt(t)).update(e)}}}),et(Zt);var Kt=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q("pattern",t),i))}return r(i,At),a(i,[{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="patternTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new Jt}}]),i}();at({Container:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}},Defs:{pattern:function(t,e,n){return this.put(new Kt).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}}),et(Kt);var te=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("image",t),e))}return r(e,Ot),a(e,[{key:"load",value:function(n,i){if(!n)return this;var r=new window.Image;return ft(r,"load",function(t){var e=this.parent(Kt);0===this.width()&&0===this.height()&&this.size(r.width,r.height),e instanceof Kt&&0===e.width()&&0===e.height()&&e.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:r.width,height:r.height,ratio:r.width/r.height,url:n})},this),ft(r,"load error",function(){dt(r)}),this.attr("href",r.src=n,B)}},{key:"attrHook",value:function(t){var e=this;return t.doc().defs().pattern(0,0,function(t){t.add(e)})}}]),e}();at({Container:{image:function(t,e){return this.put(new te).size(0,0).load(t,e)}}}),et(te);var ee=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1",delay:0},xe={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},_e=Object.freeze({noop:ke,timeline:be,attrs:xe});var Oe=Object.freeze({plain:function(t){return!1===this._build&&this.clear(),this.node.appendChild(document.createTextNode(t)),this},length:function(){return this.node.getComputedTextLength()}}),Ae=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this,Q("text",t),n))).dom.leading=new mt(1.3),e._rebuild=!0,e._build=!1,e.attr("font-family",xe["font-family"]),e}return r(n,_t),a(n,[{key:"x",value:function(t){return null==t?this.attr("x"):this.attr("x",t)}},{key:"y",value:function(t){var e=this.attr("y"),n="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-n:e:this.attr("y","number"==typeof t?t+n:t)}},{key:"cx",value:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)}},{key:"cy",value:function(t){return null==t?this.bbox().cy:this.y(t-this.bbox().height/2)}},{key:"text",value:function(t){if(void 0===t){var e=this.node.childNodes,n=0;t="";for(var i=0,r=e.length;i":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Pe=function(){function t(){o(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),De=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).ease=Ne[t||be.ease]||t,e}return r(n,Pe),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),ze=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).stepper=t,e}return r(n,Pe),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Re(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var qe=function(t){function i(t,e){var n;return o(this,i),(n=h(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,ze),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i);this._lastTime=this._time;var s=this._isDeclarative;if(this.done=!s&&!r&&this._time>=i,n||s){this._initialise(n),this.transforms=new Se;var u=this._run(s?t:e)}return this.done=this.done||u&&s,this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new De(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e",delay:0},_t={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},Ot=Object.freeze({noop:bt,timeline:xt,attrs:_t}),At=function(){function t(){o(this,t),this.init.apply(this,arguments)}return a(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?k.test(t)?(i=p.exec(t.replace(g,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):w.test(t)&&(i=y.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+z(Math.round(this.r))+z(Math.round(this.g))+z(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",w.test(t)||k.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}(),Ct=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1n.x&&e>n.y&&t=e.time?e.run():Ft.timeouts.push(e),e!==n););for(var i=null,r=Ft.frames.last();i!==r&&(i=Ft.frames.shift());)i.run();Ft.transforms.forEach(function(t){t()}),Ft.nextDraw=Ft.timeouts.first()||Ft.frames.first()?window.requestAnimationFrame(Ft._draw):null}},It=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q(t,"string"==typeof t?null:t),e))}return r(e,Dt),a(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function Xt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function Yt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function Ht(t){return null==t?this.attr("cx"):this.attr("cx",t)}function Gt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function Vt(t){return null==t?2*this.rx():this.rx(new Mt(t).divide(2))}function Bt(t){return null==t?2*this.ry():this.ry(new Mt(t).divide(2))}function Qt(t,e){var n=R(this,t,e);return this.rx(new Mt(n.width).divide(2)).ry(new Mt(n.height).divide(2))}et(It),at("Container",{element:function(t,e){return this.put(new It(t,e))}});var Ut=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:Xt,y:Yt,cx:Ht,cy:Gt,width:Vt,height:Bt,size:Qt}),$t=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("circle",t),e))}return r(e,Nt),a(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Wt(t,e){return gt((e||document).querySelectorAll(t),function(t){return tt(t)})}$($t,{x:Xt,y:Yt,cx:Ht,cy:Gt,width:Vt,height:Bt,size:Qt}),at({Element:{circle:function(t){return this.put(new $t).radius(new Mt(t).divide(2)).move(0,0)}}}),et($t),at("Dom",{find:function(t){return Wt(t,this.node)}});var Jt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("clipPath",t),e))}return r(e,Dt),a(e,[{key:"remove",value:function(){return this.targets().forEach(function(t){t.unclip()}),c(u(e.prototype),"remove",this).call(this)}},{key:"targets",value:function(){return Wt('svg [clip-path*="'+this.id()+'"]')}}]),e}();at({Container:{clip:function(){return this.defs().put(new Jt)}},Element:{clipWith:function(t){var e=t instanceof Jt?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.id()+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}}),et(Jt);var Zt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("a",t),e))}return r(e,Dt),a(e,[{key:"to",value:function(t){return this.attr("href",t,G)}},{key:"target",value:function(t){return this.attr("target",t)}}]),e}();at({Container:{link:function(t){return this.put(new Zt).to(t)}},Element:{linkTo:function(t){var e=new Zt;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}}),et(Zt);var Kt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("ellipse",t),e))}return r(e,Nt),e}();$(Kt,Ut),at("Container",{ellipse:function(t,e){return this.put(new Kt).size(t,e).move(0,0)}}),et(Kt);var te=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("stop",t),e))}return r(e,Et),a(e,[{key:"update",value:function(t){return("number"==typeof t||t instanceof Mt)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new Mt(t.offset)),this}}]),e}();et(te);var ee=Object.freeze({from:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({fx:new Mt(t),fy:new Mt(e)}):this.attr({x1:new Mt(t),y1:new Mt(e)})},to:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({cx:new Mt(t),cy:new Mt(e)}):this.attr({x2:new Mt(t),y2:new Mt(e)})}});function ne(){if(!ne.nodes){var t=(new Rt).size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"}),e=t.path().node;ne.nodes={svg:t,path:e}}if(!ne.nodes.svg.node.parentNode){var n=document.body||document.documentElement;ne.nodes.svg.addTo(n)}return ne.nodes}var ie=function(){function r(t,e,n){var i;o(this,r),n=n||{x:0,y:0},i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"===l(t)?{x:t.x,y:t.y}:{x:t,y:e},this.x=null==i.x?n.x:i.x,this.y=null==i.y?n.y:i.y}return a(r,[{key:"clone",value:function(){return new r(this)}},{key:"native",value:function(){var t=ne().svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t}},{key:"transform",value:function(t){return new r(t.a*this.x+t.c*this.y+t.e,t.b*this.x+t.d*this.y+t.f)}}]),r}();at({Element:{point:function(t,e){return new ie(t,e).transform(this.screenCTM().inverse())}}});var re=function(){function u(){o(this,u),this.init.apply(this,arguments)}return a(u,[{key:"init",value:function(t){var e;t="string"==typeof t?t.split(C).map(parseFloat):Array.isArray(t)?t:"object"===l(t)?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):[0,0,0,0],this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],null==(e=this).x&&(e.x=0,e.y=0,e.width=0,e.height=0),e.w=e.width,e.h=e.height,e.x2=e.x+e.width,e.y2=e.y+e.height,e.cx=e.x+e.width/2,e.cy=e.y+e.height/2}},{key:"merge",value:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new u(e,n,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-n)}},{key:"transform",value:function(e){var n=1/0,i=-1/0,r=1/0,s=-1/0;return[new ie(this.x,this.y),new ie(this.x2,this.y),new ie(this.x,this.y2),new ie(this.x2,this.y2)].forEach(function(t){t=t.transform(e),n=Math.min(n,t.x),i=Math.max(i,t.x),r=Math.min(r,t.y),s=Math.max(s,t.y)}),new u(n,r,i-n,s-r)}},{key:"addOffset",value:function(){return this.x+=window.pageXOffset,this.y+=window.pageYOffset,this}},{key:"toString",value:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}},{key:"toArray",value:function(){return[this.x,this.y,this.width,this.height]}}]),u}();function se(e){var n,t,i;try{if(n=e(this.node),!((i=n).w||i.h||i.x||i.y||(t=this.node,(document.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===document}).call(document.documentElement,t))))throw new Error("Element not in the dom")}catch(t){try{var r=this.clone(ne().svg).show();n=e(r.node),r.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return n}at({Element:{bbox:function(){return new re(se.call(this,function(t){return t.getBBox()}))},rbox:function(t){var e=new re(se.call(this,function(t){return t.getBoundingClientRect()}));return t?e.transform(t.screenCTM().inverse()):e.addOffset()}},viewbox:{viewbox:function(t,e,n,i){return null==t?new re(this.attr("viewBox")):this.attr("viewBox",new re(t,e,n,i))}}});var ue=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q(t+"Gradient","string"==typeof t?null:t),i))}return r(i,Dt),a(i,[{key:"stop",value:function(t,e,n){return this.put(new te).update(t,e,n)}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="gradientTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new re}}]),i}();$(ue,ee),at({Container:{gradient:function(t,e){return this.defs().gradient(t,e)}},Defs:{gradient:function(t,e){return this.put(new ue(t)).update(e)}}}),et(ue);var oe=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q("pattern",t),i))}return r(i,Dt),a(i,[{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="patternTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new re}}]),i}();at({Container:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}},Defs:{pattern:function(t,e,n){return this.put(new oe).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}}),et(oe);var ae=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("image",t),e))}return r(e,Nt),a(e,[{key:"load",value:function(n,i){if(!n)return this;var r=new window.Image;return dt(r,"load",function(t){var e=this.parent(oe);0===this.width()&&0===this.height()&&this.size(r.width,r.height),e instanceof oe&&0===e.width()&&0===e.height()&&e.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:r.width,height:r.height,ratio:r.width/r.height,url:n})},this),dt(r,"load error",function(){vt(r)}),this.attr("href",r.src=n,G)}},{key:"attrHook",value:function(t){var e=this;return t.doc().defs().pattern(0,0,function(t){t.add(e)})}}]),e}();at({Container:{image:function(t,e){return this.put(new ae).size(0,0).load(t,e)}}}),et(ae);var he=Ct("PointArray",jt);$(he,{toString:function(){for(var t=0,e=this.length,n=[];t":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Pe=function(){function t(){o(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),ze=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).ease=De[t||xt.ease]||t,e}return r(n,Pe),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),Re=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).stepper=t,e}return r(n,Pe),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function qe(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var Le=function(t){function i(t,e){var n;return o(this,i),(n=h(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,Re),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i;this._lastTime=this._time,r&&this.fire("start",this);var u=this._isDeclarative;if(this.done=!u&&!s&&this._time>=i,n||u){this._initialise(n),this.transforms=new Ee;var o=this._run(u?t:e);this.fire("step",this)}return this.done=this.done||o&&u,this.done&&this.fire("finish",this),this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new ze(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e= 0 + } + + // Get / set id + id (id) { + // generate new id if no id set + 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) + } + + // Gets index of given element + index (element) { + return [].slice.call(this.node.childNodes).indexOf(element.node) + } + + // Get the last child + last () { + return adopt(this.node.lastChild) + } + + // matches the element vs a css selector + matches (selector) { + return matcher(this.node, selector) + } + + // Returns the svg node to call native svg methods on it + native () { + return this.node + } + + // Returns the parent element instance + parent (type) { + var parent = this + + // check for parent + if (!parent.node.parentNode) return null + + // get parent element + parent = adopt(parent.node.parentNode) + + if (!type) return parent + + // loop trough ancestors if type is given + while (parent && parent.node instanceof window.SVGElement) { + 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) + return element + } + + // Add element to given container and return container + putIn (parent) { + return makeInstance(parent).add(this) + } + + // Remove element + remove () { + if (this.parent()) { + this.parent().removeElement(this) + } + + return this + } + + // Remove a given child + removeElement (element) { + this.node.removeChild(element.node) + + return this + } + + // Replace element + replace (element) { + // FIXME: after might not be available here + this.after(element).remove() + + return element + } + + // Return id on string conversion + toString () { + return this.id() + } + + // Import raw svg + svg (svg) { + var well, len + + // act as a setter if svg is given + if (svg) { + // create temporary holder + well = document.createElementNS(ns, 'svg') + // dump raw svg + well.innerHTML = svg + + // transplant nodes + for (len = well.children.length; len--;) { + this.node.appendChild(well.firstElementChild) + } + + // otherwise act as a getter + } else { + // write svgjs data to the dom + this.writeDataToDom() + + return this.node.outerHTML + } + + return this + } + + // write svgjs data to the dom + writeDataToDom () { + // dump variables recursively + this.each(function () { + this.writeDataToDom() + }) + + return this + } +} + +import {extend} from './tools.js' +import attr from './attr.js' +extend(Dom, {attr}) diff --git a/src/Element.js b/src/Element.js index 5e798ff..e7944fc 100644 --- a/src/Element.js +++ b/src/Element.js @@ -1,27 +1,20 @@ import {proportionalSize, matcher, idFromReference} from './helpers.js' -import {makeInstance, adopt, assignNewId, eid, root, getClass} from './adopter.js' +import {makeInstance, root, getClass} from './adopter.js' import {delimiter} from './regex.js' import {ns} from './namespaces.js' import SVGNumber from './SVGNumber.js' -import {registerMethods} from './methods.js' -import {registerConstructor} from './methods.js' -import EventTarget from './EventTarget.js' +import Dom from './Dom.js' const Doc = getClass(root) -//export const name = 'Element' - -export default class Element extends EventTarget { +export default class Element extends Dom { constructor (node) { - super() + super(node) - // initialize data object + // initialize data object this.dom = {} - // create circular reference - this.node = node - - this.type = node.nodeName + // create circular reference this.node.instance = this if (node.hasAttribute('svgjs:data')) { @@ -30,14 +23,9 @@ export default class Element extends EventTarget { } } - // Move over x-axis - x (x) { - return this.attr('x', x) - } - - // Move over y-axis - y (y) { - return this.attr('y', y) + // Move element by its center + center (x, y) { + return this.cx(x).cy(y) } // Move by center over x-axis @@ -52,19 +40,19 @@ export default class Element extends EventTarget { : this.y(y - this.height() / 2) } - // Move element to given x and y values - move (x, y) { - return this.x(x).y(y) + // Get defs + defs () { + return this.doc().defs() } - // Move element by its center - center (x, y) { - return this.cx(x).cy(y) + // Get parent document + doc () { + let p = this.parent(Doc) + return p && p.doc() } - // Set width of element - width (width) { - return this.attr('width', width) + getEventHolder () { + return this } // Set height of element @@ -72,65 +60,6 @@ export default class Element extends EventTarget { return this.attr('height', height) } - // Set element size to given width and height - size (width, height) { - let p = proportionalSize(this, width, height) - - return this - .width(new SVGNumber(p.width)) - .height(new SVGNumber(p.height)) - } - - // Clone element - clone (parent) { - // write dom data to the dom so the clone can pickup the data - this.writeDataToDom() - - // clone element and assign new id - let 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 () { - if (this.parent()) { this.parent().removeElement(this) } - - return this - } - - // Replace element - replace (element) { - this.after(element).remove() - - return element - } - - // Add element to given container and return self - addTo (parent) { - return makeInstance(parent).put(this) - } - - // Add element to given container and return container - putIn (parent) { - return makeInstance(parent).add(this) - } - - // Get / set id - id (id) { - // generate new id if no id set - 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) - } - // Checks whether the given point inside the bounding box of the element inside (x, y) { let box = this.bbox() @@ -141,83 +70,9 @@ export default class Element extends EventTarget { y < box.y + box.height } - // Return id on string conversion - toString () { - return this.id() - } - - // Return array of classes on the node - classes () { - var attr = this.attr('class') - return attr == null ? [] : attr.trim().split(delimiter) - } - - // Return true if class exists on the node, false otherwise - hasClass (name) { - return this.classes().indexOf(name) !== -1 - } - - // Add class to the node - addClass (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 (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 (name) { - return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) - } - - // Get referenced element form attribute value - reference (attr) { - let id = idFromReference(this.attr(attr)) - return id ? makeInstance(id) : null - } - - // Returns the parent element instance - parent (type) { - var parent = this - - // check for parent - if (!parent.node.parentNode) return null - - // get parent element - parent = adopt(parent.node.parentNode) - - if (!type) return parent - - // loop trough ancestors if type is given - while (parent && parent.node instanceof window.SVGElement) { - if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent - parent = adopt(parent.node.parentNode) - } - } - - // Get parent document - doc () { - let p = this.parent(Doc) - return p && p.doc() - } - - // Get defs - defs () { - return this.doc().defs() + // Move element to given x and y values + move (x, y) { + return this.x(x).y(y) } // return array of all ancestors of given type up to the root svg @@ -235,22 +90,30 @@ export default class Element extends EventTarget { return parents } - // matches the element vs a css selector - matches (selector) { - return matcher(this.node, selector) + // Get referenced element form attribute value + reference (attr) { + let id = idFromReference(this.attr(attr)) + return id ? makeInstance(id) : null } - // Returns the svg node to call native svg methods on it - native () { - return this.node + // set given data to the elements data property + setData (o) { + this.dom = o + return this } - // Import raw svg - svg () { - // write svgjs data to the dom - this.writeDataToDom() + // Set element size to given width and height + size (width, height) { + let p = proportionalSize(this, width, height) - return this.node.outerHTML + return this + .width(new SVGNumber(p.width)) + .height(new SVGNumber(p.height)) + } + + // Set width of element + width (width) { + return this.attr('width', width) } // write svgjs data to the dom @@ -261,17 +124,18 @@ export default class Element extends EventTarget { if (Object.keys(this.dom).length) { this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)) // see #428 } - return this + + return super.writeDataToDom() } - // set given data to the elements data property - setData (o) { - this.dom = o - return this + // Move over x-axis + x (x) { + return this.attr('x', x) } - getEventTarget () { - return this.node + // Move over y-axis + y (y) { + return this.attr('y', y) } } diff --git a/src/EventTarget.js b/src/EventTarget.js index a72cafd..637f7f8 100644 --- a/src/EventTarget.js +++ b/src/EventTarget.js @@ -3,11 +3,13 @@ import {on, off, dispatch} from './event.js' import {extend} from './tools.js' export default class EventTarget extends Base{ - constructor (node = {}) { + constructor ({events = {}} = {}) { super() - this.events = node.events || {} + this.events = events } + addEventListener () {} + // Bind given event to listener on (event, listener, binding, options) { on(this, event, listener, binding, options) @@ -24,11 +26,36 @@ export default class EventTarget extends Base{ return dispatch(this, event, data) } + dispatchEvent (event) { + const bag = this.getEventHolder().events + if (!bag) return true + + const events = bag[event.type] + + for (let i in events) { + for (let j in events[i]) { + events[i][j](event) + } + } + + return !event.defaultPrevented + } + // Fire given event fire (event, data) { this.dispatch(event, data) return this } + + getEventHolder () { + return this + } + + getEventTarget () { + return this + } + + removeEventListener () {} } diff --git a/src/HtmlNode.js b/src/HtmlNode.js index 258c0ec..ff45984 100644 --- a/src/HtmlNode.js +++ b/src/HtmlNode.js @@ -1,35 +1,9 @@ -import {makeInstance} from './adopter.js' -import Parent from './Parent.js' +import Dom from './Dom.js' import {register} from './adopter.js' -export default class HtmlNode extends Parent { - constructor (element) { - super(element, HtmlNode) - this.node = element - } - - add (element, i) { - element = makeInstance(element) - - if (element.node !== this.node.children[i]) { - this.node.insertBefore(element.node, this.node.children[i] || null) - } - - return this - } - - put (element, i) { - this.add(element, i) - return element - } - - removeElement (element) { - this.node.removeChild(element.node) - return this - } - - getEventTarget () { - return this.node +export default class HtmlNode extends Dom { + constructor (node) { + super(node, HtmlNode) } } diff --git a/src/Parent.js b/src/Parent.js deleted file mode 100644 index 6786329..0000000 --- a/src/Parent.js +++ /dev/null @@ -1,169 +0,0 @@ -import {makeInstance, adopt} from './adopter.js' -import {map} from './utils.js' -import {registerMethods} from './methods.js' -import Element from './Element.js' -import {ns} from './namespaces.js' - -export default class Parent extends Element { - // Returns all child elements - children () { - return map(this.node.children, function (node) { - return adopt(node) - }) - } - - // Add given element at a position - 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]) - } - - return this - } - - // Basically does the same as `add()` but returns the added element instead - put (element, i) { - this.add(element, i) - return element.instance || element - } - - // Checks if the given element is a child - has (element) { - return this.index(element) >= 0 - } - - // Gets index of given element - index (element) { - return [].slice.call(this.node.childNodes).indexOf(element.node) - } - - // Get a element at the given index - get (i) { - return adopt(this.node.childNodes[i]) - } - - // Get first child - first () { - return adopt(this.node.firstChild) - } - - // Get the last child - last () { - return adopt(this.node.lastChild) - } - - // Iterates over all children and invokes a given block - each (block, deep) { - var children = this.children() - var i, il - - for (i = 0, il = children.length; i < il; i++) { - if (children[i] instanceof Element) { - block.apply(children[i], [i, children]) - } - - if (deep && (children[i] instanceof Parent)) { - children[i].each(block, deep) - } - } - - return this - } - - // Remove a given child - removeElement (element) { - this.node.removeChild(element.node) - - return this - } - - // Remove all elements in this container - clear () { - // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) - } - - // remove defs reference - delete this._defs - - return this - } - - // Import raw svg - svg (svg) { - var well, len - - // act as a setter if svg is given - if (svg) { - // create temporary holder - well = document.createElementNS(ns, 'svg') - // dump raw svg - well.innerHTML = svg - - // transplant nodes - for (len = well.children.length; len--;) { - this.node.appendChild(well.firstElementChild) - } - - // otherwise act as a getter - } else { - // write svgjs data to the dom - this.writeDataToDom() - - return this.node.outerHTML - } - - return this - } - - // write svgjs data to the dom - writeDataToDom () { - // dump variables recursively - this.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 - } - - flatten (parent) { - this.each(function () { - if (this instanceof Parent) return this.flatten(parent).ungroup(parent) - return this.toParent(parent) - }) - - // we need this so that Doc does not get removed - this.node.firstElementChild || this.remove() - - return this - } - - ungroup (parent) { - parent = parent || this.parent() - - this.each(function () { - return this.toParent(parent) - }) - - this.remove() - - return this - } -} - - -// registerMethods('Container', { -// children, add, put, has, index, get, first, last, each, -// removeElement, clear, svg, writeDataToDom, flatten, ungroup -// }) diff --git a/src/Runner.js b/src/Runner.js index 52731e0..b8bafa6 100644 --- a/src/Runner.js +++ b/src/Runner.js @@ -9,6 +9,7 @@ import {extend} from './tools.js' import Animator from './Animator.js' import Point from './Point.js' import {registerMethods} from './methods.js' +import EventTarget from './EventTarget.js' // FIXME: What is this doing here? // easing = { @@ -18,8 +19,10 @@ import {registerMethods} from './methods.js' // '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } // } -export default class Runner { +export default class Runner extends EventTarget { constructor (options) { + super() + // Store a unique id on the runner, so that we can identify it later this.id = Runner.id++ @@ -266,7 +269,7 @@ export default class Runner { var justFinished = this._lastTime < this._time && this.time > duration this._lastTime = this._time if (justStarted) { - // this.fire('start', this) + this.fire('start', this) } // Work out if the runner is finished set the done flag here so animations @@ -282,14 +285,14 @@ export default class Runner { // clear the transforms on this runner so they dont get added again and again this.transforms = new Matrix() var converged = this._run(declarative ? dt : position) - // this.fire('step', this) + this.fire('step', this) } // correct the done flag here // declaritive animations itself know when they converged this.done = this.done || (converged && declarative) - // if (this.done) { - // this.fire('finish', this) - // } + if (this.done) { + this.fire('finish', this) + } return this } diff --git a/src/Shape.js b/src/Shape.js index bf4ae8f..f02fec2 100644 --- a/src/Shape.js +++ b/src/Shape.js @@ -1,2 +1,2 @@ -import Parent from './Parent.js' -export default class Shape extends Parent {} +import Element from './Element.js' +export default class Shape extends Element {} diff --git a/src/Text.js b/src/Text.js index 239b429..55fed22 100644 --- a/src/Text.js +++ b/src/Text.js @@ -1,4 +1,4 @@ -import Parent from './Parent.js' +import Shape from './Shape.js' import SVGNumber from './SVGNumber.js' import {nodeOrNew, extend} from './tools.js' import {attrs} from './defaults.js' @@ -6,7 +6,7 @@ import * as textable from './textable.js' import {register, adopt} from './adopter.js' import {registerMethods} from './methods.js' -export default class Text extends Parent { +export default class Text extends Shape { // Initialize node constructor (node) { super(nodeOrNew('text', node), Text) diff --git a/src/Tspan.js b/src/Tspan.js index 677adf4..148fb16 100644 --- a/src/Tspan.js +++ b/src/Tspan.js @@ -1,11 +1,10 @@ -import Parent from './Parent.js' +import Text from './Text.js' import {nodeOrNew, extend} from './tools.js' import * as textable from './textable.js' import {register} from './adopter.js' import {registerMethods} from './methods.js' -import Text from './Text.js' -export default class Tspan extends Parent { +export default class Tspan extends Text { // Initialize node constructor (node) { super(nodeOrNew('tspan', node), Tspan) diff --git a/src/arrange.js b/src/arrange.js index 4d4ec1c..d0a5b23 100644 --- a/src/arrange.js +++ b/src/arrange.js @@ -94,6 +94,6 @@ export function after (element) { return this } -registerMethods('Element', { +registerMethods('Dom', { siblings, position, next, prev, forward, backward, front, back, before, after }) diff --git a/src/attr.js b/src/attr.js index 23baf51..c44fa68 100644 --- a/src/attr.js +++ b/src/attr.js @@ -3,7 +3,7 @@ import {attrs as defaults} from './defaults.js' import Color from './Color.js' import SVGArray from './SVGArray.js' import SVGNumber from './SVGNumber.js' -import {registerMethods} from './methods.js' +//import {registerMethods} from './methods.js' // Set svg element attribute export default function attr (attr, val, ns) { @@ -80,4 +80,4 @@ export default function attr (attr, val, ns) { return this } -registerMethods('Element', {attr}) +//registerMethods('Element', {attr}) diff --git a/src/classHandling.js b/src/classHandling.js new file mode 100644 index 0000000..27bf11a --- /dev/null +++ b/src/classHandling.js @@ -0,0 +1,44 @@ +import {registerMethods} from './methods.js' +import {delimiter} from './regex.js' + +// Return array of classes on the node +function classes () { + var attr = this.attr('class') + return attr == null ? [] : attr.trim().split(delimiter) +} + +// Return true if class exists on the node, false otherwise +function hasClass (name) { + return this.classes().indexOf(name) !== -1 +} + +// Add class to the node +function addClass (name) { + if (!this.hasClass(name)) { + var array = this.classes() + array.push(name) + this.attr('class', array.join(' ')) + } + + return this +} + +// Remove class from the node +function removeClass (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 +function toggleClass (name) { + return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) +} + +registerMethods('Dom', { + classes, hasClass, addClass, removeClass, toggleClass +}) diff --git a/src/classes.js b/src/classes.js index 8385c20..283baaa 100644 --- a/src/classes.js +++ b/src/classes.js @@ -1,7 +1,7 @@ export {default as EventTarget} from './EventTarget.js' +export {default as Dom} from './Dom.js' export {default as Element} from './Element.js' export {default as Shape} from './Shape.js' -export {default as Parent} from './Parent.js' export {default as Container} from './Container.js' export {default as HtmlNode} from './HtmlNode.js' export {default as Doc} from './Doc.js' @@ -68,7 +68,6 @@ export {Controller, Ease, PID, Spring} from './Controller.js' // export {default as Matrix} from './Matrix.js' // export {default as Morphable} from './Morphable.js' // export {default as SVGNumber} from './SVGNumber.js' -// export {default as Parent} from './Parent.js' // export {default as Path} from './Path.js' // export {default as PathArray} from './PathArray.js' // export {default as Pattern} from './Pattern.js' diff --git a/src/css.js b/src/css.js index 795be71..b581d71 100644 --- a/src/css.js +++ b/src/css.js @@ -68,6 +68,6 @@ export function visible () { return this.css('display') !== 'none' } -registerMethods('Element', { +registerMethods('Dom', { css, show, hide, visible }) diff --git a/src/data.js b/src/data.js index c49f6a9..6374987 100644 --- a/src/data.js +++ b/src/data.js @@ -23,4 +23,4 @@ export function data (a, v, r) { return this } -registerMethods('Element', {data}) +registerMethods('Dom', {data}) diff --git a/src/elemnts-svg.js b/src/elemnts-svg.js index 5e51034..5ee97b7 100644 --- a/src/elemnts-svg.js +++ b/src/elemnts-svg.js @@ -44,10 +44,6 @@ // Act as setter if we got a string - // Make sure we are on a current when trying to import - if(!(this instanceof SVG.Parent)) - throw Error('Cannot import svg into non-current element') - // Create temporary holder well = document.createElementNS(SVG.ns, 'svg') fragment = document.createDocumentFragment() diff --git a/src/event.js b/src/event.js index acc4dd6..2aa9daf 100644 --- a/src/event.js +++ b/src/event.js @@ -1,27 +1,38 @@ import {delimiter} from './regex.js' import {registerMethods} from './methods.js' +import {makeInstance} from './adopter.js' let listenerId = 0 +function getEvents (node) { + const n = makeInstance(node).getEventHolder() + if (!n.events) n.events = {} + return n.events +} + function getEventTarget (node) { - return typeof node.getEventTarget === 'function' - ? node.getEventTarget() - : node + return makeInstance(node).getEventTarget() +} + +function clearEvents (node) { + const n = makeInstance(node).getEventHolder() + if (n.events) n.events = {} } // Add event binder in the SVG namespace export function on (node, events, listener, binding, options) { var l = listener.bind(binding || node) + var bag = getEvents(node) var n = getEventTarget(node) // events can be an array of events or a string of events events = Array.isArray(events) ? events : events.split(delimiter) // ensure instance object for nodes which are not adopted - n.instance = n.instance || {events: {}} + // n.instance = n.instance || {events: {}} // pull event handlers from the element - var bag = n.instance.events + // var bag = n.instance.events // add id to listener if (!listener._svgjsListenerId) { @@ -46,10 +57,11 @@ export function on (node, events, listener, binding, options) { // Add event unbinder in the SVG namespace export function off (node, events, listener, options) { + var bag = getEvents(node) var n = getEventTarget(node) // we cannot remove an event if its not an svg.js instance - if (!n.instance) return + // if (!n.instance) return // listener can be a function or a number if (typeof listener === 'function') { @@ -58,7 +70,7 @@ export function off (node, events, listener, options) { } // pull event handlers from the element - var bag = n.instance.events + // var bag = n.instance.events // events can be an array of events or a string or undefined events = Array.isArray(events) ? events : (events || '').split(delimiter) @@ -101,7 +113,7 @@ export function off (node, events, listener, options) { // remove all listeners on a given node for (event in bag) { off(n, event) } - n.instance.events = {} + clearEvents(node) } }) } diff --git a/src/memory.js b/src/memory.js index 77d3518..a94f0e2 100644 --- a/src/memory.js +++ b/src/memory.js @@ -42,5 +42,5 @@ export function memory () { return (this._memory = this._memory || {}) } -registerMethods('Element', {remember, forget, memory}) +registerMethods('Dom', {remember, forget, memory}) //registerConstructor('Memory', setup) diff --git a/src/selector.js b/src/selector.js index 973787d..c6717fb 100644 --- a/src/selector.js +++ b/src/selector.js @@ -37,4 +37,4 @@ export function find (query) { return baseFind(query, this.node) } -registerMethods('Element', {find}) +registerMethods('Dom', {find}) diff --git a/src/sugar.js b/src/sugar.js index e5d6b61..6465985 100644 --- a/src/sugar.js +++ b/src/sugar.js @@ -3,6 +3,7 @@ import Runner from './Runner.js' import SVGNumber from './SVGNumber.js' import Matrix from './Matrix.js' import Point from './Point.js' +import Element from './Element.js' import {registerMethods} from './methods.js' // Define list of available attributes for stroke and fill @@ -23,7 +24,7 @@ var sugar = { if (typeof o === 'undefined') { return this } - if (typeof o === 'string' || Color.isRgb(o) || (o && typeof o.fill === 'function')) { + if (typeof o === 'string' || Color.isRgb(o) || (o instanceof Element)) { this.attr(m, o) } else { // set all attributes from sugar.fill and sugar.stroke list @@ -37,7 +38,7 @@ var sugar = { return this } - registerMethods(['Element', 'Runner'], extension) + registerMethods(['Shape', 'Runner'], extension) }) registerMethods(['Element', 'Runner'], { @@ -140,7 +141,7 @@ registerMethods('Path', { } }) -registerMethods(['Parent', 'Runner'], { +registerMethods(['Element', 'Runner'], { // Set font font: function (a, v) { if (typeof a === 'object') { diff --git a/src/svg.js b/src/svg.js index 4206060..7cfbbc8 100644 --- a/src/svg.js +++ b/src/svg.js @@ -1,9 +1,3 @@ -// import {extend} from './tools.js' -// import * as Element from './Element.js' -// import Defs from './Defs.js' -// -// extend(Defs, [EventTarget, Element, Parent]) - import {makeInstance} from './adopter.js' import * as Classes from './classes.js' import * as adopter from './adopter.js' @@ -13,6 +7,7 @@ import * as elements from './elements.js' import './attr.js' import './arrange.js' import './data.js' +import './classHandling.js' import find from './selector.js' import './css.js' import './transform.js' @@ -24,7 +19,6 @@ const extend = tools.extend import './EventTarget.js' import './Element.js' -import './Parent.js' extend([ Classes.Doc, @@ -59,8 +53,9 @@ extend([ ], getMethodsFor('radius')) extend(Classes.EventTarget, getMethodsFor('EventTarget')) +extend(Classes.Dom, getMethodsFor('Dom')) extend(Classes.Element, getMethodsFor('Element')) -extend(Classes.Element, getMethodsFor('Parent')) +extend(Classes.Shape, getMethodsFor('Shape')) //extend(Classes.Element, getConstructor('Memory')) extend(Classes.Container, getMethodsFor('Container')) @@ -97,8 +92,6 @@ import * as ns from './namespaces.js' SVG.get = SVG SVG.find = find Object.assign(SVG, ns) -// import Base from './Base.js' -// SVG.Element = SVG.Parent = SVG.Shape = SVG.Container = Base import {easing} from './Controller.js' SVG.easing = easing import * as events from './event.js' -- cgit v1.2.3 From 2f8d32a1f4fbe51c4e6ac381d5d663d8f11fc1f9 Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Mon, 5 Nov 2018 19:02:35 +0100 Subject: Linted all files, upgraded all dependencies --- .config/karma.conf.js | 5 +- .eslintrc | 3 + .travis.yml | 2 +- abilities | 156 - dist/svg.js | 235 +- dist/svg.js.map | 1 - dist/svg.min.js | 2 +- package-lock.json | 4899 +++++++-------------------- package.json | 68 +- rollup.config.js | 24 +- spec/RAFPlugin.js | 84 + spec/SpecRunner.html | 14 +- spec/lib/RAFPlugin.js | 82 - spec/lib/jasmine-2.6.0/boot.js | 133 - spec/lib/jasmine-2.6.0/console.js | 190 -- spec/lib/jasmine-2.6.0/jasmine-html.js | 499 --- spec/lib/jasmine-2.6.0/jasmine.css | 58 - spec/lib/jasmine-2.6.0/jasmine.js | 4943 ---------------------------- spec/lib/jasmine-2.6.0/jasmine_favicon.png | Bin 1486 -> 0 bytes spec/spec/animator.js | 3 + spec/spec/helper.js | 13 +- spec/spec/selector.js | 2 +- src/A.js | 8 +- src/Animator.js | 4 +- src/ArrayPolyfill.js | 14 +- src/Bare.js | 7 +- src/Base.js | 20 +- src/Box.js | 17 +- src/Circle.js | 10 +- src/ClipPath.js | 15 +- src/Color.js | 6 +- src/Controller.js | 6 +- src/Defs.js | 4 +- src/Doc.js | 33 +- src/Dom.js | 16 +- src/Element.js | 8 +- src/Ellipse.js | 6 +- src/EventTarget.js | 32 +- src/G.js | 6 +- src/Gradient.js | 11 +- src/HtmlNode.js | 2 +- src/Image.js | 10 +- src/Line.js | 10 +- src/Marker.js | 6 +- src/Mask.js | 12 +- src/Matrix.js | 46 +- src/Morphable.js | 9 +- src/Path.js | 8 +- src/PathArray.js | 21 +- src/Pattern.js | 11 +- src/Point.js | 10 +- src/PointArray.js | 8 +- src/Polygon.js | 7 +- src/Polyline.js | 6 +- src/Rect.js | 6 +- src/Runner.js | 26 +- src/SVGArray.js | 13 +- src/SVGNumber.js | 5 +- src/Stop.js | 4 +- src/Symbol.js | 6 +- src/Text.js | 14 +- src/TextPath.js | 10 +- src/Timeline.js | 4 +- src/Tspan.js | 6 +- src/Use.js | 8 +- src/adopter.js | 7 +- src/arrange.js | 6 +- src/attr.js | 14 +- src/circled.js | 2 +- src/classHandling.js | 4 +- src/classes.js | 88 +- src/containers.js | 28 +- src/css.js | 23 +- src/data.js | 8 +- src/elements.js | 50 +- src/elemnts-svg.js | 107 +- src/event.js | 7 +- src/helpers.js | 6 +- src/memory.js | 11 +- src/methods.js | 11 +- src/parser.js | 3 +- src/poly.js | 4 +- src/selector.js | 9 +- src/set.js | 3 +- src/sugar.js | 28 +- src/svg.js | 37 +- src/tools.js | 7 +- src/transform.js | 8 +- src/umd.js | 28 - 89 files changed, 1881 insertions(+), 10525 deletions(-) create mode 100644 .eslintrc delete mode 100644 abilities delete mode 100644 dist/svg.js.map create mode 100644 spec/RAFPlugin.js delete mode 100644 spec/lib/RAFPlugin.js delete mode 100644 spec/lib/jasmine-2.6.0/boot.js delete mode 100644 spec/lib/jasmine-2.6.0/console.js delete mode 100644 spec/lib/jasmine-2.6.0/jasmine-html.js delete mode 100644 spec/lib/jasmine-2.6.0/jasmine.css delete mode 100644 spec/lib/jasmine-2.6.0/jasmine.js delete mode 100644 spec/lib/jasmine-2.6.0/jasmine_favicon.png delete mode 100644 src/umd.js (limited to 'src') diff --git a/.config/karma.conf.js b/.config/karma.conf.js index 9ea2a89..7421808 100644 --- a/.config/karma.conf.js +++ b/.config/karma.conf.js @@ -7,7 +7,6 @@ module.exports = function(config) { // base path that will be used to resolve all patterns (eg. files, exclude) basePath: '../', - // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter frameworks: ['jasmine'], @@ -16,7 +15,7 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ '.config/pretest.js', - 'spec/lib/RAFPlugin.js', + 'spec/RAFPlugin.js', { pattern: 'spec/fixtures/fixture.css', included: false, @@ -89,7 +88,7 @@ module.exports = function(config) { // start these browsers // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: ['Firefox'], + browsers: ['ChromeHeadless', 'FirefoxHeadless'], // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..e3578aa --- /dev/null +++ b/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": "standard" +} diff --git a/.travis.yml b/.travis.yml index 0f36329..ee9f3cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: node_js node_js: - "stable" script: - - npm run build:test + - npm run build - npm test - cat coverage/firefox/lcov.info | node_modules/.bin/coveralls #sudo: required diff --git a/abilities b/abilities deleted file mode 100644 index 4d5aa11..0000000 --- a/abilities +++ /dev/null @@ -1,156 +0,0 @@ - - ->> Element << - Stop - Bare - >> Parent << - Text - TextPath - >> Container<< - Doc - G - Symbol - Defs - ClipPath - Mask - A - Gradient - Shape - Rect - Circle - Path - Ellipse - Polygon - Polyline - Line - Image - -Animate -Box -Color -Controller - - -===================================================================== - - -classes: - - // MetaData - Title - - // Parents - SVG - G - - // Elements - Rect - Circle - Path - Ellipse - Polygon - Polyline - Line - Image - - // Text Stuff - TSpan - TextPath - - // Data Type - Box - Matrix - SVGNumber - SVGArray - PointArray - PathArray - Color - Controller - -abilities: - Animate - Container - Event - Doc - Movements - Dom - Create - - - - -// DocAbility.js - -import SVG from 'Svg.js' -export default function ( ...worksOn ) { - let workSet = new Set(worksOn) - return { - - doc: function () { - return this.parent(SVG) - } - - } -} - --> svg.js -> DocAbility.js -> 'Svg.js' - -extend ( [ Rect ], DocAbility() ) - - - -// DomAbility.js - -import {makeInstance} from 'helpers.js' - -export default function ( ...worksOn ) { - let workSet = new Set(worksOn) - let maker = makeInstance(workSet) - - return { - - addTo (parent) { - return maker(parent).put(this) - } - - } -} - -class Rect { - - - static tagName = 'Rect' -} - - - - -new SVG[capitalize[node.nodeName]] - - - -new SVG.Doc() -> ...... - -// SVG.js - -extend( [ ...Parents ], Container(...Elements, ...Parents) ) ) -extend( [ Text ], Container( TSpan, TextPath ) ) - - - -Element.js - -new Element () - -export default class Element { - - static - - static - -} - -Rect.js - -import Element from Element.js -export default class Rect extends Element diff --git a/dist/svg.js b/dist/svg.js index 1d465b9..3b71aea 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -1,3 +1,13 @@ +/*! +* svg.js - A lightweight library for manipulating and animating SVG. +* @version 3.0.0 +* https://svgdotjs.github.io/ +* +* @copyright Wout Fierens +* @license MIT +* +* BUILT: Mon Nov 05 2018 18:59:11 GMT+0100 (GMT+01:00) +*/; var SVG = (function () { 'use strict'; @@ -206,30 +216,9 @@ var SVG = (function () { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } - var Base = - /*#__PURE__*/ - function () { - function Base(node - /*, {extensions = []}*/ - ) {// this.tags = [] - // - // for (let extension of extensions) { - // extension.setup.call(this, node) - // this.tags.push(extension.name) - // } - - _classCallCheck(this, Base); - } - - _createClass(Base, [{ - key: "is", - value: function is(ability) { - return this.tags.includes(ability); - } - }]); - - return Base; - }(); + var Base = function Base() { + _classCallCheck(this, Base); + }; // Parse unit value var numberAndUnit = /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i; // Parse hex value @@ -502,6 +491,7 @@ var SVG = (function () { }; // Inherit prototype if (config.inherit) { + /* eslint new-cap: "off" */ initializer.prototype = new config.inherit(); initializer.prototype.constructor = initializer; } // Extend with methods @@ -513,7 +503,7 @@ var SVG = (function () { if (config.construct) { - extend(config.parent || Container, config.construct); + extend(config.parent || getClass('Container'), config.construct); } return initializer; @@ -617,56 +607,6 @@ var SVG = (function () { assignNewId: assignNewId }); - var methods = {}; - function registerMethods(name, m) { - if (Array.isArray(name)) { - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = name[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var _name = _step.value; - registerMethods(_name, m); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - return; - } - - if (_typeof(name) == 'object') { - var _arr = Object.entries(name); - - for (var _i = 0; _i < _arr.length; _i++) { - var _arr$_i = _slicedToArray(_arr[_i], 2), - _name2 = _arr$_i[0], - _m = _arr$_i[1]; - - registerMethods(_name2, _m); - } - - return; - } - - methods[name] = Object.assign(methods[name] || {}, m); - } - function getMethodsFor(name) { - return methods[name] || {}; - } // FIXME: save memory? - var listenerId = 0; function getEvents(node) { @@ -881,7 +821,7 @@ var SVG = (function () { return EventTarget; }(Base); // Add events to elements - var methods$1 = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove', 'mouseenter', 'mouseleave', 'touchstart', 'touchmove', 'touchleave', 'touchend', 'touchcancel'].reduce(function (last, event) { + var methods = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove', 'mouseenter', 'mouseleave', 'touchstart', 'touchmove', 'touchleave', 'touchend', 'touchcancel'].reduce(function (last, event) { // add event to Element var fn = function fn(f) { if (f === null) { @@ -896,7 +836,7 @@ var SVG = (function () { last[event] = fn; return last; }, {}); - extend(EventTarget, methods$1); // registerMethods('EventTarget', { + extend(EventTarget, methods); // registerMethods('EventTarget', { // on, off, dispatch, fire // }) // @@ -1099,6 +1039,7 @@ var SVG = (function () { return Color; }(); + /* eslint no-new-func: "off" */ var subClassArray = function () { try { // try es6 subclassing @@ -1127,7 +1068,7 @@ var SVG = (function () { }); extend(SVGArray, { init: function init() { - //this.splice(0, this.length) + // this.splice(0, this.length) this.length = 0; this.push.apply(this, _toConsumableArray(this.parse.apply(this, arguments))); }, @@ -1149,7 +1090,7 @@ var SVG = (function () { // Parse whitespace separated string parse: function parse() { var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - //array = array.valueOf() + // array = array.valueOf() // If already is an array, no need to parse it if (array instanceof Array) return array; return array.trim().split(delimiter).map(parseFloat); @@ -1357,7 +1298,7 @@ var SVG = (function () { // How does attr know about image()? - while (typeof val.attrHook == 'function') { + while (typeof val.attrHook === 'function') { val = val.attrHook(this, attr); } // ensure correct numeric values (also accepts NaN and Infinity) @@ -1390,7 +1331,7 @@ var SVG = (function () { } return this; - } //registerMethods('Element', {attr}) + } // registerMethods('Element', {attr}) var Dom = /*#__PURE__*/ @@ -1744,7 +1685,7 @@ var SVG = (function () { }, { key: "reference", - value: function reference$$1(attr) { + value: function reference(attr) { var id = idFromReference(this.attr(attr)); return id ? makeInstance(id) : null; } // set given data to the elements data property @@ -1812,7 +1753,7 @@ var SVG = (function () { return Shape; }(Element); - var Container$1 = + var Container = /*#__PURE__*/ function (_Element) { _inherits(Container, _Element); @@ -1888,9 +1829,59 @@ var SVG = (function () { }]); return Defs; - }(Container$1); + }(Container); register(Defs); + var methods$1 = {}; + function registerMethods(name, m) { + if (Array.isArray(name)) { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = name[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var _name = _step.value; + registerMethods(_name, m); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + return; + } + + if (_typeof(name) === 'object') { + var _arr = Object.entries(name); + + for (var _i = 0; _i < _arr.length; _i++) { + var _arr$_i = _slicedToArray(_arr[_i], 2), + _name2 = _arr$_i[0], + _m = _arr$_i[1]; + + registerMethods(_name2, _m); + } + + return; + } + + methods$1[name] = Object.assign(methods$1[name] || {}, m); + } + function getMethodsFor(name) { + return methods$1[name] || {}; + } // FIXME: save memory? + var Doc$1 = /*#__PURE__*/ function (_Container) { @@ -1919,7 +1910,7 @@ var SVG = (function () { key: "doc", value: function doc() { if (this.isRoot()) return this; - return _get(_getPrototypeOf(Doc.prototype), "doc", this).call(this); //return doc.call(this) + return _get(_getPrototypeOf(Doc.prototype), "doc", this).call(this); // return doc.call(this) } // Add namespaces }, { @@ -1946,7 +1937,7 @@ var SVG = (function () { return this.node.parentNode.nodeName === '#document' ? null : adopt(this.node.parentNode); } - return _get(_getPrototypeOf(Doc.prototype), "parent", this).call(this, type); //return parent.call(this, type) + return _get(_getPrototypeOf(Doc.prototype), "parent", this).call(this, type); // return parent.call(this, type) } // Removes the doc from the DOM // remove() { // if (!this.isRoot()) { @@ -1973,7 +1964,7 @@ var SVG = (function () { }]); return Doc; - }(Container$1); + }(Container); registerMethods({ Container: { // Create nested svg document @@ -1996,7 +1987,7 @@ var SVG = (function () { } return G; - }(Container$1); + }(Container); registerMethods({ Element: { // Create a group element @@ -2186,7 +2177,7 @@ var SVG = (function () { }]); return Bare; - }(Container$1); + }(Container); register(Bare); registerMethods('Container', { // Create an element that is not described by SVG.js @@ -2325,11 +2316,11 @@ var SVG = (function () { }); } // Scoped find method - function find$1(query) { + function find(query) { return baseFind(query, this.node); } registerMethods('Dom', { - find: find$1 + find: find }); var ClipPath = @@ -2352,7 +2343,7 @@ var SVG = (function () { el.unclip(); }); // remove clipPath from parent - return _get(_getPrototypeOf(ClipPath.prototype), "remove", this).call(this); //return remove.call(this) + return _get(_getPrototypeOf(ClipPath.prototype), "remove", this).call(this); // return remove.call(this) } }, { key: "targets", @@ -2362,7 +2353,7 @@ var SVG = (function () { }]); return ClipPath; - }(Container$1); + }(Container); registerMethods({ Container: { // Create clipping element @@ -2415,7 +2406,7 @@ var SVG = (function () { }]); return A; - }(Container$1); + }(Container); registerMethods({ Container: { // Create a hyperlink element @@ -2615,7 +2606,7 @@ var SVG = (function () { } }); - var Box$1 = + var Box = /*#__PURE__*/ function () { function Box() { @@ -2712,12 +2703,12 @@ var SVG = (function () { Element: { // Get bounding box bbox: function bbox() { - return new Box$1(getBox.call(this, function (node) { + return new Box(getBox.call(this, function (node) { return node.getBBox(); })); }, rbox: function rbox(el) { - var box = new Box$1(getBox.call(this, function (node) { + var box = new Box(getBox.call(this, function (node) { return node.getBoundingClientRect(); })); if (el) return box.transform(el.screenCTM().inverse()); @@ -2727,9 +2718,9 @@ var SVG = (function () { viewbox: { viewbox: function viewbox(x, y, width, height) { // act as getter - if (x == null) return new Box$1(this.attr('viewBox')); // act as setter + if (x == null) return new Box(this.attr('viewBox')); // act as setter - return this.attr('viewBox', new Box$1(x, y, width, height)); + return this.attr('viewBox', new Box(x, y, width, height)); } } }); @@ -2781,7 +2772,7 @@ var SVG = (function () { key: "attr", value: function attr(a, b, c) { if (a === 'transform') a = 'gradientTransform'; - return _get(_getPrototypeOf(Gradient.prototype), "attr", this).call(this, a, b, c); //return attr.call(this, a, b, c) + return _get(_getPrototypeOf(Gradient.prototype), "attr", this).call(this, a, b, c); // return attr.call(this, a, b, c) } }, { key: "targets", @@ -2791,12 +2782,12 @@ var SVG = (function () { }, { key: "bbox", value: function bbox() { - return new Box$1(); + return new Box(); } }]); return Gradient; - }(Container$1); + }(Container); extend(Gradient, gradiented); registerMethods({ Container: { @@ -2856,7 +2847,7 @@ var SVG = (function () { key: "attr", value: function attr(a, b, c) { if (a === 'transform') a = 'patternTransform'; - return _get(_getPrototypeOf(Pattern.prototype), "attr", this).call(this, a, b, c); //return attr.call(this, a, b, c) + return _get(_getPrototypeOf(Pattern.prototype), "attr", this).call(this, a, b, c); // return attr.call(this, a, b, c) } }, { key: "targets", @@ -2866,12 +2857,12 @@ var SVG = (function () { }, { key: "bbox", value: function bbox() { - return new Box$1(); + return new Box(); } }]); return Pattern; - }(Container$1); + }(Container); registerMethods({ Container: { // Create pattern element in defs @@ -3340,7 +3331,7 @@ var SVG = (function () { }]); return Marker; - }(Container$1); + }(Container); registerMethods({ Container: { marker: function marker(width, height, block) { @@ -3391,7 +3382,7 @@ var SVG = (function () { el.unmask(); }); // remove mask from parent - return _get(_getPrototypeOf(Mask.prototype), "remove", this).call(this); //return remove.call(this) + return _get(_getPrototypeOf(Mask.prototype), "remove", this).call(this); // return remove.call(this) } }, { key: "targets", @@ -3401,7 +3392,7 @@ var SVG = (function () { }]); return Mask; - }(Container$1); + }(Container); registerMethods({ Container: { mask: function mask() { @@ -4140,7 +4131,7 @@ var SVG = (function () { } return _Symbol; - }(Container$1); + }(Container); registerMethods({ Container: { symbol: function symbol() { @@ -6787,7 +6778,7 @@ var SVG = (function () { Dom: Dom, Element: Element, Shape: Shape, - Container: Container$1, + Container: Container, HtmlNode: HtmlNode, Doc: Doc$1, Defs: Defs, @@ -6820,7 +6811,7 @@ var SVG = (function () { PointArray: PointArray, Matrix: Matrix, Point: Point, - Box: Box$1, + Box: Box, Color: Color, Morphable: Morphable, Queue: Queue, @@ -6856,7 +6847,7 @@ var SVG = (function () { p.removeElement(this).add(this, i); // make sure defs node is always at the top - if (typeof p.isRoot == 'function' && p.isRoot()) { + if (typeof p.isRoot === 'function' && p.isRoot()) { p.node.appendChild(p.defs().node); } @@ -6878,7 +6869,7 @@ var SVG = (function () { p.node.appendChild(this.node); // Make sure defs node is always at the top - if (typeof p.isRoot == 'function' && p.isRoot()) { + if (typeof p.isRoot === 'function' && p.isRoot()) { p.node.appendChild(p.defs().node); } @@ -7010,8 +7001,8 @@ var SVG = (function () { try { for (var _iterator = style[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var _name = _step.value; - var cased = camelCase(_name); + var name = _step.value; + var cased = camelCase(name); ret[cased] = this.node.style[cased]; } } catch (err) { @@ -7039,9 +7030,9 @@ var SVG = (function () { if (_typeof(style) === 'object') { - for (name in style) { + for (var _name in style) { // set empty string if null/undefined/'' was given - this.node.style[camelCase(name)] = style[name] == null || isBlank.test(style[name]) ? '' : style[name]; + this.node.style[camelCase(_name)] = style[_name] == null || isBlank.test(style[_name]) ? '' : style[_name]; } } } // set style for property @@ -7176,7 +7167,7 @@ var SVG = (function () { remember: remember, forget: forget, memory: memory - }); //registerConstructor('Memory', setup) + }); // registerConstructor('Memory', setup) var sugar = { stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], @@ -7340,10 +7331,10 @@ var SVG = (function () { extend$1(EventTarget, getMethodsFor('EventTarget')); extend$1(Dom, getMethodsFor('Dom')); extend$1(Element, getMethodsFor('Element')); - extend$1(Shape, getMethodsFor('Shape')); //extend(Classes.Element, getConstructor('Memory')) + extend$1(Shape, getMethodsFor('Shape')); // extend(Classes.Element, getConstructor('Memory')) - extend$1(Container$1, getMethodsFor('Container')); - registerMorphableType([SVGNumber, Color, Box$1, Matrix, SVGArray, PointArray, PathArray]); + extend$1(Container, getMethodsFor('Container')); + registerMorphableType([SVGNumber, Color, Box, Matrix, SVGArray, PointArray, PathArray]); makeMorphable(); // The main wrapping element function SVG(element) { @@ -7353,7 +7344,7 @@ var SVG = (function () { Object.assign(SVG, tools); Object.assign(SVG, adopter); SVG.utils = utils; - SVG.regex = regex; // satisfy tests, fix later + SVG.regex = regex; SVG.get = SVG; SVG.find = baseFind; Object.assign(SVG, ns$1); diff --git a/dist/svg.js.map b/dist/svg.js.map deleted file mode 100644 index bc48b35..0000000 --- a/dist/svg.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["svg.js","regex.js","utilities.js","default.js","queue.js","color.js","array.js","pointarray.js","patharray.js","number.js","eventtarget.js","HtmlNode.js","element.js","event.js","matrix.js","point.js","attr.js","transform.js","css.js","parent.js","flatten.js","container.js","defs.js","group.js","arrange.js","mask.js","clip.js","gradient.js","pattern.js","doc.js","shape.js","bare.js","symbol.js","use.js","rect.js","ellipse.js","line.js","poly.js","pointed.js","path.js","image.js","text.js","textpath.js","hyperlink.js","marker.js","sugar.js","data.js","memory.js","selector.js","helpers.js","boxes.js","parser.js","animator.js","morph.js","runner.js","timeline.js","controller.js"],"names":["SVG","window","element","supported","createElement","ns","xmlns","xlink","svgjs","did","eid","name","capitalize","create","document","createElementNS","extend","modules","methods","key","i","Array","isArray","length","prototype","invent","config","initializer","node","inherit","call","constructor","construct","parent","Container","adopt","instance","Element","SVGElement","HtmlNode","nodeName","Doc","Gradient","Parent","regex","numberAndUnit","hex","rgb","reference","transforms","whitespace","isHex","isRgb","isCss","isBlank","isNumber","isPercent","isImage","delimiter","hyphen","pathLetters","isPathLetter","numbersWithDots","dots","utils","map","array","block","il","result","push","filter","radians","d","Math","PI","degrees","r","filterSVGElements","nodes","el","void","defaults","timeline","duration","ease","delay","attrs","fill","stroke","opacity","x","y","cx","cy","width","height","rx","ry","offset","Queue","_first","_last","value","item","next","prev","shift","remove","first","last","Color","color","g","b","match","test","exec","replace","parseInt","fullHex","arguments","toString","toHex","toArray","fromArray","a","compToHex","round","toRgb","join","brightness","morph","destination","at","pos","isColor","fallback","valueOf","parse","lastValue","lastDestination","settle","seen","indexOf","trim","split","parseFloat","reverse","clone","arrayClone","PointArray","reduce","curr","concat","toLine","x1","y1","x2","y2","points","pop","len","move","box","bbox","isNaN","size","maxX","Infinity","maxY","minX","minY","forEach","max","min","pathHandlers","M","c","p","p0","L","H","V","C","S","Q","T","Z","A","mlhvqtcsaz","j","jl","toUpperCase","PathArray","arrayToString","l","equalCommands","pathArray","sourceArray","destinationArray","s","paramCnt","pathRegReplace","Point","index","slice","parser","path","setAttribute","getBBox","Number","unit","isFinite","toJSON","plus","number","minus","times","divide","to","relative","EventTarget","on","event","listener","binding","options","off","dispatch","data","fire","add","children","insertBefore","put","getEventTarget","events","dom","type","hasAttribute","setData","JSON","getAttribute","attr","center","proportionalSize","writeDataToDom","assignNewId","cloneNode","after","removeElement","addTo","putIn","id","inside","show","css","hide","visible","classes","hasClass","addClass","removeClass","toggleClass","get","parentNode","matches","doc","defs","parents","selector","native","svg","well","innerHTML","appendChild","firstElementChild","outerHTML","is","each","removeAttribute","Object","keys","stringify","o","obj","f","listenerId","bind","n","bag","_svgjsListenerId","ev","addEventListener","namespace","removeEventListener","Event","dispatchEvent","CustomEvent","detail","cancelable","Matrix","source","base","arrayToMatrix","matrixify","isMatrixLike","transform","e","matrix","multiplyO","t","formatTransforms","current","ox","oy","transformer","translateO","lmultiplyO","scaleO","scaleX","scaleY","skewO","skewX","skewY","shearO","shear","rotateO","theta","px","py","origin","dx","dy","tx","ty","compose","originX","originY","sx","sy","lam","rotate","translateX","translateY","decompose","determinant","ccw","sqrt","thetaRad","atan2","ct","cos","st","sin","multiply","matrixMultiply","lmultiply","inverseO","det","Error","na","nb","nc","nd","ne","nf","inverse","translate","scale","flip","axis","around","flipO","lx","skew","tan","ly","skewXO","skewYO","aroundO","createSVGMatrix","abcdef","equals","other","comp","closeEnough","ctm","getCTM","screenCTM","isRoot","rect","m","getScreenCTM","point","createSVGPoint","v","attributes","nodeValue","image","Image","pattern","leading","setAttributeNS","rebuild","untransform","str","kv","apply","toParent","pCtm","toDoc","decomposed","getOrigin","cleanRelative","ret","style","cssText","camelCase","has","deep","removeChild","clear","hasChildNodes","lastChild","_defs","flatten","G","Defs","ungroup","group","siblings","position","forward","backward","front","back","before","Mask","targets","unmask","select","mask","maskWith","masker","ClipPath","unclip","clip","clipWith","clipper","stop","Stop","update","url","gradient","Timeline","from","_target","fx","fy","Pattern","patternUnits","version","getElementsByTagName","nested","Shape","Bare","method","words","text","createTextNode","Symbol","symbol","Use","file","use","Rect","Circle","circle","Ellipse","ellipse","Line","plot","line","Polyline","polyline","Polygon","polygon","_array","MorphArray","Path","load","callback","img","ratio","src","Text","_rebuild","_build","undefined","childNodes","firstLine","nodeType","newLined","textContent","build","tspan","newLine","self","blankLineOffset","plain","Tspan","getComputedTextLength","TextPath","track","textPath","txt","target","link","linkTo","Marker","ref","marker","viewbox","sugar","prefix","extension","mat","angle","direction","directionString","dmove","radius","getTotalLength","pointAt","getPointAtLength","font","remember","k","memory","forget","_memory","getElementById","idFromReference","query","querySelectorAll","$$","$","querySelector","makeNested","charAt","isNulledBox","w","h","domContains","documentElement","contains","arr","matchesSelector","msMatchesSelector","mozMatchesSelector","webkitMatchesSelector","oMatchesSelector","toLowerCase","substring","ensureCentre","fullBox","threshold","abs","flipBoth","flipX","flipY","positionX","positionY","relativeX","relativeY","string","bx","includes","by","Box","left","top","merge","xMin","xMax","yMin","yMax","pts","addOffset","pageXOffset","pageYOffset","Exception","console","warn","rbox","getBoundingClientRect","ForeignObject","View","body","overflow","Animator","nextDraw","frames","timeouts","timer","performance","Date","frame","fn","run","requestAnimationFrame","_draw","transform_frame","timeout","time","now","cancelFrame","clearTimeout","nextTimeout","lastTimeout","nextFrame","lastFrame","Morphable","stepper","_stepper","Ease","_from","_to","_type","_context","_morphObj","val","_set","NonMorphable","MorphableTypes","ObjectBag","done","complete","_this","step","TransformBag","assign","objOrArr","values","entries","sort","args","easing","Runner","Controller","_element","_timeline","_queue","_duration","_isDeclarative","_history","enabled","_time","tags","transformId","_haveReversed","_reverse","_loopsDone","_swing","_wait","_times","animate","when","sanitise","loop","schedule","_prepareRunner","runner","unschedule","swing","wait","queue","initFn","runFn","isTransform","initialiser","initialised","finished","_continue","during","dt","loops","loopDuration","loopsDone","floor","relativeTime","whole","partial","swinging","backwards","uncliped","pow","clipped","endTime","swingForward","forwards","progress","running","_lastPosition","justStarted","_lastTime","justFinished","declarative","_initialise","converged","_run","finish","active","tag","untag","_dispatcher","_rememberMorpher","morpher","caller","_tryRetarget","splice","needsIt","positionOrDt","allfinished","addTransform","clearTransform","Stepper","FakeRunner","mergeWith","getRunnerTransform","mergeTransforms","runners","_transformationRunners","netTransform","_frameId","RunnerArray","ids","leftSibling","lastRunner","edit","newRunner","deleteCnt","_clearTransformRunnersBefore","currentRunner","clearBefore","_currentTransform","addRunner","frameId","styleAttr","zoom","level","affine","isMatrix","currentAngle","startTransform","setup","start","rTarget","rCurrent","possibilities","distances","shortest","affineParameters","retarget","newTransforms","_queueNumber","_queueNumberDelta","_tryRetargetDelta","_queueObject","makeSchedule","runnerInfo","end","_timeSource","_startTime","_speed","_persist","_nextFrame","_paused","_runners","_order","_lastSourceTime","_lastStepTime","_step","absoluteStartTime","persist","play","pause","seek","speed","yes","currentSpeed","positive","dtOrForever","dtSource","dtTime","runnersLeft","dtToStart","makeSetterGetter","bezier","t0","x0","t1","recalculate","overshoot","_overshoot","eps","pi","os","log","zeta","wn","Spring","velocity","acceleration","newPosition","PID","windup","integral","error","P","I","D"],"mappings":"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","file":"svg.js","sourcesContent":["/* global createElement, capitalize */\r\n/* eslint-disable new-cap */\r\n\r\n// The main wrapping element\r\nvar SVG = window.SVG = function (element) {\r\n if (SVG.supported) {\r\n element = createElement(element)\r\n return element\r\n }\r\n}\r\n\r\n// Svg must be supported if we reached this stage\r\nSVG.supported = true\r\n\r\n// Default namespaces\r\nSVG.ns = 'http://www.w3.org/2000/svg'\r\nSVG.xmlns = 'http://www.w3.org/2000/xmlns/'\r\nSVG.xlink = 'http://www.w3.org/1999/xlink'\r\nSVG.svgjs = 'http://svgjs.com/svgjs'\r\n\r\n// Element id sequence\r\nSVG.did = 1000\r\n\r\n// Get next named element id\r\nSVG.eid = function (name) {\r\n return 'Svgjs' + capitalize(name) + (SVG.did++)\r\n}\r\n\r\n// Method for element creation\r\nSVG.create = function (name) {\r\n // create element\r\n return document.createElementNS(this.ns, name)\r\n}\r\n\r\n// Method for extending objects\r\nSVG.extend = function (modules, methods) {\r\n var key, i\r\n\r\n modules = Array.isArray(modules) ? modules : [modules]\r\n\r\n for (i = modules.length - 1; i >= 0; i--) {\r\n if (modules[i]) {\r\n for (key in methods) {\r\n modules[i].prototype[key] = methods[key]\r\n }\r\n }\r\n }\r\n}\r\n\r\n// Invent new element\r\nSVG.invent = function (config) {\r\n // Create element initializer\r\n var initializer = typeof config.create === 'function' ? config.create\r\n : function (node) {\r\n config.inherit.call(this, node || SVG.create(config.create))\r\n }\r\n\r\n // Inherit prototype\r\n if (config.inherit) {\r\n initializer.prototype = new config.inherit()\r\n initializer.prototype.constructor = initializer\r\n }\r\n\r\n // Extend with methods\r\n if (config.extend) {\r\n SVG.extend(initializer, config.extend)\r\n }\r\n\r\n // Attach construct method to parent\r\n if (config.construct) { SVG.extend(config.parent || SVG.Container, config.construct) }\r\n\r\n return initializer\r\n}\r\n\r\n// Adopt existing svg elements\r\nSVG.adopt = function (node) {\r\n // check for presence of node\r\n if (!node) return null\r\n\r\n // make sure a node isn't already adopted\r\n if (node.instance instanceof SVG.Element) return node.instance\r\n\r\n if (!(node instanceof window.SVGElement)) {\r\n return new SVG.HtmlNode(node)\r\n }\r\n\r\n // initialize variables\r\n var element\r\n\r\n // adopt with element-specific settings\r\n if (node.nodeName === 'svg') {\r\n element = new SVG.Doc(node)\r\n } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') {\r\n element = new SVG.Gradient(node)\r\n } else if (SVG[capitalize(node.nodeName)]) {\r\n element = new SVG[capitalize(node.nodeName)](node)\r\n } else {\r\n element = new SVG.Parent(node)\r\n }\r\n\r\n return element\r\n}\r\n","// Storage for regular expressions\r\nSVG.regex = {\r\n // Parse unit value\r\n numberAndUnit: /^([+-]?(\\d+(\\.\\d*)?|\\.\\d+)(e[+-]?\\d+)?)([a-z%]*)$/i,\r\n\r\n // Parse hex value\r\n hex: /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i,\r\n\r\n // Parse rgb value\r\n rgb: /rgb\\((\\d+),(\\d+),(\\d+)\\)/,\r\n\r\n // Parse reference id\r\n reference: /#([a-z0-9\\-_]+)/i,\r\n\r\n // splits a transformation chain\r\n transforms: /\\)\\s*,?\\s*/,\r\n\r\n // Whitespace\r\n whitespace: /\\s/g,\r\n\r\n // Test hex value\r\n isHex: /^#[a-f0-9]{3,6}$/i,\r\n\r\n // Test rgb value\r\n isRgb: /^rgb\\(/,\r\n\r\n // Test css declaration\r\n isCss: /[^:]+:[^;]+;?/,\r\n\r\n // Test for blank string\r\n isBlank: /^(\\s+)?$/,\r\n\r\n // Test for numeric string\r\n isNumber: /^[+-]?(\\d+(\\.\\d*)?|\\.\\d+)(e[+-]?\\d+)?$/i,\r\n\r\n // Test for percent value\r\n isPercent: /^-?[\\d.]+%$/,\r\n\r\n // Test for image url\r\n isImage: /\\.(jpg|jpeg|png|gif|svg)(\\?[^=]+.*)?/i,\r\n\r\n // split at whitespace and comma\r\n delimiter: /[\\s,]+/,\r\n\r\n // The following regex are used to parse the d attribute of a path\r\n\r\n // Matches all hyphens which are not after an exponent\r\n hyphen: /([^e])-/gi,\r\n\r\n // Replaces and tests for all path letters\r\n pathLetters: /[MLHVCSQTAZ]/gi,\r\n\r\n // yes we need this one, too\r\n isPathLetter: /[MLHVCSQTAZ]/i,\r\n\r\n // matches 0.154.23.45\r\n numbersWithDots: /((\\d?\\.\\d+(?:e[+-]?\\d+)?)((?:\\.\\d+(?:e[+-]?\\d+)?)+))+/gi,\r\n\r\n // matches .\r\n dots: /\\./g\r\n}\r\n","\r\nSVG.utils = {\r\n // Map function\r\n map: function (array, block) {\r\n var i\r\n var il = array.length\r\n var result = []\r\n\r\n for (i = 0; i < il; i++) {\r\n result.push(block(array[i]))\r\n }\r\n\r\n return result\r\n },\r\n\r\n // Filter function\r\n filter: function (array, block) {\r\n var i\r\n var il = array.length\r\n var result = []\r\n\r\n for (i = 0; i < il; i++) {\r\n if (block(array[i])) { result.push(array[i]) }\r\n }\r\n\r\n return result\r\n },\r\n\r\n // Degrees to radians\r\n radians: function (d) {\r\n return d % 360 * Math.PI / 180\r\n },\r\n\r\n // Radians to degrees\r\n degrees: function (r) {\r\n return r * 180 / Math.PI % 360\r\n },\r\n\r\n filterSVGElements: function (nodes) {\r\n return this.filter(nodes, function (el) { return el instanceof window.SVGElement })\r\n }\r\n\r\n}\r\n","\r\nSVG.void = function () {}\r\n\r\nSVG.defaults = {\r\n\r\n // Default animation values\r\n timeline: {\r\n duration: 400,\r\n ease: '>',\r\n delay: 0\r\n },\r\n\r\n // Default attribute values\r\n attrs: {\r\n\r\n // fill and stroke\r\n 'fill-opacity': 1,\r\n 'stroke-opacity': 1,\r\n 'stroke-width': 0,\r\n 'stroke-linejoin': 'miter',\r\n 'stroke-linecap': 'butt',\r\n fill: '#000000',\r\n stroke: '#000000',\r\n opacity: 1,\r\n\r\n // position\r\n x: 0,\r\n y: 0,\r\n cx: 0,\r\n cy: 0,\r\n\r\n // size\r\n width: 0,\r\n height: 0,\r\n\r\n // radius\r\n r: 0,\r\n rx: 0,\r\n ry: 0,\r\n\r\n // gradient\r\n offset: 0,\r\n 'stop-opacity': 1,\r\n 'stop-color': '#000000',\r\n\r\n // text\r\n 'font-size': 16,\r\n 'font-family': 'Helvetica, Arial, sans-serif',\r\n 'text-anchor': 'start'\r\n }\r\n}\r\n","SVG.Queue = SVG.invent({\r\n create: function () {\r\n this._first = null\r\n this._last = null\r\n },\r\n\r\n extend: {\r\n push: function (value) {\r\n // An item stores an id and the provided value\r\n var item = value.next ? value : { value: value, next: null, prev: null }\r\n\r\n // Deal with the queue being empty or populated\r\n if (this._last) {\r\n item.prev = this._last\r\n this._last.next = item\r\n this._last = item\r\n } else {\r\n this._last = item\r\n this._first = item\r\n }\r\n\r\n // Update the length and return the current item\r\n return item\r\n },\r\n\r\n shift: function () {\r\n // Check if we have a value\r\n var remove = this._first\r\n if (!remove) return null\r\n\r\n // If we do, remove it and relink things\r\n this._first = remove.next\r\n if (this._first) this._first.prev = null\r\n this._last = this._first ? this._last : null\r\n return remove.value\r\n },\r\n\r\n // Shows us the first item in the list\r\n first: function () {\r\n return this._first && this._first.value\r\n },\r\n\r\n // Shows us the last item in the list\r\n last: function () {\r\n return this._last && this._last.value\r\n },\r\n\r\n // Removes the item that was returned from the push\r\n remove: function (item) {\r\n // Relink the previous item\r\n if (item.prev) item.prev.next = item.next\r\n if (item.next) item.next.prev = item.prev\r\n if (item === this._last) this._last = item.prev\r\n if (item === this._first) this._first = item.next\r\n\r\n // Invalidate item\r\n item.prev = null\r\n item.next = null\r\n }\r\n }\r\n})\r\n","/* globals fullHex, compToHex */\r\n\r\n/*\r\n\r\nColor {\r\n constructor (a, b, c, space) {\r\n space: 'hsl'\r\n a: 30\r\n b: 20\r\n c: 10\r\n },\r\n\r\n toRgb () { return new Color in rgb space }\r\n toHsl () { return new Color in hsl space }\r\n toLab () { return new Color in lab space }\r\n\r\n toArray () { [space, a, b, c] }\r\n fromArray () { convert it back }\r\n}\r\n\r\n// Conversions aren't always exact because of monitor profiles etc...\r\nnew Color(h, s, l, 'hsl') !== new Color(r, g, b).hsl()\r\nnew Color(100, 100, 100, [space])\r\nnew Color('hsl(30, 20, 10)')\r\n\r\n// Sugar\r\nSVG.rgb(30, 20, 50).lab()\r\nSVG.hsl()\r\nSVG.lab('rgb(100, 100, 100)')\r\n*/\r\n\r\n// Module for color convertions\r\nSVG.Color = function (color, g, b) {\r\n var match\r\n\r\n // initialize defaults\r\n this.r = 0\r\n this.g = 0\r\n this.b = 0\r\n\r\n if (!color) return\r\n\r\n // parse color\r\n if (typeof color === 'string') {\r\n if (SVG.regex.isRgb.test(color)) {\r\n // get rgb values\r\n match = SVG.regex.rgb.exec(color.replace(SVG.regex.whitespace, ''))\r\n\r\n // parse numeric values\r\n this.r = parseInt(match[1])\r\n this.g = parseInt(match[2])\r\n this.b = parseInt(match[3])\r\n } else if (SVG.regex.isHex.test(color)) {\r\n // get hex values\r\n match = SVG.regex.hex.exec(fullHex(color))\r\n\r\n // parse numeric values\r\n this.r = parseInt(match[1], 16)\r\n this.g = parseInt(match[2], 16)\r\n this.b = parseInt(match[3], 16)\r\n }\r\n } else if (Array.isArray(color)) {\r\n this.r = color[0]\r\n this.g = color[1]\r\n this.b = color[2]\r\n } else if (typeof color === 'object') {\r\n this.r = color.r\r\n this.g = color.g\r\n this.b = color.b\r\n } else if (arguments.length === 3) {\r\n this.r = color\r\n this.g = g\r\n this.b = b\r\n }\r\n}\r\n\r\nSVG.extend(SVG.Color, {\r\n // Default to hex conversion\r\n toString: function () {\r\n return this.toHex()\r\n },\r\n toArray: function () {\r\n return [this.r, this.g, this.b]\r\n },\r\n fromArray: function (a) {\r\n return new SVG.Color(a)\r\n },\r\n // Build hex value\r\n toHex: function () {\r\n return '#' +\r\n compToHex(Math.round(this.r)) +\r\n compToHex(Math.round(this.g)) +\r\n compToHex(Math.round(this.b))\r\n },\r\n // Build rgb value\r\n toRgb: function () {\r\n return 'rgb(' + [this.r, this.g, this.b].join() + ')'\r\n },\r\n // Calculate true brightness\r\n brightness: function () {\r\n return (this.r / 255 * 0.30) +\r\n (this.g / 255 * 0.59) +\r\n (this.b / 255 * 0.11)\r\n },\r\n // Make color morphable\r\n morph: function (color) {\r\n this.destination = new SVG.Color(color)\r\n\r\n return this\r\n },\r\n // Get morphed color at given position\r\n at: function (pos) {\r\n // make sure a destination is defined\r\n if (!this.destination) return this\r\n\r\n // normalise pos\r\n pos = pos < 0 ? 0 : pos > 1 ? 1 : pos\r\n\r\n // generate morphed color\r\n return new SVG.Color({\r\n r: ~~(this.r + (this.destination.r - this.r) * pos),\r\n g: ~~(this.g + (this.destination.g - this.g) * pos),\r\n b: ~~(this.b + (this.destination.b - this.b) * pos)\r\n })\r\n }\r\n\r\n})\r\n\r\n// Testers\r\n\r\n// Test if given value is a color string\r\nSVG.Color.test = function (color) {\r\n color += ''\r\n return SVG.regex.isHex.test(color) ||\r\n SVG.regex.isRgb.test(color)\r\n}\r\n\r\n// Test if given value is a rgb object\r\nSVG.Color.isRgb = function (color) {\r\n return color && typeof color.r === 'number' &&\r\n typeof color.g === 'number' &&\r\n typeof color.b === 'number'\r\n}\r\n\r\n// Test if given value is a color\r\nSVG.Color.isColor = function (color) {\r\n return SVG.Color.isRgb(color) || SVG.Color.test(color)\r\n}\r\n","/* global arrayClone */\r\n\r\n// Module for array conversion\r\nSVG.Array = function (array, fallback) {\r\n array = (array || []).valueOf()\r\n\r\n // if array is empty and fallback is provided, use fallback\r\n if (array.length === 0 && fallback) {\r\n array = fallback.valueOf()\r\n }\r\n\r\n // parse array\r\n this.value = this.parse(array)\r\n}\r\n\r\nSVG.extend(SVG.Array, {\r\n // Make array morphable\r\n morph: function (array) {\r\n this.destination = this.parse(array)\r\n\r\n // normalize length of arrays\r\n if (this.value.length !== this.destination.length) {\r\n var lastValue = this.value[this.value.length - 1]\r\n var lastDestination = this.destination[this.destination.length - 1]\r\n\r\n while (this.value.length > this.destination.length) {\r\n this.destination.push(lastDestination)\r\n }\r\n while (this.value.length < this.destination.length) {\r\n this.value.push(lastValue)\r\n }\r\n }\r\n\r\n return this\r\n },\r\n // Clean up any duplicate points\r\n settle: function () {\r\n // find all unique values\r\n for (var i = 0, il = this.value.length, seen = []; i < il; i++) {\r\n if (seen.indexOf(this.value[i]) === -1) {\r\n seen.push(this.value[i])\r\n }\r\n }\r\n\r\n // set new value\r\n this.value = seen\r\n return seen\r\n },\r\n // Get morphed array at given position\r\n at: function (pos) {\r\n // make sure a destination is defined\r\n if (!this.destination) return this\r\n\r\n // generate morphed array\r\n for (var i = 0, il = this.value.length, array = []; i < il; i++) {\r\n array.push(this.value[i] + (this.destination[i] - this.value[i]) * pos)\r\n }\r\n\r\n return new SVG.Array(array)\r\n },\r\n toArray: function () {\r\n return this.value\r\n },\r\n // Convert array to string\r\n toString: function () {\r\n return this.value.join(' ')\r\n },\r\n // Real value\r\n valueOf: function () {\r\n return this.value\r\n },\r\n // Parse whitespace separated string\r\n parse: function (array) {\r\n array = array.valueOf()\r\n\r\n // if already is an array, no need to parse it\r\n if (Array.isArray(array)) return array\r\n\r\n return array.trim().split(SVG.regex.delimiter).map(parseFloat)\r\n },\r\n // Reverse array\r\n reverse: function () {\r\n this.value.reverse()\r\n\r\n return this\r\n },\r\n clone: function () {\r\n var clone = new this.constructor()\r\n clone.value = arrayClone(this.value)\r\n return clone\r\n }\r\n})\r\n","\r\n// Poly points array\r\nSVG.PointArray = function (array, fallback) {\r\n SVG.Array.call(this, array, fallback || [[0, 0]])\r\n}\r\n\r\n// Inherit from SVG.Array\r\nSVG.PointArray.prototype = new SVG.Array()\r\nSVG.PointArray.prototype.constructor = SVG.PointArray\r\n\r\nSVG.extend(SVG.PointArray, {\r\n // Convert array to string\r\n toString: function () {\r\n // convert to a poly point string\r\n for (var i = 0, il = this.value.length, array = []; i < il; i++) {\r\n array.push(this.value[i].join(','))\r\n }\r\n\r\n return array.join(' ')\r\n },\r\n\r\n toArray: function () {\r\n return this.value.reduce(function (prev, curr) {\r\n return [].concat.call(prev, curr)\r\n }, [])\r\n },\r\n\r\n // Convert array to line object\r\n toLine: function () {\r\n return {\r\n x1: this.value[0][0],\r\n y1: this.value[0][1],\r\n x2: this.value[1][0],\r\n y2: this.value[1][1]\r\n }\r\n },\r\n\r\n // Get morphed array at given position\r\n at: function (pos) {\r\n // make sure a destination is defined\r\n if (!this.destination) return this\r\n\r\n // generate morphed point string\r\n for (var i = 0, il = this.value.length, array = []; i < il; i++) {\r\n array.push([\r\n this.value[i][0] + (this.destination[i][0] - this.value[i][0]) * pos,\r\n this.value[i][1] + (this.destination[i][1] - this.value[i][1]) * pos\r\n ])\r\n }\r\n\r\n return new SVG.PointArray(array)\r\n },\r\n\r\n // Parse point string and flat array\r\n parse: function (array) {\r\n var points = []\r\n\r\n array = array.valueOf()\r\n\r\n // if it is an array\r\n if (Array.isArray(array)) {\r\n // and it is not flat, there is no need to parse it\r\n if (Array.isArray(array[0])) {\r\n return array\r\n }\r\n } else { // Else, it is considered as a string\r\n // parse points\r\n array = array.trim().split(SVG.regex.delimiter).map(parseFloat)\r\n }\r\n\r\n // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints\r\n // Odd number of coordinates is an error. In such cases, drop the last odd coordinate.\r\n if (array.length % 2 !== 0) array.pop()\r\n\r\n // wrap points in two-tuples and parse points as floats\r\n for (var i = 0, len = array.length; i < len; i = i + 2) {\r\n points.push([ array[i], array[i + 1] ])\r\n }\r\n\r\n return points\r\n },\r\n\r\n // Move point string\r\n move: function (x, y) {\r\n var box = this.bbox()\r\n\r\n // get relative offset\r\n x -= box.x\r\n y -= box.y\r\n\r\n // move every point\r\n if (!isNaN(x) && !isNaN(y)) {\r\n for (var i = this.value.length - 1; i >= 0; i--) {\r\n this.value[i] = [this.value[i][0] + x, this.value[i][1] + y]\r\n }\r\n }\r\n\r\n return this\r\n },\r\n // Resize poly string\r\n size: function (width, height) {\r\n var i\r\n var box = this.bbox()\r\n\r\n // recalculate position of all points according to new size\r\n for (i = this.value.length - 1; i >= 0; i--) {\r\n if (box.width) this.value[i][0] = ((this.value[i][0] - box.x) * width) / box.width + box.x\r\n if (box.height) this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y\r\n }\r\n\r\n return this\r\n },\r\n\r\n // Get bounding box of points\r\n bbox: function () {\r\n var maxX = -Infinity\r\n var maxY = -Infinity\r\n var minX = Infinity\r\n var minY = Infinity\r\n this.value.forEach(function (el) {\r\n maxX = Math.max(el[0], maxX)\r\n maxY = Math.max(el[1], maxY)\r\n minX = Math.min(el[0], minX)\r\n minY = Math.min(el[1], minY)\r\n })\r\n return {x: minX, y: minY, width: maxX - minX, height: maxY - minY}\r\n }\r\n})\r\n","/* globals arrayToString, pathRegReplace */\r\n\r\nvar pathHandlers = {\r\n M: function (c, p, p0) {\r\n p.x = p0.x = c[0]\r\n p.y = p0.y = c[1]\r\n\r\n return ['M', p.x, p.y]\r\n },\r\n L: function (c, p) {\r\n p.x = c[0]\r\n p.y = c[1]\r\n return ['L', c[0], c[1]]\r\n },\r\n H: function (c, p) {\r\n p.x = c[0]\r\n return ['H', c[0]]\r\n },\r\n V: function (c, p) {\r\n p.y = c[0]\r\n return ['V', c[0]]\r\n },\r\n C: function (c, p) {\r\n p.x = c[4]\r\n p.y = c[5]\r\n return ['C', c[0], c[1], c[2], c[3], c[4], c[5]]\r\n },\r\n S: function (c, p) {\r\n p.x = c[2]\r\n p.y = c[3]\r\n return ['S', c[0], c[1], c[2], c[3]]\r\n },\r\n Q: function (c, p) {\r\n p.x = c[2]\r\n p.y = c[3]\r\n return ['Q', c[0], c[1], c[2], c[3]]\r\n },\r\n T: function (c, p) {\r\n p.x = c[0]\r\n p.y = c[1]\r\n return ['T', c[0], c[1]]\r\n },\r\n Z: function (c, p, p0) {\r\n p.x = p0.x\r\n p.y = p0.y\r\n return ['Z']\r\n },\r\n A: function (c, p) {\r\n p.x = c[5]\r\n p.y = c[6]\r\n return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]]\r\n }\r\n}\r\n\r\nvar mlhvqtcsaz = 'mlhvqtcsaz'.split('')\r\n\r\nfor (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) {\r\n pathHandlers[mlhvqtcsaz[i]] = (function (i) {\r\n return function (c, p, p0) {\r\n if (i === 'H') c[0] = c[0] + p.x\r\n else if (i === 'V') c[0] = c[0] + p.y\r\n else if (i === 'A') {\r\n c[5] = c[5] + p.x\r\n c[6] = c[6] + p.y\r\n } else {\r\n for (var j = 0, jl = c.length; j < jl; ++j) {\r\n c[j] = c[j] + (j % 2 ? p.y : p.x)\r\n }\r\n }\r\n\r\n return pathHandlers[i](c, p, p0)\r\n }\r\n })(mlhvqtcsaz[i].toUpperCase())\r\n}\r\n\r\n// Path points array\r\nSVG.PathArray = function (array, fallback) {\r\n SVG.Array.call(this, array, fallback || [['M', 0, 0]])\r\n}\r\n\r\n// Inherit from SVG.Array\r\nSVG.PathArray.prototype = new SVG.Array()\r\nSVG.PathArray.prototype.constructor = SVG.PathArray\r\n\r\nSVG.extend(SVG.PathArray, {\r\n // Convert array to string\r\n toString: function () {\r\n return arrayToString(this.value)\r\n },\r\n toArray: function () {\r\n return this.value.reduce(function (prev, curr) {\r\n return [].concat.call(prev, curr)\r\n }, [])\r\n },\r\n // Move path string\r\n move: function (x, y) {\r\n // get bounding box of current situation\r\n var box = this.bbox()\r\n\r\n // get relative offset\r\n x -= box.x\r\n y -= box.y\r\n\r\n if (!isNaN(x) && !isNaN(y)) {\r\n // move every point\r\n for (var l, i = this.value.length - 1; i >= 0; i--) {\r\n l = this.value[i][0]\r\n\r\n if (l === 'M' || l === 'L' || l === 'T') {\r\n this.value[i][1] += x\r\n this.value[i][2] += y\r\n } else if (l === 'H') {\r\n this.value[i][1] += x\r\n } else if (l === 'V') {\r\n this.value[i][1] += y\r\n } else if (l === 'C' || l === 'S' || l === 'Q') {\r\n this.value[i][1] += x\r\n this.value[i][2] += y\r\n this.value[i][3] += x\r\n this.value[i][4] += y\r\n\r\n if (l === 'C') {\r\n this.value[i][5] += x\r\n this.value[i][6] += y\r\n }\r\n } else if (l === 'A') {\r\n this.value[i][6] += x\r\n this.value[i][7] += y\r\n }\r\n }\r\n }\r\n\r\n return this\r\n },\r\n // Resize path string\r\n size: function (width, height) {\r\n // get bounding box of current situation\r\n var box = this.bbox()\r\n var i, l\r\n\r\n // recalculate position of all points according to new size\r\n for (i = this.value.length - 1; i >= 0; i--) {\r\n l = this.value[i][0]\r\n\r\n if (l === 'M' || l === 'L' || l === 'T') {\r\n this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x\r\n this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y\r\n } else if (l === 'H') {\r\n this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x\r\n } else if (l === 'V') {\r\n this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y\r\n } else if (l === 'C' || l === 'S' || l === 'Q') {\r\n this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x\r\n this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y\r\n this.value[i][3] = ((this.value[i][3] - box.x) * width) / box.width + box.x\r\n this.value[i][4] = ((this.value[i][4] - box.y) * height) / box.height + box.y\r\n\r\n if (l === 'C') {\r\n this.value[i][5] = ((this.value[i][5] - box.x) * width) / box.width + box.x\r\n this.value[i][6] = ((this.value[i][6] - box.y) * height) / box.height + box.y\r\n }\r\n } else if (l === 'A') {\r\n // resize radii\r\n this.value[i][1] = (this.value[i][1] * width) / box.width\r\n this.value[i][2] = (this.value[i][2] * height) / box.height\r\n\r\n // move position values\r\n this.value[i][6] = ((this.value[i][6] - box.x) * width) / box.width + box.x\r\n this.value[i][7] = ((this.value[i][7] - box.y) * height) / box.height + box.y\r\n }\r\n }\r\n\r\n return this\r\n },\r\n // Test if the passed path array use the same path data commands as this path array\r\n equalCommands: function (pathArray) {\r\n var i, il, equalCommands\r\n\r\n pathArray = new SVG.PathArray(pathArray)\r\n\r\n equalCommands = this.value.length === pathArray.value.length\r\n for (i = 0, il = this.value.length; equalCommands && i < il; i++) {\r\n equalCommands = this.value[i][0] === pathArray.value[i][0]\r\n }\r\n\r\n return equalCommands\r\n },\r\n // Make path array morphable\r\n morph: function (pathArray) {\r\n pathArray = new SVG.PathArray(pathArray)\r\n\r\n if (this.equalCommands(pathArray)) {\r\n this.destination = pathArray\r\n } else {\r\n this.destination = null\r\n }\r\n\r\n return this\r\n },\r\n // Get morphed path array at given position\r\n at: function (pos) {\r\n // make sure a destination is defined\r\n if (!this.destination) return this\r\n\r\n var sourceArray = this.value\r\n var destinationArray = this.destination.value\r\n var array = []\r\n var pathArray = new SVG.PathArray()\r\n var i, il, j, jl\r\n\r\n // Animate has specified in the SVG spec\r\n // See: https://www.w3.org/TR/SVG11/paths.html#PathElement\r\n for (i = 0, il = sourceArray.length; i < il; i++) {\r\n array[i] = [sourceArray[i][0]]\r\n for (j = 1, jl = sourceArray[i].length; j < jl; j++) {\r\n array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos\r\n }\r\n // For the two flags of the elliptical arc command, the SVG spec say:\r\n // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true\r\n // Elliptical arc command as an array followed by corresponding indexes:\r\n // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y]\r\n // 0 1 2 3 4 5 6 7\r\n if (array[i][0] === 'A') {\r\n array[i][4] = +(array[i][4] !== 0)\r\n array[i][5] = +(array[i][5] !== 0)\r\n }\r\n }\r\n\r\n // Directly modify the value of a path array, this is done this way for performance\r\n pathArray.value = array\r\n return pathArray\r\n },\r\n // Absolutize and parse path to array\r\n parse: function (array) {\r\n // if it's already a patharray, no need to parse it\r\n if (array instanceof SVG.PathArray) return array.valueOf()\r\n\r\n // prepare for parsing\r\n var s\r\n var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 }\r\n\r\n if (typeof array === 'string') {\r\n array = array\r\n .replace(SVG.regex.numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123\r\n .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers\r\n .replace(SVG.regex.hyphen, '$1 -') // add space before hyphen\r\n .trim() // trim\r\n .split(SVG.regex.delimiter) // split into array\r\n } else {\r\n array = array.reduce(function (prev, curr) {\r\n return [].concat.call(prev, curr)\r\n }, [])\r\n }\r\n\r\n // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...]\r\n var result = []\r\n var p = new SVG.Point()\r\n var p0 = new SVG.Point()\r\n var index = 0\r\n var len = array.length\r\n\r\n do {\r\n // Test if we have a path letter\r\n if (SVG.regex.isPathLetter.test(array[index])) {\r\n s = array[index]\r\n ++index\r\n // If last letter was a move command and we got no new, it defaults to [L]ine\r\n } else if (s === 'M') {\r\n s = 'L'\r\n } else if (s === 'm') {\r\n s = 'l'\r\n }\r\n\r\n result.push(pathHandlers[s].call(null,\r\n array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat),\r\n p, p0\r\n )\r\n )\r\n } while (len > index)\r\n\r\n return result\r\n },\r\n // Get bounding box of path\r\n bbox: function () {\r\n SVG.parser().path.setAttribute('d', this.toString())\r\n return SVG.parser.nodes.path.getBBox()\r\n }\r\n\r\n})\r\n","\r\n// Module for unit convertions\r\nSVG.Number = SVG.invent({\r\n // Initialize\r\n create: function (value, unit) {\r\n unit = Array.isArray(value) ? value[1] : unit\r\n value = Array.isArray(value) ? value[0] : value\r\n\r\n // initialize defaults\r\n this.value = 0\r\n this.unit = unit || ''\r\n\r\n // parse value\r\n if (typeof value === 'number') {\r\n // ensure a valid numeric value\r\n this.value = isNaN(value) ? 0 : !isFinite(value) ? (value < 0 ? -3.4e+38 : +3.4e+38) : value\r\n } else if (typeof value === 'string') {\r\n unit = value.match(SVG.regex.numberAndUnit)\r\n\r\n if (unit) {\r\n // make value numeric\r\n this.value = parseFloat(unit[1])\r\n\r\n // normalize\r\n if (unit[5] === '%') { this.value /= 100 } else if (unit[5] === 's') {\r\n this.value *= 1000\r\n }\r\n\r\n // store unit\r\n this.unit = unit[5]\r\n }\r\n } else {\r\n if (value instanceof SVG.Number) {\r\n this.value = value.valueOf()\r\n this.unit = value.unit\r\n }\r\n }\r\n },\r\n // Add methods\r\n extend: {\r\n // Stringalize\r\n toString: function () {\r\n return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6\r\n : this.unit === 's' ? this.value / 1e3\r\n : this.value\r\n ) + this.unit\r\n },\r\n toJSON: function () {\r\n return this.toString()\r\n }, // Convert to primitive\r\n toArray: function () {\r\n return [this.value, this.unit]\r\n },\r\n valueOf: function () {\r\n return this.value\r\n },\r\n // Add number\r\n plus: function (number) {\r\n number = new SVG.Number(number)\r\n return new SVG.Number(this + number, this.unit || number.unit)\r\n },\r\n // Subtract number\r\n minus: function (number) {\r\n number = new SVG.Number(number)\r\n return new SVG.Number(this - number, this.unit || number.unit)\r\n },\r\n // Multiply number\r\n times: function (number) {\r\n number = new SVG.Number(number)\r\n return new SVG.Number(this * number, this.unit || number.unit)\r\n },\r\n // Divide number\r\n divide: function (number) {\r\n number = new SVG.Number(number)\r\n return new SVG.Number(this / number, this.unit || number.unit)\r\n },\r\n // Convert to different unit\r\n to: function (unit) {\r\n var number = new SVG.Number(this)\r\n\r\n if (typeof unit === 'string') {\r\n number.unit = unit\r\n }\r\n\r\n return number\r\n },\r\n // Make number morphable\r\n morph: function (number) {\r\n this.destination = new SVG.Number(number)\r\n\r\n if (number.relative) {\r\n this.destination.value += this.value\r\n }\r\n\r\n return this\r\n },\r\n // Get morphed number at given position\r\n at: function (pos) {\r\n // Make sure a destination is defined\r\n if (!this.destination) return this\r\n\r\n // Generate new morphed number\r\n return new SVG.Number(this.destination)\r\n .minus(this)\r\n .times(pos)\r\n .plus(this)\r\n }\r\n }\r\n})\r\n","SVG.EventTarget = SVG.invent({\r\n create: function () {},\r\n extend: {\r\n // Bind given event to listener\r\n on: function (event, listener, binding, options) {\r\n SVG.on(this, event, listener, binding, options)\r\n return this\r\n },\r\n // Unbind event from listener\r\n off: function (event, listener) {\r\n SVG.off(this, event, listener)\r\n return this\r\n },\r\n dispatch: function (event, data) {\r\n return SVG.dispatch(this, event, data)\r\n },\r\n // Fire given event\r\n fire: function (event, data) {\r\n this.dispatch(event, data)\r\n return this\r\n }\r\n }\r\n})\r\n","/* global createElement */\r\n\r\nSVG.HtmlNode = SVG.invent({\r\n inherit: SVG.EventTarget,\r\n create: function (element) {\r\n this.node = element\r\n },\r\n\r\n extend: {\r\n add: function (element, i) {\r\n element = createElement(element)\r\n\r\n if (element.node !== this.node.children[i]) {\r\n this.node.insertBefore(element.node, this.node.children[i] || null)\r\n }\r\n\r\n return this\r\n },\r\n\r\n put: function (element, i) {\r\n this.add(element, i)\r\n return element\r\n },\r\n\r\n getEventTarget: function () {\r\n return this.node\r\n }\r\n }\r\n})\r\n","/* global proportionalSize, assignNewId, createElement, matches, is */\r\n\r\nSVG.Element = SVG.invent({\r\n inherit: SVG.EventTarget,\r\n\r\n // Initialize node\r\n create: function (node) {\r\n // event listener\r\n this.events = {}\r\n\r\n // initialize data object\r\n this.dom = {}\r\n\r\n // create circular reference\r\n this.node = node\r\n if (this.node) {\r\n this.type = node.nodeName\r\n this.node.instance = this\r\n this.events = node.events || {}\r\n\r\n if (node.hasAttribute('svgjs:data')) {\r\n // pull svgjs data from the dom (getAttributeNS doesn't work in html5)\r\n this.setData(JSON.parse(node.getAttribute('svgjs:data')) || {})\r\n }\r\n }\r\n },\r\n\r\n // Add class methods\r\n extend: {\r\n // Move over x-axis\r\n x: function (x) {\r\n return this.attr('x', x)\r\n },\r\n\r\n // Move over y-axis\r\n y: function (y) {\r\n return this.attr('y', y)\r\n },\r\n\r\n // Move by center over x-axis\r\n cx: function (x) {\r\n return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2)\r\n },\r\n\r\n // Move by center over y-axis\r\n cy: function (y) {\r\n return y == null\r\n ? this.y() + this.height() / 2\r\n : this.y(y - this.height() / 2)\r\n },\r\n\r\n // Move element to given x and y values\r\n move: function (x, y) {\r\n return this.x(x).y(y)\r\n },\r\n\r\n // Move element by its center\r\n center: function (x, y) {\r\n return this.cx(x).cy(y)\r\n },\r\n\r\n // Set width of element\r\n width: function (width) {\r\n return this.attr('width', width)\r\n },\r\n\r\n // Set height of element\r\n height: function (height) {\r\n return this.attr('height', height)\r\n },\r\n\r\n // Set element size to given width and height\r\n size: function (width, height) {\r\n var p = proportionalSize(this, width, height)\r\n\r\n return this\r\n .width(new SVG.Number(p.width))\r\n .height(new SVG.Number(p.height))\r\n },\r\n\r\n // Clone element\r\n clone: function (parent) {\r\n // write dom data to the dom so the clone can pickup the data\r\n this.writeDataToDom()\r\n\r\n // clone element and assign new id\r\n var clone = assignNewId(this.node.cloneNode(true))\r\n\r\n // insert the clone in the given parent or after myself\r\n if (parent) parent.add(clone)\r\n else this.after(clone)\r\n\r\n return clone\r\n },\r\n\r\n // Remove element\r\n remove: function () {\r\n if (this.parent()) { this.parent().removeElement(this) }\r\n\r\n return this\r\n },\r\n\r\n // Replace element\r\n replace: function (element) {\r\n this.after(element).remove()\r\n\r\n return element\r\n },\r\n\r\n // Add element to given container and return self\r\n addTo: function (parent) {\r\n return createElement(parent).put(this)\r\n },\r\n\r\n // Add element to given container and return container\r\n putIn: function (parent) {\r\n return createElement(parent).add(this)\r\n },\r\n\r\n // Get / set id\r\n id: function (id) {\r\n // generate new id if no id set\r\n if (typeof id === 'undefined' && !this.node.id) {\r\n this.node.id = SVG.eid(this.type)\r\n }\r\n\r\n // dont't set directly width this.node.id to make `null` work correctly\r\n return this.attr('id', id)\r\n },\r\n\r\n // Checks whether the given point inside the bounding box of the element\r\n inside: function (x, y) {\r\n var box = this.bbox()\r\n\r\n return x > box.x &&\r\n y > box.y &&\r\n x < box.x + box.width &&\r\n y < box.y + box.height\r\n },\r\n\r\n // Show element\r\n show: function () {\r\n return this.css('display', '')\r\n },\r\n\r\n // Hide element\r\n hide: function () {\r\n return this.css('display', 'none')\r\n },\r\n\r\n // Is element visible?\r\n visible: function () {\r\n return this.css('display') !== 'none'\r\n },\r\n\r\n // Return id on string conversion\r\n toString: function () {\r\n return this.id()\r\n },\r\n\r\n // Return array of classes on the node\r\n classes: function () {\r\n var attr = this.attr('class')\r\n return attr == null ? [] : attr.trim().split(SVG.regex.delimiter)\r\n },\r\n\r\n // Return true if class exists on the node, false otherwise\r\n hasClass: function (name) {\r\n return this.classes().indexOf(name) !== -1\r\n },\r\n\r\n // Add class to the node\r\n addClass: function (name) {\r\n if (!this.hasClass(name)) {\r\n var array = this.classes()\r\n array.push(name)\r\n this.attr('class', array.join(' '))\r\n }\r\n\r\n return this\r\n },\r\n\r\n // Remove class from the node\r\n removeClass: function (name) {\r\n if (this.hasClass(name)) {\r\n this.attr('class', this.classes().filter(function (c) {\r\n return c !== name\r\n }).join(' '))\r\n }\r\n\r\n return this\r\n },\r\n\r\n // Toggle the presence of a class on the node\r\n toggleClass: function (name) {\r\n return this.hasClass(name) ? this.removeClass(name) : this.addClass(name)\r\n },\r\n\r\n // Get referenced element form attribute value\r\n reference: function (attr) {\r\n return SVG.get(this.attr(attr))\r\n },\r\n\r\n // Returns the parent element instance\r\n parent: function (type) {\r\n var parent = this\r\n\r\n // check for parent\r\n if (!parent.node.parentNode) return null\r\n\r\n // get parent element\r\n parent = SVG.adopt(parent.node.parentNode)\r\n\r\n if (!type) return parent\r\n\r\n // loop trough ancestors if type is given\r\n while (parent && parent.node instanceof window.SVGElement) {\r\n if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent\r\n parent = SVG.adopt(parent.node.parentNode)\r\n }\r\n },\r\n\r\n // Get parent document\r\n doc: function () {\r\n var p = this.parent(SVG.Doc)\r\n return p && p.doc()\r\n },\r\n\r\n // Get defs\r\n defs: function () {\r\n return this.doc().defs()\r\n },\r\n\r\n // return array of all ancestors of given type up to the root svg\r\n parents: function (type) {\r\n var parents = []\r\n var parent = this\r\n\r\n do {\r\n parent = parent.parent(type)\r\n if (!parent || !parent.node) break\r\n\r\n parents.push(parent)\r\n } while (parent.parent)\r\n\r\n return parents\r\n },\r\n\r\n // matches the element vs a css selector\r\n matches: function (selector) {\r\n return matches(this.node, selector)\r\n },\r\n\r\n // Returns the svg node to call native svg methods on it\r\n native: function () {\r\n return this.node\r\n },\r\n\r\n // Import raw svg\r\n svg: function (svg) {\r\n var well, len\r\n\r\n // act as a setter if svg is given\r\n if (svg && this instanceof SVG.Parent) {\r\n // create temporary holder\r\n well = document.createElementNS(SVG.ns, 'svg')\r\n // dump raw svg\r\n well.innerHTML = svg\r\n\r\n // transplant nodes\r\n for (len = well.children.length; len--;) {\r\n this.node.appendChild(well.firstElementChild)\r\n }\r\n\r\n // otherwise act as a getter\r\n } else {\r\n // write svgjs data to the dom\r\n this.writeDataToDom()\r\n\r\n return this.node.outerHTML\r\n }\r\n\r\n return this\r\n },\r\n\r\n // write svgjs data to the dom\r\n writeDataToDom: function () {\r\n // dump variables recursively\r\n if (this.is(SVG.Parent)) {\r\n this.each(function () {\r\n this.writeDataToDom()\r\n })\r\n }\r\n\r\n // remove previously set data\r\n this.node.removeAttribute('svgjs:data')\r\n\r\n if (Object.keys(this.dom).length) {\r\n this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)) // see #428\r\n }\r\n return this\r\n },\r\n\r\n // set given data to the elements data property\r\n setData: function (o) {\r\n this.dom = o\r\n return this\r\n },\r\n is: function (obj) {\r\n return is(this, obj)\r\n },\r\n getEventTarget: function () {\r\n return this.node\r\n }\r\n }\r\n})\r\n","// Add events to elements\r\n;[ 'click',\r\n 'dblclick',\r\n 'mousedown',\r\n 'mouseup',\r\n 'mouseover',\r\n 'mouseout',\r\n 'mousemove',\r\n 'mouseenter',\r\n 'mouseleave',\r\n 'touchstart',\r\n 'touchmove',\r\n 'touchleave',\r\n 'touchend',\r\n 'touchcancel' ].forEach(function (event) {\r\n // add event to SVG.Element\r\n SVG.Element.prototype[event] = function (f) {\r\n if (f === null) {\r\n SVG.off(this, event)\r\n } else {\r\n SVG.on(this, event, f)\r\n }\r\n return this\r\n }\r\n })\r\n\r\nSVG.listenerId = 0\r\n\r\n// Add event binder in the SVG namespace\r\nSVG.on = function (node, events, listener, binding, options) {\r\n var l = listener.bind(binding || node)\r\n var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node\r\n\r\n // events can be an array of events or a string of events\r\n events = Array.isArray(events) ? events : events.split(SVG.regex.delimiter)\r\n\r\n // ensure instance object for nodes which are not adopted\r\n n.instance = n.instance || {events: {}}\r\n\r\n // pull event handlers from the element\r\n var bag = n.instance.events\r\n\r\n // add id to listener\r\n if (!listener._svgjsListenerId) {\r\n listener._svgjsListenerId = ++SVG.listenerId\r\n }\r\n\r\n events.forEach(function (event) {\r\n var ev = event.split('.')[0]\r\n var ns = event.split('.')[1] || '*'\r\n\r\n // ensure valid object\r\n bag[ev] = bag[ev] || {}\r\n bag[ev][ns] = bag[ev][ns] || {}\r\n\r\n // reference listener\r\n bag[ev][ns][listener._svgjsListenerId] = l\r\n\r\n // add listener\r\n n.addEventListener(ev, l, options || false)\r\n })\r\n}\r\n\r\n// Add event unbinder in the SVG namespace\r\nSVG.off = function (node, events, listener, options) {\r\n var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node\r\n if (!n.instance) return\r\n\r\n // listener can be a function or a number\r\n if (typeof listener === 'function') {\r\n listener = listener._svgjsListenerId\r\n if (!listener) return\r\n }\r\n\r\n // pull event handlers from the element\r\n var bag = n.instance.events\r\n\r\n // events can be an array of events or a string or undefined\r\n events = Array.isArray(events) ? events : (events || '').split(SVG.regex.delimiter)\r\n\r\n events.forEach(function (event) {\r\n var ev = event && event.split('.')[0]\r\n var ns = event && event.split('.')[1]\r\n var namespace, l\r\n\r\n if (listener) {\r\n // remove listener reference\r\n if (bag[ev] && bag[ev][ns || '*']) {\r\n // removeListener\r\n n.removeEventListener(ev, bag[ev][ns || '*'][listener], options || false)\r\n\r\n delete bag[ev][ns || '*'][listener]\r\n }\r\n } else if (ev && ns) {\r\n // remove all listeners for a namespaced event\r\n if (bag[ev] && bag[ev][ns]) {\r\n for (l in bag[ev][ns]) { SVG.off(n, [ev, ns].join('.'), l) }\r\n\r\n delete bag[ev][ns]\r\n }\r\n } else if (ns) {\r\n // remove all listeners for a specific namespace\r\n for (event in bag) {\r\n for (namespace in bag[event]) {\r\n if (ns === namespace) { SVG.off(n, [event, ns].join('.')) }\r\n }\r\n }\r\n } else if (ev) {\r\n // remove all listeners for the event\r\n if (bag[ev]) {\r\n for (namespace in bag[ev]) { SVG.off(n, [ev, namespace].join('.')) }\r\n\r\n delete bag[ev]\r\n }\r\n } else {\r\n // remove all listeners on a given node\r\n for (event in bag) { SVG.off(n, event) }\r\n\r\n n.instance.events = {}\r\n }\r\n })\r\n}\r\n\r\nSVG.dispatch = function (node, event, data) {\r\n var n = node instanceof SVG.EventTarget ? node.getEventTarget() : node\r\n\r\n // Dispatch event\r\n if (event instanceof window.Event) {\r\n n.dispatchEvent(event)\r\n } else {\r\n event = new window.CustomEvent(event, {detail: data, cancelable: true})\r\n n.dispatchEvent(event)\r\n }\r\n return event\r\n}\r\n","/* global abcdef arrayToMatrix closeEnough formatTransforms isMatrixLike matrixMultiply */\r\n\r\nSVG.Matrix = SVG.invent({\r\n // Initialize\r\n create: function (source) {\r\n var base = arrayToMatrix([1, 0, 0, 1, 0, 0])\r\n\r\n // ensure source as object\r\n source = source instanceof SVG.Element ? source.matrixify()\r\n : typeof source === 'string' ? arrayToMatrix(source.split(SVG.regex.delimiter).map(parseFloat))\r\n : Array.isArray(source) ? arrayToMatrix(source)\r\n : (typeof source === 'object' && isMatrixLike(source)) ? source\r\n : (typeof source === 'object') ? new SVG.Matrix().transform(source)\r\n : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments))\r\n : base\r\n\r\n // Merge the source matrix with the base matrix\r\n this.a = source.a != null ? source.a : base.a\r\n this.b = source.b != null ? source.b : base.b\r\n this.c = source.c != null ? source.c : base.c\r\n this.d = source.d != null ? source.d : base.d\r\n this.e = source.e != null ? source.e : base.e\r\n this.f = source.f != null ? source.f : base.f\r\n },\r\n\r\n // Add methods\r\n extend: {\r\n\r\n // Clones this matrix\r\n clone: function () {\r\n return new SVG.Matrix(this)\r\n },\r\n\r\n // Transform a matrix into another matrix by manipulating the space\r\n transform: function (o) {\r\n // Check if o is a matrix and then left multiply it directly\r\n if (isMatrixLike(o)) {\r\n var matrix = new SVG.Matrix(o)\r\n return matrix.multiplyO(this)\r\n }\r\n\r\n // Get the proposed transformations and the current transformations\r\n var t = formatTransforms(o)\r\n var current = this\r\n let { x: ox, y: oy } = new SVG.Point(t.ox, t.oy).transform(current)\r\n\r\n // Construct the resulting matrix\r\n var transformer = new SVG.Matrix()\r\n .translateO(t.rx, t.ry)\r\n .lmultiplyO(current)\r\n .translateO(-ox, -oy)\r\n .scaleO(t.scaleX, t.scaleY)\r\n .skewO(t.skewX, t.skewY)\r\n .shearO(t.shear)\r\n .rotateO(t.theta)\r\n .translateO(ox, oy)\r\n\r\n // If we want the origin at a particular place, we force it there\r\n if (isFinite(t.px) || isFinite(t.py)) {\r\n const origin = new SVG.Point(ox, oy).transform(transformer)\r\n // TODO: Replace t.px with isFinite(t.px)\r\n const dx = t.px ? t.px - origin.x : 0\r\n const dy = t.py ? t.py - origin.y : 0\r\n transformer.translateO(dx, dy)\r\n }\r\n\r\n // Translate now after positioning\r\n transformer.translateO(t.tx, t.ty)\r\n return transformer\r\n },\r\n\r\n // Applies a matrix defined by its affine parameters\r\n compose: function (o) {\r\n if (o.origin) {\r\n o.originX = o.origin[0]\r\n o.originY = o.origin[1]\r\n }\r\n // Get the parameters\r\n var ox = o.originX || 0\r\n var oy = o.originY || 0\r\n var sx = o.scaleX || 1\r\n var sy = o.scaleY || 1\r\n var lam = o.shear || 0\r\n var theta = o.rotate || 0\r\n var tx = o.translateX || 0\r\n var ty = o.translateY || 0\r\n\r\n // Apply the standard matrix\r\n var result = new SVG.Matrix()\r\n .translateO(-ox, -oy)\r\n .scaleO(sx, sy)\r\n .shearO(lam)\r\n .rotateO(theta)\r\n .translateO(tx, ty)\r\n .lmultiplyO(this)\r\n .translateO(ox, oy)\r\n return result\r\n },\r\n\r\n // Decomposes this matrix into its affine parameters\r\n decompose: function (cx = 0, cy = 0) {\r\n // Get the parameters from the matrix\r\n var a = this.a\r\n var b = this.b\r\n var c = this.c\r\n var d = this.d\r\n var e = this.e\r\n var f = this.f\r\n\r\n // Figure out if the winding direction is clockwise or counterclockwise\r\n var determinant = a * d - b * c\r\n var ccw = determinant > 0 ? 1 : -1\r\n\r\n // Since we only shear in x, we can use the x basis to get the x scale\r\n // and the rotation of the resulting matrix\r\n var sx = ccw * Math.sqrt(a * a + b * b)\r\n var thetaRad = Math.atan2(ccw * b, ccw * a)\r\n var theta = 180 / Math.PI * thetaRad\r\n var ct = Math.cos(thetaRad)\r\n var st = Math.sin(thetaRad)\r\n\r\n // We can then solve the y basis vector simultaneously to get the other\r\n // two affine parameters directly from these parameters\r\n var lam = (a * c + b * d) / determinant\r\n var sy = ((c * sx) / (lam * a - b)) || ((d * sx) / (lam * b + a))\r\n\r\n // Use the translations\r\n let tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy)\r\n let ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy)\r\n\r\n // Construct the decomposition and return it\r\n return {\r\n // Return the affine parameters\r\n scaleX: sx,\r\n scaleY: sy,\r\n shear: lam,\r\n rotate: theta,\r\n translateX: tx,\r\n translateY: ty,\r\n originX: cx,\r\n originY: cy,\r\n\r\n // Return the matrix parameters\r\n a: this.a,\r\n b: this.b,\r\n c: this.c,\r\n d: this.d,\r\n e: this.e,\r\n f: this.f\r\n }\r\n },\r\n\r\n // Morph one matrix into another\r\n morph: function (matrix) {\r\n // Store new destination\r\n this.destination = new SVG.Matrix(matrix)\r\n return this\r\n },\r\n\r\n // Get morphed matrix at a given position\r\n at: function (pos) {\r\n // Make sure a destination is defined\r\n if (!this.destination) return this\r\n\r\n // Calculate morphed matrix at a given position\r\n var matrix = new SVG.Matrix({\r\n a: this.a + (this.destination.a - this.a) * pos,\r\n b: this.b + (this.destination.b - this.b) * pos,\r\n c: this.c + (this.destination.c - this.c) * pos,\r\n d: this.d + (this.destination.d - this.d) * pos,\r\n e: this.e + (this.destination.e - this.e) * pos,\r\n f: this.f + (this.destination.f - this.f) * pos\r\n })\r\n\r\n return matrix\r\n },\r\n\r\n // Left multiplies by the given matrix\r\n multiply: function (matrix) {\r\n return this.clone().multiplyO(matrix)\r\n },\r\n\r\n multiplyO: function (matrix) {\r\n // Get the matrices\r\n var l = this\r\n var r = matrix instanceof SVG.Matrix\r\n ? matrix\r\n : new SVG.Matrix(matrix)\r\n\r\n return matrixMultiply(l, r, this)\r\n },\r\n\r\n lmultiply: function (matrix) {\r\n return this.clone().lmultiplyO(matrix)\r\n },\r\n\r\n lmultiplyO: function (matrix) {\r\n var r = this\r\n var l = matrix instanceof SVG.Matrix\r\n ? matrix\r\n : new SVG.Matrix(matrix)\r\n\r\n return matrixMultiply(l, r, this)\r\n },\r\n\r\n // Inverses matrix\r\n inverseO: function () {\r\n // Get the current parameters out of the matrix\r\n var a = this.a\r\n var b = this.b\r\n var c = this.c\r\n var d = this.d\r\n var e = this.e\r\n var f = this.f\r\n\r\n // Invert the 2x2 matrix in the top left\r\n var det = a * d - b * c\r\n if (!det) throw new Error('Cannot invert ' + this)\r\n\r\n // Calculate the top 2x2 matrix\r\n var na = d / det\r\n var nb = -b / det\r\n var nc = -c / det\r\n var nd = a / det\r\n\r\n // Apply the inverted matrix to the top right\r\n var ne = -(na * e + nc * f)\r\n var nf = -(nb * e + nd * f)\r\n\r\n // Construct the inverted matrix\r\n this.a = na\r\n this.b = nb\r\n this.c = nc\r\n this.d = nd\r\n this.e = ne\r\n this.f = nf\r\n\r\n return this\r\n },\r\n\r\n inverse: function () {\r\n return this.clone().inverseO()\r\n },\r\n\r\n // Translate matrix\r\n translate: function (x, y) {\r\n return this.clone().translateO(x, y)\r\n },\r\n\r\n translateO: function (x, y) {\r\n this.e += x || 0\r\n this.f += y || 0\r\n return this\r\n },\r\n\r\n // Scale matrix\r\n scale: function (x, y, cx, cy) {\r\n return this.clone().scaleO(...arguments)\r\n },\r\n\r\n scaleO: function (x, y = x, cx = 0, cy = 0) {\r\n // Support uniform scaling\r\n if (arguments.length === 3) {\r\n cy = cx\r\n cx = y\r\n y = x\r\n }\r\n\r\n let {a, b, c, d, e, f} = this\r\n\r\n this.a = a * x\r\n this.b = b * y\r\n this.c = c * x\r\n this.d = d * y\r\n this.e = e * x - cx * x + cx\r\n this.f = f * y - cy * y + cy\r\n\r\n return this\r\n },\r\n\r\n // Rotate matrix\r\n rotate: function (r, cx, cy) {\r\n return this.clone().rotateO(r, cx, cy)\r\n },\r\n\r\n rotateO: function (r, cx = 0, cy = 0) {\r\n // Convert degrees to radians\r\n r = SVG.utils.radians(r)\r\n\r\n let cos = Math.cos(r)\r\n let sin = Math.sin(r)\r\n\r\n let {a, b, c, d, e, f} = this\r\n\r\n this.a = a * cos - b * sin\r\n this.b = b * cos + a * sin\r\n this.c = c * cos - d * sin\r\n this.d = d * cos + c * sin\r\n this.e = e * cos - f * sin + cy * sin - cx * cos + cx\r\n this.f = f * cos + e * sin - cx * sin - cy * cos + cy\r\n\r\n return this\r\n },\r\n\r\n // Flip matrix on x or y, at a given offset\r\n flip: function (axis, around) {\r\n return this.clone().flipO(axis, around)\r\n },\r\n\r\n flipO: function (axis, around) {\r\n return axis === 'x' ? this.scaleO(-1, 1, around, 0)\r\n : axis === 'y' ? this.scaleO(1, -1, 0, around)\r\n : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point\r\n },\r\n\r\n // Shear matrix\r\n shear: function (a, cx, cy) {\r\n return this.clone().shearO(a, cx, cy)\r\n },\r\n\r\n shearO: function (lx, cx = 0, cy = 0) {\r\n let {a, b, c, d, e, f} = this\r\n\r\n this.a = a + b * lx\r\n this.c = c + d * lx\r\n this.e = e + f * lx - cy * lx\r\n\r\n return this\r\n },\r\n\r\n // Skew Matrix\r\n skew: function (x, y, cx, cy) {\r\n return this.clone().skewO(...arguments)\r\n },\r\n\r\n skewO: function (x, y = x, cx = 0, cy = 0) {\r\n // support uniformal skew\r\n if (arguments.length === 3) {\r\n cy = cx\r\n cx = y\r\n y = x\r\n }\r\n\r\n // Convert degrees to radians\r\n x = SVG.utils.radians(x)\r\n y = SVG.utils.radians(y)\r\n\r\n let lx = Math.tan(x)\r\n let ly = Math.tan(y)\r\n\r\n let {a, b, c, d, e, f} = this\r\n\r\n this.a = a + b * lx\r\n this.b = b + a * ly\r\n this.c = c + d * lx\r\n this.d = d + c * ly\r\n this.e = e + f * lx - cy * lx\r\n this.f = f + e * ly - cx * ly\r\n\r\n return this\r\n },\r\n\r\n // SkewX\r\n skewX: function (x, cx, cy) {\r\n return this.skew(x, 0, cx, cy)\r\n },\r\n\r\n skewXO: function (x, cx, cy) {\r\n return this.skewO(x, 0, cx, cy)\r\n },\r\n\r\n // SkewY\r\n skewY: function (y, cx, cy) {\r\n return this.skew(0, y, cx, cy)\r\n },\r\n\r\n skewYO: function (y, cx, cy) {\r\n return this.skewO(0, y, cx, cy)\r\n },\r\n\r\n // Transform around a center point\r\n aroundO: function (cx, cy, matrix) {\r\n var dx = cx || 0\r\n var dy = cy || 0\r\n return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy)\r\n },\r\n\r\n around: function (cx, cy, matrix) {\r\n return this.clone().aroundO(cx, cy, matrix)\r\n },\r\n\r\n // Convert to native SVGMatrix\r\n native: function () {\r\n // create new matrix\r\n var matrix = SVG.parser.nodes.svg.node.createSVGMatrix()\r\n\r\n // update with current values\r\n for (var i = abcdef.length - 1; i >= 0; i--) {\r\n matrix[abcdef[i]] = this[abcdef[i]]\r\n }\r\n\r\n return matrix\r\n },\r\n\r\n // Check if two matrices are equal\r\n equals: function (other) {\r\n var comp = new SVG.Matrix(other)\r\n return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) &&\r\n closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) &&\r\n closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f)\r\n },\r\n\r\n // Convert matrix to string\r\n toString: function () {\r\n return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'\r\n },\r\n\r\n toArray: function () {\r\n return [this.a, this.b, this.c, this.d, this.e, this.f]\r\n },\r\n\r\n valueOf: function () {\r\n return {\r\n a: this.a,\r\n b: this.b,\r\n c: this.c,\r\n d: this.d,\r\n e: this.e,\r\n f: this.f\r\n }\r\n }\r\n },\r\n\r\n // Define parent\r\n parent: SVG.Element,\r\n\r\n // Add parent method\r\n construct: {\r\n // Get current matrix\r\n ctm: function () {\r\n return new SVG.Matrix(this.node.getCTM())\r\n },\r\n // Get current screen matrix\r\n screenCTM: function () {\r\n /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537\r\n This is needed because FF does not return the transformation matrix\r\n for the inner coordinate system when getScreenCTM() is called on nested svgs.\r\n However all other Browsers do that */\r\n if (this instanceof SVG.Doc && !this.isRoot()) {\r\n var rect = this.rect(1, 1)\r\n var m = rect.node.getScreenCTM()\r\n rect.remove()\r\n return new SVG.Matrix(m)\r\n }\r\n return new SVG.Matrix(this.node.getScreenCTM())\r\n }\r\n }\r\n})\r\n\r\n// let extensions = {}\r\n// ['rotate'].forEach((method) => {\r\n// let methodO = method + 'O'\r\n// extensions[method] = function (...args) {\r\n// return new SVG.Matrix(this)[methodO](...args)\r\n// }\r\n// })\r\n//\r\n// SVG.extend(SVG.Matrix, extensions)\r\n\r\n// function matrixMultiplyParams (matrix, a, b, c, d, e, f) {\r\n// return matrixMultiply({a, b, c, d, e, f}, matrix, matrix)\r\n// }\r\n","\r\nSVG.Point = SVG.invent({\r\n // Initialize\r\n create: function (x, y, base) {\r\n var source\r\n base = base || {x: 0, y: 0}\r\n\r\n // ensure source as object\r\n source = Array.isArray(x) ? {x: x[0], y: x[1]}\r\n : typeof x === 'object' ? {x: x.x, y: x.y}\r\n : {x: x, y: y}\r\n\r\n // merge source\r\n this.x = source.x == null ? base.x : source.x\r\n this.y = source.y == null ? base.y : source.y\r\n },\r\n\r\n // Add methods\r\n extend: {\r\n // Clone point\r\n clone: function () {\r\n return new SVG.Point(this)\r\n },\r\n\r\n // Morph one point into another\r\n morph: function (x, y) {\r\n // store new destination\r\n this.destination = new SVG.Point(x, y)\r\n return this\r\n },\r\n\r\n // Get morphed point at a given position\r\n at: function (pos) {\r\n // make sure a destination is defined\r\n if (!this.destination) return this\r\n\r\n // calculate morphed matrix at a given position\r\n var point = new SVG.Point({\r\n x: this.x + (this.destination.x - this.x) * pos,\r\n y: this.y + (this.destination.y - this.y) * pos\r\n })\r\n return point\r\n },\r\n\r\n // Convert to native SVGPoint\r\n native: function () {\r\n // create new point\r\n var point = SVG.parser.nodes.svg.node.createSVGPoint()\r\n\r\n // update with current values\r\n point.x = this.x\r\n point.y = this.y\r\n return point\r\n },\r\n\r\n // transform point with matrix\r\n transform: function (m) {\r\n // Perform the matrix multiplication\r\n var x = m.a * this.x + m.c * this.y + m.e\r\n var y = m.b * this.x + m.d * this.y + m.f\r\n\r\n // Return the required point\r\n return new SVG.Point(x, y)\r\n }\r\n }\r\n})\r\n\r\nSVG.extend(SVG.Element, {\r\n\r\n // Get point\r\n point: function (x, y) {\r\n return new SVG.Point(x, y).transform(this.screenCTM().inverse())\r\n }\r\n})\r\n","SVG.extend(SVG.Element, {\r\n // Set svg element attribute\r\n attr: function (a, v, n) {\r\n // act as full getter\r\n if (a == null) {\r\n // get an object of attributes\r\n a = {}\r\n v = this.node.attributes\r\n for (n = v.length - 1; n >= 0; n--) {\r\n a[v[n].nodeName] = SVG.regex.isNumber.test(v[n].nodeValue)\r\n ? parseFloat(v[n].nodeValue)\r\n : v[n].nodeValue\r\n }\r\n return a\r\n } else if (typeof a === 'object') {\r\n // apply every attribute individually if an object is passed\r\n for (v in a) this.attr(v, a[v])\r\n } else if (v === null) {\r\n // remove value\r\n this.node.removeAttribute(a)\r\n } else if (v == null) {\r\n // act as a getter if the first and only argument is not an object\r\n v = this.node.getAttribute(a)\r\n return v == null ? SVG.defaults.attrs[a]\r\n : SVG.regex.isNumber.test(v) ? parseFloat(v)\r\n : v\r\n } else {\r\n // convert image fill and stroke to patterns\r\n if (a === 'fill' || a === 'stroke') {\r\n if (SVG.regex.isImage.test(v)) {\r\n v = this.doc().defs().image(v)\r\n }\r\n\r\n if (v instanceof SVG.Image) {\r\n v = this.doc().defs().pattern(0, 0, function () {\r\n this.add(v)\r\n })\r\n }\r\n }\r\n\r\n // ensure correct numeric values (also accepts NaN and Infinity)\r\n if (typeof v === 'number') {\r\n v = new SVG.Number(v)\r\n } else if (SVG.Color.isColor(v)) {\r\n // ensure full hex color\r\n v = new SVG.Color(v)\r\n } else if (Array.isArray(v)) {\r\n // parse array values\r\n v = new SVG.Array(v)\r\n }\r\n\r\n // if the passed attribute is leading...\r\n if (a === 'leading') {\r\n // ... call the leading method instead\r\n if (this.leading) {\r\n this.leading(v)\r\n }\r\n } else {\r\n // set given attribute on node\r\n typeof n === 'string' ? this.node.setAttributeNS(n, a, v.toString())\r\n : this.node.setAttribute(a, v.toString())\r\n }\r\n\r\n // rebuild if required\r\n if (this.rebuild && (a === 'font-size' || a === 'x')) {\r\n this.rebuild(a, v)\r\n }\r\n }\r\n\r\n return this\r\n }\r\n})\r\n","/* global arrayToMatrix getOrigin isMatrixLike */\r\n\r\nSVG.extend(SVG.Element, {\r\n // Reset all transformations\r\n untransform: function () {\r\n return this.attr('transform', null)\r\n },\r\n\r\n // merge the whole transformation chain into one matrix and returns it\r\n matrixify: function () {\r\n var matrix = (this.attr('transform') || '')\r\n // split transformations\r\n .split(SVG.regex.transforms).slice(0, -1).map(function (str) {\r\n // generate key => value pairs\r\n var kv = str.trim().split('(')\r\n return [kv[0],\r\n kv[1].split(SVG.regex.delimiter)\r\n .map(function (str) { return parseFloat(str) })\r\n ]\r\n })\r\n .reverse()\r\n // merge every transformation into one matrix\r\n .reduce(function (matrix, transform) {\r\n if (transform[0] === 'matrix') {\r\n return matrix.lmultiply(arrayToMatrix(transform[1]))\r\n }\r\n return matrix[transform[0]].apply(matrix, transform[1])\r\n }, new SVG.Matrix())\r\n\r\n return matrix\r\n },\r\n\r\n // add an element to another parent without changing the visual representation on the screen\r\n toParent: function (parent) {\r\n if (this === parent) return this\r\n var ctm = this.screenCTM()\r\n var pCtm = parent.screenCTM().inverse()\r\n\r\n this.addTo(parent).untransform().transform(pCtm.multiply(ctm))\r\n\r\n return this\r\n },\r\n\r\n // same as above with parent equals root-svg\r\n toDoc: function () {\r\n return this.toParent(this.doc())\r\n }\r\n})\r\n\r\nSVG.extend(SVG.Element, {\r\n\r\n // Add transformations\r\n transform: function (o, relative) {\r\n // Act as a getter if no object was passed\r\n if (o == null || typeof o === 'string') {\r\n var decomposed = new SVG.Matrix(this).decompose()\r\n return decomposed[o] || decomposed\r\n }\r\n\r\n if (!isMatrixLike(o)) {\r\n // Set the origin according to the defined transform\r\n o = {...o, origin: getOrigin(o, this)}\r\n }\r\n\r\n // The user can pass a boolean, an SVG.Element or an SVG.Matrix or nothing\r\n var cleanRelative = relative === true ? this : (relative || false)\r\n var result = new SVG.Matrix(cleanRelative).transform(o)\r\n return this.attr('transform', result)\r\n }\r\n})\r\n","/* global camelCase */\r\n\r\nSVG.extend(SVG.Element, {\r\n // Dynamic style generator\r\n css: function (s, v) {\r\n var ret = {}\r\n var t, i\r\n if (arguments.length === 0) {\r\n // get full style as object\r\n this.node.style.cssText.split(/\\s*;\\s*/).filter(function (el) { return !!el.length }).forEach(function (el) {\r\n t = el.split(/\\s*:\\s*/)\r\n ret[t[0]] = t[1]\r\n })\r\n return ret\r\n }\r\n\r\n if (arguments.length < 2) {\r\n // get style properties in the array\r\n if (Array.isArray(s)) {\r\n for (i = s.length; i--;) {\r\n ret[camelCase(s[i])] = this.node.style[camelCase(s[i])]\r\n }\r\n return ret\r\n }\r\n\r\n // get style for property\r\n if (typeof s === 'string') {\r\n return this.node.style[camelCase(s)]\r\n }\r\n\r\n // set styles in object\r\n if (typeof s === 'object') {\r\n for (i in s) {\r\n // set empty string if null/undefined/'' was given\r\n this.node.style[camelCase(i)] = (s[i] == null || SVG.regex.isBlank.test(s[i])) ? '' : s[i]\r\n }\r\n }\r\n }\r\n\r\n // set style for property\r\n if (arguments.length === 2) {\r\n this.node.style[camelCase(s)] = (v == null || SVG.regex.isBlank.test(v)) ? '' : v\r\n }\r\n\r\n return this\r\n }\r\n})\r\n","/* global createElement */\r\n\r\nSVG.Parent = SVG.invent({\r\n // Initialize node\r\n create: function (node) {\r\n SVG.Element.call(this, node)\r\n },\r\n\r\n // Inherit from\r\n inherit: SVG.Element,\r\n\r\n // Add class methods\r\n extend: {\r\n // Returns all child elements\r\n children: function () {\r\n return SVG.utils.map(this.node.children, function (node) {\r\n return SVG.adopt(node)\r\n })\r\n },\r\n // Add given element at a position\r\n add: function (element, i) {\r\n element = createElement(element)\r\n\r\n if (element.node !== this.node.children[i]) {\r\n this.node.insertBefore(element.node, this.node.children[i] || null)\r\n }\r\n\r\n return this\r\n },\r\n // Basically does the same as `add()` but returns the added element instead\r\n put: function (element, i) {\r\n this.add(element, i)\r\n return element.instance || element\r\n },\r\n // Checks if the given element is a child\r\n has: function (element) {\r\n return this.index(element) >= 0\r\n },\r\n // Gets index of given element\r\n index: function (element) {\r\n return [].slice.call(this.node.children).indexOf(element.node)\r\n },\r\n // Get a element at the given index\r\n get: function (i) {\r\n return SVG.adopt(this.node.children[i])\r\n },\r\n // Get first child\r\n first: function () {\r\n return this.get(0)\r\n },\r\n // Get the last child\r\n last: function () {\r\n return this.get(this.node.children.length - 1)\r\n },\r\n // Iterates over all children and invokes a given block\r\n each: function (block, deep) {\r\n var children = this.children()\r\n var i, il\r\n\r\n for (i = 0, il = children.length; i < il; i++) {\r\n if (children[i] instanceof SVG.Element) {\r\n block.apply(children[i], [i, children])\r\n }\r\n\r\n if (deep && (children[i] instanceof SVG.Parent)) {\r\n children[i].each(block, deep)\r\n }\r\n }\r\n\r\n return this\r\n },\r\n // Remove a given child\r\n removeElement: function (element) {\r\n this.node.removeChild(element.node)\r\n\r\n return this\r\n },\r\n // Remove all elements in this container\r\n clear: function () {\r\n // remove children\r\n while (this.node.hasChildNodes()) {\r\n this.node.removeChild(this.node.lastChild)\r\n }\r\n\r\n // remove defs reference\r\n delete this._defs\r\n\r\n return this\r\n }\r\n }\r\n\r\n})\r\n","SVG.extend(SVG.Parent, {\r\n flatten: function (parent) {\r\n // flattens is only possible for nested svgs and groups\r\n if (!(this instanceof SVG.G || this instanceof SVG.Doc)) {\r\n return this\r\n }\r\n\r\n parent = parent || (this instanceof SVG.Doc && this.isRoot() ? this : this.parent(SVG.Parent))\r\n\r\n this.each(function () {\r\n if (this instanceof SVG.Defs) return this\r\n if (this instanceof SVG.Parent) return this.flatten(parent)\r\n return this.toParent(parent)\r\n })\r\n\r\n // we need this so that SVG.Doc does not get removed\r\n this.node.firstElementChild || this.remove()\r\n\r\n return this\r\n },\r\n ungroup: function (parent) {\r\n // ungroup is only possible for nested svgs and groups\r\n if (!(this instanceof SVG.G || (this instanceof SVG.Doc && !this.isRoot()))) {\r\n return this\r\n }\r\n\r\n parent = parent || this.parent(SVG.Parent)\r\n\r\n this.each(function () {\r\n return this.toParent(parent)\r\n })\r\n\r\n // we need this so that SVG.Doc does not get removed\r\n this.remove()\r\n\r\n return this\r\n }\r\n})\r\n","SVG.Container = SVG.invent({\r\n // Initialize node\r\n create: function (node) {\r\n SVG.Element.call(this, node)\r\n },\r\n\r\n // Inherit from\r\n inherit: SVG.Parent\r\n})\r\n","SVG.Defs = SVG.invent({\r\n // Initialize node\r\n create: 'defs',\r\n\r\n // Inherit from\r\n inherit: SVG.Container\r\n})\r\n","SVG.G = SVG.invent({\r\n // Initialize node\r\n create: 'g',\r\n\r\n // Inherit from\r\n inherit: SVG.Container,\r\n\r\n // Add class methods\r\n extend: {\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n // Create a group element\r\n group: function () {\r\n return this.put(new SVG.G())\r\n }\r\n }\r\n})\r\n","// ### This module adds backward / forward functionality to elements.\r\n\r\n//\r\nSVG.extend(SVG.Element, {\r\n // Get all siblings, including myself\r\n siblings: function () {\r\n return this.parent().children()\r\n },\r\n\r\n // Get the curent position siblings\r\n position: function () {\r\n return this.parent().index(this)\r\n },\r\n\r\n // Get the next element (will return null if there is none)\r\n next: function () {\r\n return this.siblings()[this.position() + 1]\r\n },\r\n\r\n // Get the next element (will return null if there is none)\r\n prev: function () {\r\n return this.siblings()[this.position() - 1]\r\n },\r\n\r\n // Send given element one step forward\r\n forward: function () {\r\n var i = this.position() + 1\r\n var p = this.parent()\r\n\r\n // move node one step forward\r\n p.removeElement(this).add(this, i)\r\n\r\n // make sure defs node is always at the top\r\n if (p instanceof SVG.Doc) {\r\n p.node.appendChild(p.defs().node)\r\n }\r\n\r\n return this\r\n },\r\n\r\n // Send given element one step backward\r\n backward: function () {\r\n var i = this.position()\r\n\r\n if (i > 0) {\r\n this.parent().removeElement(this).add(this, i - 1)\r\n }\r\n\r\n return this\r\n },\r\n\r\n // Send given element all the way to the front\r\n front: function () {\r\n var p = this.parent()\r\n\r\n // Move node forward\r\n p.node.appendChild(this.node)\r\n\r\n // Make sure defs node is always at the top\r\n if (p instanceof SVG.Doc) {\r\n p.node.appendChild(p.defs().node)\r\n }\r\n\r\n return this\r\n },\r\n\r\n // Send given element all the way to the back\r\n back: function () {\r\n if (this.position() > 0) {\r\n this.parent().removeElement(this).add(this, 0)\r\n }\r\n\r\n return this\r\n },\r\n\r\n // Inserts a given element before the targeted element\r\n before: function (element) {\r\n element.remove()\r\n\r\n var i = this.position()\r\n\r\n this.parent().add(element, i)\r\n\r\n return this\r\n },\r\n\r\n // Insters a given element after the targeted element\r\n after: function (element) {\r\n element.remove()\r\n\r\n var i = this.position()\r\n\r\n this.parent().add(element, i + 1)\r\n\r\n return this\r\n }\r\n})\r\n","SVG.Mask = SVG.invent({\r\n // Initialize node\r\n create: 'mask',\r\n\r\n // Inherit from\r\n inherit: SVG.Container,\r\n\r\n // Add class methods\r\n extend: {\r\n // Unmask all masked elements and remove itself\r\n remove: function () {\r\n // unmask all targets\r\n this.targets().forEach(function (el) {\r\n el.unmask()\r\n })\r\n\r\n // remove mask from parent\r\n return SVG.Element.prototype.remove.call(this)\r\n },\r\n\r\n targets: function () {\r\n return SVG.select('svg [mask*=\"' + this.id() + '\"]')\r\n }\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n // Create masking element\r\n mask: function () {\r\n return this.defs().put(new SVG.Mask())\r\n }\r\n }\r\n})\r\n\r\nSVG.extend(SVG.Element, {\r\n // Distribute mask to svg element\r\n maskWith: function (element) {\r\n // use given mask or create a new one\r\n var masker = element instanceof SVG.Mask ? element : this.parent().mask().add(element)\r\n\r\n // apply mask\r\n return this.attr('mask', 'url(\"#' + masker.id() + '\")')\r\n },\r\n // Unmask element\r\n unmask: function () {\r\n return this.attr('mask', null)\r\n },\r\n masker: function () {\r\n return this.reference('mask')\r\n }\r\n})\r\n","SVG.ClipPath = SVG.invent({\r\n // Initialize node\r\n create: 'clipPath',\r\n\r\n // Inherit from\r\n inherit: SVG.Container,\r\n\r\n // Add class methods\r\n extend: {\r\n // Unclip all clipped elements and remove itself\r\n remove: function () {\r\n // unclip all targets\r\n this.targets().forEach(function (el) {\r\n el.unclip()\r\n })\r\n\r\n // remove clipPath from parent\r\n return SVG.Element.prototype.remove.call(this)\r\n },\r\n\r\n targets: function () {\r\n return SVG.select('svg [clip-path*=\"' + this.id() + '\"]')\r\n }\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n // Create clipping element\r\n clip: function () {\r\n return this.defs().put(new SVG.ClipPath())\r\n }\r\n }\r\n})\r\n\r\n//\r\nSVG.extend(SVG.Element, {\r\n // Distribute clipPath to svg element\r\n clipWith: function (element) {\r\n // use given clip or create a new one\r\n var clipper = element instanceof SVG.ClipPath ? element : this.parent().clip().add(element)\r\n\r\n // apply mask\r\n return this.attr('clip-path', 'url(\"#' + clipper.id() + '\")')\r\n },\r\n // Unclip element\r\n unclip: function () {\r\n return this.attr('clip-path', null)\r\n },\r\n clipper: function () {\r\n return this.reference('clip-path')\r\n }\r\n\r\n})\r\n","SVG.Gradient = SVG.invent({\r\n // Initialize node\r\n create: function (type) {\r\n SVG.Element.call(this, typeof type === 'object' ? type : SVG.create(type + 'Gradient'))\r\n },\r\n\r\n // Inherit from\r\n inherit: SVG.Container,\r\n\r\n // Add class methods\r\n extend: {\r\n // Add a color stop\r\n stop: function (offset, color, opacity) {\r\n return this.put(new SVG.Stop()).update(offset, color, opacity)\r\n },\r\n // Update gradient\r\n update: function (block) {\r\n // remove all stops\r\n this.clear()\r\n\r\n // invoke passed block\r\n if (typeof block === 'function') {\r\n block.call(this, this)\r\n }\r\n\r\n return this\r\n },\r\n // Return the fill id\r\n url: function () {\r\n return 'url(#' + this.id() + ')'\r\n },\r\n // Alias string convertion to fill\r\n toString: function () {\r\n return this.url()\r\n },\r\n // custom attr to handle transform\r\n attr: function (a, b, c) {\r\n if (a === 'transform') a = 'gradientTransform'\r\n return SVG.Container.prototype.attr.call(this, a, b, c)\r\n }\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n // Create gradient element in defs\r\n gradient: function (type, block) {\r\n return this.defs().gradient(type, block)\r\n }\r\n }\r\n})\r\n\r\n// Add animatable methods to both gradient and fx module\r\nSVG.extend([SVG.Gradient, SVG.Timeline], {\r\n // From position\r\n from: function (x, y) {\r\n return (this._target || this).type === 'radialGradient'\r\n ? this.attr({ fx: new SVG.Number(x), fy: new SVG.Number(y) })\r\n : this.attr({ x1: new SVG.Number(x), y1: new SVG.Number(y) })\r\n },\r\n // To position\r\n to: function (x, y) {\r\n return (this._target || this).type === 'radialGradient'\r\n ? this.attr({ cx: new SVG.Number(x), cy: new SVG.Number(y) })\r\n : this.attr({ x2: new SVG.Number(x), y2: new SVG.Number(y) })\r\n }\r\n})\r\n\r\n// Base gradient generation\r\nSVG.extend(SVG.Defs, {\r\n // define gradient\r\n gradient: function (type, block) {\r\n return this.put(new SVG.Gradient(type)).update(block)\r\n }\r\n\r\n})\r\n\r\nSVG.Stop = SVG.invent({\r\n // Initialize node\r\n create: 'stop',\r\n\r\n // Inherit from\r\n inherit: SVG.Element,\r\n\r\n // Add class methods\r\n extend: {\r\n // add color stops\r\n update: function (o) {\r\n if (typeof o === 'number' || o instanceof SVG.Number) {\r\n o = {\r\n offset: arguments[0],\r\n color: arguments[1],\r\n opacity: arguments[2]\r\n }\r\n }\r\n\r\n // set attributes\r\n if (o.opacity != null) this.attr('stop-opacity', o.opacity)\r\n if (o.color != null) this.attr('stop-color', o.color)\r\n if (o.offset != null) this.attr('offset', new SVG.Number(o.offset))\r\n\r\n return this\r\n }\r\n }\r\n})\r\n","SVG.Pattern = SVG.invent({\r\n // Initialize node\r\n create: 'pattern',\r\n\r\n // Inherit from\r\n inherit: SVG.Container,\r\n\r\n // Add class methods\r\n extend: {\r\n // Return the fill id\r\n url: function () {\r\n return 'url(#' + this.id() + ')'\r\n },\r\n // Update pattern by rebuilding\r\n update: function (block) {\r\n // remove content\r\n this.clear()\r\n\r\n // invoke passed block\r\n if (typeof block === 'function') {\r\n block.call(this, this)\r\n }\r\n\r\n return this\r\n },\r\n // Alias string convertion to fill\r\n toString: function () {\r\n return this.url()\r\n },\r\n // custom attr to handle transform\r\n attr: function (a, b, c) {\r\n if (a === 'transform') a = 'patternTransform'\r\n return SVG.Container.prototype.attr.call(this, a, b, c)\r\n }\r\n\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n // Create pattern element in defs\r\n pattern: function (width, height, block) {\r\n return this.defs().pattern(width, height, block)\r\n }\r\n }\r\n})\r\n\r\nSVG.extend(SVG.Defs, {\r\n // Define gradient\r\n pattern: function (width, height, block) {\r\n return this.put(new SVG.Pattern()).update(block).attr({\r\n x: 0,\r\n y: 0,\r\n width: width,\r\n height: height,\r\n patternUnits: 'userSpaceOnUse'\r\n })\r\n }\r\n\r\n})\r\n","SVG.Doc = SVG.invent({\r\n // Initialize node\r\n create: function (node) {\r\n SVG.Element.call(this, node || SVG.create('svg'))\r\n\r\n // set svg element attributes and ensure defs node\r\n this.namespace()\r\n },\r\n\r\n // Inherit from\r\n inherit: SVG.Container,\r\n\r\n // Add class methods\r\n extend: {\r\n isRoot: function () {\r\n return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document'\r\n },\r\n // Check if this is a root svg. If not, call docs from this element\r\n doc: function () {\r\n if (this.isRoot()) return this\r\n return SVG.Element.prototype.doc.call(this)\r\n },\r\n // Add namespaces\r\n namespace: function () {\r\n if (!this.isRoot()) return this.doc().namespace()\r\n return this\r\n .attr({ xmlns: SVG.ns, version: '1.1' })\r\n .attr('xmlns:xlink', SVG.xlink, SVG.xmlns)\r\n .attr('xmlns:svgjs', SVG.svgjs, SVG.xmlns)\r\n },\r\n // Creates and returns defs element\r\n defs: function () {\r\n if (!this.isRoot()) return this.doc().defs()\r\n return SVG.adopt(this.node.getElementsByTagName('defs')[0]) || this.put(new SVG.Defs())\r\n },\r\n // custom parent method\r\n parent: function (type) {\r\n if (this.isRoot()) {\r\n return this.node.parentNode.nodeName === '#document' ? null : this.node.parentNode\r\n }\r\n\r\n return SVG.Element.prototype.parent.call(this, type)\r\n },\r\n // Removes the doc from the DOM\r\n remove: function () {\r\n if (!this.isRoot()) {\r\n return SVG.Element.prototype.remove.call(this)\r\n }\r\n\r\n if (this.parent()) {\r\n this.parent().removeChild(this.node)\r\n }\r\n\r\n return this\r\n },\r\n clear: function () {\r\n // remove children\r\n while (this.node.hasChildNodes()) {\r\n this.node.removeChild(this.node.lastChild)\r\n }\r\n return this\r\n }\r\n },\r\n construct: {\r\n // Create nested svg document\r\n nested: function () {\r\n return this.put(new SVG.Doc())\r\n }\r\n }\r\n})\r\n","\r\nSVG.Shape = SVG.invent({\r\n // Initialize node\r\n create: function (node) {\r\n SVG.Element.call(this, node)\r\n },\r\n\r\n // Inherit from\r\n inherit: SVG.Element\r\n})\r\n","\r\nSVG.Bare = SVG.invent({\r\n // Initialize\r\n create: function (element, inherit) {\r\n // construct element\r\n SVG.Element.call(this, SVG.create(element))\r\n\r\n // inherit custom methods\r\n if (inherit) {\r\n for (var method in inherit.prototype) {\r\n if (typeof inherit.prototype[method] === 'function') {\r\n this[method] = inherit.prototype[method]\r\n }\r\n }\r\n }\r\n },\r\n\r\n // Inherit from\r\n inherit: SVG.Element,\r\n\r\n // Add methods\r\n extend: {\r\n // Insert some plain text\r\n words: function (text) {\r\n // remove contents\r\n while (this.node.hasChildNodes()) {\r\n this.node.removeChild(this.node.lastChild)\r\n }\r\n\r\n // create text node\r\n this.node.appendChild(document.createTextNode(text))\r\n\r\n return this\r\n }\r\n }\r\n})\r\n\r\nSVG.extend(SVG.Parent, {\r\n // Create an element that is not described by SVG.js\r\n element: function (element, inherit) {\r\n return this.put(new SVG.Bare(element, inherit))\r\n }\r\n})\r\n","\r\nSVG.Symbol = SVG.invent({\r\n // Initialize node\r\n create: 'symbol',\r\n\r\n // Inherit from\r\n inherit: SVG.Container,\r\n\r\n construct: {\r\n // create symbol\r\n symbol: function () {\r\n return this.put(new SVG.Symbol())\r\n }\r\n }\r\n})\r\n","\r\nSVG.Use = SVG.invent({\r\n // Initialize node\r\n create: 'use',\r\n\r\n // Inherit from\r\n inherit: SVG.Shape,\r\n\r\n // Add class methods\r\n extend: {\r\n // Use element as a reference\r\n element: function (element, file) {\r\n // Set lined element\r\n return this.attr('href', (file || '') + '#' + element, SVG.xlink)\r\n }\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n // Create a use element\r\n use: function (element, file) {\r\n return this.put(new SVG.Use()).element(element, file)\r\n }\r\n }\r\n})\r\n","\r\nSVG.Rect = SVG.invent({\r\n // Initialize node\r\n create: 'rect',\r\n\r\n // Inherit from\r\n inherit: SVG.Shape,\r\n\r\n // Add parent method\r\n construct: {\r\n // Create a rect element\r\n rect: function (width, height) {\r\n return this.put(new SVG.Rect()).size(width, height)\r\n }\r\n }\r\n})\r\n","/* global proportionalSize */\r\n\r\nSVG.Circle = SVG.invent({\r\n // Initialize node\r\n create: 'circle',\r\n\r\n // Inherit from\r\n inherit: SVG.Shape,\r\n\r\n // Add parent method\r\n construct: {\r\n // Create circle element, based on ellipse\r\n circle: function (size) {\r\n return this.put(new SVG.Circle()).rx(new SVG.Number(size).divide(2)).move(0, 0)\r\n }\r\n }\r\n})\r\n\r\nSVG.extend([SVG.Circle, SVG.Timeline], {\r\n // Radius x value\r\n rx: function (rx) {\r\n return this.attr('r', rx)\r\n },\r\n // Alias radius x value\r\n ry: function (ry) {\r\n return this.rx(ry)\r\n }\r\n})\r\n\r\nSVG.Ellipse = SVG.invent({\r\n // Initialize node\r\n create: 'ellipse',\r\n\r\n // Inherit from\r\n inherit: SVG.Shape,\r\n\r\n // Add parent method\r\n construct: {\r\n // Create an ellipse\r\n ellipse: function (width, height) {\r\n return this.put(new SVG.Ellipse()).size(width, height).move(0, 0)\r\n }\r\n }\r\n})\r\n\r\nSVG.extend([SVG.Ellipse, SVG.Rect, SVG.Timeline], {\r\n // Radius x value\r\n rx: function (rx) {\r\n return this.attr('rx', rx)\r\n },\r\n // Radius y value\r\n ry: function (ry) {\r\n return this.attr('ry', ry)\r\n }\r\n})\r\n\r\n// Add common method\r\nSVG.extend([SVG.Circle, SVG.Ellipse], {\r\n // Move over x-axis\r\n x: function (x) {\r\n return x == null ? this.cx() - this.rx() : this.cx(x + this.rx())\r\n },\r\n // Move over y-axis\r\n y: function (y) {\r\n return y == null ? this.cy() - this.ry() : this.cy(y + this.ry())\r\n },\r\n // Move by center over x-axis\r\n cx: function (x) {\r\n return x == null ? this.attr('cx') : this.attr('cx', x)\r\n },\r\n // Move by center over y-axis\r\n cy: function (y) {\r\n return y == null ? this.attr('cy') : this.attr('cy', y)\r\n },\r\n // Set width of element\r\n width: function (width) {\r\n return width == null ? this.rx() * 2 : this.rx(new SVG.Number(width).divide(2))\r\n },\r\n // Set height of element\r\n height: function (height) {\r\n return height == null ? this.ry() * 2 : this.ry(new SVG.Number(height).divide(2))\r\n },\r\n // Custom size function\r\n size: function (width, height) {\r\n var p = proportionalSize(this, width, height)\r\n\r\n return this\r\n .rx(new SVG.Number(p.width).divide(2))\r\n .ry(new SVG.Number(p.height).divide(2))\r\n }\r\n})\r\n","/* global proportionalSize */\r\n\r\nSVG.Line = SVG.invent({\r\n // Initialize node\r\n create: 'line',\r\n\r\n // Inherit from\r\n inherit: SVG.Shape,\r\n\r\n // Add class methods\r\n extend: {\r\n // Get array\r\n array: function () {\r\n return new SVG.PointArray([\r\n [ this.attr('x1'), this.attr('y1') ],\r\n [ this.attr('x2'), this.attr('y2') ]\r\n ])\r\n },\r\n\r\n // Overwrite native plot() method\r\n plot: function (x1, y1, x2, y2) {\r\n if (x1 == null) {\r\n return this.array()\r\n } else if (typeof y1 !== 'undefined') {\r\n x1 = { x1: x1, y1: y1, x2: x2, y2: y2 }\r\n } else {\r\n x1 = new SVG.PointArray(x1).toLine()\r\n }\r\n\r\n return this.attr(x1)\r\n },\r\n\r\n // Move by left top corner\r\n move: function (x, y) {\r\n return this.attr(this.array().move(x, y).toLine())\r\n },\r\n\r\n // Set element size to given width and height\r\n size: function (width, height) {\r\n var p = proportionalSize(this, width, height)\r\n return this.attr(this.array().size(p.width, p.height).toLine())\r\n }\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n // Create a line element\r\n line: function (x1, y1, x2, y2) {\r\n // make sure plot is called as a setter\r\n // x1 is not necessarily a number, it can also be an array, a string and a SVG.PointArray\r\n return SVG.Line.prototype.plot.apply(\r\n this.put(new SVG.Line())\r\n , x1 != null ? [x1, y1, x2, y2] : [0, 0, 0, 0]\r\n )\r\n }\r\n }\r\n})\r\n","/* global proportionalSize */\r\n\r\nSVG.Polyline = SVG.invent({\r\n // Initialize node\r\n create: 'polyline',\r\n\r\n // Inherit from\r\n inherit: SVG.Shape,\r\n\r\n // Add parent method\r\n construct: {\r\n // Create a wrapped polyline element\r\n polyline: function (p) {\r\n // make sure plot is called as a setter\r\n return this.put(new SVG.Polyline()).plot(p || new SVG.PointArray())\r\n }\r\n }\r\n})\r\n\r\nSVG.Polygon = SVG.invent({\r\n // Initialize node\r\n create: 'polygon',\r\n\r\n // Inherit from\r\n inherit: SVG.Shape,\r\n\r\n // Add parent method\r\n construct: {\r\n // Create a wrapped polygon element\r\n polygon: function (p) {\r\n // make sure plot is called as a setter\r\n return this.put(new SVG.Polygon()).plot(p || new SVG.PointArray())\r\n }\r\n }\r\n})\r\n\r\n// Add polygon-specific functions\r\nSVG.extend([SVG.Polyline, SVG.Polygon], {\r\n // Get array\r\n array: function () {\r\n return this._array || (this._array = new SVG.PointArray(this.attr('points')))\r\n },\r\n\r\n // Plot new path\r\n plot: function (p) {\r\n return (p == null) ? this.array()\r\n : this.clear().attr('points', typeof p === 'string' ? p\r\n : (this._array = new SVG.PointArray(p)))\r\n },\r\n\r\n // Clear array cache\r\n clear: function () {\r\n delete this._array\r\n return this\r\n },\r\n\r\n // Move by left top corner\r\n move: function (x, y) {\r\n return this.attr('points', this.array().move(x, y))\r\n },\r\n\r\n // Set element size to given width and height\r\n size: function (width, height) {\r\n var p = proportionalSize(this, width, height)\r\n return this.attr('points', this.array().size(p.width, p.height))\r\n }\r\n})\r\n","// unify all point to point elements\r\nSVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon], {\r\n // Define morphable array\r\n MorphArray: SVG.PointArray,\r\n // Move by left top corner over x-axis\r\n x: function (x) {\r\n return x == null ? this.bbox().x : this.move(x, this.bbox().y)\r\n },\r\n // Move by left top corner over y-axis\r\n y: function (y) {\r\n return y == null ? this.bbox().y : this.move(this.bbox().x, y)\r\n },\r\n // Set width of element\r\n width: function (width) {\r\n var b = this.bbox()\r\n\r\n return width == null ? b.width : this.size(width, b.height)\r\n },\r\n // Set height of element\r\n height: function (height) {\r\n var b = this.bbox()\r\n\r\n return height == null ? b.height : this.size(b.width, height)\r\n }\r\n})\r\n","/* global proportionalSize */\r\n\r\nSVG.Path = SVG.invent({\r\n // Initialize node\r\n create: 'path',\r\n\r\n // Inherit from\r\n inherit: SVG.Shape,\r\n\r\n // Add class methods\r\n extend: {\r\n // Define morphable array\r\n MorphArray: SVG.PathArray,\r\n // Get array\r\n array: function () {\r\n return this._array || (this._array = new SVG.PathArray(this.attr('d')))\r\n },\r\n // Plot new path\r\n plot: function (d) {\r\n return (d == null) ? this.array()\r\n : this.clear().attr('d', typeof d === 'string' ? d : (this._array = new SVG.PathArray(d)))\r\n },\r\n // Clear array cache\r\n clear: function () {\r\n delete this._array\r\n return this\r\n },\r\n // Move by left top corner\r\n move: function (x, y) {\r\n return this.attr('d', this.array().move(x, y))\r\n },\r\n // Move by left top corner over x-axis\r\n x: function (x) {\r\n return x == null ? this.bbox().x : this.move(x, this.bbox().y)\r\n },\r\n // Move by left top corner over y-axis\r\n y: function (y) {\r\n return y == null ? this.bbox().y : this.move(this.bbox().x, y)\r\n },\r\n // Set element size to given width and height\r\n size: function (width, height) {\r\n var p = proportionalSize(this, width, height)\r\n return this.attr('d', this.array().size(p.width, p.height))\r\n },\r\n // Set width of element\r\n width: function (width) {\r\n return width == null ? this.bbox().width : this.size(width, this.bbox().height)\r\n },\r\n // Set height of element\r\n height: function (height) {\r\n return height == null ? this.bbox().height : this.size(this.bbox().width, height)\r\n }\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n // Create a wrapped path element\r\n path: function (d) {\r\n // make sure plot is called as a setter\r\n return this.put(new SVG.Path()).plot(d || new SVG.PathArray())\r\n }\r\n }\r\n})\r\n","SVG.Image = SVG.invent({\r\n // Initialize node\r\n create: 'image',\r\n\r\n // Inherit from\r\n inherit: SVG.Shape,\r\n\r\n // Add class methods\r\n extend: {\r\n // (re)load image\r\n load: function (url, callback) {\r\n if (!url) return this\r\n\r\n var img = new window.Image()\r\n\r\n SVG.on(img, 'load', function (e) {\r\n var p = this.parent(SVG.Pattern)\r\n\r\n // ensure image size\r\n if (this.width() === 0 && this.height() === 0) {\r\n this.size(img.width, img.height)\r\n }\r\n\r\n if (p instanceof SVG.Pattern) {\r\n // ensure pattern size if not set\r\n if (p.width() === 0 && p.height() === 0) {\r\n p.size(this.width(), this.height())\r\n }\r\n }\r\n\r\n if (typeof callback === 'function') {\r\n callback.call(this, {\r\n width: img.width,\r\n height: img.height,\r\n ratio: img.width / img.height,\r\n url: url\r\n })\r\n }\r\n }, this)\r\n\r\n SVG.on(img, 'load error', function () {\r\n // dont forget to unbind memory leaking events\r\n SVG.off(img)\r\n })\r\n\r\n return this.attr('href', (img.src = url), SVG.xlink)\r\n }\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n // create image element, load image and set its size\r\n image: function (source, callback) {\r\n return this.put(new SVG.Image()).size(0, 0).load(source, callback)\r\n }\r\n }\r\n})\r\n","SVG.Text = SVG.invent({\r\n // Initialize node\r\n create: function (node) {\r\n SVG.Element.call(this, node || SVG.create('text'))\r\n this.dom.leading = new SVG.Number(1.3) // store leading value for rebuilding\r\n this._rebuild = true // enable automatic updating of dy values\r\n this._build = false // disable build mode for adding multiple lines\r\n\r\n // set default font\r\n this.attr('font-family', SVG.defaults.attrs['font-family'])\r\n },\r\n\r\n // Inherit from\r\n inherit: SVG.Parent,\r\n\r\n // Add class methods\r\n extend: {\r\n // Move over x-axis\r\n x: function (x) {\r\n // act as getter\r\n if (x == null) {\r\n return this.attr('x')\r\n }\r\n\r\n return this.attr('x', x)\r\n },\r\n // Move over y-axis\r\n y: function (y) {\r\n var oy = this.attr('y')\r\n var o = typeof oy === 'number' ? oy - this.bbox().y : 0\r\n\r\n // act as getter\r\n if (y == null) {\r\n return typeof oy === 'number' ? oy - o : oy\r\n }\r\n\r\n return this.attr('y', typeof y === 'number' ? y + o : y)\r\n },\r\n // Move center over x-axis\r\n cx: function (x) {\r\n return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2)\r\n },\r\n // Move center over y-axis\r\n cy: function (y) {\r\n return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2)\r\n },\r\n // Set the text content\r\n text: function (text) {\r\n // act as getter\r\n if (text === undefined) {\r\n var children = this.node.childNodes\r\n var firstLine = 0\r\n text = ''\r\n\r\n for (var i = 0, len = children.length; i < len; ++i) {\r\n // skip textPaths - they are no lines\r\n if (children[i].nodeName === 'textPath') {\r\n if (i === 0) firstLine = 1\r\n continue\r\n }\r\n\r\n // add newline if its not the first child and newLined is set to true\r\n if (i !== firstLine && children[i].nodeType !== 3 && SVG.adopt(children[i]).dom.newLined === true) {\r\n text += '\\n'\r\n }\r\n\r\n // add content of this node\r\n text += children[i].textContent\r\n }\r\n\r\n return text\r\n }\r\n\r\n // remove existing content\r\n this.clear().build(true)\r\n\r\n if (typeof text === 'function') {\r\n // call block\r\n text.call(this, this)\r\n } else {\r\n // store text and make sure text is not blank\r\n text = text.split('\\n')\r\n\r\n // build new lines\r\n for (var j = 0, jl = text.length; j < jl; j++) {\r\n this.tspan(text[j]).newLine()\r\n }\r\n }\r\n\r\n // disable build mode and rebuild lines\r\n return this.build(false).rebuild()\r\n },\r\n // Set / get leading\r\n leading: function (value) {\r\n // act as getter\r\n if (value == null) {\r\n return this.dom.leading\r\n }\r\n\r\n // act as setter\r\n this.dom.leading = new SVG.Number(value)\r\n\r\n return this.rebuild()\r\n },\r\n // Rebuild appearance type\r\n rebuild: function (rebuild) {\r\n // store new rebuild flag if given\r\n if (typeof rebuild === 'boolean') {\r\n this._rebuild = rebuild\r\n }\r\n\r\n // define position of all lines\r\n if (this._rebuild) {\r\n var self = this\r\n var blankLineOffset = 0\r\n var dy = this.dom.leading * new SVG.Number(this.attr('font-size'))\r\n\r\n this.each(function () {\r\n if (this.dom.newLined) {\r\n this.attr('x', self.attr('x'))\r\n\r\n if (this.text() === '\\n') {\r\n blankLineOffset += dy\r\n } else {\r\n this.attr('dy', dy + blankLineOffset)\r\n blankLineOffset = 0\r\n }\r\n }\r\n })\r\n\r\n this.fire('rebuild')\r\n }\r\n\r\n return this\r\n },\r\n // Enable / disable build mode\r\n build: function (build) {\r\n this._build = !!build\r\n return this\r\n },\r\n // overwrite method from parent to set data properly\r\n setData: function (o) {\r\n this.dom = o\r\n this.dom.leading = new SVG.Number(o.leading || 1.3)\r\n return this\r\n }\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n // Create text element\r\n text: function (text) {\r\n return this.put(new SVG.Text()).text(text)\r\n },\r\n // Create plain text element\r\n plain: function (text) {\r\n return this.put(new SVG.Text()).plain(text)\r\n }\r\n }\r\n\r\n})\r\n\r\nSVG.Tspan = SVG.invent({\r\n // Initialize node\r\n create: 'tspan',\r\n\r\n // Inherit from\r\n inherit: SVG.Parent,\r\n\r\n // Add class methods\r\n extend: {\r\n // Set text content\r\n text: function (text) {\r\n if (text == null) return this.node.textContent + (this.dom.newLined ? '\\n' : '')\r\n\r\n typeof text === 'function' ? text.call(this, this) : this.plain(text)\r\n\r\n return this\r\n },\r\n // Shortcut dx\r\n dx: function (dx) {\r\n return this.attr('dx', dx)\r\n },\r\n // Shortcut dy\r\n dy: function (dy) {\r\n return this.attr('dy', dy)\r\n },\r\n // Create new line\r\n newLine: function () {\r\n // fetch text parent\r\n var t = this.parent(SVG.Text)\r\n\r\n // mark new line\r\n this.dom.newLined = true\r\n\r\n // apply new position\r\n return this.dy(t.dom.leading * t.attr('font-size')).attr('x', t.x())\r\n }\r\n }\r\n})\r\n\r\nSVG.extend([SVG.Text, SVG.Tspan], {\r\n // Create plain text node\r\n plain: function (text) {\r\n // clear if build mode is disabled\r\n if (this._build === false) {\r\n this.clear()\r\n }\r\n\r\n // create text node\r\n this.node.appendChild(document.createTextNode(text))\r\n\r\n return this\r\n },\r\n // Create a tspan\r\n tspan: function (text) {\r\n var tspan = new SVG.Tspan()\r\n\r\n // clear if build mode is disabled\r\n if (!this._build) {\r\n this.clear()\r\n }\r\n\r\n // add new tspan\r\n this.node.appendChild(tspan.node)\r\n\r\n return tspan.text(text)\r\n },\r\n // FIXME: Does this also work for textpath?\r\n // Get length of text element\r\n length: function () {\r\n return this.node.getComputedTextLength()\r\n }\r\n})\r\n","SVG.TextPath = SVG.invent({\r\n // Initialize node\r\n create: 'textPath',\r\n\r\n // Inherit from\r\n inherit: SVG.Text,\r\n\r\n // Define parent class\r\n parent: SVG.Parent,\r\n\r\n // Add parent method\r\n extend: {\r\n MorphArray: SVG.PathArray,\r\n // return the array of the path track element\r\n array: function () {\r\n var track = this.track()\r\n\r\n return track ? track.array() : null\r\n },\r\n // Plot path if any\r\n plot: function (d) {\r\n var track = this.track()\r\n var pathArray = null\r\n\r\n if (track) {\r\n pathArray = track.plot(d)\r\n }\r\n\r\n return (d == null) ? pathArray : this\r\n },\r\n // Get the path element\r\n track: function () {\r\n return this.reference('href')\r\n }\r\n },\r\n construct: {\r\n textPath: function (text, path) {\r\n return this.defs().path(path).text(text).addTo(this)\r\n }\r\n }\r\n})\r\n\r\nSVG.extend([SVG.Text], {\r\n // Create path for text to run on\r\n path: function (track) {\r\n var path = new SVG.TextPath()\r\n\r\n // if d is a path, reuse it\r\n if (!(track instanceof SVG.Path)) {\r\n // create path element\r\n track = this.doc().defs().path(track)\r\n }\r\n\r\n // link textPath to path and add content\r\n path.attr('href', '#' + track, SVG.xlink)\r\n\r\n // add textPath element as child node and return textPath\r\n return this.put(path)\r\n },\r\n // Todo: make this plural?\r\n // Get the textPath children\r\n textPath: function () {\r\n return this.select('textPath')\r\n }\r\n})\r\n\r\nSVG.extend([SVG.Path], {\r\n // creates a textPath from this path\r\n text: function (text) {\r\n if (text instanceof SVG.Text) {\r\n var txt = text.text()\r\n return text.clear().path(this).text(txt)\r\n }\r\n return this.parent().put(new SVG.Text()).path(this).text(text)\r\n }\r\n // TODO: Maybe add `targets` to get all textPaths associated with this path\r\n})\r\n","SVG.A = SVG.invent({\r\n // Initialize node\r\n create: 'a',\r\n\r\n // Inherit from\r\n inherit: SVG.Container,\r\n\r\n // Add class methods\r\n extend: {\r\n // Link url\r\n to: function (url) {\r\n return this.attr('href', url, SVG.xlink)\r\n },\r\n // Link target attribute\r\n target: function (target) {\r\n return this.attr('target', target)\r\n }\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n // Create a hyperlink element\r\n link: function (url) {\r\n return this.put(new SVG.A()).to(url)\r\n }\r\n }\r\n})\r\n\r\nSVG.extend(SVG.Element, {\r\n // Create a hyperlink element\r\n linkTo: function (url) {\r\n var link = new SVG.A()\r\n\r\n if (typeof url === 'function') { url.call(link, link) } else {\r\n link.to(url)\r\n }\r\n\r\n return this.parent().put(link).put(this)\r\n }\r\n\r\n})\r\n","SVG.Marker = SVG.invent({\r\n // Initialize node\r\n create: 'marker',\r\n\r\n // Inherit from\r\n inherit: SVG.Container,\r\n\r\n // Add class methods\r\n extend: {\r\n // Set width of element\r\n width: function (width) {\r\n return this.attr('markerWidth', width)\r\n },\r\n // Set height of element\r\n height: function (height) {\r\n return this.attr('markerHeight', height)\r\n },\r\n // Set marker refX and refY\r\n ref: function (x, y) {\r\n return this.attr('refX', x).attr('refY', y)\r\n },\r\n // Update marker\r\n update: function (block) {\r\n // remove all content\r\n this.clear()\r\n\r\n // invoke passed block\r\n if (typeof block === 'function') { block.call(this, this) }\r\n\r\n return this\r\n },\r\n // Return the fill id\r\n toString: function () {\r\n return 'url(#' + this.id() + ')'\r\n }\r\n },\r\n\r\n // Add parent method\r\n construct: {\r\n marker: function (width, height, block) {\r\n // Create marker element in defs\r\n return this.defs().marker(width, height, block)\r\n }\r\n }\r\n\r\n})\r\n\r\nSVG.extend(SVG.Defs, {\r\n // Create marker\r\n marker: function (width, height, block) {\r\n // Set default viewbox to match the width and height, set ref to cx and cy and set orient to auto\r\n return this.put(new SVG.Marker())\r\n .size(width, height)\r\n .ref(width / 2, height / 2)\r\n .viewbox(0, 0, width, height)\r\n .attr('orient', 'auto')\r\n .update(block)\r\n }\r\n\r\n})\r\n\r\nSVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon, SVG.Path], {\r\n // Create and attach markers\r\n marker: function (marker, width, height, block) {\r\n var attr = ['marker']\r\n\r\n // Build attribute name\r\n if (marker !== 'all') attr.push(marker)\r\n attr = attr.join('-')\r\n\r\n // Set marker attribute\r\n marker = arguments[1] instanceof SVG.Marker\r\n ? arguments[1]\r\n : this.doc().marker(width, height, block)\r\n\r\n return this.attr(attr, marker)\r\n }\r\n})\r\n","// Define list of available attributes for stroke and fill\r\nvar sugar = {\r\n stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'],\r\n fill: ['color', 'opacity', 'rule'],\r\n prefix: function (t, a) {\r\n return a === 'color' ? t : t + '-' + a\r\n }\r\n}\r\n\r\n// Add sugar for fill and stroke\r\n;['fill', 'stroke'].forEach(function (m) {\r\n var extension = {}\r\n var i\r\n\r\n extension[m] = function (o) {\r\n if (typeof o === 'undefined') {\r\n return this\r\n }\r\n if (typeof o === 'string' || SVG.Color.isRgb(o) || (o && typeof o.fill === 'function')) {\r\n this.attr(m, o)\r\n } else {\r\n // set all attributes from sugar.fill and sugar.stroke list\r\n for (i = sugar[m].length - 1; i >= 0; i--) {\r\n if (o[sugar[m][i]] != null) {\r\n this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]])\r\n }\r\n }\r\n }\r\n\r\n return this\r\n }\r\n\r\n SVG.extend([SVG.Element, SVG.Timeline], extension)\r\n})\r\n\r\nSVG.extend([SVG.Element, SVG.Timeline], {\r\n // Let the user set the matrix directly\r\n matrix: function (mat, b, c, d, e, f) {\r\n // Act as a getter\r\n if (mat == null) {\r\n return new SVG.Matrix(this)\r\n }\r\n\r\n // Act as a setter, the user can pass a matrix or a set of numbers\r\n return this.attr('transform', new SVG.Matrix(mat, b, c, d, e, f))\r\n },\r\n\r\n // Map rotation to transform\r\n rotate: function (angle, cx, cy) {\r\n return this.transform({rotate: angle, ox: cx, oy: cy}, true)\r\n },\r\n\r\n // Map skew to transform\r\n skew: function (x, y, cx, cy) {\r\n return arguments.length === 1 || arguments.length === 3\r\n ? this.transform({skew: x, ox: y, oy: cx}, true)\r\n : this.transform({skew: [x, y], ox: cx, oy: cy}, true)\r\n },\r\n\r\n shear: function (lam, cx, cy) {\r\n return this.transform({shear: lam, ox: cx, oy: cy}, true)\r\n },\r\n\r\n // Map scale to transform\r\n scale: function (x, y, cx, cy) {\r\n return arguments.length === 1 || arguments.length === 3\r\n ? this.transform({ scale: x, ox: y, oy: cx }, true)\r\n : this.transform({ scale: [x, y], ox: cx, oy: cy }, true)\r\n },\r\n\r\n // Map translate to transform\r\n translate: function (x, y) {\r\n return this.transform({ translate: [x, y] }, true)\r\n },\r\n\r\n // Map relative translations to transform\r\n relative: function (x, y) {\r\n return this.transform({ relative: [x, y] }, true)\r\n },\r\n\r\n // Map flip to transform\r\n flip: function (direction, around) {\r\n var directionString = typeof direction === 'string' ? direction\r\n : isFinite(direction) ? 'both'\r\n : 'both'\r\n var origin = (direction === 'both' && isFinite(around)) ? [around, around]\r\n : (direction === 'x') ? [around, 0]\r\n : (direction === 'y') ? [0, around]\r\n : isFinite(direction) ? [direction, direction]\r\n : [0, 0]\r\n this.transform({flip: directionString, origin: origin}, true)\r\n },\r\n\r\n // Opacity\r\n opacity: function (value) {\r\n return this.attr('opacity', value)\r\n },\r\n\r\n // Relative move over x axis\r\n dx: function (x) {\r\n return this.x(new SVG.Number(x).plus(this instanceof SVG.Timeline ? 0 : this.x()), true)\r\n },\r\n\r\n // Relative move over y axis\r\n dy: function (y) {\r\n return this.y(new SVG.Number(y).plus(this instanceof SVG.Timeline ? 0 : this.y()), true)\r\n },\r\n\r\n // Relative move over x and y axes\r\n dmove: function (x, y) {\r\n return this.dx(x).dy(y)\r\n }\r\n})\r\n\r\nSVG.extend([SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.Timeline], {\r\n // Add x and y radius\r\n radius: function (x, y) {\r\n var type = (this._target || this).type\r\n return type === 'radialGradient' || type === 'radialGradient'\r\n ? this.attr('r', new SVG.Number(x))\r\n : this.rx(x).ry(y == null ? x : y)\r\n }\r\n})\r\n\r\nSVG.extend(SVG.Path, {\r\n // Get path length\r\n length: function () {\r\n return this.node.getTotalLength()\r\n },\r\n // Get point at length\r\n pointAt: function (length) {\r\n return new SVG.Point(this.node.getPointAtLength(length))\r\n }\r\n})\r\n\r\nSVG.extend([SVG.Parent, SVG.Text, SVG.Tspan, SVG.Timeline], {\r\n // Set font\r\n font: function (a, v) {\r\n if (typeof a === 'object') {\r\n for (v in a) this.font(v, a[v])\r\n }\r\n\r\n return a === 'leading'\r\n ? this.leading(v)\r\n : a === 'anchor'\r\n ? this.attr('text-anchor', v)\r\n : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style'\r\n ? this.attr('font-' + a, v)\r\n : this.attr(a, v)\r\n }\r\n})\r\n","\r\nSVG.extend(SVG.Element, {\r\n // Store data values on svg nodes\r\n data: function (a, v, r) {\r\n if (typeof a === 'object') {\r\n for (v in a) {\r\n this.data(v, a[v])\r\n }\r\n } else if (arguments.length < 2) {\r\n try {\r\n return JSON.parse(this.attr('data-' + a))\r\n } catch (e) {\r\n return this.attr('data-' + a)\r\n }\r\n } else {\r\n this.attr('data-' + a,\r\n v === null ? null\r\n : r === true || typeof v === 'string' || typeof v === 'number' ? v\r\n : JSON.stringify(v)\r\n )\r\n }\r\n\r\n return this\r\n }\r\n})\r\n","\r\nSVG.extend(SVG.Element, {\r\n // Remember arbitrary data\r\n remember: function (k, v) {\r\n // remember every item in an object individually\r\n if (typeof arguments[0] === 'object') {\r\n for (var key in k) {\r\n this.remember(key, k[key])\r\n }\r\n } else if (arguments.length === 1) {\r\n // retrieve memory\r\n return this.memory()[k]\r\n } else {\r\n // store memory\r\n this.memory()[k] = v\r\n }\r\n\r\n return this\r\n },\r\n\r\n // Erase a given memory\r\n forget: function () {\r\n if (arguments.length === 0) {\r\n this._memory = {}\r\n } else {\r\n for (var i = arguments.length - 1; i >= 0; i--) {\r\n delete this.memory()[arguments[i]]\r\n }\r\n }\r\n return this\r\n },\r\n\r\n // Initialize or return local memory object\r\n memory: function () {\r\n return this._memory || (this._memory = {})\r\n }\r\n})\r\n","/* global idFromReference */\r\n\r\n// Method for getting an element by id\r\nSVG.get = function (id) {\r\n var node = document.getElementById(idFromReference(id) || id)\r\n return SVG.adopt(node)\r\n}\r\n\r\n// Select elements by query string\r\nSVG.select = function (query, parent) {\r\n return SVG.utils.map((parent || document).querySelectorAll(query), function (node) {\r\n return SVG.adopt(node)\r\n })\r\n}\r\n\r\nSVG.$$ = function (query, parent) {\r\n return SVG.utils.map((parent || document).querySelectorAll(query), function (node) {\r\n return SVG.adopt(node)\r\n })\r\n}\r\n\r\nSVG.$ = function (query, parent) {\r\n return SVG.adopt((parent || document).querySelector(query))\r\n}\r\n\r\nSVG.extend(SVG.Parent, {\r\n // Scoped select method\r\n select: function (query) {\r\n return SVG.select(query, this.node)\r\n }\r\n})\r\n","/* eslint no-unused-vars: 0 */\r\n\r\nfunction createElement (element, makeNested) {\r\n if (element instanceof SVG.Element) return element\r\n\r\n if (typeof element === 'object') {\r\n return SVG.adopt(element)\r\n }\r\n\r\n if (element == null) {\r\n return new SVG.Doc()\r\n }\r\n\r\n if (typeof element === 'string' && element.charAt(0) !== '<') {\r\n return SVG.adopt(document.querySelector(element))\r\n }\r\n\r\n var node = SVG.create('svg')\r\n node.innerHTML = element\r\n\r\n element = SVG.adopt(node.firstElementChild)\r\n\r\n return element\r\n}\r\n\r\nfunction isNulledBox (box) {\r\n return !box.w && !box.h && !box.x && !box.y\r\n}\r\n\r\nfunction domContains (node) {\r\n return (document.documentElement.contains || function (node) {\r\n // This is IE - it does not support contains() for top-level SVGs\r\n while (node.parentNode) {\r\n node = node.parentNode\r\n }\r\n return node === document\r\n }).call(document.documentElement, node)\r\n}\r\n\r\nfunction pathRegReplace (a, b, c, d) {\r\n return c + d.replace(SVG.regex.dots, ' .')\r\n}\r\n\r\n// creates deep clone of array\r\nfunction arrayClone (arr) {\r\n var clone = arr.slice(0)\r\n for (var i = clone.length; i--;) {\r\n if (Array.isArray(clone[i])) {\r\n clone[i] = arrayClone(clone[i])\r\n }\r\n }\r\n return clone\r\n}\r\n\r\n// tests if a given element is instance of an object\r\nfunction is (el, obj) {\r\n return el instanceof obj\r\n}\r\n\r\n// tests if a given selector matches an element\r\nfunction matches (el, selector) {\r\n return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector)\r\n}\r\n\r\n// Convert dash-separated-string to camelCase\r\nfunction camelCase (s) {\r\n return s.toLowerCase().replace(/-(.)/g, function (m, g) {\r\n return g.toUpperCase()\r\n })\r\n}\r\n\r\n// Capitalize first letter of a string\r\nfunction capitalize (s) {\r\n return s.charAt(0).toUpperCase() + s.slice(1)\r\n}\r\n\r\n// Ensure to six-based hex\r\nfunction fullHex (hex) {\r\n return hex.length === 4\r\n ? [ '#',\r\n hex.substring(1, 2), hex.substring(1, 2),\r\n hex.substring(2, 3), hex.substring(2, 3),\r\n hex.substring(3, 4), hex.substring(3, 4)\r\n ].join('')\r\n : hex\r\n}\r\n\r\n// Component to hex value\r\nfunction compToHex (comp) {\r\n var hex = comp.toString(16)\r\n return hex.length === 1 ? '0' + hex : hex\r\n}\r\n\r\n// Calculate proportional width and height values when necessary\r\nfunction proportionalSize (element, width, height) {\r\n if (width == null || height == null) {\r\n var box = element.bbox()\r\n\r\n if (width == null) {\r\n width = box.width / box.height * height\r\n } else if (height == null) {\r\n height = box.height / box.width * width\r\n }\r\n }\r\n\r\n return {\r\n width: width,\r\n height: height\r\n }\r\n}\r\n\r\n// Map matrix array to object\r\nfunction arrayToMatrix (a) {\r\n return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] }\r\n}\r\n\r\n// Add centre point to transform object\r\nfunction ensureCentre (o, target) {\r\n o.cx = o.cx == null ? target.bbox().cx : o.cx\r\n o.cy = o.cy == null ? target.bbox().cy : o.cy\r\n}\r\n\r\n// PathArray Helpers\r\nfunction arrayToString (a) {\r\n for (var i = 0, il = a.length, s = ''; i < il; i++) {\r\n s += a[i][0]\r\n\r\n if (a[i][1] != null) {\r\n s += a[i][1]\r\n\r\n if (a[i][2] != null) {\r\n s += ' '\r\n s += a[i][2]\r\n\r\n if (a[i][3] != null) {\r\n s += ' '\r\n s += a[i][3]\r\n s += ' '\r\n s += a[i][4]\r\n\r\n if (a[i][5] != null) {\r\n s += ' '\r\n s += a[i][5]\r\n s += ' '\r\n s += a[i][6]\r\n\r\n if (a[i][7] != null) {\r\n s += ' '\r\n s += a[i][7]\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return s + ' '\r\n}\r\n\r\n// Deep new id assignment\r\nfunction assignNewId (node) {\r\n // do the same for SVG child nodes as well\r\n for (var i = node.children.length - 1; i >= 0; i--) {\r\n assignNewId(node.children[i])\r\n }\r\n\r\n if (node.id) {\r\n return SVG.adopt(node).id(SVG.eid(node.nodeName))\r\n }\r\n\r\n return SVG.adopt(node)\r\n}\r\n\r\n// Add more bounding box properties\r\nfunction fullBox (b) {\r\n if (b.x == null) {\r\n b.x = 0\r\n b.y = 0\r\n b.width = 0\r\n b.height = 0\r\n }\r\n\r\n b.w = b.width\r\n b.h = b.height\r\n b.x2 = b.x + b.width\r\n b.y2 = b.y + b.height\r\n b.cx = b.x + b.width / 2\r\n b.cy = b.y + b.height / 2\r\n\r\n return b\r\n}\r\n\r\n// Get id from reference string\r\nfunction idFromReference (url) {\r\n var m = (url || '').toString().match(SVG.regex.reference)\r\n\r\n if (m) return m[1]\r\n}\r\n\r\n// Create matrix array for looping\r\nvar abcdef = 'abcdef'.split('')\r\n\r\nfunction closeEnough (a, b, threshold) {\r\n return Math.abs(b - a) < (threshold || 1e-6)\r\n}\r\n\r\nfunction isMatrixLike (o) {\r\n return (\r\n o.a != null ||\r\n o.b != null ||\r\n o.c != null ||\r\n o.d != null ||\r\n o.e != null ||\r\n o.f != null\r\n )\r\n}\r\n\r\n// TODO: Refactor this to a static function of matrix.js\r\nfunction formatTransforms (o) {\r\n // Get all of the parameters required to form the matrix\r\n var flipBoth = o.flip === 'both' || o.flip === true\r\n var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1\r\n var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1\r\n var skewX = o.skew && o.skew.length ? o.skew[0]\r\n : isFinite(o.skew) ? o.skew\r\n : isFinite(o.skewX) ? o.skewX\r\n : 0\r\n var skewY = o.skew && o.skew.length ? o.skew[1]\r\n : isFinite(o.skew) ? o.skew\r\n : isFinite(o.skewY) ? o.skewY\r\n : 0\r\n var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX\r\n : isFinite(o.scale) ? o.scale * flipX\r\n : isFinite(o.scaleX) ? o.scaleX * flipX\r\n : flipX\r\n var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY\r\n : isFinite(o.scale) ? o.scale * flipY\r\n : isFinite(o.scaleY) ? o.scaleY * flipY\r\n : flipY\r\n var shear = o.shear || 0\r\n var theta = o.rotate || o.theta || 0\r\n var origin = new SVG.Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY)\r\n var ox = origin.x\r\n var oy = origin.y\r\n var position = new SVG.Point(o.position || o.px || o.positionX, o.py || o.positionY)\r\n var px = position.x\r\n var py = position.y\r\n var translate = new SVG.Point(o.translate || o.tx || o.translateX, o.ty || o.translateY)\r\n var tx = translate.x\r\n var ty = translate.y\r\n var relative = new SVG.Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY)\r\n var rx = relative.x\r\n var ry = relative.y\r\n\r\n // Populate all of the values\r\n return {\r\n scaleX, scaleY, skewX, skewY, shear, theta, rx, ry, tx, ty, ox, oy, px, py\r\n }\r\n}\r\n\r\n// left matrix, right matrix, target matrix which is overwritten\r\nfunction matrixMultiply (l, r, o) {\r\n // Work out the product directly\r\n var a = l.a * r.a + l.c * r.b\r\n var b = l.b * r.a + l.d * r.b\r\n var c = l.a * r.c + l.c * r.d\r\n var d = l.b * r.c + l.d * r.d\r\n var e = l.e + l.a * r.e + l.c * r.f\r\n var f = l.f + l.b * r.e + l.d * r.f\r\n\r\n // make sure to use local variables because l/r and o could be the same\r\n o.a = a\r\n o.b = b\r\n o.c = c\r\n o.d = d\r\n o.e = e\r\n o.f = f\r\n\r\n return o\r\n}\r\n\r\nfunction getOrigin (o, element) {\r\n // Allow origin or around as the names\r\n let origin = o.origin // o.around == null ? o.origin : o.around\r\n let ox, oy\r\n\r\n // Allow the user to pass a string to rotate around a given point\r\n if (typeof origin === 'string' || origin == null) {\r\n // Get the bounding box of the element with no transformations applied\r\n const string = (origin || 'center').toLowerCase().trim()\r\n const { height, width, x, y } = element.bbox()\r\n\r\n // Calculate the transformed x and y coordinates\r\n let bx = string.includes('left') ? x\r\n : string.includes('right') ? x + width\r\n : x + width / 2\r\n let by = string.includes('top') ? y\r\n : string.includes('bottom') ? y + height\r\n : y + height / 2\r\n\r\n // Set the bounds eg : \"bottom-left\", \"Top right\", \"middle\" etc...\r\n ox = o.ox != null ? o.ox : bx\r\n oy = o.oy != null ? o.oy : by\r\n } else {\r\n ox = origin[0]\r\n oy = origin[1]\r\n }\r\n\r\n // Return the origin as it is if it wasn't a string\r\n return [ ox, oy ]\r\n}\r\n","/* globals fullBox, domContains, isNulledBox, Exception */\r\n\r\nSVG.Box = SVG.invent({\r\n create: function (source) {\r\n var base = [0, 0, 0, 0]\r\n source = typeof source === 'string' ? source.split(SVG.regex.delimiter).map(parseFloat)\r\n : Array.isArray(source) ? source\r\n : typeof source === 'object' ? [source.left != null ? source.left\r\n : source.x, source.top != null ? source.top : source.y, source.width, source.height]\r\n : arguments.length === 4 ? [].slice.call(arguments)\r\n : base\r\n\r\n this.x = source[0]\r\n this.y = source[1]\r\n this.width = source[2]\r\n this.height = source[3]\r\n\r\n // add center, right, bottom...\r\n fullBox(this)\r\n },\r\n extend: {\r\n // Merge rect box with another, return a new instance\r\n merge: function (box) {\r\n var x = Math.min(this.x, box.x)\r\n var y = Math.min(this.y, box.y)\r\n\r\n return new SVG.Box(\r\n x, y,\r\n Math.max(this.x + this.width, box.x + box.width) - x,\r\n Math.max(this.y + this.height, box.y + box.height) - y\r\n )\r\n },\r\n\r\n transform: function (m) {\r\n var xMin = Infinity\r\n var xMax = -Infinity\r\n var yMin = Infinity\r\n var yMax = -Infinity\r\n\r\n var pts = [\r\n new SVG.Point(this.x, this.y),\r\n new SVG.Point(this.x2, this.y),\r\n new SVG.Point(this.x, this.y2),\r\n new SVG.Point(this.x2, this.y2)\r\n ]\r\n\r\n pts.forEach(function (p) {\r\n p = p.transform(m)\r\n xMin = Math.min(xMin, p.x)\r\n xMax = Math.max(xMax, p.x)\r\n yMin = Math.min(yMin, p.y)\r\n yMax = Math.max(yMax, p.y)\r\n })\r\n\r\n return new SVG.Box(\r\n xMin, yMin,\r\n xMax - xMin,\r\n yMax - yMin\r\n )\r\n },\r\n\r\n addOffset: function () {\r\n // offset by window scroll position, because getBoundingClientRect changes when window is scrolled\r\n this.x += window.pageXOffset\r\n this.y += window.pageYOffset\r\n return this\r\n },\r\n toString: function () {\r\n return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height\r\n },\r\n toArray: function () {\r\n return [this.x, this.y, this.width, this.height]\r\n },\r\n morph: function (x, y, width, height) {\r\n this.destination = new SVG.Box(x, y, width, height)\r\n return this\r\n },\r\n\r\n at: function (pos) {\r\n if (!this.destination) return this\r\n\r\n return new SVG.Box(\r\n this.x + (this.destination.x - this.x) * pos\r\n , this.y + (this.destination.y - this.y) * pos\r\n , this.width + (this.destination.width - this.width) * pos\r\n , this.height + (this.destination.height - this.height) * pos\r\n )\r\n }\r\n },\r\n\r\n // Define Parent\r\n parent: SVG.Element,\r\n\r\n // Constructor\r\n construct: {\r\n // Get bounding box\r\n bbox: function () {\r\n var box\r\n\r\n try {\r\n // find native bbox\r\n box = this.node.getBBox()\r\n\r\n if (isNulledBox(box) && !domContains(this.node)) {\r\n throw new Exception('Element not in the dom')\r\n }\r\n } catch (e) {\r\n try {\r\n var clone = this.clone(SVG.parser().svg).show()\r\n box = clone.node.getBBox()\r\n clone.remove()\r\n } catch (e) {\r\n console.warn('Getting a bounding box of this element is not possible')\r\n }\r\n }\r\n\r\n return new SVG.Box(box)\r\n },\r\n\r\n rbox: function (el) {\r\n // IE11 throws an error when element not in dom\r\n try {\r\n var box = new SVG.Box(this.node.getBoundingClientRect())\r\n if (el) return box.transform(el.screenCTM().inverse())\r\n return box.addOffset()\r\n } catch (e) {\r\n return new SVG.Box()\r\n }\r\n }\r\n }\r\n})\r\n\r\nSVG.extend([SVG.Doc, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View], {\r\n viewbox: function (x, y, width, height) {\r\n // act as getter\r\n if (x == null) return new SVG.Box(this.attr('viewBox'))\r\n\r\n // act as setter\r\n return this.attr('viewBox', new SVG.Box(x, y, width, height))\r\n }\r\n})\r\n","\r\nSVG.parser = function () {\r\n var b\r\n\r\n if (!SVG.parser.nodes.svg.node.parentNode) {\r\n b = document.body || document.documentElement\r\n SVG.parser.nodes.svg.addTo(b)\r\n }\r\n\r\n return SVG.parser.nodes\r\n}\r\n\r\nSVG.parser.nodes = {\r\n svg: SVG().size(2, 0).css({\r\n opacity: 0,\r\n position: 'absolute',\r\n left: '-100%',\r\n top: '-100%',\r\n overflow: 'hidden'\r\n })\r\n}\r\n\r\nSVG.parser.nodes.path = SVG.parser.nodes.svg.path().node\r\n","/* global requestAnimationFrame */\n\nSVG.Animator = {\n nextDraw: null,\n frames: new SVG.Queue(),\n timeouts: new SVG.Queue(),\n timer: window.performance || window.Date,\n transforms: [],\n\n frame: function (fn) {\n // Store the node\n var node = SVG.Animator.frames.push({ run: fn })\n\n // Request an animation frame if we don't have one\n if (SVG.Animator.nextDraw === null) {\n SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw)\n }\n\n // Return the node so we can remove it easily\n return node\n },\n\n transform_frame: function (fn, id) {\n SVG.Animator.transforms[id] = fn\n },\n\n timeout: function (fn, delay) {\n delay = delay || 0\n\n // Work out when the event should fire\n var time = SVG.Animator.timer.now() + delay\n\n // Add the timeout to the end of the queue\n var node = SVG.Animator.timeouts.push({ run: fn, time: time })\n\n // Request another animation frame if we need one\n if (SVG.Animator.nextDraw === null) {\n SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw)\n }\n\n return node\n },\n\n cancelFrame: function (node) {\n SVG.Animator.frames.remove(node)\n },\n\n clearTimeout: function (node) {\n SVG.Animator.timeouts.remove(node)\n },\n\n _draw: function (now) {\n // Run all the timeouts we can run, if they are not ready yet, add them\n // to the end of the queue immediately! (bad timeouts!!! [sarcasm])\n var nextTimeout = null\r\n var lastTimeout = SVG.Animator.timeouts.last()\n while ((nextTimeout = SVG.Animator.timeouts.shift())) {\n // Run the timeout if its time, or push it to the end\n if (now >= nextTimeout.time) {\n nextTimeout.run()\n } else {\n SVG.Animator.timeouts.push(nextTimeout)\n }\n\n // If we hit the last item, we should stop shifting out more items\n if (nextTimeout === lastTimeout) break\n }\n\n // Run all of the animation frames\n var nextFrame = null\n var lastFrame = SVG.Animator.frames.last()\n while ((nextFrame !== lastFrame) && (nextFrame = SVG.Animator.frames.shift())) {\n nextFrame.run()\n }\n\n SVG.Animator.transforms.forEach(function (el) { el() })\n\n // If we have remaining timeouts or frames, draw until we don't anymore\n SVG.Animator.nextDraw = SVG.Animator.timeouts.first() || SVG.Animator.frames.first()\n ? requestAnimationFrame(SVG.Animator._draw)\n : null\n }\n}\n","\r\nSVG.Morphable = SVG.invent({\r\n create: function (stepper) {\r\n // FIXME: the default stepper does not know about easing\r\n this._stepper = stepper || new SVG.Ease('-')\r\n\r\n this._from = null\r\n this._to = null\r\n this._type = null\r\n this._context = null\r\n this._morphObj = null\r\n },\r\n\r\n extend: {\r\n\r\n from: function (val) {\r\n if (val == null) {\r\n return this._from\r\n }\r\n\r\n this._from = this._set(val)\r\n return this\r\n },\r\n\r\n to: function (val) {\r\n if (val == null) {\r\n return this._to\r\n }\r\n\r\n this._to = this._set(val)\r\n return this\r\n },\r\n\r\n type: function (type) {\r\n // getter\r\n if (type == null) {\r\n return this._type\r\n }\r\n\r\n // setter\r\n this._type = type\r\n return this\r\n },\r\n\r\n _set: function (value) {\r\n if (!this._type) {\r\n var type = typeof value\r\n\r\n if (type === 'number') {\r\n this.type(SVG.Number)\r\n } else if (type === 'string') {\r\n if (SVG.Color.isColor(value)) {\r\n this.type(SVG.Color)\r\n } else if (SVG.regex.delimiter.test(value)) {\r\n this.type(SVG.regex.pathLetters.test(value)\r\n ? SVG.PathArray\r\n : SVG.Array\r\n )\r\n } else if (SVG.regex.numberAndUnit.test(value)) {\r\n this.type(SVG.Number)\r\n } else {\r\n this.type(SVG.Morphable.NonMorphable)\r\n }\r\n } else if (SVG.MorphableTypes.indexOf(value.constructor) > -1) {\r\n this.type(value.constructor)\r\n } else if (Array.isArray(value)) {\r\n this.type(SVG.Array)\r\n } else if (type === 'object') {\r\n this.type(SVG.Morphable.ObjectBag)\r\n } else {\r\n this.type(SVG.Morphable.NonMorphable)\r\n }\r\n }\r\n\r\n var result = (new this._type(value)).toArray()\r\n this._morphObj = this._morphObj || new this._type()\r\n this._context = this._context ||\r\n Array.apply(null, Array(result.length)).map(Object)\r\n return result\r\n },\r\n\r\n stepper: function (stepper) {\r\n if (stepper == null) return this._stepper\r\n this._stepper = stepper\r\n return this\r\n },\r\n\r\n done: function () {\r\n var complete = this._context\r\n .map(this._stepper.done)\r\n .reduce(function (last, curr) {\r\n return last && curr\r\n }, true)\r\n return complete\r\n },\r\n\r\n at: function (pos) {\r\n var _this = this\r\n\r\n return this._morphObj.fromArray(\r\n this._from.map(function (i, index) {\r\n return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context)\r\n })\r\n )\r\n }\r\n }\r\n})\r\n\r\nSVG.Morphable.NonMorphable = SVG.invent({\r\n create: function (val) {\r\n val = Array.isArray(val) ? val[0] : val\r\n this.value = val\r\n },\r\n\r\n extend: {\r\n valueOf: function () {\r\n return this.value\r\n },\r\n\r\n toArray: function () {\r\n return [this.value]\r\n }\r\n }\r\n})\r\n\r\nSVG.Morphable.TransformBag = SVG.invent({\r\n create: function (obj) {\r\n if (Array.isArray(obj)) {\r\n obj = {\r\n scaleX: obj[0],\r\n scaleY: obj[1],\r\n shear: obj[2],\r\n rotate: obj[3],\r\n translateX: obj[4],\r\n translateY: obj[5],\r\n originX: obj[6],\r\n originY: obj[7]\r\n }\r\n }\r\n\r\n Object.assign(this, SVG.Morphable.TransformBag.defaults, obj)\r\n },\r\n\r\n extend: {\r\n toArray: function () {\r\n var v = this\r\n\r\n return [\r\n v.scaleX,\r\n v.scaleY,\r\n v.shear,\r\n v.rotate,\r\n v.translateX,\r\n v.translateY,\r\n v.originX,\r\n v.originY\r\n ]\r\n }\r\n }\r\n})\r\n\r\nSVG.Morphable.TransformBag.defaults = {\r\n scaleX: 1,\r\n scaleY: 1,\r\n shear: 0,\r\n rotate: 0,\r\n translateX: 0,\r\n translateY: 0,\r\n originX: 0,\r\n originY: 0\r\n}\r\n\r\nSVG.Morphable.ObjectBag = SVG.invent({\r\n create: function (objOrArr) {\r\n this.values = []\r\n\r\n if (Array.isArray(objOrArr)) {\r\n this.values = objOrArr\r\n return\r\n }\r\n\r\n var entries = Object.entries(objOrArr || {}).sort((a, b) => {\r\n return a[0] - b[0]\r\n })\r\n\r\n this.values = entries.reduce((last, curr) => last.concat(curr), [])\r\n },\r\n\r\n extend: {\r\n valueOf: function () {\r\n var obj = {}\r\n var arr = this.values\r\n\r\n for (var i = 0, len = arr.length; i < len; i += 2) {\r\n obj[arr[i]] = arr[i + 1]\r\n }\r\n\r\n return obj\r\n },\r\n\r\n toArray: function () {\r\n return this.values\r\n }\r\n }\r\n})\r\n\r\nSVG.MorphableTypes = [\r\n SVG.Number,\r\n SVG.Color,\r\n SVG.Box,\r\n SVG.Matrix,\r\n SVG.Array,\r\n SVG.PointArray,\r\n SVG.PathArray,\r\n SVG.Morphable.NonMorphable,\r\n SVG.Morphable.TransformBag,\r\n SVG.Morphable.ObjectBag\r\n]\r\n\r\nSVG.extend(SVG.MorphableTypes, {\r\n to: function (val, args) {\r\n return new SVG.Morphable()\r\n .type(this.constructor)\r\n .from(this.valueOf())\r\n .to(val, args)\r\n },\r\n fromArray: function (arr) {\r\n this.constructor(arr)\r\n return this\r\n }\r\n})\r\n","/* global isMatrixLike getOrigin */\r\n\r\nSVG.easing = {\r\n '-': function (pos) { return pos },\r\n '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 },\r\n '>': function (pos) { return Math.sin(pos * Math.PI / 2) },\r\n '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }\r\n}\r\n\r\nSVG.Runner = SVG.invent({\r\n parent: SVG.Element,\r\n\r\n create: function (options) {\r\n // Store a unique id on the runner, so that we can identify it later\r\n this.id = SVG.Runner.id++\r\n\r\n // Ensure a default value\r\n options = options == null\r\n ? SVG.defaults.timeline.duration\r\n : options\r\n\r\n // Ensure that we get a controller\r\n options = typeof options === 'function'\r\n ? new SVG.Controller(options)\r\n : options\r\n\r\n // Declare all of the variables\r\n this._element = null\r\n this._timeline = null\r\n this.done = false\r\n this._queue = []\r\n\r\n // Work out the stepper and the duration\r\n this._duration = typeof options === 'number' && options\r\n this._isDeclarative = options instanceof SVG.Controller\r\n this._stepper = this._isDeclarative ? options : new SVG.Ease()\r\n\r\n // We copy the current values from the timeline because they can change\r\n this._history = {}\r\n\r\n // Store the state of the runner\r\n this.enabled = true\r\n this._time = 0\r\n this._last = 0\r\n this.tags = {}\r\n\r\n // Save transforms applied to this runner\r\n this.transforms = new SVG.Matrix()\r\n this.transformId = 1\r\n\r\n // Looping variables\r\n this._haveReversed = false\r\n this._reverse = false\r\n this._loopsDone = 0\r\n this._swing = false\r\n this._wait = 0\r\n this._times = 1\r\n },\r\n\r\n construct: {\r\n\r\n animate: function (duration, delay, when) {\r\n var o = SVG.Runner.sanitise(duration, delay, when)\r\n var timeline = this.timeline()\r\n return new SVG.Runner(o.duration)\r\n .loop(o)\r\n .element(this)\r\n .timeline(timeline)\r\n .schedule(delay, when)\r\n },\r\n\r\n delay: function (by, when) {\r\n return this.animate(0, by, when)\r\n }\r\n },\r\n\r\n extend: {\r\n\r\n /*\r\n Runner Definitions\r\n ==================\r\n These methods help us define the runtime behaviour of the Runner or they\r\n help us make new runners from the current runner\r\n */\r\n\r\n element: function (element) {\r\n if (element == null) return this._element\r\n this._element = element\r\n element._prepareRunner()\r\n return this\r\n },\r\n\r\n timeline: function (timeline) {\r\n // check explicitly for undefined so we can set the timeline to null\r\n if (typeof timeline === 'undefined') return this._timeline\r\n this._timeline = timeline\r\n return this\r\n },\r\n\r\n animate: function (duration, delay, when) {\r\n var o = SVG.Runner.sanitise(duration, delay, when)\r\n var runner = new SVG.Runner(o.duration)\r\n if (this._timeline) runner.timeline(this._timeline)\r\n if (this._element) runner.element(this._element)\r\n return runner.loop(o).schedule(delay, when)\r\n },\r\n\r\n schedule: function (timeline, delay, when) {\r\n // The user doesn't need to pass a timeline if we already have one\r\n if (!(timeline instanceof SVG.Timeline)) {\r\n when = delay\r\n delay = timeline\r\n timeline = this.timeline()\r\n }\r\n\r\n // If there is no timeline, yell at the user...\r\n if (!timeline) {\r\n throw Error('Runner cannot be scheduled without timeline')\r\n }\r\n\r\n // Schedule the runner on the timeline provided\r\n timeline.schedule(this, delay, when)\r\n return this\r\n },\r\n\r\n unschedule: function () {\r\n var timeline = this.timeline()\r\n timeline && timeline.unschedule(this)\r\n return this\r\n },\r\n\r\n loop: function (times, swing, wait) {\r\n // Deal with the user passing in an object\r\n if (typeof times === 'object') {\r\n swing = times.swing\r\n wait = times.wait\r\n times = times.times\r\n }\r\n\r\n // Sanitise the values and store them\r\n this._times = times || Infinity\r\n this._swing = swing || false\r\n this._wait = wait || 0\r\n return this\r\n },\r\n\r\n delay: function (delay) {\r\n return this.animate(0, delay)\r\n },\r\n\r\n /*\r\n Basic Functionality\r\n ===================\r\n These methods allow us to attach basic functions to the runner directly\r\n */\r\n\r\n queue: function (initFn, runFn, isTransform) {\r\n this._queue.push({\r\n initialiser: initFn || SVG.void,\r\n runner: runFn || SVG.void,\r\n isTransform: isTransform,\r\n initialised: false,\r\n finished: false\r\n })\r\n var timeline = this.timeline()\r\n timeline && this.timeline()._continue()\r\n return this\r\n },\r\n\r\n during: function (fn) {\r\n return this.queue(null, fn)\r\n },\r\n\r\n after (fn) {\r\n return this.on('finish', fn)\r\n },\r\n\r\n /*\r\n Runner animation methods\r\n ========================\r\n Control how the animation plays\r\n */\r\n\r\n time: function (time) {\r\n if (time == null) {\r\n return this._time\r\n }\r\n let dt = time - this._time\r\n this.step(dt)\r\n return this\r\n },\r\n\r\n duration: function () {\r\n return this._times * (this._wait + this._duration) - this._wait\r\n },\r\n\r\n loops: function (p) {\r\n var loopDuration = this._duration + this._wait\r\n if (p == null) {\r\n var loopsDone = Math.floor(this._time / loopDuration)\r\n var relativeTime = (this._time - loopsDone * loopDuration)\r\n var position = relativeTime / this._duration\r\n return Math.min(loopsDone + position, this._times)\r\n }\r\n var whole = Math.floor(p)\r\n var partial = p % 1\r\n var time = loopDuration * whole + this._duration * partial\r\n return this.time(time)\r\n },\r\n\r\n position: function (p) {\r\n // Get all of the variables we need\r\n var x = this._time\r\n var d = this._duration\r\n var w = this._wait\r\n var t = this._times\r\n var s = this._swing\r\n var r = this._reverse\r\n var position\r\n\r\n if (p == null) {\r\n /*\r\n This function converts a time to a position in the range [0, 1]\r\n The full explanation can be found in this desmos demonstration\r\n https://www.desmos.com/calculator/u4fbavgche\r\n The logic is slightly simplified here because we can use booleans\r\n */\r\n\r\n // Figure out the value without thinking about the start or end time\r\n const f = function (x) {\r\n var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d))\r\n var backwards = (swinging && !r) || (!swinging && r)\r\n var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards\r\n var clipped = Math.max(Math.min(uncliped, 1), 0)\r\n return clipped\r\n }\r\n\r\n // Figure out the value by incorporating the start time\r\n var endTime = t * (w + d) - w\r\n position = x <= 0 ? Math.round(f(1e-5))\r\n : x < endTime ? f(x)\r\n : Math.round(f(endTime - 1e-5))\r\n return position\r\n }\r\n\r\n // Work out the loops done and add the position to the loops done\r\n var loopsDone = Math.floor(this.loops())\r\n var swingForward = s && (loopsDone % 2 === 0)\r\n var forwards = (swingForward && !r) || (r && swingForward)\r\n position = loopsDone + (forwards ? p : 1 - p)\r\n return this.loops(position)\r\n },\r\n\r\n progress: function (p) {\r\n if (p == null) {\r\n return Math.min(1, this._time / this.duration())\r\n }\r\n return this.time(p * this.duration())\r\n },\r\n\r\n step: function (dt) {\r\n // If we are inactive, this stepper just gets skipped\r\n if (!this.enabled) return this\r\n\r\n // Update the time and get the new position\r\n dt = dt == null ? 16 : dt\r\n this._time += dt\r\n var position = this.position()\r\n\r\n // Figure out if we need to run the stepper in this frame\r\n var running = this._lastPosition !== position && this._time >= 0\r\n this._lastPosition = position\r\n\r\n // Figure out if we just started\r\n var duration = this.duration()\r\n var justStarted = this._lastTime < 0 && this._time > 0\r\n var justFinished = this._lastTime < this._time && this.time > duration\r\n this._lastTime = this._time\r\n if (justStarted) {\r\n // this.fire('start', this)\r\n }\r\n\r\n // Work out if the runner is finished set the done flag here so animations\r\n // know, that they are running in the last step (this is good for\r\n // transformations which can be merged)\r\n var declarative = this._isDeclarative\r\n this.done = !declarative && !justFinished && this._time >= duration\r\n\r\n // Call initialise and the run function\r\n if (running || declarative) {\r\n this._initialise(running)\r\n\r\n // clear the transforms on this runner so they dont get added again and again\r\n this.transforms = new SVG.Matrix()\r\n var converged = this._run(declarative ? dt : position)\r\n // this.fire('step', this)\r\n }\r\n // correct the done flag here\r\n // declaritive animations itself know when they converged\r\n this.done = this.done || (converged && declarative)\r\n // if (this.done) {\r\n // this.fire('finish', this)\r\n // }\r\n return this\r\n },\r\n\r\n finish: function () {\r\n return this.step(Infinity)\r\n },\r\n\r\n reverse: function (reverse) {\r\n this._reverse = reverse == null ? !this._reverse : reverse\r\n return this\r\n },\r\n\r\n ease: function (fn) {\r\n this._stepper = new SVG.Ease(fn)\r\n return this\r\n },\r\n\r\n active: function (enabled) {\r\n if (enabled == null) return this.enabled\r\n this.enabled = enabled\r\n return this\r\n },\r\n\r\n /*\r\n Runner Management\r\n =================\r\n Functions that are used to help index the runner\r\n */\r\n\r\n tag: function (name) {\r\n // Act as a getter to get all of the tags on this object\r\n if (name == null) return Object.keys(this.tags)\r\n\r\n // Add all of the tags to the object directly\r\n name = Array.isArray(name) ? name : [name]\r\n for (var i = name.length; i--;) {\r\n this.tags[name[i]] = true\r\n }\r\n return this\r\n },\r\n\r\n untag: function (name) {\r\n name = Array.isArray(name) ? name : [name]\r\n for (var i = name.length; i--;) {\r\n delete this.tags[name[i]]\r\n }\r\n return this\r\n },\r\n\r\n getEventTarget: function () {\r\n return this._dispatcher\r\n },\r\n\r\n /*\r\n Private Methods\r\n ===============\r\n Methods that shouldn't be used externally\r\n */\r\n\r\n // Save a morpher to the morpher list so that we can retarget it later\r\n _rememberMorpher: function (method, morpher) {\r\n this._history[method] = {\r\n morpher: morpher,\r\n caller: this._queue[this._queue.length - 1]\r\n }\r\n },\r\n\r\n // Try to set the target for a morpher if the morpher exists, otherwise\r\n // do nothing and return false\r\n _tryRetarget: function (method, target) {\r\n if (this._history[method]) {\r\n // if the last method wasnt even initialised, throw it away\r\n if (!this._history[method].caller.initialised) {\r\n let index = this._queue.indexOf(this._history[method].caller)\r\n this._queue.splice(index, 1)\r\n return false\r\n }\r\n\r\n // for the case of transformations, we use the special retarget function\r\n // which has access to the outer scope\r\n if (this._history[method].caller.isTransform) {\r\n this._history[method].caller.isTransform(target)\r\n // for everything else a simple morpher change is sufficient\r\n } else {\r\n this._history[method].morpher.to(target)\r\n }\r\n\r\n this._history[method].caller.finished = false\r\n var timeline = this.timeline()\r\n timeline && timeline._continue()\r\n return true\r\n }\r\n return false\r\n },\r\n\r\n // Run each initialise function in the runner if required\r\n _initialise: function (running) {\r\n // If we aren't running, we shouldn't initialise when not declarative\r\n if (!running && !this._isDeclarative) return\r\n\r\n // Loop through all of the initialisers\r\n for (var i = 0, len = this._queue.length; i < len; ++i) {\r\n // Get the current initialiser\r\n var current = this._queue[i]\r\n\r\n // Determine whether we need to initialise\r\n var needsIt = this._isDeclarative || (!current.initialised && running)\r\n running = !current.finished\r\n\r\n // Call the initialiser if we need to\r\n if (needsIt && running) {\r\n current.initialiser.call(this)\r\n current.initialised = true\r\n }\r\n }\r\n },\r\n\r\n // Run each run function for the position or dt given\r\n _run: function (positionOrDt) {\r\n // Run all of the _queue directly\r\n var allfinished = true\r\n for (var i = 0, len = this._queue.length; i < len; ++i) {\r\n // Get the current function to run\r\n var current = this._queue[i]\r\n\r\n // Run the function if its not finished, we keep track of the finished\r\n // flag for the sake of declarative _queue\r\n var converged = current.runner.call(this, positionOrDt)\r\n current.finished = current.finished || (converged === true)\r\n allfinished = allfinished && current.finished\r\n }\r\n\r\n // We report when all of the constructors are finished\r\n return allfinished\r\n },\r\n\r\n addTransform: function (transform, index) {\r\n this.transforms.lmultiplyO(transform)\r\n return this\r\n },\r\n\r\n clearTransform: function () {\r\n this.transforms = new SVG.Matrix()\r\n return this\r\n }\r\n }\r\n})\r\n\r\nSVG.Runner.id = 0\r\n\r\nSVG.Runner.sanitise = function (duration, delay, when) {\r\n // Initialise the default parameters\r\n var times = 1\r\n var swing = false\r\n var wait = 0\r\n duration = duration || SVG.defaults.timeline.duration\r\n delay = delay || SVG.defaults.timeline.delay\r\n when = when || 'last'\r\n\r\n // If we have an object, unpack the values\r\n if (typeof duration === 'object' && !(duration instanceof SVG.Stepper)) {\r\n delay = duration.delay || delay\r\n when = duration.when || when\r\n swing = duration.swing || swing\r\n times = duration.times || times\r\n wait = duration.wait || wait\r\n duration = duration.duration || SVG.defaults.timeline.duration\r\n }\r\n\r\n return {\r\n duration: duration,\r\n delay: delay,\r\n swing: swing,\r\n times: times,\r\n wait: wait,\r\n when: when\r\n }\r\n}\r\n\r\nSVG.FakeRunner = class {\r\n constructor (transforms = new SVG.Matrix(), id = -1, done = true) {\r\n this.transforms = transforms\r\n this.id = id\r\n this.done = done\r\n }\r\n}\r\n\r\nSVG.extend([SVG.Runner, SVG.FakeRunner], {\r\n mergeWith (runner) {\r\n return new SVG.FakeRunner(\r\n runner.transforms.lmultiply(this.transforms),\r\n runner.id\r\n )\r\n }\r\n})\r\n\r\n// SVG.FakeRunner.emptyRunner = new SVG.FakeRunner()\r\n\r\nconst lmultiply = (last, curr) => last.lmultiplyO(curr)\r\nconst getRunnerTransform = (runner) => runner.transforms\r\n\r\nfunction mergeTransforms () {\r\n // Find the matrix to apply to the element and apply it\r\n let runners = this._transformationRunners.runners\r\n let netTransform = runners\r\n .map(getRunnerTransform)\r\n .reduce(lmultiply, new SVG.Matrix())\r\n\r\n this.transform(netTransform)\r\n\r\n this._transformationRunners.merge()\r\n\r\n if (this._transformationRunners.length() === 1) {\r\n this._frameId = null\r\n }\r\n}\r\n\r\nclass RunnerArray {\r\n constructor () {\r\n this.runners = []\r\n this.ids = []\r\n }\r\n\r\n add (runner) {\r\n if (this.runners.includes(runner)) return\r\n\r\n let id = runner.id + 1\r\n\r\n let leftSibling = this.ids.reduce((last, curr) => {\r\n if (curr > last && curr < id) return curr\r\n return last\r\n }, 0)\r\n\r\n let index = this.ids.indexOf(leftSibling) + 1\r\n\r\n this.ids.splice(index, 0, id)\r\n this.runners.splice(index, 0, runner)\r\n\r\n return this\r\n }\r\n\r\n getByID (id) {\r\n return this.runners[this.ids.indexOf(id + 1)]\r\n }\r\n\r\n remove (id) {\r\n let index = this.ids.indexOf(id + 1)\r\n this.ids.splice(index, 1)\r\n this.runners.splice(index, 1)\r\n return this\r\n }\r\n\r\n merge () {\r\n let lastRunner = null\r\n this.runners.forEach((runner, i) => {\r\n if (lastRunner && runner.done && lastRunner.done) {\r\n this.remove(runner.id)\r\n this.edit(lastRunner.id, runner.mergeWith(lastRunner))\r\n }\r\n\r\n lastRunner = runner\r\n })\r\n\r\n return this\r\n }\r\n\r\n edit (id, newRunner) {\r\n let index = this.ids.indexOf(id + 1)\r\n this.ids.splice(index, 1, id)\r\n this.runners.splice(index, 1, newRunner)\r\n return this\r\n }\r\n\r\n length () {\r\n return this.ids.length\r\n }\r\n\r\n clearBefore (id) {\r\n let deleteCnt = this.ids.indexOf(id + 1) || 1\r\n this.ids.splice(0, deleteCnt, 0)\r\n this.runners.splice(0, deleteCnt, new SVG.FakeRunner())\r\n return this\r\n }\r\n}\r\n\r\nSVG.extend(SVG.Element, {\r\n // this function searches for all runners on the element and deletes the ones\r\n // which run before the current one. This is because absolute transformations\r\n // overwfrite anything anyway so there is no need to waste time computing\r\n // other runners\r\n _clearTransformRunnersBefore: function (currentRunner) {\r\n this._transformationRunners.clearBefore(currentRunner.id)\r\n },\r\n\r\n _currentTransform (current) {\r\n return this._transformationRunners.runners\r\n // we need the equal sign here to make sure, that also transformations\r\n // on the same runner which execute before the current transformation are\r\n // taken into account\r\n .filter((runner) => runner.id <= current.id)\r\n .map(getRunnerTransform)\r\n .reduce(lmultiply, new SVG.Matrix())\r\n },\r\n\r\n addRunner: function (runner) {\r\n this._transformationRunners.add(runner)\r\n\r\n SVG.Animator.transform_frame(\r\n mergeTransforms.bind(this), this._frameId\r\n )\r\n },\r\n\r\n _prepareRunner: function () {\r\n if (this._frameId == null) {\r\n this._transformationRunners = new RunnerArray()\r\n .add(new SVG.FakeRunner(new SVG.Matrix(this)))\r\n\r\n this._frameId = SVG.Element.frameId++\r\n }\r\n }\r\n})\r\n\r\nSVG.Element.frameId = 0\r\n\r\nSVG.extend(SVG.Runner, {\r\n attr: function (a, v) {\r\n return this.styleAttr('attr', a, v)\r\n },\r\n\r\n // Add animatable styles\r\n css: function (s, v) {\r\n return this.styleAttr('css', s, v)\r\n },\r\n\r\n styleAttr (type, name, val) {\r\n // apply attributes individually\r\n if (typeof name === 'object') {\r\n for (var key in val) {\r\n this.styleAttr(type, key, val[key])\r\n }\r\n }\r\n\r\n var morpher = new SVG.Morphable(this._stepper).to(val)\r\n\r\n this.queue(function () {\r\n morpher = morpher.from(this.element()[type](name))\r\n }, function (pos) {\r\n this.element()[type](name, morpher.at(pos))\r\n return morpher.done()\r\n })\r\n\r\n return this\r\n },\r\n\r\n zoom: function (level, point) {\r\n var morpher = new SVG.Morphable(this._stepper).to(new SVG.Number(level))\r\n\r\n this.queue(function () {\r\n morpher = morpher.from(this.zoom())\r\n }, function (pos) {\r\n this.element().zoom(morpher.at(pos), point)\r\n return morpher.done()\r\n })\r\n\r\n return this\r\n },\r\n\r\n /**\r\n ** absolute transformations\r\n **/\r\n\r\n //\r\n // M v -----|-----(D M v = F v)------|-----> T v\r\n //\r\n // 1. define the final state (T) and decompose it (once)\r\n // t = [tx, ty, the, lam, sy, sx]\r\n // 2. on every frame: pull the current state of all previous transforms\r\n // (M - m can change)\r\n // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0]\r\n // 3. Find the interpolated matrix F(pos) = m + pos * (t - m)\r\n // - Note F(0) = M\r\n // - Note F(1) = T\r\n // 4. Now you get the delta matrix as a result: D = F * inv(M)\r\n\r\n transform: function (transforms, relative, affine) {\r\n // If we have a declarative function, we should retarget it if possible\r\n relative = transforms.relative || relative\r\n if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) {\r\n return this\r\n }\r\n\r\n // Parse the parameters\r\n var isMatrix = isMatrixLike(transforms)\r\n affine = transforms.affine != null\r\n ? transforms.affine\r\n : (affine != null ? affine : !isMatrix)\r\n\r\n // Create a morepher and set its type\r\n const morpher = new SVG.Morphable()\r\n .type(affine ? SVG.Morphable.TransformBag : SVG.Matrix)\r\n .stepper(this._stepper)\r\n\r\n let origin\r\n let element\r\n let current\r\n let currentAngle\r\n let startTransform\r\n\r\n function setup () {\r\n // make sure element and origin is defined\r\n element = element || this.element()\r\n origin = origin || getOrigin(transforms, element)\r\n\r\n startTransform = new SVG.Matrix(relative ? undefined : element)\r\n\r\n // add the runner to the element so it can merge transformations\r\n element.addRunner(this)\r\n\r\n // Deactivate all transforms that have run so far if we are absolute\r\n if (!relative) {\r\n element._clearTransformRunnersBefore(this)\r\n }\r\n }\r\n\r\n function run (pos) {\r\n // clear all other transforms before this in case something is saved\r\n // on this runner. We are absolute. We dont need these!\r\n if (!relative) this.clearTransform()\r\n\r\n let {x, y} = new SVG.Point(origin).transform(element._currentTransform(this))\r\n\r\n let target = new SVG.Matrix({...transforms, origin: [x, y]})\r\n let start = this._isDeclarative && current\r\n ? current\r\n : startTransform\r\n\r\n if (affine) {\r\n target = target.decompose(x, y)\r\n start = start.decompose(x, y)\r\n\r\n // Get the current and target angle as it was set\r\n const rTarget = target.rotate\r\n const rCurrent = start.rotate\r\n\r\n // Figure out the shortest path to rotate directly\r\n const possibilities = [rTarget - 360, rTarget, rTarget + 360]\r\n const distances = possibilities.map(a => Math.abs(a - rCurrent))\r\n const shortest = Math.min(...distances)\r\n const index = distances.indexOf(shortest)\r\n target.rotate = possibilities[index]\r\n }\r\n\r\n if (relative) {\r\n // we have to be careful here not to overwrite the rotation\r\n // with the rotate method of SVG.Matrix\r\n if (!isMatrix) {\r\n target.rotate = transforms.rotate || 0\r\n }\r\n if (this._isDeclarative && currentAngle) {\r\n start.rotate = currentAngle\r\n }\r\n }\r\n\r\n morpher.from(start)\r\n morpher.to(target)\r\n\r\n let affineParameters = morpher.at(pos)\r\n currentAngle = affineParameters.rotate\r\n current = new SVG.Matrix(affineParameters)\r\n\r\n this.addTransform(current)\r\n return morpher.done()\r\n }\r\n\r\n function retarget (newTransforms) {\r\n // only get a new origin if it changed since the last call\r\n if (\r\n (newTransforms.origin || 'center').toString() !==\r\n (transforms.origin || 'center').toString()\r\n ) {\r\n origin = getOrigin(transforms, element)\r\n }\r\n\r\n // overwrite the old transformations with the new ones\r\n transforms = {...newTransforms, origin}\r\n }\r\n\r\n this.queue(setup, run, retarget)\r\n this._isDeclarative && this._rememberMorpher('transform', morpher)\r\n return this\r\n },\r\n\r\n // Animatable x-axis\r\n x: function (x, relative) {\r\n return this._queueNumber('x', x)\r\n },\r\n\r\n // Animatable y-axis\r\n y: function (y) {\r\n return this._queueNumber('y', y)\r\n },\r\n\r\n dx: function (x) {\r\n return this._queueNumberDelta('dx', x)\r\n },\r\n\r\n dy: function (y) {\r\n return this._queueNumberDelta('dy', y)\r\n },\r\n\r\n _queueNumberDelta: function (method, to) {\r\n to = new SVG.Number(to)\r\n\r\n // Try to change the target if we have this method already registerd\r\n if (this._tryRetargetDelta(method, to)) return this\r\n\r\n // Make a morpher and queue the animation\r\n var morpher = new SVG.Morphable(this._stepper).to(to)\r\n this.queue(function () {\r\n var from = this.element()[method]()\r\n morpher.from(from)\r\n morpher.to(from + to)\r\n }, function (pos) {\r\n this.element()[method](morpher.at(pos))\r\n return morpher.done()\r\n })\r\n\r\n // Register the morpher so that if it is changed again, we can retarget it\r\n this._rememberMorpher(method, morpher)\r\n return this\r\n },\r\n\r\n _queueObject: function (method, to) {\r\n // Try to change the target if we have this method already registerd\r\n if (this._tryRetarget(method, to)) return this\r\n\r\n // Make a morpher and queue the animation\r\n var morpher = new SVG.Morphable(this._stepper).to(to)\r\n this.queue(function () {\r\n morpher.from(this.element()[method]())\r\n }, function (pos) {\r\n this.element()[method](morpher.at(pos))\r\n return morpher.done()\r\n })\r\n\r\n // Register the morpher so that if it is changed again, we can retarget it\r\n this._rememberMorpher(method, morpher)\r\n return this\r\n },\r\n\r\n _queueNumber: function (method, value) {\r\n return this._queueObject(method, new SVG.Number(value))\r\n },\r\n\r\n // Animatable center x-axis\r\n cx: function (x) {\r\n return this._queueNumber('cx', x)\r\n },\r\n\r\n // Animatable center y-axis\r\n cy: function (y) {\r\n return this._queueNumber('cy', y)\r\n },\r\n\r\n // Add animatable move\r\n move: function (x, y) {\r\n return this.x(x).y(y)\r\n },\r\n\r\n // Add animatable center\r\n center: function (x, y) {\r\n return this.cx(x).cy(y)\r\n },\r\n\r\n // Add animatable size\r\n size: function (width, height) {\r\n // animate bbox based size for all other elements\r\n var box\r\n\r\n if (!width || !height) {\r\n box = this._element.bbox()\r\n }\r\n\r\n if (!width) {\r\n width = box.width / box.height * height\r\n }\r\n\r\n if (!height) {\r\n height = box.height / box.width * width\r\n }\r\n\r\n return this\r\n .width(width)\r\n .height(height)\r\n },\r\n\r\n // Add animatable width\r\n width: function (width) {\r\n return this._queueNumber('width', width)\r\n },\r\n\r\n // Add animatable height\r\n height: function (height) {\r\n return this._queueNumber('height', height)\r\n },\r\n\r\n // Add animatable plot\r\n plot: function (a, b, c, d) {\r\n // Lines can be plotted with 4 arguments\r\n if (arguments.length === 4) {\r\n return this.plot([a, b, c, d])\r\n }\r\n\r\n // FIXME: this needs to be rewritten such that the element is only accesed\r\n // in the init function\r\n return this._queueObject('plot', new this._element.MorphArray(a))\r\n\r\n /*\r\n var morpher = this._element.morphArray().to(a)\r\n\r\n this.queue(function () {\r\n morpher.from(this._element.array())\r\n }, function (pos) {\r\n this._element.plot(morpher.at(pos))\r\n })\r\n\r\n return this\r\n */\r\n },\r\n\r\n // Add leading method\r\n leading: function (value) {\r\n return this._queueNumber('leading', value)\r\n },\r\n\r\n // Add animatable viewbox\r\n viewbox: function (x, y, width, height) {\r\n return this._queueObject('viewbox', new SVG.Box(x, y, width, height))\r\n },\r\n\r\n update: function (o) {\r\n if (typeof o !== 'object') {\r\n return this.update({\r\n offset: arguments[0],\r\n color: arguments[1],\r\n opacity: arguments[2]\r\n })\r\n }\r\n\r\n if (o.opacity != null) this.attr('stop-opacity', o.opacity)\r\n if (o.color != null) this.attr('stop-color', o.color)\r\n if (o.offset != null) this.attr('offset', o.offset)\r\n\r\n return this\r\n }\r\n})\r\n","\r\n// Must Change ....\r\nSVG.easing = {\r\n '-': function (pos) { return pos },\r\n '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 },\r\n '>': function (pos) { return Math.sin(pos * Math.PI / 2) },\r\n '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }\r\n}\r\n\r\nvar time = window.performance || Date\r\n\r\nvar makeSchedule = function (runnerInfo) {\r\n var start = runnerInfo.start\r\n var duration = runnerInfo.runner.duration()\r\n var end = start + duration\r\n return {start: start, duration: duration, end: end, runner: runnerInfo.runner}\r\n}\r\n\r\nSVG.Timeline = SVG.invent({\r\n inherit: SVG.EventTarget,\r\n\r\n // Construct a new timeline on the given element\r\n create: function () {\r\n this._timeSource = function () {\r\n return time.now()\r\n }\r\n\r\n this._dispatcher = document.createElement('div')\r\n\r\n // Store the timing variables\r\n this._startTime = 0\r\n this._speed = 1.0\r\n\r\n // Play control variables control how the animation proceeds\r\n this._reverse = false\r\n this._persist = 0\r\n\r\n // Keep track of the running animations and their starting parameters\r\n this._nextFrame = null\r\n this._paused = false\r\n this._runners = []\r\n this._order = []\r\n this._time = 0\r\n this._lastSourceTime = 0\r\n this._lastStepTime = 0\r\n },\r\n\r\n extend: {\r\n\r\n getEventTarget () {\r\n return this._dispatcher\r\n },\r\n\r\n /**\r\n *\r\n */\r\n\r\n // schedules a runner on the timeline\r\n schedule (runner, delay, when) {\r\n if (runner == null) {\r\n return this._runners.map(makeSchedule).sort(function (a, b) {\r\n return (a.start - b.start) || (a.duration - b.duration)\r\n })\r\n }\r\n\r\n if (!this.active()) {\r\n this._step()\r\n if (when == null) {\r\n when = 'now'\r\n }\r\n }\r\n\r\n // The start time for the next animation can either be given explicitly,\r\n // derived from the current timeline time or it can be relative to the\r\n // last start time to chain animations direclty\r\n var absoluteStartTime = 0\r\n delay = delay || 0\r\n\r\n // Work out when to start the animation\r\n if (when == null || when === 'last' || when === 'after') {\r\n // Take the last time and increment\r\n absoluteStartTime = this._startTime\r\n } else if (when === 'absolute' || when === 'start') {\r\n absoluteStartTime = delay\r\n delay = 0\r\n } else if (when === 'now') {\r\n absoluteStartTime = this._time\r\n } else if (when === 'relative') {\r\n let runnerInfo = this._runners[runner.id]\r\n if (runnerInfo) {\r\n absoluteStartTime = runnerInfo.start + delay\r\n delay = 0\r\n }\r\n } else {\r\n throw new Error('Invalid value for the \"when\" parameter')\r\n }\r\n\r\n // Manage runner\r\n runner.unschedule()\r\n runner.timeline(this)\r\n runner.time(-delay)\r\n\r\n // Save startTime for next runner\r\n this._startTime = absoluteStartTime + runner.duration() + delay\r\n\r\n // Save runnerInfo\r\n this._runners[runner.id] = {\r\n persist: this.persist(),\r\n runner: runner,\r\n start: absoluteStartTime\r\n }\r\n\r\n // Save order and continue\r\n this._order.push(runner.id)\r\n this._continue()\r\n return this\r\n },\r\n\r\n // Remove the runner from this timeline\r\n unschedule (runner) {\r\n var index = this._order.indexOf(runner.id)\r\n if (index < 0) return this\r\n\r\n delete this._runners[runner.id]\r\n this._order.splice(index, 1)\r\n runner.timeline(null)\r\n return this\r\n },\r\n\r\n play () {\r\n // Now make sure we are not paused and continue the animation\r\n this._paused = false\r\n return this._continue()\r\n },\r\n\r\n pause () {\r\n // Cancel the next animation frame and pause\r\n this._nextFrame = null\r\n this._paused = true\r\n return this\r\n },\r\n\r\n stop () {\r\n // Cancel the next animation frame and go to start\r\n this.seek(-this._time)\r\n return this.pause()\r\n },\r\n\r\n finish () {\r\n this.seek(Infinity)\r\n return this.pause()\r\n },\r\n\r\n speed (speed) {\r\n if (speed == null) return this._speed\r\n this._speed = speed\r\n return this\r\n },\r\n\r\n reverse (yes) {\r\n var currentSpeed = this.speed()\r\n if (yes == null) return this.speed(-currentSpeed)\r\n\r\n var positive = Math.abs(currentSpeed)\r\n return this.speed(yes ? positive : -positive)\r\n },\r\n\r\n seek (dt) {\r\n this._time += dt\r\n return this._continue()\r\n },\r\n\r\n time (time) {\r\n if (time == null) return this._time\r\n this._time = time\r\n return this\r\n },\r\n\r\n persist (dtOrForever) {\r\n if (dtOrForever == null) return this._persist\r\n this._persist = dtOrForever\r\n return this\r\n },\r\n\r\n source (fn) {\r\n if (fn == null) return this._timeSource\r\n this._timeSource = fn\r\n return this\r\n },\r\n\r\n _step () {\r\n // If the timeline is paused, just do nothing\r\n if (this._paused) return\r\n\r\n // Get the time delta from the last time and update the time\r\n // TODO: Deal with window.blur window.focus to pause animations\r\n var time = this._timeSource()\r\n var dtSource = time - this._lastSourceTime\r\n var dtTime = this._speed * dtSource + (this._time - this._lastStepTime)\r\n this._lastSourceTime = time\r\n\r\n // Update the time\r\n this._time += dtTime\r\n this._lastStepTime = this._time\r\n // this.fire('time', this._time)\r\n\r\n // Run all of the runners directly\r\n var runnersLeft = false\r\n for (var i = 0, len = this._order.length; i < len; i++) {\r\n // Get and run the current runner and ignore it if its inactive\r\n var runnerInfo = this._runners[this._order[i]]\r\n var runner = runnerInfo.runner\r\n let dt = dtTime\r\n\r\n // Make sure that we give the actual difference\r\n // between runner start time and now\r\n let dtToStart = this._time - runnerInfo.start\r\n\r\n // Dont run runner if not started yet\r\n if (dtToStart < 0) {\r\n runnersLeft = true\r\n continue\r\n } else if (dtToStart < dt) {\r\n // Adjust dt to make sure that animation is on point\r\n dt = dtToStart\r\n }\r\n\r\n if (!runner.active()) continue\r\n\r\n // If this runner is still going, signal that we need another animation\r\n // frame, otherwise, remove the completed runner\r\n var finished = runner.step(dt).done\r\n if (!finished) {\r\n runnersLeft = true\r\n // continue\r\n } else if (runnerInfo.persist !== true) {\r\n // runner is finished. And runner might get removed\r\n\r\n // TODO: Figure out end time of runner\r\n var endTime = runner.duration() - runner.time() + this._time\r\n\r\n if (endTime + this._persist < this._time) {\r\n // Delete runner and correct index\r\n delete this._runners[this._order[i]]\r\n this._order.splice(i--, 1) && --len\r\n runner.timeline(null)\r\n }\r\n }\r\n }\r\n\r\n // Get the next animation frame to keep the simulation going\r\n if (runnersLeft) {\r\n this._nextFrame = SVG.Animator.frame(this._step.bind(this))\r\n } else {\r\n this._nextFrame = null\r\n }\r\n return this\r\n },\r\n\r\n // Checks if we are running and continues the animation\r\n _continue () {\r\n if (this._paused) return this\r\n if (!this._nextFrame) {\r\n this._nextFrame = SVG.Animator.frame(this._step.bind(this))\r\n }\r\n return this\r\n },\r\n\r\n active () {\r\n return !!this._nextFrame\r\n }\r\n },\r\n\r\n // These methods will be added to all SVG.Element objects\r\n parent: SVG.Element,\r\n construct: {\r\n timeline: function () {\r\n this._timeline = (this._timeline || new SVG.Timeline())\r\n return this._timeline\r\n }\r\n }\r\n})\r\n","\r\n// c = {\r\n// finished: Whether or not we are finished\r\n// }\r\n\r\n/***\r\nBase Class\r\n==========\r\nThe base stepper class that will be\r\n***/\r\n\r\nfunction makeSetterGetter (k, f) {\r\n return function (v) {\r\n if (v == null) return this[v]\r\n this[k] = v\r\n if (f) f.call(this)\r\n return this\r\n }\r\n}\r\n\r\nSVG.Stepper = SVG.invent({\r\n create: function () {}\r\n})\r\n\r\n/***\r\nEasing Functions\r\n================\r\n***/\r\n\r\nSVG.Ease = SVG.invent({\r\n inherit: SVG.Stepper,\r\n\r\n create: function (fn) {\r\n SVG.Stepper.call(this, fn)\r\n\r\n this.ease = SVG.easing[fn || SVG.defaults.timeline.ease] || fn\r\n },\r\n\r\n extend: {\r\n\r\n step: function (from, to, pos) {\r\n if (typeof from !== 'number') {\r\n return pos < 1 ? from : to\r\n }\r\n return from + (to - from) * this.ease(pos)\r\n },\r\n\r\n done: function (dt, c) {\r\n return false\r\n }\r\n }\r\n})\r\n\r\nSVG.easing = {\r\n '-': function (pos) { return pos },\r\n '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 },\r\n '>': function (pos) { return Math.sin(pos * Math.PI / 2) },\r\n '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 },\r\n bezier: function (t0, x0, t1, x1) {\r\n return function (t) {\r\n // TODO: FINISH\r\n }\r\n }\r\n}\r\n\r\n/***\r\nController Types\r\n================\r\n***/\r\n\r\nSVG.Controller = SVG.invent({\r\n inherit: SVG.Stepper,\r\n\r\n create: function (fn) {\r\n SVG.Stepper.call(this, fn)\r\n this.stepper = fn\r\n },\r\n\r\n extend: {\r\n\r\n step: function (current, target, dt, c) {\r\n return this.stepper(current, target, dt, c)\r\n },\r\n\r\n done: function (c) {\r\n return c.done\r\n }\r\n }\r\n})\r\n\r\nfunction recalculate () {\r\n // Apply the default parameters\r\n var duration = (this._duration || 500) / 1000\r\n var overshoot = this._overshoot || 0\r\n\r\n // Calculate the PID natural response\r\n var eps = 1e-10\r\n var pi = Math.PI\r\n var os = Math.log(overshoot / 100 + eps)\r\n var zeta = -os / Math.sqrt(pi * pi + os * os)\r\n var wn = 3.9 / (zeta * duration)\r\n\r\n // Calculate the Spring values\r\n this.d = 2 * zeta * wn\r\n this.k = wn * wn\r\n}\r\n\r\nSVG.Spring = SVG.invent({\r\n inherit: SVG.Controller,\r\n\r\n create: function (duration, overshoot) {\r\n this.duration(duration || 500)\r\n .overshoot(overshoot || 0)\r\n },\r\n\r\n extend: {\r\n step: function (current, target, dt, c) {\r\n if (typeof current === 'string') return current\r\n c.done = dt === Infinity\r\n if (dt === Infinity) return target\r\n if (dt === 0) return current\r\n\r\n if (dt > 100) dt = 16\r\n\r\n dt /= 1000\r\n\r\n // Get the previous velocity\r\n var velocity = c.velocity || 0\r\n\r\n // Apply the control to get the new position and store it\r\n var acceleration = -this.d * velocity - this.k * (current - target)\r\n var newPosition = current +\r\n velocity * dt +\r\n acceleration * dt * dt / 2\r\n\r\n // Store the velocity\r\n c.velocity = velocity + acceleration * dt\r\n\r\n // Figure out if we have converged, and if so, pass the value\r\n c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002\r\n return c.done ? target : newPosition\r\n },\r\n\r\n duration: makeSetterGetter('_duration', recalculate),\r\n overshoot: makeSetterGetter('_overshoot', recalculate)\r\n }\r\n})\r\n\r\nSVG.PID = SVG.invent({\r\n inherit: SVG.Controller,\r\n\r\n create: function (p, i, d, windup) {\r\n SVG.Controller.call(this)\r\n\r\n p = p == null ? 0.1 : p\r\n i = i == null ? 0.01 : i\r\n d = d == null ? 0 : d\r\n windup = windup == null ? 1000 : windup\r\n this.p(p).i(i).d(d).windup(windup)\r\n },\r\n\r\n extend: {\r\n step: function (current, target, dt, c) {\r\n if (typeof current === 'string') return current\r\n c.done = dt === Infinity\r\n\r\n if (dt === Infinity) return target\r\n if (dt === 0) return current\r\n\r\n var p = target - current\r\n var i = (c.integral || 0) + p * dt\r\n var d = (p - (c.error || 0)) / dt\r\n var windup = this.windup\r\n\r\n // antiwindup\r\n if (windup !== false) {\r\n i = Math.max(-windup, Math.min(i, windup))\r\n }\r\n\r\n c.error = p\r\n c.integral = i\r\n\r\n c.done = Math.abs(p) < 0.001\r\n\r\n return c.done ? target : current + (this.P * p + this.I * i + this.D * d)\r\n },\r\n\r\n windup: makeSetterGetter('windup'),\r\n p: makeSetterGetter('P'),\r\n i: makeSetterGetter('I'),\r\n d: makeSetterGetter('D')\r\n }\r\n})\r\n"]} \ No newline at end of file diff --git a/dist/svg.min.js b/dist/svg.min.js index ed14bb2..7f3eb18 100644 --- a/dist/svg.min.js +++ b/dist/svg.min.js @@ -1 +1 @@ -var SVG=function(){"use strict";function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;n",delay:0},_t={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},Ot=Object.freeze({noop:bt,timeline:xt,attrs:_t}),At=function(){function t(){o(this,t),this.init.apply(this,arguments)}return a(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?k.test(t)?(i=p.exec(t.replace(g,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):w.test(t)&&(i=y.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+z(Math.round(this.r))+z(Math.round(this.g))+z(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",w.test(t)||k.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}(),Ct=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1n.x&&e>n.y&&t=e.time?e.run():Ft.timeouts.push(e),e!==n););for(var i=null,r=Ft.frames.last();i!==r&&(i=Ft.frames.shift());)i.run();Ft.transforms.forEach(function(t){t()}),Ft.nextDraw=Ft.timeouts.first()||Ft.frames.first()?window.requestAnimationFrame(Ft._draw):null}},It=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q(t,"string"==typeof t?null:t),e))}return r(e,Dt),a(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function Xt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function Yt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function Ht(t){return null==t?this.attr("cx"):this.attr("cx",t)}function Gt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function Vt(t){return null==t?2*this.rx():this.rx(new Mt(t).divide(2))}function Bt(t){return null==t?2*this.ry():this.ry(new Mt(t).divide(2))}function Qt(t,e){var n=R(this,t,e);return this.rx(new Mt(n.width).divide(2)).ry(new Mt(n.height).divide(2))}et(It),at("Container",{element:function(t,e){return this.put(new It(t,e))}});var Ut=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:Xt,y:Yt,cx:Ht,cy:Gt,width:Vt,height:Bt,size:Qt}),$t=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("circle",t),e))}return r(e,Nt),a(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Wt(t,e){return gt((e||document).querySelectorAll(t),function(t){return tt(t)})}$($t,{x:Xt,y:Yt,cx:Ht,cy:Gt,width:Vt,height:Bt,size:Qt}),at({Element:{circle:function(t){return this.put(new $t).radius(new Mt(t).divide(2)).move(0,0)}}}),et($t),at("Dom",{find:function(t){return Wt(t,this.node)}});var Jt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("clipPath",t),e))}return r(e,Dt),a(e,[{key:"remove",value:function(){return this.targets().forEach(function(t){t.unclip()}),c(u(e.prototype),"remove",this).call(this)}},{key:"targets",value:function(){return Wt('svg [clip-path*="'+this.id()+'"]')}}]),e}();at({Container:{clip:function(){return this.defs().put(new Jt)}},Element:{clipWith:function(t){var e=t instanceof Jt?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.id()+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}}),et(Jt);var Zt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("a",t),e))}return r(e,Dt),a(e,[{key:"to",value:function(t){return this.attr("href",t,G)}},{key:"target",value:function(t){return this.attr("target",t)}}]),e}();at({Container:{link:function(t){return this.put(new Zt).to(t)}},Element:{linkTo:function(t){var e=new Zt;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}}),et(Zt);var Kt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("ellipse",t),e))}return r(e,Nt),e}();$(Kt,Ut),at("Container",{ellipse:function(t,e){return this.put(new Kt).size(t,e).move(0,0)}}),et(Kt);var te=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("stop",t),e))}return r(e,Et),a(e,[{key:"update",value:function(t){return("number"==typeof t||t instanceof Mt)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new Mt(t.offset)),this}}]),e}();et(te);var ee=Object.freeze({from:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({fx:new Mt(t),fy:new Mt(e)}):this.attr({x1:new Mt(t),y1:new Mt(e)})},to:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({cx:new Mt(t),cy:new Mt(e)}):this.attr({x2:new Mt(t),y2:new Mt(e)})}});function ne(){if(!ne.nodes){var t=(new Rt).size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"}),e=t.path().node;ne.nodes={svg:t,path:e}}if(!ne.nodes.svg.node.parentNode){var n=document.body||document.documentElement;ne.nodes.svg.addTo(n)}return ne.nodes}var ie=function(){function r(t,e,n){var i;o(this,r),n=n||{x:0,y:0},i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"===l(t)?{x:t.x,y:t.y}:{x:t,y:e},this.x=null==i.x?n.x:i.x,this.y=null==i.y?n.y:i.y}return a(r,[{key:"clone",value:function(){return new r(this)}},{key:"native",value:function(){var t=ne().svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t}},{key:"transform",value:function(t){return new r(t.a*this.x+t.c*this.y+t.e,t.b*this.x+t.d*this.y+t.f)}}]),r}();at({Element:{point:function(t,e){return new ie(t,e).transform(this.screenCTM().inverse())}}});var re=function(){function u(){o(this,u),this.init.apply(this,arguments)}return a(u,[{key:"init",value:function(t){var e;t="string"==typeof t?t.split(C).map(parseFloat):Array.isArray(t)?t:"object"===l(t)?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):[0,0,0,0],this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],null==(e=this).x&&(e.x=0,e.y=0,e.width=0,e.height=0),e.w=e.width,e.h=e.height,e.x2=e.x+e.width,e.y2=e.y+e.height,e.cx=e.x+e.width/2,e.cy=e.y+e.height/2}},{key:"merge",value:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new u(e,n,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-n)}},{key:"transform",value:function(e){var n=1/0,i=-1/0,r=1/0,s=-1/0;return[new ie(this.x,this.y),new ie(this.x2,this.y),new ie(this.x,this.y2),new ie(this.x2,this.y2)].forEach(function(t){t=t.transform(e),n=Math.min(n,t.x),i=Math.max(i,t.x),r=Math.min(r,t.y),s=Math.max(s,t.y)}),new u(n,r,i-n,s-r)}},{key:"addOffset",value:function(){return this.x+=window.pageXOffset,this.y+=window.pageYOffset,this}},{key:"toString",value:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}},{key:"toArray",value:function(){return[this.x,this.y,this.width,this.height]}}]),u}();function se(e){var n,t,i;try{if(n=e(this.node),!((i=n).w||i.h||i.x||i.y||(t=this.node,(document.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===document}).call(document.documentElement,t))))throw new Error("Element not in the dom")}catch(t){try{var r=this.clone(ne().svg).show();n=e(r.node),r.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return n}at({Element:{bbox:function(){return new re(se.call(this,function(t){return t.getBBox()}))},rbox:function(t){var e=new re(se.call(this,function(t){return t.getBoundingClientRect()}));return t?e.transform(t.screenCTM().inverse()):e.addOffset()}},viewbox:{viewbox:function(t,e,n,i){return null==t?new re(this.attr("viewBox")):this.attr("viewBox",new re(t,e,n,i))}}});var ue=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q(t+"Gradient","string"==typeof t?null:t),i))}return r(i,Dt),a(i,[{key:"stop",value:function(t,e,n){return this.put(new te).update(t,e,n)}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="gradientTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new re}}]),i}();$(ue,ee),at({Container:{gradient:function(t,e){return this.defs().gradient(t,e)}},Defs:{gradient:function(t,e){return this.put(new ue(t)).update(e)}}}),et(ue);var oe=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q("pattern",t),i))}return r(i,Dt),a(i,[{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="patternTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return find('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new re}}]),i}();at({Container:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}},Defs:{pattern:function(t,e,n){return this.put(new oe).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}}),et(oe);var ae=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("image",t),e))}return r(e,Nt),a(e,[{key:"load",value:function(n,i){if(!n)return this;var r=new window.Image;return dt(r,"load",function(t){var e=this.parent(oe);0===this.width()&&0===this.height()&&this.size(r.width,r.height),e instanceof oe&&0===e.width()&&0===e.height()&&e.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:r.width,height:r.height,ratio:r.width/r.height,url:n})},this),dt(r,"load error",function(){vt(r)}),this.attr("href",r.src=n,G)}},{key:"attrHook",value:function(t){var e=this;return t.doc().defs().pattern(0,0,function(t){t.add(e)})}}]),e}();at({Container:{image:function(t,e){return this.put(new ae).size(0,0).load(t,e)}}}),et(ae);var he=Ct("PointArray",jt);$(he,{toString:function(){for(var t=0,e=this.length,n=[];t":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Pe=function(){function t(){o(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),ze=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).ease=De[t||xt.ease]||t,e}return r(n,Pe),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),Re=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).stepper=t,e}return r(n,Pe),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function qe(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var Le=function(t){function i(t,e){var n;return o(this,i),(n=h(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,Re),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i;this._lastTime=this._time,r&&this.fire("start",this);var u=this._isDeclarative;if(this.done=!u&&!s&&this._time>=i,n||u){this._initialise(n),this.transforms=new Ee;var o=this._run(u?t:e);this.fire("step",this)}return this.done=this.done||o&&u,this.done&&this.fire("finish",this),this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new ze(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e",delay:0},kt={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},bt=Object.freeze({noop:gt,timeline:wt,attrs:kt}),xt=function(){function t(){o(this,t),this.init.apply(this,arguments)}return a(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?k.test(t)?(i=p.exec(t.replace(g,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):w.test(t)&&(i=y.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+z(Math.round(this.r))+z(Math.round(this.g))+z(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",w.test(t)||k.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}(),_t=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1n.x&&e>n.y&&t=e.time?e.run():Ft.timeouts.push(e),e!==n););for(var i=null,r=Ft.frames.last();i!==r&&(i=Ft.frames.shift());)i.run();Ft.transforms.forEach(function(t){t()}),Ft.nextDraw=Ft.timeouts.first()||Ft.frames.first()?window.requestAnimationFrame(Ft._draw):null}},It=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q(t,"string"==typeof t?null:t),e))}return r(e,Tt),a(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function Xt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function Yt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function Ht(t){return null==t?this.attr("cx"):this.attr("cx",t)}function Gt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function Vt(t){return null==t?2*this.rx():this.rx(new At(t).divide(2))}function Bt(t){return null==t?2*this.ry():this.ry(new At(t).divide(2))}function Qt(t,e){var n=R(this,t,e);return this.rx(new At(n.width).divide(2)).ry(new At(n.height).divide(2))}et(It),Pt("Container",{element:function(t,e){return this.put(new It(t,e))}});var Ut=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:Xt,y:Yt,cx:Ht,cy:Gt,width:Vt,height:Bt,size:Qt}),$t=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("circle",t),e))}return r(e,St),a(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Wt(t,e){return yt((e||document).querySelectorAll(t),function(t){return tt(t)})}function Jt(t){return Wt(t,this.node)}$($t,{x:Xt,y:Yt,cx:Ht,cy:Gt,width:Vt,height:Bt,size:Qt}),Pt({Element:{circle:function(t){return this.put(new $t).radius(new At(t).divide(2)).move(0,0)}}}),et($t),Pt("Dom",{find:Jt});var Zt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("clipPath",t),e))}return r(e,Tt),a(e,[{key:"remove",value:function(){return this.targets().forEach(function(t){t.unclip()}),c(u(e.prototype),"remove",this).call(this)}},{key:"targets",value:function(){return Wt('svg [clip-path*="'+this.id()+'"]')}}]),e}();Pt({Container:{clip:function(){return this.defs().put(new Zt)}},Element:{clipWith:function(t){var e=t instanceof Zt?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.id()+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}}),et(Zt);var Kt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("a",t),e))}return r(e,Tt),a(e,[{key:"to",value:function(t){return this.attr("href",t,G)}},{key:"target",value:function(t){return this.attr("target",t)}}]),e}();Pt({Container:{link:function(t){return this.put(new Kt).to(t)}},Element:{linkTo:function(t){var e=new Kt;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}}),et(Kt);var te=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("ellipse",t),e))}return r(e,St),e}();$(te,Ut),Pt("Container",{ellipse:function(t,e){return this.put(new te).size(t,e).move(0,0)}}),et(te);var ee=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("stop",t),e))}return r(e,Mt),a(e,[{key:"update",value:function(t){return("number"==typeof t||t instanceof At)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new At(t.offset)),this}}]),e}();et(ee);var ne=Object.freeze({from:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({fx:new At(t),fy:new At(e)}):this.attr({x1:new At(t),y1:new At(e)})},to:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({cx:new At(t),cy:new At(e)}):this.attr({x2:new At(t),y2:new At(e)})}});function ie(){if(!ie.nodes){var t=(new Rt).size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"}),e=t.path().node;ie.nodes={svg:t,path:e}}if(!ie.nodes.svg.node.parentNode){var n=document.body||document.documentElement;ie.nodes.svg.addTo(n)}return ie.nodes}var re=function(){function r(t,e,n){var i;o(this,r),n=n||{x:0,y:0},i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"===l(t)?{x:t.x,y:t.y}:{x:t,y:e},this.x=null==i.x?n.x:i.x,this.y=null==i.y?n.y:i.y}return a(r,[{key:"clone",value:function(){return new r(this)}},{key:"native",value:function(){var t=ie().svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t}},{key:"transform",value:function(t){return new r(t.a*this.x+t.c*this.y+t.e,t.b*this.x+t.d*this.y+t.f)}}]),r}();Pt({Element:{point:function(t,e){return new re(t,e).transform(this.screenCTM().inverse())}}});var se=function(){function u(){o(this,u),this.init.apply(this,arguments)}return a(u,[{key:"init",value:function(t){var e;t="string"==typeof t?t.split(C).map(parseFloat):Array.isArray(t)?t:"object"===l(t)?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):[0,0,0,0],this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],null==(e=this).x&&(e.x=0,e.y=0,e.width=0,e.height=0),e.w=e.width,e.h=e.height,e.x2=e.x+e.width,e.y2=e.y+e.height,e.cx=e.x+e.width/2,e.cy=e.y+e.height/2}},{key:"merge",value:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new u(e,n,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-n)}},{key:"transform",value:function(e){var n=1/0,i=-1/0,r=1/0,s=-1/0;return[new re(this.x,this.y),new re(this.x2,this.y),new re(this.x,this.y2),new re(this.x2,this.y2)].forEach(function(t){t=t.transform(e),n=Math.min(n,t.x),i=Math.max(i,t.x),r=Math.min(r,t.y),s=Math.max(s,t.y)}),new u(n,r,i-n,s-r)}},{key:"addOffset",value:function(){return this.x+=window.pageXOffset,this.y+=window.pageYOffset,this}},{key:"toString",value:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}},{key:"toArray",value:function(){return[this.x,this.y,this.width,this.height]}}]),u}();function ue(e){var n,t,i;try{if(n=e(this.node),!((i=n).w||i.h||i.x||i.y||(t=this.node,(document.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===document}).call(document.documentElement,t))))throw new Error("Element not in the dom")}catch(t){try{var r=this.clone(ie().svg).show();n=e(r.node),r.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return n}Pt({Element:{bbox:function(){return new se(ue.call(this,function(t){return t.getBBox()}))},rbox:function(t){var e=new se(ue.call(this,function(t){return t.getBoundingClientRect()}));return t?e.transform(t.screenCTM().inverse()):e.addOffset()}},viewbox:{viewbox:function(t,e,n,i){return null==t?new se(this.attr("viewBox")):this.attr("viewBox",new se(t,e,n,i))}}});var oe=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q(t+"Gradient","string"==typeof t?null:t),i))}return r(i,Tt),a(i,[{key:"stop",value:function(t,e,n){return this.put(new ee).update(t,e,n)}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="gradientTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return Jt('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new se}}]),i}();$(oe,ne),Pt({Container:{gradient:function(t,e){return this.defs().gradient(t,e)}},Defs:{gradient:function(t,e){return this.put(new oe(t)).update(e)}}}),et(oe);var ae=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q("pattern",t),i))}return r(i,Tt),a(i,[{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="patternTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return Jt('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new se}}]),i}();Pt({Container:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}},Defs:{pattern:function(t,e,n){return this.put(new ae).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}}),et(ae);var he=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("image",t),e))}return r(e,St),a(e,[{key:"load",value:function(n,i){if(!n)return this;var r=new window.Image;return lt(r,"load",function(t){var e=this.parent(ae);0===this.width()&&0===this.height()&&this.size(r.width,r.height),e instanceof ae&&0===e.width()&&0===e.height()&&e.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:r.width,height:r.height,ratio:r.width/r.height,url:n})},this),lt(r,"load error",function(){ct(r)}),this.attr("href",r.src=n,G)}},{key:"attrHook",value:function(t){var e=this;return t.doc().defs().pattern(0,0,function(t){t.add(e)})}}]),e}();Pt({Container:{image:function(t,e){return this.put(new he).size(0,0).load(t,e)}}}),et(he);var le=_t("PointArray",Ot);$(le,{toString:function(){for(var t=0,e=this.length,n=[];t":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},ze=function(){function t(){o(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),Re=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).ease=Pe[t||wt.ease]||t,e}return r(n,ze),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),qe=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).stepper=t,e}return r(n,ze),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Le(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var Fe=function(t){function i(t,e){var n;return o(this,i),(n=h(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,qe),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i;this._lastTime=this._time,r&&this.fire("start",this);var u=this._isDeclarative;if(this.done=!u&&!s&&this._time>=i,n||u){this._initialise(n),this.transforms=new Ne;var o=this._run(u?t:e);this.fire("step",this)}return this.done=this.done||o&&u,this.done&&this.fire("finish",this),this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new Re(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e= 2.1.2 < 3" + } } } }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.x.x" - } - }, "boxen": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-2.0.0.tgz", @@ -1929,15 +1700,6 @@ "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", "dev": true }, - "bufferstreams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz", - "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", - "dev": true, - "requires": { - "readable-stream": "^1.0.33" - } - }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -2010,22 +1772,6 @@ "integrity": "sha512-enC3zKfUCJxxwvUIsBkbHd54CtJw1KtIWvrK0JZxWD/fEN2knHaai45lndJ4xXAkyRAPyk60J3yagkKDWhfeMA==", "dev": true }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -2039,36 +1785,61 @@ "supports-color": "^2.0.0" } }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", "dev": true, "requires": { - "anymatch": "^1.3.0", + "anymatch": "^2.0.0", "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", "inherits": "^2.0.1", "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" + "readdirp": "^2.0.0", + "upath": "^1.0.5" }, "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } }, "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "^2.1.1" } } } @@ -2115,12 +1886,12 @@ "dev": true }, "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "^1.0.1" + "restore-cursor": "^2.0.0" } }, "cli-width": { @@ -2129,78 +1900,12 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -2238,16 +1943,10 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, "colors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz", - "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", + "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==", "dev": true }, "combine-lists": { @@ -2260,9 +1959,9 @@ }, "dependencies": { "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true } } @@ -2277,10 +1976,11 @@ } }, "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true, + "optional": true }, "component-bind": { "version": "1.0.0", @@ -2350,23 +2050,6 @@ } } }, - "concat-with-sourcemaps": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", - "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "connect": { "version": "3.6.6", "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", @@ -2385,15 +2068,6 @@ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, - "consolidate": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz", - "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", - "dev": true, - "requires": { - "bluebird": "^3.1.1" - } - }, "contains-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", @@ -2424,16 +2098,6 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, - "copy-props": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-1.6.0.tgz", - "integrity": "sha1-8DJLvumXcRAeezraES8xPDk9uO0=", - "dev": true, - "requires": { - "each-props": "^1.2.1", - "is-plain-object": "^2.0.1" - } - }, "core-js": { "version": "2.5.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", @@ -2453,44 +2117,33 @@ "dev": true }, "coveralls": { - "version": "2.13.3", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", - "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.2.tgz", + "integrity": "sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw==", "dev": true, "requires": { - "js-yaml": "3.6.1", - "lcov-parse": "0.0.10", - "log-driver": "1.2.5", - "minimist": "1.2.0", - "request": "2.79.0" + "growl": "~> 1.10.0", + "js-yaml": "^3.11.0", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.85.0" }, "dependencies": { - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "caseless": "~0.11.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.1.1", - "har-validator": "~2.0.6", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "oauth-sign": "~0.8.1", - "qs": "~6.3.0", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "~0.4.1", - "uuid": "^3.0.0" + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" } } } @@ -2518,35 +2171,6 @@ } } }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "2.x.x" - } - }, - "css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -2562,15 +2186,6 @@ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "^0.10.9" - } - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -2588,10 +2203,10 @@ } } }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "date-format": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", "dev": true }, "debug": { @@ -2603,40 +2218,6 @@ "ms": "2.0.0" } }, - "debug-fabulous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", - "dev": true, - "requires": { - "debug": "3.X", - "memoizee": "0.4.X", - "object-assign": "4.X" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "debug-log": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", - "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", - "dev": true - }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -2658,15 +2239,6 @@ "mimic-response": "^1.0.0" } }, - "deep-assign": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz", - "integrity": "sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s=", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, "deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", @@ -2685,25 +2257,6 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, - "requires": { - "foreach": "^2.0.5", - "object-keys": "^1.0.8" - } - }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -2745,20 +2298,6 @@ } } }, - "deglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz", - "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==", - "dev": true, - "requires": { - "find-root": "^1.0.0", - "glob": "^7.0.5", - "ignore": "^3.0.9", - "pkg-config": "^1.1.0", - "run-parallel": "^1.1.2", - "uniq": "^1.0.1" - } - }, "del": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", @@ -2792,30 +2331,12 @@ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true - }, "dfa": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.1.0.tgz", @@ -2858,25 +2379,6 @@ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9" - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", @@ -2917,106 +2419,72 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "~1.3.0" - }, - "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1" - } - } - } - }, "engine.io": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.3.tgz", - "integrity": "sha1-jef5eJXSDTm4X4ju7nd7K9QrE9Q=", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { - "accepts": "1.3.3", + "accepts": "~1.3.4", "base64id": "1.0.0", "cookie": "0.3.1", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", - "ws": "1.1.2" + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" }, "dependencies": { "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.2" + "ms": "2.0.0" } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true } } }, "engine.io-client": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.3.tgz", - "integrity": "sha1-F5jtk0USRkU9TG9jXXogH+lA1as=", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { "component-emitter": "1.2.1", "component-inherit": "0.0.3", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", "has-cors": "1.1.0", "indexof": "0.0.1", - "parsejson": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "ws": "1.1.2", - "xmlhttprequest-ssl": "1.5.3", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", "yeast": "0.1.2" }, "dependencies": { "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.2" + "ms": "2.0.0" } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true } } }, "engine.io-parser": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz", - "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", "dev": true, "requires": { "after": "0.8.2", - "arraybuffer.slice": "0.0.6", + "arraybuffer.slice": "~0.0.7", "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", - "has-binary": "0.1.7", - "wtf-8": "1.0.0" + "blob": "0.0.5", + "has-binary2": "~1.0.2" } }, "ent": { @@ -3034,123 +2502,22 @@ "is-arrayish": "^0.2.1" } }, - "es-abstract": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", - "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" - } - }, - "es-to-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", - "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", - "dev": true, - "requires": { - "is-callable": "^1.1.1", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.1" - } - }, - "es5-ext": { - "version": "0.10.45", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", - "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "1" - } + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", - "dev": true - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.14", - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, "requires": { "esprima": "^2.7.1", @@ -3178,105 +2545,178 @@ } } }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "^0.1.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, "eslint": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", - "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.8.0.tgz", + "integrity": "sha512-Zok6Bru3y2JprqTNm14mgQ15YQu/SMDkWdnmHfFg770DIUlmMFd/gqqzCHekxzjHZJxXv3tmTpH0C1icaYJsRQ==", "dev": true, "requires": { - "babel-code-frame": "^6.16.0", - "chalk": "^1.1.3", - "concat-stream": "^1.5.2", - "debug": "^2.1.1", - "doctrine": "^2.0.0", - "escope": "^3.6.0", - "espree": "^3.4.0", - "esquery": "^1.0.0", - "estraverse": "^4.2.0", + "@babel/code-frame": "^7.0.0", + "ajv": "^6.5.3", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^2.1.0", + "eslint-scope": "^4.0.0", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^4.0.0", + "esquery": "^1.0.1", "esutils": "^2.0.2", "file-entry-cache": "^2.0.0", - "glob": "^7.0.3", - "globals": "^9.14.0", - "ignore": "^3.2.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", "imurmurhash": "^0.1.4", - "inquirer": "^0.12.0", - "is-my-json-valid": "^2.10.0", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.5.1", - "json-stable-stringify": "^1.0.0", + "inquirer": "^6.1.0", + "is-resolvable": "^1.1.0", + "js-yaml": "^3.12.0", + "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", - "lodash": "^4.0.0", - "mkdirp": "^0.5.0", + "lodash": "^4.17.5", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", "optionator": "^0.8.2", - "path-is-inside": "^1.0.1", - "pluralize": "^1.2.1", - "progress": "^1.1.8", - "require-uncached": "^1.0.2", - "shelljs": "^0.7.5", - "strip-bom": "^3.0.0", - "strip-json-comments": "~2.0.1", - "table": "^3.7.8", - "text-table": "~0.2.0", - "user-home": "^2.0.0" + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "require-uncached": "^1.0.3", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.0.2", + "text-table": "^0.2.0" }, "dependencies": { - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "strip-bom": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "os-homedir": "^1.0.0" + "has-flag": "^3.0.0" } } } }, "eslint-config-standard": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", - "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", - "dev": true - }, - "eslint-config-standard-jsx": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-4.0.2.tgz", - "integrity": "sha512-F8fRh2WFnTek7dZH9ZaE0PCBwdVGkwVWZmizla/DDNOmg7Tx6B/IlK5+oYpiX29jpu73LszeJj5i1axEZv6VMw==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz", + "integrity": "sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ==", "dev": true }, "eslint-import-resolver-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", - "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, "requires": { - "debug": "^2.2.0", - "object-assign": "^4.0.1", - "resolve": "^1.1.6" + "debug": "^2.6.9", + "resolve": "^1.5.0" } }, "eslint-module-utils": { @@ -3289,22 +2729,32 @@ "pkg-dir": "^1.0.0" } }, + "eslint-plugin-es": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.3.1.tgz", + "integrity": "sha512-9XcVyZiQRVeFjqHw8qHNDAZcQLqaHlOGGpeYqzYh8S4JYCWTCO3yzyen8yVmA5PratfzTRWDwCOFphtDEG+w/w==", + "dev": true, + "requires": { + "eslint-utils": "^1.3.0", + "regexpp": "^2.0.0" + } + }, "eslint-plugin-import": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz", - "integrity": "sha1-crowb60wXWfEgWNIpGmaQimsi04=", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", + "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", "dev": true, "requires": { - "builtin-modules": "^1.1.1", "contains-path": "^0.1.0", - "debug": "^2.2.0", + "debug": "^2.6.8", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.2.0", - "eslint-module-utils": "^2.0.0", + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.2.0", "has": "^1.0.1", - "lodash.cond": "^4.3.0", + "lodash": "^4.17.4", "minimatch": "^3.0.3", - "pkg-up": "^1.0.0" + "read-pkg-up": "^2.0.0", + "resolve": "^1.6.0" }, "dependencies": { "doctrine": { @@ -3317,86 +2767,138 @@ "isarray": "^1.0.0" } }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } } } }, "eslint-plugin-node": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-4.2.3.tgz", - "integrity": "sha512-vIUQPuwbVYdz/CYnlTLsJrRy7iXHQjdEe5wz0XhhdTym3IInM/zZLlPf9nZ2mThsH0QcsieCOWs2vOeCy/22LQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-8.0.0.tgz", + "integrity": "sha512-Y+ln8iQ52scz9+rSPnSWRaAxeWaoJZ4wIveDR0vLHkuSZGe44Vk1J4HX7WvEP5Cm+iXPE8ixo7OM7gAO3/OKpQ==", "dev": true, "requires": { - "ignore": "^3.0.11", - "minimatch": "^3.0.2", - "object-assign": "^4.0.1", - "resolve": "^1.1.7", - "semver": "5.3.0" + "eslint-plugin-es": "^1.3.1", + "eslint-utils": "^1.3.1", + "ignore": "^5.0.2", + "minimatch": "^3.0.4", + "resolve": "^1.8.1", + "semver": "^5.5.0" }, "dependencies": { + "ignore": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.0.4.tgz", + "integrity": "sha512-WLsTMEhsQuXpCiG173+f3aymI43SXa+fB1rSfbzyP4GkPP+ZFVuO0/3sFUGNBtifisPeDcl/uD/Y2NxZ7xFq4g==", + "dev": true + }, "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true } } }, "eslint-plugin-promise": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz", - "integrity": "sha1-ePu2/+BHIBYnVp6FpsU3OvKmj8o=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz", + "integrity": "sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==", + "dev": true + }, + "eslint-plugin-standard": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz", + "integrity": "sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==", "dev": true }, - "eslint-plugin-react": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz", - "integrity": "sha1-xUNb6wZ3ThLH2y9qut3L+QDNP3g=", + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { - "array.prototype.find": "^2.0.1", - "doctrine": "^1.2.2", - "has": "^1.0.1", - "jsx-ast-utils": "^1.3.4", - "object.assign": "^4.0.4" - }, - "dependencies": { - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, - "eslint-plugin-standard": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", - "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", "dev": true }, "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", + "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", "dev": true, "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" + "acorn": "^6.0.2", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + }, + "dependencies": { + "acorn": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz", + "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==", + "dev": true + } } }, "esprima": { @@ -3441,16 +2943,6 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "eventemitter3": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", @@ -3472,12 +2964,6 @@ "strip-eof": "^1.0.0" } }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, "expand-braces": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", @@ -3632,15 +3118,6 @@ "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==", "dev": true }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", @@ -3668,6 +3145,17 @@ } } }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -3733,18 +3221,6 @@ } } }, - "extract-zip": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", - "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", - "dev": true, - "requires": { - "concat-stream": "1.6.2", - "debug": "2.6.9", - "mkdirp": "0.5.1", - "yauzl": "2.4.1" - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -3763,17 +3239,6 @@ "object-keys": "^1.0.6" } }, - "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "time-stamp": "^1.0.0" - } - }, "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", @@ -3792,23 +3257,13 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "^1.0.5" } }, "file-entry-cache": { @@ -3879,18 +3334,6 @@ } } }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true - }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -3901,43 +3344,6 @@ "pinkie-promise": "^2.0.0" } }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", - "dev": true - }, "flat-cache": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", @@ -3948,14 +3354,6 @@ "del": "^2.0.2", "graceful-fs": "^4.1.2", "write": "^0.2.1" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } } }, "follow-redirects": { @@ -4003,15 +3401,6 @@ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, "foreach": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", @@ -4024,17 +3413,6 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.12" - } - }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -4044,48 +3422,21 @@ "map-cache": "^0.2.2" } }, + "fs-access": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "dev": true, + "requires": { + "null-check": "^1.0.0" + } + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "dev": true }, - "fs-extra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", - "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "fs-readfile-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fs-readfile-promise/-/fs-readfile-promise-2.0.1.tgz", - "integrity": "sha1-gAI4I5gfn//+AWCei+Zo9prknnA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4133,14 +3484,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4160,8 +3509,7 @@ "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", @@ -4309,7 +3657,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4631,6 +3978,12 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -4647,36 +4000,6 @@ "wide-align": "^1.1.0" } }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "~0.1.0" - } - }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "^1.0.0" - } - }, - "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", - "dev": true - }, "get-stream": { "version": "3.0.0", "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -4719,9 +4042,9 @@ "dev": true }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -4785,111 +4108,10 @@ } } }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" - }, - "dependencies": { - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "^1.0.0" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - } - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "^0.5.1" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "^0.1.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", + "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", "dev": true }, "globby": { @@ -4906,634 +4128,150 @@ "pinkie-promise": "^2.0.0" } }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "handlebars": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", + "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", "dev": true, "requires": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" + "async": "^2.5.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" }, "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" + "lodash": "^4.17.10" } }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" - } } } }, - "glogg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", - "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "natives": "^1.1.0" + "function-bind": "^1.1.1" } }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" + "ansi-regex": "^2.0.0" } }, - "gulp-babel": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-8.0.0.tgz", - "integrity": "sha512-oomaIqDXxFkg7lbpBou/gnUkX51/Y/M2ZfSjL2hdqXTAlSWZcgZtd2o0cOH0r/eE8LWD0+Q/PsLsr2DKOoqToQ==", + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dev": true, "requires": { - "plugin-error": "^1.0.1", - "replace-ext": "^1.0.0", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" + "isarray": "2.0.1" }, "dependencies": { - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true } } }, - "gulp-chmod": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz", - "integrity": "sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw=", + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "deep-assign": "^1.0.0", - "stat-mode": "^0.2.0", - "through2": "^2.0.0" + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" } }, - "gulp-cli": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-1.4.0.tgz", - "integrity": "sha1-b1u+LNC9tISdEs+eEkalhh+LT4g=", - "dev": true, - "requires": { - "archy": "^1.0.0", - "chalk": "^1.1.0", - "copy-props": "^1.4.1", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.3.0", - "lodash.isfunction": "^3.0.8", - "lodash.isplainobject": "^4.0.4", - "lodash.sortby": "^4.5.0", - "matchdep": "^1.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "semver-greatest-satisfied-range": "^1.0.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.9", - "wreck": "^6.3.0", - "yargs": "^3.28.0" - } - }, - "gulp-concat": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", - "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "is-buffer": "^1.1.5" } } } }, - "gulp-header": { - "version": "1.8.12", - "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", - "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", - "dev": true, - "requires": { - "concat-with-sourcemaps": "*", - "lodash.template": "^4.4.0", - "through2": "^2.0.0" - }, - "dependencies": { - "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0" - } - } - } - }, - "gulp-rename": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", - "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", - "dev": true - }, - "gulp-size": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/gulp-size/-/gulp-size-2.1.0.tgz", - "integrity": "sha1-HCtk8X+QcdWr2Z0VS3s0gfj7oSg=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "gulp-util": "^3.0.0", - "gzip-size": "^3.0.0", - "object-assign": "^4.0.1", - "pretty-bytes": "^3.0.1", - "stream-counter": "^1.0.0", - "through2": "^2.0.0" - } - }, - "gulp-sourcemaps": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", - "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", - "dev": true, - "requires": { - "@gulp-sourcemaps/identity-map": "1.X", - "@gulp-sourcemaps/map-sources": "1.X", - "acorn": "5.X", - "convert-source-map": "1.X", - "css": "2.X", - "debug-fabulous": "1.X", - "detect-newline": "2.X", - "graceful-fs": "4.X", - "source-map": "~0.6.0", - "strip-bom-string": "1.X", - "through2": "2.X" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "gulp-standard": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/gulp-standard/-/gulp-standard-10.1.2.tgz", - "integrity": "sha512-w+VBktDzONh807qzV5FvngPgmzuGRWu7oMlIpIvOOmSPlyy/ixM138DGOuMWy1M9bRVMDKEfQSj0aGB2ZjzQSA==", - "dev": true, - "requires": { - "app-root-path": "^2.0.0", - "colors": "^1.1.2", - "log-symbols": "^1.0.2", - "path": "^0.12.7", - "plugin-error": "^1.0.0", - "standard": "^10.0.0", - "through2": "^2.0.0" - }, - "dependencies": { - "standard": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/standard/-/standard-10.0.3.tgz", - "integrity": "sha512-JURZ+85ExKLQULckDFijdX5WHzN6RC7fgiZNSV4jFQVo+3tPoQGHyBrGekye/yf0aOfb4210EM5qPNlc2cRh4w==", - "dev": true, - "requires": { - "eslint": "~3.19.0", - "eslint-config-standard": "10.2.1", - "eslint-config-standard-jsx": "4.0.2", - "eslint-plugin-import": "~2.2.0", - "eslint-plugin-node": "~4.2.2", - "eslint-plugin-promise": "~3.5.0", - "eslint-plugin-react": "~6.10.0", - "eslint-plugin-standard": "~3.0.1", - "standard-engine": "~7.0.0" - } - } - } - }, - "gulp-trimlines": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gulp-trimlines/-/gulp-trimlines-1.0.1.tgz", - "integrity": "sha1-exeRa4UMoPBa9BkN0k6aweJunyY=", - "dev": true, - "requires": { - "through2": "^0.6.3" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - } - } - }, - "gulp-uglify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-2.1.2.tgz", - "integrity": "sha1-bbhbHQ7mPRgFhZK2WGSdZcLsRUE=", - "dev": true, - "requires": { - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash": "^4.13.1", - "make-error-cause": "^1.1.1", - "through2": "^2.0.0", - "uglify-js": "~2.8.10", - "uglify-save-license": "^0.4.1", - "vinyl-sourcemaps-apply": "^0.2.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - } - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, - "dependencies": { - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - } - } - }, - "gulp-wrap": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/gulp-wrap/-/gulp-wrap-0.13.0.tgz", - "integrity": "sha1-kPsLSieiZkM4Mv98YSLbXB7olMY=", - "dev": true, - "requires": { - "consolidate": "^0.14.1", - "es6-promise": "^3.1.2", - "fs-readfile-promise": "^2.0.1", - "gulp-util": "^3.0.3", - "js-yaml": "^3.2.6", - "lodash": "^4.11.1", - "node.extend": "^1.1.2", - "through2": "^2.0.1", - "tryit": "^1.0.1", - "vinyl-bufferstream": "^1.0.1" - }, - "dependencies": { - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "gzip-size": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", - "integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=", - "dev": true, - "requires": { - "duplexer": "^0.1.1" - } - }, - "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, - "requires": { - "async": "^1.4.0", - "optimist": "^0.6.1", - "source-map": "^0.4.4", - "uglify-js": "^2.6" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "requires": { - "chalk": "^1.1.1", - "commander": "^2.9.0", - "is-my-json-valid": "^2.12.4", - "pinkie-promise": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-binary": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz", - "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hasha": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", - "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", - "dev": true, - "requires": { - "is-stream": "^1.0.1", - "pinkie-promise": "^2.0.0" - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" - } - }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, "hosted-git-info": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.1.tgz", @@ -5542,7 +4280,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -5587,30 +4325,19 @@ } } }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } }, "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, "iltorb": { @@ -5675,69 +4402,101 @@ "dev": true }, "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", + "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", "dev": true, "requires": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", + "external-editor": "^3.0.0", + "figures": "^2.0.0", + "lodash": "^4.17.10", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.1.0", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", "through": "^2.3.6" }, "dependencies": { - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true - } - } - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", - "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=", - "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" + "loose-envify": "^1.0.0" } }, "is-accessor-descriptor": { @@ -5790,12 +4549,6 @@ "builtin-modules": "^1.0.0" } }, - "is-callable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", - "dev": true - }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -5816,12 +4569,6 @@ } } }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -5886,34 +4633,6 @@ "number-is-nan": "^1.0.0" } }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true - }, - "is-my-json-valid": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", - "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", - "dev": true, - "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^4.0.0", - "xtend": "^4.0.0" - } - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -5991,30 +4710,6 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "^1.0.1" - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", @@ -6027,27 +4722,12 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, - "is-symbol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -6067,10 +4747,13 @@ "dev": true }, "isbinaryfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", - "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } }, "isexe": { "version": "2.0.0", @@ -6143,9 +4826,9 @@ } }, "jasmine-core": { - "version": "2.99.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz", - "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.3.0.tgz", + "integrity": "sha512-3/xSmG/d35hf80BEN66Y6g9Ca5l/Isdeg/j6zvbTYlTzeKinzmaTM4p9am5kYqOmE05D7s1t8FGjzdSnbUbceA==", "dev": true }, "jest-worker": { @@ -6192,12 +4875,6 @@ "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", "dev": true }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -6210,14 +4887,11 @@ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, - "json-stable-stringify": { + "json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true }, "json-stringify-safe": { "version": "5.0.1", @@ -6225,48 +4899,12 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, "json5": { "version": "0.5.1", "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true, - "optional": true - } - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -6287,21 +4925,15 @@ } } }, - "jsx-ast-utils": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", - "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", - "dev": true - }, "karma": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz", - "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.1.tgz", + "integrity": "sha512-NetT3wPCQMNB36uiL9LLyhrOt8SQwrEKt0xD3+KpTCfm0VxVyUJdPL5oTq2Ic5ouemgL/Iz4wqXEbF3zea9kQQ==", "dev": true, "requires": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", - "chokidar": "^1.4.1", + "chokidar": "^2.0.3", "colors": "^1.1.0", "combine-lists": "^1.0.0", "connect": "^3.6.0", @@ -6313,35 +4945,57 @@ "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^3.8.0", - "log4js": "^0.6.31", - "mime": "^1.3.4", + "lodash": "^4.17.4", + "log4js": "^3.0.0", + "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", "qjobs": "^1.1.4", "range-parser": "^1.2.0", "rimraf": "^2.6.0", "safe-buffer": "^5.0.1", - "socket.io": "1.7.3", - "source-map": "^0.5.3", - "tmp": "0.0.31", - "useragent": "^2.1.12" + "socket.io": "2.1.1", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.2.1" }, "dependencies": { "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "mime": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } }, + "karma-chrome-launcher": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", + "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "dev": true, + "requires": { + "fs-access": "^1.0.0", + "which": "^1.2.1" + } + }, "karma-coverage": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-1.1.2.tgz", @@ -6372,9 +5026,9 @@ "dev": true }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true } } @@ -6391,69 +5045,12 @@ "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=", "dev": true }, - "karma-phantomjs-launcher": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/karma-phantomjs-launcher/-/karma-phantomjs-launcher-1.0.4.tgz", - "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", - "dev": true, - "requires": { - "lodash": "^4.0.1", - "phantomjs-prebuilt": "^2.1.7" - }, - "dependencies": { - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - } - } - }, - "kew": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", - "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", - "dev": true - }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true, - "optional": true - } - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "lcov-parse": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", @@ -6470,44 +5067,22 @@ "type-check": "~0.3.2" } }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", + "parse-json": "^2.2.0", + "pify": "^2.0.0", "strip-bom": "^3.0.0" }, "dependencies": { "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, "strip-bom": { @@ -6537,199 +5112,59 @@ } }, "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash.cond": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", - "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", - "dev": true - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "^3.0.0" - } - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" - } - }, "log-driver": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", - "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", "dev": true }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, - "requires": { - "chalk": "^1.0.0" - } - }, "log4js": { - "version": "0.6.38", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz", - "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { - "readable-stream": "~1.0.2", - "semver": "~4.3.3" + "circular-json": "^0.5.5", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "rfdc": "^1.1.2", + "streamroller": "0.7.0" }, "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "circular-json": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -6749,21 +5184,6 @@ "signal-exit": "^3.0.0" } }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } - }, "magic-string": { "version": "0.22.5", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", @@ -6773,30 +5193,6 @@ "vlq": "^0.2.2" } }, - "make-error": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", - "dev": true - }, - "make-error-cause": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", - "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true, - "requires": { - "make-error": "^1.2.0" - } - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -6808,145 +5204,14 @@ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "matchdep": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-1.0.1.tgz", - "integrity": "sha1-pXozgESR+64girqPaDgEN6vC3KU=", - "dev": true, - "requires": { - "findup-sync": "~0.3.0", - "micromatch": "^2.3.7", - "resolve": "~1.1.6", - "stack-trace": "0.0.9" - }, - "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "findup-sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", - "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", - "dev": true, - "requires": { - "glob": "~5.0.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" } }, "math-random": { @@ -6957,26 +5222,10 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, - "memoizee": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.45", - "es6-weak-map": "^2.0.2", - "event-emitter": "^0.3.5", - "is-promise": "^2.1", - "lru-queue": "0.1", - "next-tick": "1", - "timers-ext": "^0.1.5" - } - }, "meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", @@ -7073,20 +5322,26 @@ "dev": true }, "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", "dev": true }, "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", "dev": true, "requires": { - "mime-db": "~1.33.0" + "mime-db": "~1.37.0" } }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -7152,31 +5407,16 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - } - }, - "mute-stdout": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.0.tgz", - "integrity": "sha1-WzLqB+tDyd7WEwQ0z5JvRrKn/U0=", - "dev": true - }, "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", "dev": true, "optional": true }, @@ -7205,12 +5445,6 @@ "integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==", "dev": true }, - "natives": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.4.tgz", - "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==", - "dev": true - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -7223,10 +5457,10 @@ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "node-abi": { @@ -7263,15 +5497,6 @@ } } }, - "node.extend": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", - "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", - "dev": true, - "requires": { - "is": "^3.1.0" - } - }, "noop-logger": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", @@ -7329,18 +5554,18 @@ "set-blocking": "~2.0.0" } }, + "null-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", + "dev": true + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7405,40 +5630,6 @@ "isobject": "^3.0.0" } }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", @@ -7488,10 +5679,13 @@ } }, "onetime": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } }, "opener": { "version": "1.4.3", @@ -7537,44 +5731,12 @@ "wordwrap": "~1.0.0" } }, - "options": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", - "dev": true - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" - } - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -7617,17 +5779,6 @@ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", "dev": true }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -7658,28 +5809,12 @@ } }, "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parsejson": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz", - "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "better-assert": "~1.0.0" + "error-ex": "^1.2.0" } }, "parseqs": { @@ -7712,15 +5847,11 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, - "path": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", - "dev": true, - "requires": { - "process": "^0.11.1", - "util": "^0.10.3" - } + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true }, "path-exists": { "version": "2.1.0", @@ -7755,21 +5886,6 @@ "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", "dev": true }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", @@ -7789,43 +5905,12 @@ } } }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "phantomjs-prebuilt": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", - "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3", - "extract-zip": "^1.6.5", - "fs-extra": "^1.0.0", - "hasha": "^2.2.0", - "kew": "^0.7.0", - "progress": "^1.1.8", - "request": "^2.81.0", - "request-progress": "^2.0.1", - "which": "^1.2.10" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", - "dev": true - } - } - }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -7847,38 +5932,6 @@ "pinkie": "^2.0.0" } }, - "pkg-conf": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", - "integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "load-json-file": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - } - } - }, - "pkg-config": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", - "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", - "dev": true, - "requires": { - "debug-log": "^1.0.0", - "find-root": "^1.0.0", - "xtend": "^4.0.1" - } - }, "pkg-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", @@ -7888,31 +5941,10 @@ "find-up": "^1.0.0" } }, - "pkg-up": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", - "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } - }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - } - }, "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, "portfinder": { @@ -7979,33 +6011,12 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, - "pretty-bytes": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz", - "integrity": "sha1-J9AAjXeAY6C0gRuzXHnxvV1fvM8=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -8013,9 +6024,9 @@ "dev": true }, "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz", + "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==", "dev": true }, "pseudomap": { @@ -8064,9 +6075,9 @@ "dev": true }, "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, "quote-stream": { @@ -8115,6 +6126,17 @@ "http-errors": "1.6.3", "iconv-lite": "0.4.23", "unpipe": "1.0.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } } }, "rc": { @@ -8189,34 +6211,21 @@ "read-pkg": "^1.0.0" } }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" }, "dependencies": { "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, "isarray": { @@ -8227,7 +6236,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -8251,26 +6260,6 @@ } } }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "mute-stream": "0.0.5" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", @@ -8330,6 +6319,12 @@ "safe-regex": "^1.1.0" } }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, "regexpu-core": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.2.0.tgz", @@ -8394,12 +6389,6 @@ "is-finite": "^1.0.0" } }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -8556,15 +6545,6 @@ } } }, - "request-progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", - "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", - "dev": true, - "requires": { - "throttleit": "^1.0.0" - } - }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -8590,16 +6570,6 @@ "path-parse": "^1.0.5" } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, "resolve-from": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", @@ -8613,13 +6583,13 @@ "dev": true }, "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" } }, "restructure": { @@ -8637,14 +6607,11 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "^0.1.1" - } + "rfdc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "dev": true }, "rimraf": { "version": "2.6.2", @@ -8656,9 +6623,9 @@ } }, "rollup": { - "version": "0.66.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.66.6.tgz", - "integrity": "sha512-J7/SWanrcb83vfIHqa8+aVVGzy457GcjA6GVZEnD0x2u4OnOd0Q1pCrEoNe8yLwM6z6LZP02zBT2uW0yh5TqOw==", + "version": "0.67.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.67.0.tgz", + "integrity": "sha512-p34buXxArhwv9ieTdHvdhdo65Cbig68s/Z8llbZuiX5e+3zCqnBF02Ck9IH0tECrmvvrJVMws32Ry84hTnS1Tw==", "dev": true, "requires": { "@types/estree": "0.0.39", @@ -8723,6 +6690,34 @@ } } }, + "rollup-plugin-progress": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-progress/-/rollup-plugin-progress-0.4.0.tgz", + "integrity": "sha1-7AtO4zlkNGRUEjJykmKLh7O0Tx4=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "rollup-pluginutils": "^1.5.1" + }, + "dependencies": { + "estree-walker": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.2.1.tgz", + "integrity": "sha1-va/oCVOD2EFNXcLs9MkXO225QS4=", + "dev": true + }, + "rollup-pluginutils": { + "version": "1.5.2", + "resolved": "http://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz", + "integrity": "sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg=", + "dev": true, + "requires": { + "estree-walker": "^0.2.1", + "minimatch": "^3.0.2" + } + } + } + }, "rollup-plugin-uglify": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/rollup-plugin-uglify/-/rollup-plugin-uglify-6.0.0.tgz", @@ -8861,25 +6856,22 @@ } }, "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "once": "^1.3.0" + "is-promise": "^2.1.0" } }, - "run-parallel": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true - }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } }, "safe-buffer": { "version": "5.1.2", @@ -8908,25 +6900,10 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } - }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", "dev": true }, "serialize-javascript": { @@ -8941,12 +6918,6 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", @@ -8997,23 +6968,6 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -9038,10 +6992,21 @@ } }, "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } }, "snapdragon": { "version": "0.8.2", @@ -9150,194 +7115,94 @@ } } }, - "snazzy": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/snazzy/-/snazzy-6.0.0.tgz", - "integrity": "sha1-ahfUeYy7yLxuETFTaUkHqLrJSU0=", - "dev": true, - "requires": { - "chalk": "^1.1.0", - "inherits": "^2.0.1", - "minimist": "^1.1.1", - "readable-stream": "^2.0.6", - "standard": "*", - "standard-json": "^1.0.0", - "text-table": "^0.2.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { - "hoek": "2.x.x" - } - }, - "socket.io": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.7.3.tgz", - "integrity": "sha1-uK+cq6AJSeVo42nxMn6pvp6iRhs=", - "dev": true, - "requires": { - "debug": "2.3.3", - "engine.io": "1.8.3", - "has-binary": "0.1.7", - "object-assign": "4.1.0", - "socket.io-adapter": "0.5.0", - "socket.io-client": "1.7.3", - "socket.io-parser": "2.3.1" + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" }, "dependencies": { "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.2" + "ms": "2.0.0" } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - }, - "object-assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", - "dev": true } } }, "socket.io-adapter": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz", - "integrity": "sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s=", - "dev": true, - "requires": { - "debug": "2.3.3", - "socket.io-parser": "2.3.1" - }, - "dependencies": { - "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", - "dev": true, - "requires": { - "ms": "0.7.2" - } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } - } + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true }, "socket.io-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.3.tgz", - "integrity": "sha1-sw6GqhDV7zVGYBwJzeR2Xjgdo3c=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "2.3.3", - "engine.io-client": "1.8.3", - "has-binary": "0.1.7", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", + "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "2.3.1", + "socket.io-parser": "~3.2.0", "to-array": "0.1.4" }, "dependencies": { "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.2" + "ms": "2.0.0" } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true } } }, "socket.io-parser": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz", - "integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { - "component-emitter": "1.1.2", - "debug": "2.2.0", - "isarray": "0.0.1", - "json3": "3.3.2" + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" }, "dependencies": { - "component-emitter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", - "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=", - "dev": true - }, "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "2.0.0" } }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true } } @@ -9385,12 +7250,6 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, "spdx-correct": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", @@ -9463,186 +7322,6 @@ } } }, - "stack-trace": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", - "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=", - "dev": true - }, - "standard": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/standard/-/standard-9.0.2.tgz", - "integrity": "sha1-m9O5RnSS4hKxkU14VTlD/5tI/Zk=", - "dev": true, - "requires": { - "eslint": "~3.18.0", - "eslint-config-standard": "7.1.0", - "eslint-config-standard-jsx": "3.3.0", - "eslint-plugin-promise": "~3.4.0", - "eslint-plugin-react": "~6.9.0", - "eslint-plugin-standard": "~2.0.1", - "standard-engine": "~5.4.0" - }, - "dependencies": { - "eslint": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.18.0.tgz", - "integrity": "sha1-ZH6YXErnFQLSCsYsEJ9m1RBMiks=", - "dev": true, - "requires": { - "babel-code-frame": "^6.16.0", - "chalk": "^1.1.3", - "concat-stream": "^1.5.2", - "debug": "^2.1.1", - "doctrine": "^2.0.0", - "escope": "^3.6.0", - "espree": "^3.4.0", - "esquery": "^1.0.0", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "glob": "^7.0.3", - "globals": "^9.14.0", - "ignore": "^3.2.0", - "imurmurhash": "^0.1.4", - "inquirer": "^0.12.0", - "is-my-json-valid": "^2.10.0", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.5.1", - "json-stable-stringify": "^1.0.0", - "levn": "^0.3.0", - "lodash": "^4.0.0", - "mkdirp": "^0.5.0", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.1", - "pluralize": "^1.2.1", - "progress": "^1.1.8", - "require-uncached": "^1.0.2", - "shelljs": "^0.7.5", - "strip-bom": "^3.0.0", - "strip-json-comments": "~2.0.1", - "table": "^3.7.8", - "text-table": "~0.2.0", - "user-home": "^2.0.0" - } - }, - "eslint-config-standard": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-7.1.0.tgz", - "integrity": "sha1-R+dp6gc59bLVaTsaUBwhyWUPr88=", - "dev": true - }, - "eslint-config-standard-jsx": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-3.3.0.tgz", - "integrity": "sha1-yrCAGhWjYL9j+suXqyL73YjYpeA=", - "dev": true - }, - "eslint-plugin-promise": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.4.2.tgz", - "integrity": "sha1-G+J5Pq/i0YtbEjuBNsJp+AT+cSI=", - "dev": true - }, - "eslint-plugin-react": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.9.0.tgz", - "integrity": "sha1-VMLpkGt2+dEBQgML3DTp1oQKC7I=", - "dev": true, - "requires": { - "array.prototype.find": "^2.0.1", - "doctrine": "^1.2.2", - "jsx-ast-utils": "^1.3.4" - }, - "dependencies": { - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - } - } - }, - "eslint-plugin-standard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-2.0.1.tgz", - "integrity": "sha1-NYlpn/nJF/LCX3apFmh/ZBw2n/M=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - }, - "standard-engine": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-5.4.0.tgz", - "integrity": "sha1-4OhpWeoHhkJdM4PkDBv3DS+YVXk=", - "dev": true, - "requires": { - "deglob": "^2.1.0", - "get-stdin": "^5.0.1", - "home-or-tmp": "^2.0.0", - "minimist": "^1.1.0", - "pkg-conf": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - } - } - }, - "standard-engine": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-7.0.0.tgz", - "integrity": "sha1-67d7nI/CyBZf+jU72Rug3/Qa9pA=", - "dev": true, - "requires": { - "deglob": "^2.1.0", - "get-stdin": "^5.0.1", - "minimist": "^1.1.0", - "pkg-conf": "^2.0.0" - } - }, - "standard-json": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/standard-json/-/standard-json-1.0.3.tgz", - "integrity": "sha512-lhMP+KREBcfyyMe2ObJlEjJ0lc0ItA9uny83d9ZL6ggYtB79DuaAKCxJVoiflg5EV3D2rpuWn+n4+zXjWXk0sQ==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0" - } - }, - "stat-mode": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", - "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", - "dev": true - }, "static-eval": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.0.tgz", @@ -9710,28 +7389,100 @@ "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", "dev": true, "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "streamroller": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "dev": true, + "requires": { + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" } }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -9744,13 +7495,6 @@ "util-deprecate": "~1.0.1" } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -9762,24 +7506,6 @@ } } }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", - "dev": true - }, - "stream-counter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-1.0.0.tgz", - "integrity": "sha1-kc8lac5NxQYf6816yyY5SloRR1E=", - "dev": true - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -9791,18 +7517,6 @@ "strip-ansi": "^3.0.0" } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -9812,22 +7526,6 @@ "ansi-regex": "^2.0.0" } }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "^1.0.0", - "is-utf8": "^0.2.0" - } - }, - "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", - "dev": true - }, "strip-eof": { "version": "1.0.0", "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -9863,16 +7561,6 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, "svgdom": { "version": "0.0.15", "resolved": "https://registry.npmjs.org/svgdom/-/svgdom-0.0.15.tgz", @@ -9886,17 +7574,15 @@ } }, "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz", + "integrity": "sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg==", "dev": true, "requires": { - "ajv": "^4.7.0", - "ajv-keywords": "^1.0.0", - "chalk": "^1.1.1", - "lodash": "^4.0.0", - "slice-ansi": "0.0.4", - "string-width": "^2.0.0" + "ajv": "^6.5.3", + "lodash": "^4.17.10", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" }, "dependencies": { "ansi-regex": { @@ -9911,12 +7597,6 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -10067,12 +7747,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -10121,44 +7795,6 @@ } } }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" - }, - "dependencies": { - "es5-ext": { - "version": "0.10.46", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "1" - } - } - } - }, "tiny-inflate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.2.tgz", @@ -10166,12 +7802,12 @@ "dev": true }, "tmp": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", - "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "os-tmpdir": "~1.0.1" + "os-tmpdir": "~1.0.2" } }, "to-array": { @@ -10234,15 +7870,6 @@ "repeat-string": "^1.6.1" } }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true, - "requires": { - "punycode": "^1.4.1" - } - }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", @@ -10255,16 +7882,10 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, - "tryit": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", - "dev": true - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, "tweetnacl": { @@ -10300,82 +7921,29 @@ "dev": true }, "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", "dev": true, + "optional": true, "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" + "commander": "~2.17.1", + "source-map": "~0.6.1" }, "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } + "optional": true } } }, - "uglify-save-license": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", - "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", - "dev": true - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, "ultron": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", - "dev": true - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", "dev": true }, "unicode-canonical-property-names-ecmascript": { @@ -10478,18 +8046,6 @@ } } }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -10542,6 +8098,29 @@ } } }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -10563,43 +8142,24 @@ "kind-of": "^6.0.2" } }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, "useragent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", + "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", "dev": true, "requires": { - "lru-cache": "4.1.x", + "lru-cache": "2.2.x", "tmp": "0.0.x" }, "dependencies": { "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", + "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", + "dev": true } } }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -10612,21 +8172,6 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", "dev": true }, - "uuid": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.0.tgz", - "integrity": "sha512-ijO9N2xY/YaOqQ5yz5c4sy2ZjWmA6AR6zASb/gdpeKZ8+948CxwfMW9RrKVk5may6ev8c0/Xguu32e2Llelpqw==", - "dev": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "^1.1.1" - } - }, "validate-npm-package-license": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", @@ -10656,91 +8201,6 @@ } } }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-bufferstream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz", - "integrity": "sha1-BTeGn1gO/6TKRay0dXnkuf5jCBo=", - "dev": true, - "requires": { - "bufferstreams": "1.0.1" - } - }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - } - } - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "^0.5.1" - } - }, "vlq": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", @@ -10819,44 +8279,18 @@ } } }, - "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", - "dev": true - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "wreck": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/wreck/-/wreck-6.3.0.tgz", - "integrity": "sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs=", - "dev": true, - "requires": { - "boom": "2.x.x", - "hoek": "2.x.x" - } - }, "write": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", @@ -10867,25 +8301,20 @@ } }, "ws": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.2.tgz", - "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "dev": true, "requires": { - "options": ">=0.0.5", - "ultron": "1.0.x" + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" } }, - "wtf-8": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz", - "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=", - "dev": true - }, "xmlhttprequest-ssl": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz", - "integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", "dev": true }, "xtend": { @@ -10894,42 +8323,12 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, - "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "dev": true, - "requires": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" - } - }, - "yauzl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", - "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", - "dev": true, - "requires": { - "fd-slicer": "~1.0.1" - } - }, "yeast": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", diff --git a/package.json b/package.json index d26147f..0a5de2c 100644 --- a/package.json +++ b/package.json @@ -54,59 +54,39 @@ "license": "MIT", "typings": "./svg.js.d.ts", "scripts": { - "build": "gulp", - "lint": "gulp lint", - "build:test": "gulp unify", - "build:dev": "gulp --dont-break", - "test": "karma start .config/karma.conf.js --single-run", - "test:dots": "karma start .config/karma.conf.js --single-run --reporters dots", - "test:quick": "karma start .config/karma.quick.js", - "server": "http-server ./ -d", - "rollup": "rollup -c" + "build": "npx rollup -c", + "lint": "npx eslint ./src", + "fix": "npx eslint ./src --fix", + "test": "npx karma start .config/karma.conf.js --single-run", + "test:dots": "npx karma start .config/karma.conf.js --single-run --reporters dots", + "test:quick": "npx karma start .config/karma.quick.js", + "server": "npx http-server ./ -d" }, "devDependencies": { "@babel/core": "^7.1.2", "@babel/plugin-external-helpers": "^7.0.0", "@babel/preset-env": "^7.1.0", - "coveralls": "^2.11.15", - "del": "^2.2.0", - "gulp": "^3.8.6", - "gulp-babel": "^8.0.0", - "gulp-chmod": "^2.0.0", - "gulp-cli": "^1.2.2", - "gulp-concat": "^2.3.3", - "gulp-header": "^1.0.5", - "gulp-rename": "^1.4.0", - "gulp-size": "^2.1.0", - "gulp-sourcemaps": "^2.6.4", - "gulp-standard": "^10.1.2", - "gulp-trimlines": "^1.0.0", - "gulp-uglify": "^2.0.0", - "gulp-wrap": "^0.13.0", + "babel-eslint": "^10.0.1", + "coveralls": "^3.0.2", + "eslint": "^5.8.0", + "eslint-config-standard": "^12.0.0", + "eslint-plugin-import": "^2.14.0", + "eslint-plugin-node": "^8.0.0", + "eslint-plugin-promise": "^4.0.1", + "eslint-plugin-standard": "^4.0.0", "http-server": "^0.11.1", - "jasmine-core": "^2.5.2", - "karma": "^1.3.0", - "karma-coverage": "^1.1.1", - "karma-firefox-launcher": "^1.0.0", - "karma-jasmine": "^1.0.2", - "karma-phantomjs-launcher": "^1.0.2", - "request": "^2.88.0", - "rollup": "^0.66.6", + "jasmine-core": "^3.3.0", + "karma": "^3.1.1", + "karma-chrome-launcher": "^2.2.0", + "karma-coverage": "^1.1.2", + "karma-firefox-launcher": "^1.1.0", + "karma-jasmine": "^1.1.2", + "rollup": "^0.67.0", "rollup-plugin-babel": "^4.0.3", "rollup-plugin-filesize": "^5.0.1", + "rollup-plugin-progress": "^0.4.0", "rollup-plugin-uglify": "^6.0.0", - "snazzy": "^6.0.0", - "standard": "^9.0.1", "svgdom": "latest" }, - "standard": { - "ignore": [ - "/dist", - "/spec", - "/src/umd.js" - ], - "globals": [ - "SVG" - ] - } + "dependencies": {} } diff --git a/rollup.config.js b/rollup.config.js index 339328c..3d4f61a 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,6 +1,23 @@ import babel from 'rollup-plugin-babel' import { uglify } from "rollup-plugin-uglify" import filesize from 'rollup-plugin-filesize' +import progress from 'rollup-plugin-progress' +const pkg = require('./package.json') + +const buildDate = Date() + +const headerLong = `/*! +* ${pkg.name} - ${pkg.description} +* @version ${pkg.version} +* ${pkg.homepage} +* +* @copyright ${pkg.author} +* @license ${pkg.license} +* +* BUILT: ${buildDate} +*/;` + +var headerShort = `/*! ${pkg.name} v${pkg.version} ${pkg.license}*/;` export default [{ input: 'src/svg.js', @@ -8,9 +25,11 @@ export default [{ file: 'dist/svg.js', name: 'SVG', sourceMap: true, - format: 'iife' + format: 'iife', + banner: headerLong }, plugins: [ + progress(), babel({ include: 'src/**' }), @@ -22,7 +41,8 @@ export default [{ file: 'dist/svg.min.js', name: 'SVG', sourceMap: true, - format: 'iife' + format: 'iife', + banner: headerShort }, plugins: [ babel({ diff --git a/spec/RAFPlugin.js b/spec/RAFPlugin.js new file mode 100644 index 0000000..2dea383 --- /dev/null +++ b/spec/RAFPlugin.js @@ -0,0 +1,84 @@ +/** + * Jasmine RequestAnimationFrame: a set of helpers for testing funcionality + * that uses requestAnimationFrame under the Jasmine BDD framework for JavaScript. + */ +;(function() { + + var index = 0, + callbacks = []; + + function MockRAF(global) { + this.realRAF = global.requestAnimationFrame, + this.realCAF = global.cancelAnimationFrame, + this.realPerf = global.performance, + this.nextTime = 0 + + var _this = this + + /** + * Mock for window.requestAnimationFrame + */ + this.mockRAF = function(fn) { + if (typeof fn !== 'function') { + throw new Error('You should pass a function to requestAnimationFrame'); + } + + callbacks[index++] = fn; + + return index; + }; + + /** + * Mock for window.cancelAnimationFrame + */ + this.mockCAF = function(requestID) { + callbacks.splice(requestID, 1) + }; + + this.mockPerf = { + now: function () { + return _this.nextTime + } + } + + /** + * Install request animation frame mocks. + */ + this.install = function() { + global.requestAnimationFrame = _this.mockRAF; + global.cancelAnimationFrame = _this.mockCAF; + global.performance = _this.mockPerf; + }; + + /** + * Uninstall request animation frame mocks. + */ + this.uninstall = function() { + global.requestAnimationFrame = _this.realRAF; + global.cancelAnimationFrame = _this.realCAF; + global.performance = _this.realPerf; + _this.nextTime = 0 + callbacks = [] + }; + + /** + * Simulate animation frame readiness. + */ + this.tick = function(dt) { + _this.nextTime += (dt || 1) + + var fns = callbacks, fn, i; + + callbacks = []; + index = 0; + + for (i in fns) { + fn = fns[i]; + fn(_this.nextTime); + } + }; + } + + + jasmine.RequestAnimationFrame = new MockRAF(window); +}()); diff --git a/spec/SpecRunner.html b/spec/SpecRunner.html index 8701a8a..9d84677 100644 --- a/spec/SpecRunner.html +++ b/spec/SpecRunner.html @@ -2,15 +2,15 @@ - SVG.js - Jasmine Spec Runner v2.6.0 + SVG.js - Jasmine Spec Runner - - + + - - - - + + + + diff --git a/spec/lib/RAFPlugin.js b/spec/lib/RAFPlugin.js deleted file mode 100644 index fefdda6..0000000 --- a/spec/lib/RAFPlugin.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Jasmine RequestAnimationFrame: a set of helpers for testing funcionality - * that uses requestAnimationFrame under the Jasmine BDD framework for JavaScript. - */ -;(function() { - - var index = 0, - callbacks = []; - - function MockRAF(global) { - this.realRAF = global.requestAnimationFrame, - this.realCAF = global.cancelAnimationFrame, - this.realPerf = global.performance, - this.nextTime = 0 - - var _this = this - - /** - * Mock for window.requestAnimationFrame - */ - this.mockRAF = function(fn) { - if (typeof fn !== 'function') { - throw new Error('You should pass a function to requestAnimationFrame'); - } - - callbacks[index++] = fn; - - return index; - }; - - /** - * Mock for window.cancelAnimationFrame - */ - this.mockCAF = function(requestID) { - callbacks.splice(requestID, 1) - }; - - this.mockPerf = { - now: function () { - return _this.nextTime - } - } - - /** - * Install request animation frame mocks. - */ - this.install = function() { - global.requestAnimationFrame = _this.mockRAF; - global.cancelAnimationFrame = _this.mockCAF; - global.performance = _this.mockPerf; - }; - - /** - * Uninstall request animation frame mocks. - */ - this.uninstall = function() { - global.requestAnimationFrame = _this.realRAF; - global.cancelAnimationFrame = _this.realCAF; - global.performance = _this.realPerf; - }; - - /** - * Simulate animation frame readiness. - */ - this.tick = function(dt) { - _this.nextTime += (dt || 1) - - var fns = callbacks, fn, i; - - callbacks = []; - index = 0; - - for (i in fns) { - fn = fns[i]; - fn(_this.nextTime); - } - }; - } - - - jasmine.RequestAnimationFrame = new MockRAF(window); -}()); diff --git a/spec/lib/jasmine-2.6.0/boot.js b/spec/lib/jasmine-2.6.0/boot.js deleted file mode 100644 index d9b5a80..0000000 --- a/spec/lib/jasmine-2.6.0/boot.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. - - If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms. - - The location of `boot.js` can be specified and/or overridden in `jasmine.yml`. - - [jasmine-gem]: http://github.com/pivotal/jasmine-gem - */ - -(function() { - - /** - * ## Require & Instantiate - * - * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. - */ - window.jasmine = jasmineRequire.core(jasmineRequire); - - /** - * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. - */ - jasmineRequire.html(jasmine); - - /** - * Create the Jasmine environment. This is used to run all specs in a project. - */ - var env = jasmine.getEnv(); - - /** - * ## The Global Interface - * - * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged. - */ - var jasmineInterface = jasmineRequire.interface(jasmine, env); - - /** - * Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. - */ - extend(window, jasmineInterface); - - /** - * ## Runner Parameters - * - * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface. - */ - - var queryString = new jasmine.QueryString({ - getWindowLocation: function() { return window.location; } - }); - - var filterSpecs = !!queryString.getParam("spec"); - - var catchingExceptions = queryString.getParam("catch"); - env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); - - var throwingExpectationFailures = queryString.getParam("throwFailures"); - env.throwOnExpectationFailure(throwingExpectationFailures); - - var random = queryString.getParam("random"); - env.randomizeTests(random); - - var seed = queryString.getParam("seed"); - if (seed) { - env.seed(seed); - } - - /** - * ## Reporters - * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any). - */ - var htmlReporter = new jasmine.HtmlReporter({ - env: env, - onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); }, - onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); }, - onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); }, - addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); }, - getContainer: function() { return document.body; }, - createElement: function() { return document.createElement.apply(document, arguments); }, - createTextNode: function() { return document.createTextNode.apply(document, arguments); }, - timer: new jasmine.Timer(), - filterSpecs: filterSpecs - }); - - /** - * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript. - */ - env.addReporter(jasmineInterface.jsApiReporter); - env.addReporter(htmlReporter); - - /** - * Filter which specs will be run by matching the start of the full name against the `spec` query param. - */ - var specFilter = new jasmine.HtmlSpecFilter({ - filterString: function() { return queryString.getParam("spec"); } - }); - - env.specFilter = function(spec) { - return specFilter.matches(spec.getFullName()); - }; - - /** - * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack. - */ - window.setTimeout = window.setTimeout; - window.setInterval = window.setInterval; - window.clearTimeout = window.clearTimeout; - window.clearInterval = window.clearInterval; - - /** - * ## Execution - * - * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded. - */ - var currentWindowOnload = window.onload; - - window.onload = function() { - if (currentWindowOnload) { - currentWindowOnload(); - } - htmlReporter.initialize(); - env.execute(); - }; - - /** - * Helper function for readability above. - */ - function extend(destination, source) { - for (var property in source) destination[property] = source[property]; - return destination; - } - -}()); diff --git a/spec/lib/jasmine-2.6.0/console.js b/spec/lib/jasmine-2.6.0/console.js deleted file mode 100644 index 38ad952..0000000 --- a/spec/lib/jasmine-2.6.0/console.js +++ /dev/null @@ -1,190 +0,0 @@ -/* -Copyright (c) 2008-2017 Pivotal Labs - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -function getJasmineRequireObj() { - if (typeof module !== 'undefined' && module.exports) { - return exports; - } else { - window.jasmineRequire = window.jasmineRequire || {}; - return window.jasmineRequire; - } -} - -getJasmineRequireObj().console = function(jRequire, j$) { - j$.ConsoleReporter = jRequire.ConsoleReporter(); -}; - -getJasmineRequireObj().ConsoleReporter = function() { - - var noopTimer = { - start: function(){}, - elapsed: function(){ return 0; } - }; - - function ConsoleReporter(options) { - var print = options.print, - showColors = options.showColors || false, - onComplete = options.onComplete || function() {}, - timer = options.timer || noopTimer, - specCount, - failureCount, - failedSpecs = [], - pendingCount, - ansi = { - green: '\x1B[32m', - red: '\x1B[31m', - yellow: '\x1B[33m', - none: '\x1B[0m' - }, - failedSuites = []; - - print('ConsoleReporter is deprecated and will be removed in a future version.'); - - this.jasmineStarted = function() { - specCount = 0; - failureCount = 0; - pendingCount = 0; - print('Started'); - printNewline(); - timer.start(); - }; - - this.jasmineDone = function() { - printNewline(); - for (var i = 0; i < failedSpecs.length; i++) { - specFailureDetails(failedSpecs[i]); - } - - if(specCount > 0) { - printNewline(); - - var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' + - failureCount + ' ' + plural('failure', failureCount); - - if (pendingCount) { - specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount); - } - - print(specCounts); - } else { - print('No specs found'); - } - - printNewline(); - var seconds = timer.elapsed() / 1000; - print('Finished in ' + seconds + ' ' + plural('second', seconds)); - printNewline(); - - for(i = 0; i < failedSuites.length; i++) { - suiteFailureDetails(failedSuites[i]); - } - - onComplete(failureCount === 0); - }; - - this.specDone = function(result) { - specCount++; - - if (result.status == 'pending') { - pendingCount++; - print(colored('yellow', '*')); - return; - } - - if (result.status == 'passed') { - print(colored('green', '.')); - return; - } - - if (result.status == 'failed') { - failureCount++; - failedSpecs.push(result); - print(colored('red', 'F')); - } - }; - - this.suiteDone = function(result) { - if (result.failedExpectations && result.failedExpectations.length > 0) { - failureCount++; - failedSuites.push(result); - } - }; - - return this; - - function printNewline() { - print('\n'); - } - - function colored(color, str) { - return showColors ? (ansi[color] + str + ansi.none) : str; - } - - function plural(str, count) { - return count == 1 ? str : str + 's'; - } - - function repeat(thing, times) { - var arr = []; - for (var i = 0; i < times; i++) { - arr.push(thing); - } - return arr; - } - - function indent(str, spaces) { - var lines = (str || '').split('\n'); - var newArr = []; - for (var i = 0; i < lines.length; i++) { - newArr.push(repeat(' ', spaces).join('') + lines[i]); - } - return newArr.join('\n'); - } - - function specFailureDetails(result) { - printNewline(); - print(result.fullName); - - for (var i = 0; i < result.failedExpectations.length; i++) { - var failedExpectation = result.failedExpectations[i]; - printNewline(); - print(indent(failedExpectation.message, 2)); - print(indent(failedExpectation.stack, 2)); - } - - printNewline(); - } - - function suiteFailureDetails(result) { - for (var i = 0; i < result.failedExpectations.length; i++) { - printNewline(); - print(colored('red', 'An error was thrown in an afterAll')); - printNewline(); - print(colored('red', 'AfterAll ' + result.failedExpectations[i].message)); - - } - printNewline(); - } - } - - return ConsoleReporter; -}; diff --git a/spec/lib/jasmine-2.6.0/jasmine-html.js b/spec/lib/jasmine-2.6.0/jasmine-html.js deleted file mode 100644 index 90407cc..0000000 --- a/spec/lib/jasmine-2.6.0/jasmine-html.js +++ /dev/null @@ -1,499 +0,0 @@ -/* -Copyright (c) 2008-2017 Pivotal Labs - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -jasmineRequire.html = function(j$) { - j$.ResultsNode = jasmineRequire.ResultsNode(); - j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); - j$.QueryString = jasmineRequire.QueryString(); - j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); -}; - -jasmineRequire.HtmlReporter = function(j$) { - - var noopTimer = { - start: function() {}, - elapsed: function() { return 0; } - }; - - function HtmlReporter(options) { - var env = options.env || {}, - getContainer = options.getContainer, - createElement = options.createElement, - createTextNode = options.createTextNode, - onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {}, - onThrowExpectationsClick = options.onThrowExpectationsClick || function() {}, - onRandomClick = options.onRandomClick || function() {}, - addToExistingQueryString = options.addToExistingQueryString || defaultQueryString, - filterSpecs = options.filterSpecs, - timer = options.timer || noopTimer, - results = [], - specsExecuted = 0, - failureCount = 0, - pendingSpecCount = 0, - htmlReporterMain, - symbols, - failedSuites = []; - - this.initialize = function() { - clearPrior(); - htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'}, - createDom('div', {className: 'jasmine-banner'}, - createDom('a', {className: 'jasmine-title', href: 'http://jasmine.github.io/', target: '_blank'}), - createDom('span', {className: 'jasmine-version'}, j$.version) - ), - createDom('ul', {className: 'jasmine-symbol-summary'}), - createDom('div', {className: 'jasmine-alert'}), - createDom('div', {className: 'jasmine-results'}, - createDom('div', {className: 'jasmine-failures'}) - ) - ); - getContainer().appendChild(htmlReporterMain); - }; - - var totalSpecsDefined; - this.jasmineStarted = function(options) { - totalSpecsDefined = options.totalSpecsDefined || 0; - timer.start(); - }; - - var summary = createDom('div', {className: 'jasmine-summary'}); - - var topResults = new j$.ResultsNode({}, '', null), - currentParent = topResults; - - this.suiteStarted = function(result) { - currentParent.addChild(result, 'suite'); - currentParent = currentParent.last(); - }; - - this.suiteDone = function(result) { - if (result.status == 'failed') { - failedSuites.push(result); - } - - if (currentParent == topResults) { - return; - } - - currentParent = currentParent.parent; - }; - - this.specStarted = function(result) { - currentParent.addChild(result, 'spec'); - }; - - var failures = []; - this.specDone = function(result) { - if(noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') { - console.error('Spec \'' + result.fullName + '\' has no expectations.'); - } - - if (result.status != 'disabled') { - specsExecuted++; - } - - if (!symbols){ - symbols = find('.jasmine-symbol-summary'); - } - - symbols.appendChild(createDom('li', { - className: noExpectations(result) ? 'jasmine-empty' : 'jasmine-' + result.status, - id: 'spec_' + result.id, - title: result.fullName - } - )); - - if (result.status == 'failed') { - failureCount++; - - var failure = - createDom('div', {className: 'jasmine-spec-detail jasmine-failed'}, - createDom('div', {className: 'jasmine-description'}, - createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) - ), - createDom('div', {className: 'jasmine-messages'}) - ); - var messages = failure.childNodes[1]; - - for (var i = 0; i < result.failedExpectations.length; i++) { - var expectation = result.failedExpectations[i]; - messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message)); - messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack)); - } - - failures.push(failure); - } - - if (result.status == 'pending') { - pendingSpecCount++; - } - }; - - this.jasmineDone = function(doneResult) { - var banner = find('.jasmine-banner'); - var alert = find('.jasmine-alert'); - var order = doneResult && doneResult.order; - alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); - - banner.appendChild( - createDom('div', { className: 'jasmine-run-options' }, - createDom('span', { className: 'jasmine-trigger' }, 'Options'), - createDom('div', { className: 'jasmine-payload' }, - createDom('div', { className: 'jasmine-exceptions' }, - createDom('input', { - className: 'jasmine-raise', - id: 'jasmine-raise-exceptions', - type: 'checkbox' - }), - createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')), - createDom('div', { className: 'jasmine-throw-failures' }, - createDom('input', { - className: 'jasmine-throw', - id: 'jasmine-throw-failures', - type: 'checkbox' - }), - createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')), - createDom('div', { className: 'jasmine-random-order' }, - createDom('input', { - className: 'jasmine-random', - id: 'jasmine-random-order', - type: 'checkbox' - }), - createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order')) - ) - )); - - var raiseCheckbox = find('#jasmine-raise-exceptions'); - - raiseCheckbox.checked = !env.catchingExceptions(); - raiseCheckbox.onclick = onRaiseExceptionsClick; - - var throwCheckbox = find('#jasmine-throw-failures'); - throwCheckbox.checked = env.throwingExpectationFailures(); - throwCheckbox.onclick = onThrowExpectationsClick; - - var randomCheckbox = find('#jasmine-random-order'); - randomCheckbox.checked = env.randomTests(); - randomCheckbox.onclick = onRandomClick; - - var optionsMenu = find('.jasmine-run-options'), - optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'), - optionsPayload = optionsMenu.querySelector('.jasmine-payload'), - isOpen = /\bjasmine-open\b/; - - optionsTrigger.onclick = function() { - if (isOpen.test(optionsPayload.className)) { - optionsPayload.className = optionsPayload.className.replace(isOpen, ''); - } else { - optionsPayload.className += ' jasmine-open'; - } - }; - - if (specsExecuted < totalSpecsDefined) { - var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; - var skippedLink = order && order.random ? '?random=true' : '?'; - alert.appendChild( - createDom('span', {className: 'jasmine-bar jasmine-skipped'}, - createDom('a', {href: skippedLink, title: 'Run all specs'}, skippedMessage) - ) - ); - } - var statusBarMessage = ''; - var statusBarClassName = 'jasmine-bar '; - - if (totalSpecsDefined > 0) { - statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); - if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } - statusBarClassName += (failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed'; - } else { - statusBarClassName += 'jasmine-skipped'; - statusBarMessage += 'No specs found'; - } - - var seedBar; - if (order && order.random) { - seedBar = createDom('span', {className: 'jasmine-seed-bar'}, - ', randomized with seed ', - createDom('a', {title: 'randomized with seed ' + order.seed, href: seedHref(order.seed)}, order.seed) - ); - } - - alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar)); - - var errorBarClassName = 'jasmine-bar jasmine-errored'; - var errorBarMessagePrefix = 'AfterAll '; - - for(var i = 0; i < failedSuites.length; i++) { - var failedSuite = failedSuites[i]; - for(var j = 0; j < failedSuite.failedExpectations.length; j++) { - alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failedSuite.failedExpectations[j].message)); - } - } - - var globalFailures = (doneResult && doneResult.failedExpectations) || []; - for(i = 0; i < globalFailures.length; i++) { - var failure = globalFailures[i]; - alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failure.message)); - } - - var results = find('.jasmine-results'); - results.appendChild(summary); - - summaryList(topResults, summary); - - function summaryList(resultsTree, domParent) { - var specListNode; - for (var i = 0; i < resultsTree.children.length; i++) { - var resultNode = resultsTree.children[i]; - if (filterSpecs && !hasActiveSpec(resultNode)) { - continue; - } - if (resultNode.type == 'suite') { - var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id}, - createDom('li', {className: 'jasmine-suite-detail'}, - createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) - ) - ); - - summaryList(resultNode, suiteListNode); - domParent.appendChild(suiteListNode); - } - if (resultNode.type == 'spec') { - if (domParent.getAttribute('class') != 'jasmine-specs') { - specListNode = createDom('ul', {className: 'jasmine-specs'}); - domParent.appendChild(specListNode); - } - var specDescription = resultNode.result.description; - if(noExpectations(resultNode.result)) { - specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; - } - if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') { - specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason; - } - specListNode.appendChild( - createDom('li', { - className: 'jasmine-' + resultNode.result.status, - id: 'spec-' + resultNode.result.id - }, - createDom('a', {href: specHref(resultNode.result)}, specDescription) - ) - ); - } - } - } - - if (failures.length) { - alert.appendChild( - createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'}, - createDom('span', {}, 'Spec List | '), - createDom('a', {className: 'jasmine-failures-menu', href: '#'}, 'Failures'))); - alert.appendChild( - createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-failure-list'}, - createDom('a', {className: 'jasmine-spec-list-menu', href: '#'}, 'Spec List'), - createDom('span', {}, ' | Failures '))); - - find('.jasmine-failures-menu').onclick = function() { - setMenuModeTo('jasmine-failure-list'); - }; - find('.jasmine-spec-list-menu').onclick = function() { - setMenuModeTo('jasmine-spec-list'); - }; - - setMenuModeTo('jasmine-failure-list'); - - var failureNode = find('.jasmine-failures'); - for (i = 0; i < failures.length; i++) { - failureNode.appendChild(failures[i]); - } - } - }; - - return this; - - function find(selector) { - return getContainer().querySelector('.jasmine_html-reporter ' + selector); - } - - function clearPrior() { - // return the reporter - var oldReporter = find(''); - - if(oldReporter) { - getContainer().removeChild(oldReporter); - } - } - - function createDom(type, attrs, childrenVarArgs) { - var el = createElement(type); - - for (var i = 2; i < arguments.length; i++) { - var child = arguments[i]; - - if (typeof child === 'string') { - el.appendChild(createTextNode(child)); - } else { - if (child) { - el.appendChild(child); - } - } - } - - for (var attr in attrs) { - if (attr == 'className') { - el[attr] = attrs[attr]; - } else { - el.setAttribute(attr, attrs[attr]); - } - } - - return el; - } - - function pluralize(singular, count) { - var word = (count == 1 ? singular : singular + 's'); - - return '' + count + ' ' + word; - } - - function specHref(result) { - return addToExistingQueryString('spec', result.fullName); - } - - function seedHref(seed) { - return addToExistingQueryString('seed', seed); - } - - function defaultQueryString(key, value) { - return '?' + key + '=' + value; - } - - function setMenuModeTo(mode) { - htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode); - } - - function noExpectations(result) { - return (result.failedExpectations.length + result.passedExpectations.length) === 0 && - result.status === 'passed'; - } - - function hasActiveSpec(resultNode) { - if (resultNode.type == 'spec' && resultNode.result.status != 'disabled') { - return true; - } - - if (resultNode.type == 'suite') { - for (var i = 0, j = resultNode.children.length; i < j; i++) { - if (hasActiveSpec(resultNode.children[i])) { - return true; - } - } - } - } - } - - return HtmlReporter; -}; - -jasmineRequire.HtmlSpecFilter = function() { - function HtmlSpecFilter(options) { - var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); - var filterPattern = new RegExp(filterString); - - this.matches = function(specName) { - return filterPattern.test(specName); - }; - } - - return HtmlSpecFilter; -}; - -jasmineRequire.ResultsNode = function() { - function ResultsNode(result, type, parent) { - this.result = result; - this.type = type; - this.parent = parent; - - this.children = []; - - this.addChild = function(result, type) { - this.children.push(new ResultsNode(result, type, this)); - }; - - this.last = function() { - return this.children[this.children.length - 1]; - }; - } - - return ResultsNode; -}; - -jasmineRequire.QueryString = function() { - function QueryString(options) { - - this.navigateWithNewParam = function(key, value) { - options.getWindowLocation().search = this.fullStringWithNewParam(key, value); - }; - - this.fullStringWithNewParam = function(key, value) { - var paramMap = queryStringToParamMap(); - paramMap[key] = value; - return toQueryString(paramMap); - }; - - this.getParam = function(key) { - return queryStringToParamMap()[key]; - }; - - return this; - - function toQueryString(paramMap) { - var qStrPairs = []; - for (var prop in paramMap) { - qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); - } - return '?' + qStrPairs.join('&'); - } - - function queryStringToParamMap() { - var paramStr = options.getWindowLocation().search.substring(1), - params = [], - paramMap = {}; - - if (paramStr.length > 0) { - params = paramStr.split('&'); - for (var i = 0; i < params.length; i++) { - var p = params[i].split('='); - var value = decodeURIComponent(p[1]); - if (value === 'true' || value === 'false') { - value = JSON.parse(value); - } - paramMap[decodeURIComponent(p[0])] = value; - } - } - - return paramMap; - } - - } - - return QueryString; -}; diff --git a/spec/lib/jasmine-2.6.0/jasmine.css b/spec/lib/jasmine-2.6.0/jasmine.css deleted file mode 100644 index 6319982..0000000 --- a/spec/lib/jasmine-2.6.0/jasmine.css +++ /dev/null @@ -1,58 +0,0 @@ -body { overflow-y: scroll; } - -.jasmine_html-reporter { background-color: #eee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333; } -.jasmine_html-reporter a { text-decoration: none; } -.jasmine_html-reporter a:hover { text-decoration: underline; } -.jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; } -.jasmine_html-reporter .jasmine-banner, .jasmine_html-reporter .jasmine-symbol-summary, .jasmine_html-reporter .jasmine-summary, .jasmine_html-reporter .jasmine-result-message, .jasmine_html-reporter .jasmine-spec .jasmine-description, .jasmine_html-reporter .jasmine-spec-detail .jasmine-description, .jasmine_html-reporter .jasmine-alert .jasmine-bar, .jasmine_html-reporter .jasmine-stack-trace { padding-left: 9px; padding-right: 9px; } -.jasmine_html-reporter .jasmine-banner { position: relative; } -.jasmine_html-reporter .jasmine-banner .jasmine-title { background: url('data:image/png;base64,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') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -moz-background-size: 100%; -o-background-size: 100%; -webkit-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } -.jasmine_html-reporter .jasmine-banner .jasmine-version { margin-left: 14px; position: relative; top: 6px; } -.jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; } -.jasmine_html-reporter .jasmine-version { color: #aaa; } -.jasmine_html-reporter .jasmine-banner { margin-top: 14px; } -.jasmine_html-reporter .jasmine-duration { color: #fff; float: right; line-height: 28px; padding-right: 9px; } -.jasmine_html-reporter .jasmine-symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } -.jasmine_html-reporter .jasmine-symbol-summary li { display: inline-block; height: 10px; width: 14px; font-size: 16px; } -.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed { font-size: 14px; } -.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed:before { color: #007069; content: "\02022"; } -.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed { line-height: 9px; } -.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } -.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled { font-size: 14px; } -.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled:before { color: #bababa; content: "\02022"; } -.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending { line-height: 17px; } -.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending:before { color: #ba9d37; content: "*"; } -.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty { font-size: 14px; } -.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty:before { color: #ba9d37; content: "\02022"; } -.jasmine_html-reporter .jasmine-run-options { float: right; margin-right: 5px; border: 1px solid #8a4182; color: #8a4182; position: relative; line-height: 20px; } -.jasmine_html-reporter .jasmine-run-options .jasmine-trigger { cursor: pointer; padding: 8px 16px; } -.jasmine_html-reporter .jasmine-run-options .jasmine-payload { position: absolute; display: none; right: -1px; border: 1px solid #8a4182; background-color: #eee; white-space: nowrap; padding: 4px 8px; } -.jasmine_html-reporter .jasmine-run-options .jasmine-payload.jasmine-open { display: block; } -.jasmine_html-reporter .jasmine-bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } -.jasmine_html-reporter .jasmine-bar.jasmine-failed { background-color: #ca3a11; } -.jasmine_html-reporter .jasmine-bar.jasmine-passed { background-color: #007069; } -.jasmine_html-reporter .jasmine-bar.jasmine-skipped { background-color: #bababa; } -.jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; } -.jasmine_html-reporter .jasmine-bar.jasmine-menu { background-color: #fff; color: #aaa; } -.jasmine_html-reporter .jasmine-bar.jasmine-menu a { color: #333; } -.jasmine_html-reporter .jasmine-bar a { color: white; } -.jasmine_html-reporter.jasmine-spec-list .jasmine-bar.jasmine-menu.jasmine-failure-list, .jasmine_html-reporter.jasmine-spec-list .jasmine-results .jasmine-failures { display: none; } -.jasmine_html-reporter.jasmine-failure-list .jasmine-bar.jasmine-menu.jasmine-spec-list, .jasmine_html-reporter.jasmine-failure-list .jasmine-summary { display: none; } -.jasmine_html-reporter .jasmine-results { margin-top: 14px; } -.jasmine_html-reporter .jasmine-summary { margin-top: 14px; } -.jasmine_html-reporter .jasmine-summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } -.jasmine_html-reporter .jasmine-summary ul.jasmine-suite { margin-top: 7px; margin-bottom: 7px; } -.jasmine_html-reporter .jasmine-summary li.jasmine-passed a { color: #007069; } -.jasmine_html-reporter .jasmine-summary li.jasmine-failed a { color: #ca3a11; } -.jasmine_html-reporter .jasmine-summary li.jasmine-empty a { color: #ba9d37; } -.jasmine_html-reporter .jasmine-summary li.jasmine-pending a { color: #ba9d37; } -.jasmine_html-reporter .jasmine-summary li.jasmine-disabled a { color: #bababa; } -.jasmine_html-reporter .jasmine-description + .jasmine-suite { margin-top: 0; } -.jasmine_html-reporter .jasmine-suite { margin-top: 14px; } -.jasmine_html-reporter .jasmine-suite a { color: #333; } -.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail { margin-bottom: 28px; } -.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description { background-color: #ca3a11; } -.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description a { color: white; } -.jasmine_html-reporter .jasmine-result-message { padding-top: 14px; color: #333; white-space: pre; } -.jasmine_html-reporter .jasmine-result-message span.jasmine-result { display: block; } -.jasmine_html-reporter .jasmine-stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666; border: 1px solid #ddd; background: white; white-space: pre; } diff --git a/spec/lib/jasmine-2.6.0/jasmine.js b/spec/lib/jasmine-2.6.0/jasmine.js deleted file mode 100644 index 57b5afe..0000000 --- a/spec/lib/jasmine-2.6.0/jasmine.js +++ /dev/null @@ -1,4943 +0,0 @@ -/* -Copyright (c) 2008-2017 Pivotal Labs - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -var getJasmineRequireObj = (function (jasmineGlobal) { - var jasmineRequire; - - if (typeof module !== 'undefined' && module.exports && typeof exports !== 'undefined') { - if (typeof global !== 'undefined') { - jasmineGlobal = global; - } else { - jasmineGlobal = {}; - } - jasmineRequire = exports; - } else { - if (typeof window !== 'undefined' && typeof window.toString === 'function' && window.toString() === '[object GjsGlobal]') { - jasmineGlobal = window; - } - jasmineRequire = jasmineGlobal.jasmineRequire = jasmineGlobal.jasmineRequire || {}; - } - - function getJasmineRequire() { - return jasmineRequire; - } - - getJasmineRequire().core = function(jRequire) { - var j$ = {}; - - jRequire.base(j$, jasmineGlobal); - j$.util = jRequire.util(); - j$.errors = jRequire.errors(); - j$.formatErrorMsg = jRequire.formatErrorMsg(); - j$.Any = jRequire.Any(j$); - j$.Anything = jRequire.Anything(j$); - j$.CallTracker = jRequire.CallTracker(j$); - j$.MockDate = jRequire.MockDate(); - j$.getClearStack = jRequire.clearStack(j$); - j$.Clock = jRequire.Clock(); - j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); - j$.Env = jRequire.Env(j$); - j$.ExceptionFormatter = jRequire.ExceptionFormatter(); - j$.Expectation = jRequire.Expectation(); - j$.buildExpectationResult = jRequire.buildExpectationResult(); - j$.JsApiReporter = jRequire.JsApiReporter(); - j$.matchersUtil = jRequire.matchersUtil(j$); - j$.ObjectContaining = jRequire.ObjectContaining(j$); - j$.ArrayContaining = jRequire.ArrayContaining(j$); - j$.pp = jRequire.pp(j$); - j$.QueueRunner = jRequire.QueueRunner(j$); - j$.ReportDispatcher = jRequire.ReportDispatcher(); - j$.Spec = jRequire.Spec(j$); - j$.Spy = jRequire.Spy(j$); - j$.SpyRegistry = jRequire.SpyRegistry(j$); - j$.SpyStrategy = jRequire.SpyStrategy(j$); - j$.StringMatching = jRequire.StringMatching(j$); - j$.Suite = jRequire.Suite(j$); - j$.Timer = jRequire.Timer(); - j$.TreeProcessor = jRequire.TreeProcessor(); - j$.version = jRequire.version(); - j$.Order = jRequire.Order(); - j$.DiffBuilder = jRequire.DiffBuilder(j$); - j$.NullDiffBuilder = jRequire.NullDiffBuilder(j$); - j$.ObjectPath = jRequire.ObjectPath(j$); - j$.GlobalErrors = jRequire.GlobalErrors(j$); - - j$.matchers = jRequire.requireMatchers(jRequire, j$); - - return j$; - }; - - return getJasmineRequire; -})(this); - -getJasmineRequireObj().requireMatchers = function(jRequire, j$) { - var availableMatchers = [ - 'toBe', - 'toBeCloseTo', - 'toBeDefined', - 'toBeFalsy', - 'toBeGreaterThan', - 'toBeGreaterThanOrEqual', - 'toBeLessThan', - 'toBeLessThanOrEqual', - 'toBeNaN', - 'toBeNegativeInfinity', - 'toBeNull', - 'toBePositiveInfinity', - 'toBeTruthy', - 'toBeUndefined', - 'toContain', - 'toEqual', - 'toHaveBeenCalled', - 'toHaveBeenCalledBefore', - 'toHaveBeenCalledTimes', - 'toHaveBeenCalledWith', - 'toMatch', - 'toThrow', - 'toThrowError' - ], - matchers = {}; - - for (var i = 0; i < availableMatchers.length; i++) { - var name = availableMatchers[i]; - matchers[name] = jRequire[name](j$); - } - - return matchers; -}; - -getJasmineRequireObj().base = function(j$, jasmineGlobal) { - j$.unimplementedMethod_ = function() { - throw new Error('unimplemented method'); - }; - - /** - * Maximum object depth the pretty printer will print to. - * Set this to a lower value to speed up pretty printing if you have large objects. - * @name jasmine.MAX_PRETTY_PRINT_DEPTH - */ - j$.MAX_PRETTY_PRINT_DEPTH = 40; - /** - * Maximum number of array elements to display when pretty printing objects. - * Elements past this number will be ellipised. - * @name jasmine.MAX_PRETTY_PRINT_ARRAY_LENGTH - */ - j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; - /** - * Default number of milliseconds Jasmine will wait for an asynchronous spec to complete. - * @name jasmine.DEFAULT_TIMEOUT_INTERVAL - */ - j$.DEFAULT_TIMEOUT_INTERVAL = 5000; - - j$.getGlobal = function() { - return jasmineGlobal; - }; - - /** - * Get the currently booted Jasmine Environment. - * - * @name jasmine.getEnv - * @function - * @return {Env} - */ - j$.getEnv = function(options) { - var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); - //jasmine. singletons in here (setTimeout blah blah). - return env; - }; - - j$.isArray_ = function(value) { - return j$.isA_('Array', value); - }; - - j$.isObject_ = function(value) { - return !j$.util.isUndefined(value) && value !== null && j$.isA_('Object', value); - }; - - j$.isString_ = function(value) { - return j$.isA_('String', value); - }; - - j$.isNumber_ = function(value) { - return j$.isA_('Number', value); - }; - - j$.isFunction_ = function(value) { - return j$.isA_('Function', value); - }; - - j$.isA_ = function(typeName, value) { - return j$.getType_(value) === '[object ' + typeName + ']'; - }; - - j$.getType_ = function(value) { - return Object.prototype.toString.apply(value); - }; - - j$.isDomNode = function(obj) { - return obj.nodeType > 0; - }; - - j$.fnNameFor = function(func) { - if (func.name) { - return func.name; - } - - var matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/); - return matches ? matches[1] : ''; - }; - - /** - * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), - * that will succeed if the actual value being compared is an instance of the specified class/constructor. - * @name jasmine.any - * @function - * @param {Constructor} clazz - The constructor to check against. - */ - j$.any = function(clazz) { - return new j$.Any(clazz); - }; - - /** - * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), - * that will succeed if the actual value being compared is not `null` and not `undefined`. - * @name jasmine.anything - * @function - */ - j$.anything = function() { - return new j$.Anything(); - }; - - /** - * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), - * that will succeed if the actual value being compared contains at least the keys and values. - * @name jasmine.objectContaining - * @function - * @param {Object} sample - The subset of properties that _must_ be in the actual. - */ - j$.objectContaining = function(sample) { - return new j$.ObjectContaining(sample); - }; - - /** - * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), - * that will succeed if the actual value is a `String` that matches the `RegExp` or `String`. - * @name jasmine.stringMatching - * @function - * @param {RegExp|String} expected - */ - j$.stringMatching = function(expected) { - return new j$.StringMatching(expected); - }; - - /** - * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), - * that will succeed if the actual value is an `Array` that contains at least the elements in the sample. - * @name jasmine.arrayContaining - * @function - * @param {Array} sample - */ - j$.arrayContaining = function(sample) { - return new j$.ArrayContaining(sample); - }; - - /** - * Create a bare {@link Spy} object. This won't be installed anywhere and will not have any implementation behind it. - * @name jasmine.createSpy - * @function - * @param {String} [name] - Name to give the spy. This will be displayed in failure messages. - * @param {Function} [originalFn] - Function to act as the real implementation. - * @return {Spy} - */ - j$.createSpy = function(name, originalFn) { - return j$.Spy(name, originalFn); - }; - - j$.isSpy = function(putativeSpy) { - if (!putativeSpy) { - return false; - } - return putativeSpy.and instanceof j$.SpyStrategy && - putativeSpy.calls instanceof j$.CallTracker; - }; - - /** - * Create an object with multiple {@link Spy}s as its members. - * @name jasmine.createSpyObj - * @function - * @param {String} [baseName] - Base name for the spies in the object. - * @param {String[]|Object} methodNames - Array of method names to create spies for, or Object whose keys will be method names and values the {@link Spy#and#returnValue|returnValue}. - * @return {Object} - */ - j$.createSpyObj = function(baseName, methodNames) { - var baseNameIsCollection = j$.isObject_(baseName) || j$.isArray_(baseName); - - if (baseNameIsCollection && j$.util.isUndefined(methodNames)) { - methodNames = baseName; - baseName = 'unknown'; - } - - var obj = {}; - var spiesWereSet = false; - - if (j$.isArray_(methodNames)) { - for (var i = 0; i < methodNames.length; i++) { - obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); - spiesWereSet = true; - } - } else if (j$.isObject_(methodNames)) { - for (var key in methodNames) { - if (methodNames.hasOwnProperty(key)) { - obj[key] = j$.createSpy(baseName + '.' + key); - obj[key].and.returnValue(methodNames[key]); - spiesWereSet = true; - } - } - } - - if (!spiesWereSet) { - throw 'createSpyObj requires a non-empty array or object of method names to create spies for'; - } - - return obj; - }; -}; - -getJasmineRequireObj().util = function() { - - var util = {}; - - util.inherit = function(childClass, parentClass) { - var Subclass = function() { - }; - Subclass.prototype = parentClass.prototype; - childClass.prototype = new Subclass(); - }; - - util.htmlEscape = function(str) { - if (!str) { - return str; - } - return str.replace(/&/g, '&') - .replace(//g, '>'); - }; - - util.argsToArray = function(args) { - var arrayOfArgs = []; - for (var i = 0; i < args.length; i++) { - arrayOfArgs.push(args[i]); - } - return arrayOfArgs; - }; - - util.isUndefined = function(obj) { - return obj === void 0; - }; - - util.arrayContains = function(array, search) { - var i = array.length; - while (i--) { - if (array[i] === search) { - return true; - } - } - return false; - }; - - util.clone = function(obj) { - if (Object.prototype.toString.apply(obj) === '[object Array]') { - return obj.slice(); - } - - var cloned = {}; - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { - cloned[prop] = obj[prop]; - } - } - - return cloned; - }; - - util.getPropertyDescriptor = function(obj, methodName) { - var descriptor, - proto = obj; - - do { - descriptor = Object.getOwnPropertyDescriptor(proto, methodName); - proto = Object.getPrototypeOf(proto); - } while (!descriptor && proto); - - return descriptor; - }; - - util.objectDifference = function(obj, toRemove) { - var diff = {}; - - for (var key in obj) { - if (util.has(obj, key) && !util.has(toRemove, key)) { - diff[key] = obj[key]; - } - } - - return diff; - }; - - util.has = function(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); - }; - - return util; -}; - -getJasmineRequireObj().Spec = function(j$) { - function Spec(attrs) { - this.expectationFactory = attrs.expectationFactory; - this.resultCallback = attrs.resultCallback || function() {}; - this.id = attrs.id; - this.description = attrs.description || ''; - this.queueableFn = attrs.queueableFn; - this.beforeAndAfterFns = attrs.beforeAndAfterFns || function() { return {befores: [], afters: []}; }; - this.userContext = attrs.userContext || function() { return {}; }; - this.onStart = attrs.onStart || function() {}; - this.getSpecName = attrs.getSpecName || function() { return ''; }; - this.expectationResultFactory = attrs.expectationResultFactory || function() { }; - this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; - this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; - this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; - - if (!this.queueableFn.fn) { - this.pend(); - } - - this.result = { - id: this.id, - description: this.description, - fullName: this.getFullName(), - failedExpectations: [], - passedExpectations: [], - pendingReason: '' - }; - } - - Spec.prototype.addExpectationResult = function(passed, data, isError) { - var expectationResult = this.expectationResultFactory(data); - if (passed) { - this.result.passedExpectations.push(expectationResult); - } else { - this.result.failedExpectations.push(expectationResult); - - if (this.throwOnExpectationFailure && !isError) { - throw new j$.errors.ExpectationFailed(); - } - } - }; - - Spec.prototype.expect = function(actual) { - return this.expectationFactory(actual, this); - }; - - Spec.prototype.execute = function(onComplete, enabled) { - var self = this; - - this.onStart(this); - - if (!this.isExecutable() || this.markedPending || enabled === false) { - complete(enabled); - return; - } - - var fns = this.beforeAndAfterFns(); - var allFns = fns.befores.concat(this.queueableFn).concat(fns.afters); - - this.queueRunnerFactory({ - queueableFns: allFns, - onException: function() { self.onException.apply(self, arguments); }, - onComplete: complete, - userContext: this.userContext() - }); - - function complete(enabledAgain) { - self.result.status = self.status(enabledAgain); - self.resultCallback(self.result); - - if (onComplete) { - onComplete(); - } - } - }; - - Spec.prototype.onException = function onException(e) { - if (Spec.isPendingSpecException(e)) { - this.pend(extractCustomPendingMessage(e)); - return; - } - - if (e instanceof j$.errors.ExpectationFailed) { - return; - } - - this.addExpectationResult(false, { - matcherName: '', - passed: false, - expected: '', - actual: '', - error: e - }, true); - }; - - Spec.prototype.disable = function() { - this.disabled = true; - }; - - Spec.prototype.pend = function(message) { - this.markedPending = true; - if (message) { - this.result.pendingReason = message; - } - }; - - Spec.prototype.getResult = function() { - this.result.status = this.status(); - return this.result; - }; - - Spec.prototype.status = function(enabled) { - if (this.disabled || enabled === false) { - return 'disabled'; - } - - if (this.markedPending) { - return 'pending'; - } - - if (this.result.failedExpectations.length > 0) { - return 'failed'; - } else { - return 'passed'; - } - }; - - Spec.prototype.isExecutable = function() { - return !this.disabled; - }; - - Spec.prototype.getFullName = function() { - return this.getSpecName(this); - }; - - var extractCustomPendingMessage = function(e) { - var fullMessage = e.toString(), - boilerplateStart = fullMessage.indexOf(Spec.pendingSpecExceptionMessage), - boilerplateEnd = boilerplateStart + Spec.pendingSpecExceptionMessage.length; - - return fullMessage.substr(boilerplateEnd); - }; - - Spec.pendingSpecExceptionMessage = '=> marked Pending'; - - Spec.isPendingSpecException = function(e) { - return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1); - }; - - return Spec; -}; - -if (typeof window == void 0 && typeof exports == 'object') { - exports.Spec = jasmineRequire.Spec; -} - -/*jshint bitwise: false*/ - -getJasmineRequireObj().Order = function() { - function Order(options) { - this.random = 'random' in options ? options.random : true; - var seed = this.seed = options.seed || generateSeed(); - this.sort = this.random ? randomOrder : naturalOrder; - - function naturalOrder(items) { - return items; - } - - function randomOrder(items) { - var copy = items.slice(); - copy.sort(function(a, b) { - return jenkinsHash(seed + a.id) - jenkinsHash(seed + b.id); - }); - return copy; - } - - function generateSeed() { - return String(Math.random()).slice(-5); - } - - // Bob Jenkins One-at-a-Time Hash algorithm is a non-cryptographic hash function - // used to get a different output when the key changes slighly. - // We use your return to sort the children randomly in a consistent way when - // used in conjunction with a seed - - function jenkinsHash(key) { - var hash, i; - for(hash = i = 0; i < key.length; ++i) { - hash += key.charCodeAt(i); - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - return hash; - } - - } - - return Order; -}; - -getJasmineRequireObj().Env = function(j$) { - /** - * _Note:_ Do not construct this directly, Jasmine will make one during booting. - * @name Env - * @classdesc The Jasmine environment - * @constructor - */ - function Env(options) { - options = options || {}; - - var self = this; - var global = options.global || j$.getGlobal(); - - var totalSpecsDefined = 0; - - var catchExceptions = true; - - var realSetTimeout = j$.getGlobal().setTimeout; - var realClearTimeout = j$.getGlobal().clearTimeout; - var clearStack = j$.getClearStack(j$.getGlobal()); - this.clock = new j$.Clock(global, function () { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global)); - - var runnableResources = {}; - - var currentSpec = null; - var currentlyExecutingSuites = []; - var currentDeclarationSuite = null; - var throwOnExpectationFailure = false; - var random = false; - var seed = null; - - var currentSuite = function() { - return currentlyExecutingSuites[currentlyExecutingSuites.length - 1]; - }; - - var currentRunnable = function() { - return currentSpec || currentSuite(); - }; - - var reporter = new j$.ReportDispatcher([ - 'jasmineStarted', - 'jasmineDone', - 'suiteStarted', - 'suiteDone', - 'specStarted', - 'specDone' - ]); - - var globalErrors = new j$.GlobalErrors(); - - this.specFilter = function() { - return true; - }; - - this.addCustomEqualityTester = function(tester) { - if(!currentRunnable()) { - throw new Error('Custom Equalities must be added in a before function or a spec'); - } - runnableResources[currentRunnable().id].customEqualityTesters.push(tester); - }; - - this.addMatchers = function(matchersToAdd) { - if(!currentRunnable()) { - throw new Error('Matchers must be added in a before function or a spec'); - } - var customMatchers = runnableResources[currentRunnable().id].customMatchers; - for (var matcherName in matchersToAdd) { - customMatchers[matcherName] = matchersToAdd[matcherName]; - } - }; - - j$.Expectation.addCoreMatchers(j$.matchers); - - var nextSpecId = 0; - var getNextSpecId = function() { - return 'spec' + nextSpecId++; - }; - - var nextSuiteId = 0; - var getNextSuiteId = function() { - return 'suite' + nextSuiteId++; - }; - - var expectationFactory = function(actual, spec) { - return j$.Expectation.Factory({ - util: j$.matchersUtil, - customEqualityTesters: runnableResources[spec.id].customEqualityTesters, - customMatchers: runnableResources[spec.id].customMatchers, - actual: actual, - addExpectationResult: addExpectationResult - }); - - function addExpectationResult(passed, result) { - return spec.addExpectationResult(passed, result); - } - }; - - var defaultResourcesForRunnable = function(id, parentRunnableId) { - var resources = {spies: [], customEqualityTesters: [], customMatchers: {}}; - - if(runnableResources[parentRunnableId]){ - resources.customEqualityTesters = j$.util.clone(runnableResources[parentRunnableId].customEqualityTesters); - resources.customMatchers = j$.util.clone(runnableResources[parentRunnableId].customMatchers); - } - - runnableResources[id] = resources; - }; - - var clearResourcesForRunnable = function(id) { - spyRegistry.clearSpies(); - delete runnableResources[id]; - }; - - var beforeAndAfterFns = function(suite) { - return function() { - var befores = [], - afters = []; - - while(suite) { - befores = befores.concat(suite.beforeFns); - afters = afters.concat(suite.afterFns); - - suite = suite.parentSuite; - } - - return { - befores: befores.reverse(), - afters: afters - }; - }; - }; - - var getSpecName = function(spec, suite) { - var fullName = [spec.description], - suiteFullName = suite.getFullName(); - - if (suiteFullName !== '') { - fullName.unshift(suiteFullName); - } - return fullName.join(' '); - }; - - // TODO: we may just be able to pass in the fn instead of wrapping here - var buildExpectationResult = j$.buildExpectationResult, - exceptionFormatter = new j$.ExceptionFormatter(), - expectationResultFactory = function(attrs) { - attrs.messageFormatter = exceptionFormatter.message; - attrs.stackFormatter = exceptionFormatter.stack; - - return buildExpectationResult(attrs); - }; - - // TODO: fix this naming, and here's where the value comes in - this.catchExceptions = function(value) { - catchExceptions = !!value; - return catchExceptions; - }; - - this.catchingExceptions = function() { - return catchExceptions; - }; - - var maximumSpecCallbackDepth = 20; - var currentSpecCallbackDepth = 0; - - var catchException = function(e) { - return j$.Spec.isPendingSpecException(e) || catchExceptions; - }; - - this.throwOnExpectationFailure = function(value) { - throwOnExpectationFailure = !!value; - }; - - this.throwingExpectationFailures = function() { - return throwOnExpectationFailure; - }; - - this.randomizeTests = function(value) { - random = !!value; - }; - - this.randomTests = function() { - return random; - }; - - this.seed = function(value) { - if (value) { - seed = value; - } - return seed; - }; - - var queueRunnerFactory = function(options) { - options.catchException = catchException; - options.clearStack = options.clearStack || clearStack; - options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; - options.fail = self.fail; - options.globalErrors = globalErrors; - - new j$.QueueRunner(options).execute(); - }; - - var topSuite = new j$.Suite({ - env: this, - id: getNextSuiteId(), - description: 'Jasmine__TopLevel__Suite', - expectationFactory: expectationFactory, - expectationResultFactory: expectationResultFactory - }); - defaultResourcesForRunnable(topSuite.id); - currentDeclarationSuite = topSuite; - - this.topSuite = function() { - return topSuite; - }; - - this.execute = function(runnablesToRun) { - if(!runnablesToRun) { - if (focusedRunnables.length) { - runnablesToRun = focusedRunnables; - } else { - runnablesToRun = [topSuite.id]; - } - } - - var order = new j$.Order({ - random: random, - seed: seed - }); - - var processor = new j$.TreeProcessor({ - tree: topSuite, - runnableIds: runnablesToRun, - queueRunnerFactory: queueRunnerFactory, - nodeStart: function(suite) { - currentlyExecutingSuites.push(suite); - defaultResourcesForRunnable(suite.id, suite.parentSuite.id); - reporter.suiteStarted(suite.result); - }, - nodeComplete: function(suite, result) { - if (!suite.markedPending) { - clearResourcesForRunnable(suite.id); - } - currentlyExecutingSuites.pop(); - reporter.suiteDone(result); - }, - orderChildren: function(node) { - return order.sort(node.children); - } - }); - - if(!processor.processTree().valid) { - throw new Error('Invalid order: would cause a beforeAll or afterAll to be run multiple times'); - } - - reporter.jasmineStarted({ - totalSpecsDefined: totalSpecsDefined - }); - - currentlyExecutingSuites.push(topSuite); - - globalErrors.install(); - processor.execute(function() { - clearResourcesForRunnable(topSuite.id); - currentlyExecutingSuites.pop(); - globalErrors.uninstall(); - - reporter.jasmineDone({ - order: order, - failedExpectations: topSuite.result.failedExpectations - }); - }); - }; - - /** - * Add a custom reporter to the Jasmine environment. - * @name Env#addReporter - * @function - * @see custom_reporter - */ - this.addReporter = function(reporterToAdd) { - reporter.addReporter(reporterToAdd); - }; - - this.provideFallbackReporter = function(reporterToAdd) { - reporter.provideFallbackReporter(reporterToAdd); - }; - - this.clearReporters = function() { - reporter.clearReporters(); - }; - - var spyRegistry = new j$.SpyRegistry({currentSpies: function() { - if(!currentRunnable()) { - throw new Error('Spies must be created in a before function or a spec'); - } - return runnableResources[currentRunnable().id].spies; - }}); - - this.allowRespy = function(allow){ - spyRegistry.allowRespy(allow); - }; - - this.spyOn = function() { - return spyRegistry.spyOn.apply(spyRegistry, arguments); - }; - - this.spyOnProperty = function() { - return spyRegistry.spyOnProperty.apply(spyRegistry, arguments); - }; - - var ensureIsFunction = function(fn, caller) { - if (!j$.isFunction_(fn)) { - throw new Error(caller + ' expects a function argument; received ' + j$.getType_(fn)); - } - }; - - var suiteFactory = function(description) { - var suite = new j$.Suite({ - env: self, - id: getNextSuiteId(), - description: description, - parentSuite: currentDeclarationSuite, - expectationFactory: expectationFactory, - expectationResultFactory: expectationResultFactory, - throwOnExpectationFailure: throwOnExpectationFailure - }); - - return suite; - }; - - this.describe = function(description, specDefinitions) { - ensureIsFunction(specDefinitions, 'describe'); - var suite = suiteFactory(description); - if (specDefinitions.length > 0) { - throw new Error('describe does not expect any arguments'); - } - if (currentDeclarationSuite.markedPending) { - suite.pend(); - } - addSpecsToSuite(suite, specDefinitions); - return suite; - }; - - this.xdescribe = function(description, specDefinitions) { - ensureIsFunction(specDefinitions, 'xdescribe'); - var suite = suiteFactory(description); - suite.pend(); - addSpecsToSuite(suite, specDefinitions); - return suite; - }; - - var focusedRunnables = []; - - this.fdescribe = function(description, specDefinitions) { - ensureIsFunction(specDefinitions, 'fdescribe'); - var suite = suiteFactory(description); - suite.isFocused = true; - - focusedRunnables.push(suite.id); - unfocusAncestor(); - addSpecsToSuite(suite, specDefinitions); - - return suite; - }; - - function addSpecsToSuite(suite, specDefinitions) { - var parentSuite = currentDeclarationSuite; - parentSuite.addChild(suite); - currentDeclarationSuite = suite; - - var declarationError = null; - try { - specDefinitions.call(suite); - } catch (e) { - declarationError = e; - } - - if (declarationError) { - self.it('encountered a declaration exception', function() { - throw declarationError; - }); - } - - currentDeclarationSuite = parentSuite; - } - - function findFocusedAncestor(suite) { - while (suite) { - if (suite.isFocused) { - return suite.id; - } - suite = suite.parentSuite; - } - - return null; - } - - function unfocusAncestor() { - var focusedAncestor = findFocusedAncestor(currentDeclarationSuite); - if (focusedAncestor) { - for (var i = 0; i < focusedRunnables.length; i++) { - if (focusedRunnables[i] === focusedAncestor) { - focusedRunnables.splice(i, 1); - break; - } - } - } - } - - var specFactory = function(description, fn, suite, timeout) { - totalSpecsDefined++; - var spec = new j$.Spec({ - id: getNextSpecId(), - beforeAndAfterFns: beforeAndAfterFns(suite), - expectationFactory: expectationFactory, - resultCallback: specResultCallback, - getSpecName: function(spec) { - return getSpecName(spec, suite); - }, - onStart: specStarted, - description: description, - expectationResultFactory: expectationResultFactory, - queueRunnerFactory: queueRunnerFactory, - userContext: function() { return suite.clonedSharedUserContext(); }, - queueableFn: { - fn: fn, - timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } - }, - throwOnExpectationFailure: throwOnExpectationFailure - }); - - if (!self.specFilter(spec)) { - spec.disable(); - } - - return spec; - - function specResultCallback(result) { - clearResourcesForRunnable(spec.id); - currentSpec = null; - reporter.specDone(result); - } - - function specStarted(spec) { - currentSpec = spec; - defaultResourcesForRunnable(spec.id, suite.id); - reporter.specStarted(spec.result); - } - }; - - this.it = function(description, fn, timeout) { - // it() sometimes doesn't have a fn argument, so only check the type if - // it's given. - if (arguments.length > 1) { - ensureIsFunction(fn, 'it'); - } - var spec = specFactory(description, fn, currentDeclarationSuite, timeout); - if (currentDeclarationSuite.markedPending) { - spec.pend(); - } - currentDeclarationSuite.addChild(spec); - return spec; - }; - - this.xit = function(description, fn, timeout) { - // xit(), like it(), doesn't always have a fn argument, so only check the - // type when needed. - if (arguments.length > 1) { - ensureIsFunction(fn, 'xit'); - } - var spec = this.it.apply(this, arguments); - spec.pend('Temporarily disabled with xit'); - return spec; - }; - - this.fit = function(description, fn, timeout){ - ensureIsFunction(fn, 'fit'); - var spec = specFactory(description, fn, currentDeclarationSuite, timeout); - currentDeclarationSuite.addChild(spec); - focusedRunnables.push(spec.id); - unfocusAncestor(); - return spec; - }; - - this.expect = function(actual) { - if (!currentRunnable()) { - throw new Error('\'expect\' was used when there was no current spec, this could be because an asynchronous test timed out'); - } - - return currentRunnable().expect(actual); - }; - - this.beforeEach = function(beforeEachFunction, timeout) { - ensureIsFunction(beforeEachFunction, 'beforeEach'); - currentDeclarationSuite.beforeEach({ - fn: beforeEachFunction, - timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } - }); - }; - - this.beforeAll = function(beforeAllFunction, timeout) { - ensureIsFunction(beforeAllFunction, 'beforeAll'); - currentDeclarationSuite.beforeAll({ - fn: beforeAllFunction, - timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } - }); - }; - - this.afterEach = function(afterEachFunction, timeout) { - ensureIsFunction(afterEachFunction, 'afterEach'); - currentDeclarationSuite.afterEach({ - fn: afterEachFunction, - timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } - }); - }; - - this.afterAll = function(afterAllFunction, timeout) { - ensureIsFunction(afterAllFunction, 'afterAll'); - currentDeclarationSuite.afterAll({ - fn: afterAllFunction, - timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } - }); - }; - - this.pending = function(message) { - var fullMessage = j$.Spec.pendingSpecExceptionMessage; - if(message) { - fullMessage += message; - } - throw fullMessage; - }; - - this.fail = function(error) { - if (!currentRunnable()) { - throw new Error('\'fail\' was used when there was no current spec, this could be because an asynchronous test timed out'); - } - - var message = 'Failed'; - if (error) { - message += ': '; - if (error.message) { - message += error.message; - } else if (jasmine.isString_(error)) { - message += error; - } else { - // pretty print all kind of objects. This includes arrays. - message += jasmine.pp(error); - } - } - - currentRunnable().addExpectationResult(false, { - matcherName: '', - passed: false, - expected: '', - actual: '', - message: message, - error: error && error.message ? error : null - }); - }; - } - - return Env; -}; - -getJasmineRequireObj().JsApiReporter = function() { - - var noopTimer = { - start: function(){}, - elapsed: function(){ return 0; } - }; - - /** - * _Note:_ Do not construct this directly, use the global `jsApiReporter` to retrieve the instantiated object. - * - * @name jsApiReporter - * @classdesc Reporter added by default in `boot.js` to record results for retrieval in javascript code. - * @class - */ - function JsApiReporter(options) { - var timer = options.timer || noopTimer, - status = 'loaded'; - - this.started = false; - this.finished = false; - this.runDetails = {}; - - this.jasmineStarted = function() { - this.started = true; - status = 'started'; - timer.start(); - }; - - var executionTime; - - this.jasmineDone = function(runDetails) { - this.finished = true; - this.runDetails = runDetails; - executionTime = timer.elapsed(); - status = 'done'; - }; - - /** - * Get the current status for the Jasmine environment. - * @name jsApiReporter#status - * @function - * @return {String} - One of `loaded`, `started`, or `done` - */ - this.status = function() { - return status; - }; - - var suites = [], - suites_hash = {}; - - this.suiteStarted = function(result) { - suites_hash[result.id] = result; - }; - - this.suiteDone = function(result) { - storeSuite(result); - }; - - /** - * Get the results for a set of suites. - * - * Retrievable in slices for easier serialization. - * @name jsApiReporter#suiteResults - * @function - * @param {Number} index - The position in the suites list to start from. - * @param {Number} length - Maximum number of suite results to return. - * @return {Object[]} - */ - this.suiteResults = function(index, length) { - return suites.slice(index, index + length); - }; - - function storeSuite(result) { - suites.push(result); - suites_hash[result.id] = result; - } - - /** - * Get all of the suites in a single object, with their `id` as the key. - * @name jsApiReporter#suites - * @function - * @return {Object} - */ - this.suites = function() { - return suites_hash; - }; - - var specs = []; - - this.specDone = function(result) { - specs.push(result); - }; - - /** - * Get the results for a set of specs. - * - * Retrievable in slices for easier serialization. - * @name jsApiReporter#specResults - * @function - * @param {Number} index - The position in the specs list to start from. - * @param {Number} length - Maximum number of specs results to return. - * @return {Object[]} - */ - this.specResults = function(index, length) { - return specs.slice(index, index + length); - }; - - /** - * Get all spec results. - * @name jsApiReporter#specs - * @function - * @return {Object[]} - */ - this.specs = function() { - return specs; - }; - - /** - * Get the number of milliseconds it took for the full Jasmine suite to run. - * @name jsApiReporter#executionTime - * @function - * @return {Number} - */ - this.executionTime = function() { - return executionTime; - }; - - } - - return JsApiReporter; -}; - -getJasmineRequireObj().Any = function(j$) { - - function Any(expectedObject) { - if (typeof expectedObject === 'undefined') { - throw new TypeError( - 'jasmine.any() expects to be passed a constructor function. ' + - 'Please pass one or use jasmine.anything() to match any object.' - ); - } - this.expectedObject = expectedObject; - } - - Any.prototype.asymmetricMatch = function(other) { - if (this.expectedObject == String) { - return typeof other == 'string' || other instanceof String; - } - - if (this.expectedObject == Number) { - return typeof other == 'number' || other instanceof Number; - } - - if (this.expectedObject == Function) { - return typeof other == 'function' || other instanceof Function; - } - - if (this.expectedObject == Object) { - return typeof other == 'object'; - } - - if (this.expectedObject == Boolean) { - return typeof other == 'boolean'; - } - - return other instanceof this.expectedObject; - }; - - Any.prototype.jasmineToString = function() { - return ''; - }; - - return Any; -}; - -getJasmineRequireObj().Anything = function(j$) { - - function Anything() {} - - Anything.prototype.asymmetricMatch = function(other) { - return !j$.util.isUndefined(other) && other !== null; - }; - - Anything.prototype.jasmineToString = function() { - return ''; - }; - - return Anything; -}; - -getJasmineRequireObj().ArrayContaining = function(j$) { - function ArrayContaining(sample) { - this.sample = sample; - } - - ArrayContaining.prototype.asymmetricMatch = function(other, customTesters) { - var className = Object.prototype.toString.call(this.sample); - if (className !== '[object Array]') { throw new Error('You must provide an array to arrayContaining, not \'' + this.sample + '\'.'); } - - for (var i = 0; i < this.sample.length; i++) { - var item = this.sample[i]; - if (!j$.matchersUtil.contains(other, item, customTesters)) { - return false; - } - } - - return true; - }; - - ArrayContaining.prototype.jasmineToString = function () { - return ''; - }; - - return ArrayContaining; -}; - -getJasmineRequireObj().ObjectContaining = function(j$) { - - function ObjectContaining(sample) { - this.sample = sample; - } - - function getPrototype(obj) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(obj); - } - - if (obj.constructor.prototype == obj) { - return null; - } - - return obj.constructor.prototype; - } - - function hasProperty(obj, property) { - if (!obj) { - return false; - } - - if (Object.prototype.hasOwnProperty.call(obj, property)) { - return true; - } - - return hasProperty(getPrototype(obj), property); - } - - ObjectContaining.prototype.asymmetricMatch = function(other, customTesters) { - if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); } - - for (var property in this.sample) { - if (!hasProperty(other, property) || - !j$.matchersUtil.equals(this.sample[property], other[property], customTesters)) { - return false; - } - } - - return true; - }; - - ObjectContaining.prototype.jasmineToString = function() { - return ''; - }; - - return ObjectContaining; -}; - -getJasmineRequireObj().StringMatching = function(j$) { - - function StringMatching(expected) { - if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) { - throw new Error('Expected is not a String or a RegExp'); - } - - this.regexp = new RegExp(expected); - } - - StringMatching.prototype.asymmetricMatch = function(other) { - return this.regexp.test(other); - }; - - StringMatching.prototype.jasmineToString = function() { - return ''; - }; - - return StringMatching; -}; - -getJasmineRequireObj().CallTracker = function(j$) { - - /** - * @namespace Spy#calls - */ - function CallTracker() { - var calls = []; - var opts = {}; - - function argCloner(context) { - var clonedArgs = []; - var argsAsArray = j$.util.argsToArray(context.args); - for(var i = 0; i < argsAsArray.length; i++) { - if(Object.prototype.toString.apply(argsAsArray[i]).match(/^\[object/)) { - clonedArgs.push(j$.util.clone(argsAsArray[i])); - } else { - clonedArgs.push(argsAsArray[i]); - } - } - context.args = clonedArgs; - } - - this.track = function(context) { - if(opts.cloneArgs) { - argCloner(context); - } - calls.push(context); - }; - - /** - * Check whether this spy has been invoked. - * @name Spy#calls#any - * @function - * @return {Boolean} - */ - this.any = function() { - return !!calls.length; - }; - - /** - * Get the number of invocations of this spy. - * @name Spy#calls#count - * @function - * @return {Integer} - */ - this.count = function() { - return calls.length; - }; - - /** - * Get the arguments that were passed to a specific invocation of this spy. - * @name Spy#calls#argsFor - * @function - * @param {Integer} index The 0-based invocation index. - * @return {Array} - */ - this.argsFor = function(index) { - var call = calls[index]; - return call ? call.args : []; - }; - - /** - * Get the raw calls array for this spy. - * @name Spy#calls#all - * @function - * @return {Spy.callData[]} - */ - this.all = function() { - return calls; - }; - - /** - * Get all of the arguments for each invocation of this spy in the order they were received. - * @name Spy#calls#allArgs - * @function - * @return {Array} - */ - this.allArgs = function() { - var callArgs = []; - for(var i = 0; i < calls.length; i++){ - callArgs.push(calls[i].args); - } - - return callArgs; - }; - - /** - * Get the first invocation of this spy. - * @name Spy#calls#first - * @function - * @return {ObjecSpy.callData} - */ - this.first = function() { - return calls[0]; - }; - - /** - * Get the most recent invocation of this spy. - * @name Spy#calls#mostRecent - * @function - * @return {ObjecSpy.callData} - */ - this.mostRecent = function() { - return calls[calls.length - 1]; - }; - - /** - * Reset this spy as if it has never been called. - * @name Spy#calls#reset - * @function - */ - this.reset = function() { - calls = []; - }; - - /** - * Set this spy to do a shallow clone of arguments passed to each invocation. - * @name Spy#calls#saveArgumentsByValue - * @function - */ - this.saveArgumentsByValue = function() { - opts.cloneArgs = true; - }; - - } - - return CallTracker; -}; - -getJasmineRequireObj().clearStack = function(j$) { - function messageChannelImpl(global) { - var channel = new global.MessageChannel(), - head = {}, - tail = head; - - channel.port1.onmessage = function() { - head = head.next; - var task = head.task; - delete head.task; - task(); - }; - - return function clearStack(fn) { - tail = tail.next = { task: fn }; - channel.port2.postMessage(0); - }; - } - - function getClearStack(global) { - if (global && global.process && j$.isFunction_(global.process.nextTick)) { - return global.process.nextTick; - } else if (j$.isFunction_(global.setImmediate)) { - var realSetImmediate = global.setImmediate; - return function(fn) { - realSetImmediate(fn); - }; - } else if (!j$.util.isUndefined(global.MessageChannel)) { - return messageChannelImpl(global); - } else { - var realSetTimeout = global.setTimeout; - return function clearStack(fn) { - Function.prototype.apply.apply(realSetTimeout, [global, [fn, 0]]); - }; - } - } - - return getClearStack; -}; - -getJasmineRequireObj().Clock = function() { - /** - * _Note:_ Do not construct this directly, Jasmine will make one during booting. You can get the current clock with {@link jasmine.clock}. - * @class Clock - * @classdesc Jasmine's mock clock is used when testing time dependent code. - */ - function Clock(global, delayedFunctionSchedulerFactory, mockDate) { - var self = this, - realTimingFunctions = { - setTimeout: global.setTimeout, - clearTimeout: global.clearTimeout, - setInterval: global.setInterval, - clearInterval: global.clearInterval - }, - fakeTimingFunctions = { - setTimeout: setTimeout, - clearTimeout: clearTimeout, - setInterval: setInterval, - clearInterval: clearInterval - }, - installed = false, - delayedFunctionScheduler, - timer; - - - /** - * Install the mock clock over the built-in methods. - * @name Clock#install - * @function - * @return {Clock} - */ - self.install = function() { - if(!originalTimingFunctionsIntact()) { - throw new Error('Jasmine Clock was unable to install over custom global timer functions. Is the clock already installed?'); - } - replace(global, fakeTimingFunctions); - timer = fakeTimingFunctions; - delayedFunctionScheduler = delayedFunctionSchedulerFactory(); - installed = true; - - return self; - }; - - /** - * Uninstall the mock clock, returning the built-in methods to their places. - * @name Clock#uninstall - * @function - */ - self.uninstall = function() { - delayedFunctionScheduler = null; - mockDate.uninstall(); - replace(global, realTimingFunctions); - - timer = realTimingFunctions; - installed = false; - }; - - /** - * Execute a function with a mocked Clock - * - * The clock will be {@link Clock#install|install}ed before the function is called and {@link Clock#uninstall|uninstall}ed in a `finally` after the function completes. - * @name Clock#withMock - * @function - * @param {closure} Function The function to be called. - */ - self.withMock = function(closure) { - this.install(); - try { - closure(); - } finally { - this.uninstall(); - } - }; - - /** - * Instruct the installed Clock to also mock the date returned by `new Date()` - * @name Clock#mockDate - * @function - * @param {Date} [initialDate=now] The `Date` to provide. - */ - self.mockDate = function(initialDate) { - mockDate.install(initialDate); - }; - - self.setTimeout = function(fn, delay, params) { - if (legacyIE()) { - if (arguments.length > 2) { - throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill'); - } - return timer.setTimeout(fn, delay); - } - return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]); - }; - - self.setInterval = function(fn, delay, params) { - if (legacyIE()) { - if (arguments.length > 2) { - throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill'); - } - return timer.setInterval(fn, delay); - } - return Function.prototype.apply.apply(timer.setInterval, [global, arguments]); - }; - - self.clearTimeout = function(id) { - return Function.prototype.call.apply(timer.clearTimeout, [global, id]); - }; - - self.clearInterval = function(id) { - return Function.prototype.call.apply(timer.clearInterval, [global, id]); - }; - - /** - * Tick the Clock forward, running any enqueued timeouts along the way - * @name Clock#tick - * @function - * @param {int} millis The number of milliseconds to tick. - */ - self.tick = function(millis) { - if (installed) { - delayedFunctionScheduler.tick(millis, function(millis) { mockDate.tick(millis); }); - } else { - throw new Error('Mock clock is not installed, use jasmine.clock().install()'); - } - }; - - return self; - - function originalTimingFunctionsIntact() { - return global.setTimeout === realTimingFunctions.setTimeout && - global.clearTimeout === realTimingFunctions.clearTimeout && - global.setInterval === realTimingFunctions.setInterval && - global.clearInterval === realTimingFunctions.clearInterval; - } - - function legacyIE() { - //if these methods are polyfilled, apply will be present - return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply; - } - - function replace(dest, source) { - for (var prop in source) { - dest[prop] = source[prop]; - } - } - - function setTimeout(fn, delay) { - return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2)); - } - - function clearTimeout(id) { - return delayedFunctionScheduler.removeFunctionWithId(id); - } - - function setInterval(fn, interval) { - return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true); - } - - function clearInterval(id) { - return delayedFunctionScheduler.removeFunctionWithId(id); - } - - function argSlice(argsObj, n) { - return Array.prototype.slice.call(argsObj, n); - } - } - - return Clock; -}; - -getJasmineRequireObj().DelayedFunctionScheduler = function() { - function DelayedFunctionScheduler() { - var self = this; - var scheduledLookup = []; - var scheduledFunctions = {}; - var currentTime = 0; - var delayedFnCount = 0; - - self.tick = function(millis, tickDate) { - millis = millis || 0; - var endTime = currentTime + millis; - - runScheduledFunctions(endTime, tickDate); - currentTime = endTime; - }; - - self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) { - var f; - if (typeof(funcToCall) === 'string') { - /* jshint evil: true */ - f = function() { return eval(funcToCall); }; - /* jshint evil: false */ - } else { - f = funcToCall; - } - - millis = millis || 0; - timeoutKey = timeoutKey || ++delayedFnCount; - runAtMillis = runAtMillis || (currentTime + millis); - - var funcToSchedule = { - runAtMillis: runAtMillis, - funcToCall: f, - recurring: recurring, - params: params, - timeoutKey: timeoutKey, - millis: millis - }; - - if (runAtMillis in scheduledFunctions) { - scheduledFunctions[runAtMillis].push(funcToSchedule); - } else { - scheduledFunctions[runAtMillis] = [funcToSchedule]; - scheduledLookup.push(runAtMillis); - scheduledLookup.sort(function (a, b) { - return a - b; - }); - } - - return timeoutKey; - }; - - self.removeFunctionWithId = function(timeoutKey) { - for (var runAtMillis in scheduledFunctions) { - var funcs = scheduledFunctions[runAtMillis]; - var i = indexOfFirstToPass(funcs, function (func) { - return func.timeoutKey === timeoutKey; - }); - - if (i > -1) { - if (funcs.length === 1) { - delete scheduledFunctions[runAtMillis]; - deleteFromLookup(runAtMillis); - } else { - funcs.splice(i, 1); - } - - // intervals get rescheduled when executed, so there's never more - // than a single scheduled function with a given timeoutKey - break; - } - } - }; - - return self; - - function indexOfFirstToPass(array, testFn) { - var index = -1; - - for (var i = 0; i < array.length; ++i) { - if (testFn(array[i])) { - index = i; - break; - } - } - - return index; - } - - function deleteFromLookup(key) { - var value = Number(key); - var i = indexOfFirstToPass(scheduledLookup, function (millis) { - return millis === value; - }); - - if (i > -1) { - scheduledLookup.splice(i, 1); - } - } - - function reschedule(scheduledFn) { - self.scheduleFunction(scheduledFn.funcToCall, - scheduledFn.millis, - scheduledFn.params, - true, - scheduledFn.timeoutKey, - scheduledFn.runAtMillis + scheduledFn.millis); - } - - function forEachFunction(funcsToRun, callback) { - for (var i = 0; i < funcsToRun.length; ++i) { - callback(funcsToRun[i]); - } - } - - function runScheduledFunctions(endTime, tickDate) { - tickDate = tickDate || function() {}; - if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) { - tickDate(endTime - currentTime); - return; - } - - do { - var newCurrentTime = scheduledLookup.shift(); - tickDate(newCurrentTime - currentTime); - - currentTime = newCurrentTime; - - var funcsToRun = scheduledFunctions[currentTime]; - delete scheduledFunctions[currentTime]; - - forEachFunction(funcsToRun, function(funcToRun) { - if (funcToRun.recurring) { - reschedule(funcToRun); - } - }); - - forEachFunction(funcsToRun, function(funcToRun) { - funcToRun.funcToCall.apply(null, funcToRun.params || []); - }); - } while (scheduledLookup.length > 0 && - // checking first if we're out of time prevents setTimeout(0) - // scheduled in a funcToRun from forcing an extra iteration - currentTime !== endTime && - scheduledLookup[0] <= endTime); - - // ran out of functions to call, but still time left on the clock - if (currentTime !== endTime) { - tickDate(endTime - currentTime); - } - } - } - - return DelayedFunctionScheduler; -}; - -getJasmineRequireObj().errors = function() { - function ExpectationFailed() {} - - ExpectationFailed.prototype = new Error(); - ExpectationFailed.prototype.constructor = ExpectationFailed; - - return { - ExpectationFailed: ExpectationFailed - }; -}; -getJasmineRequireObj().ExceptionFormatter = function() { - function ExceptionFormatter() { - this.message = function(error) { - var message = ''; - - if (error.name && error.message) { - message += error.name + ': ' + error.message; - } else { - message += error.toString() + ' thrown'; - } - - if (error.fileName || error.sourceURL) { - message += ' in ' + (error.fileName || error.sourceURL); - } - - if (error.line || error.lineNumber) { - message += ' (line ' + (error.line || error.lineNumber) + ')'; - } - - return message; - }; - - this.stack = function(error) { - return error ? error.stack : null; - }; - } - - return ExceptionFormatter; -}; - -getJasmineRequireObj().Expectation = function() { - - /** - * Matchers that come with Jasmine out of the box. - * @namespace matchers - */ - function Expectation(options) { - this.util = options.util || { buildFailureMessage: function() {} }; - this.customEqualityTesters = options.customEqualityTesters || []; - this.actual = options.actual; - this.addExpectationResult = options.addExpectationResult || function(){}; - this.isNot = options.isNot; - - var customMatchers = options.customMatchers || {}; - for (var matcherName in customMatchers) { - this[matcherName] = Expectation.prototype.wrapCompare(matcherName, customMatchers[matcherName]); - } - } - - Expectation.prototype.wrapCompare = function(name, matcherFactory) { - return function() { - var args = Array.prototype.slice.call(arguments, 0), - expected = args.slice(0), - message = ''; - - args.unshift(this.actual); - - var matcher = matcherFactory(this.util, this.customEqualityTesters), - matcherCompare = matcher.compare; - - function defaultNegativeCompare() { - var result = matcher.compare.apply(null, args); - result.pass = !result.pass; - return result; - } - - if (this.isNot) { - matcherCompare = matcher.negativeCompare || defaultNegativeCompare; - } - - var result = matcherCompare.apply(null, args); - - if (!result.pass) { - if (!result.message) { - args.unshift(this.isNot); - args.unshift(name); - message = this.util.buildFailureMessage.apply(null, args); - } else { - if (Object.prototype.toString.apply(result.message) === '[object Function]') { - message = result.message(); - } else { - message = result.message; - } - } - } - - if (expected.length == 1) { - expected = expected[0]; - } - - // TODO: how many of these params are needed? - this.addExpectationResult( - result.pass, - { - matcherName: name, - passed: result.pass, - message: message, - error: result.error, - actual: this.actual, - expected: expected // TODO: this may need to be arrayified/sliced - } - ); - }; - }; - - Expectation.addCoreMatchers = function(matchers) { - var prototype = Expectation.prototype; - for (var matcherName in matchers) { - var matcher = matchers[matcherName]; - prototype[matcherName] = prototype.wrapCompare(matcherName, matcher); - } - }; - - Expectation.Factory = function(options) { - options = options || {}; - - var expect = new Expectation(options); - - // TODO: this would be nice as its own Object - NegativeExpectation - // TODO: copy instead of mutate options - options.isNot = true; - expect.not = new Expectation(options); - - return expect; - }; - - return Expectation; -}; - -//TODO: expectation result may make more sense as a presentation of an expectation. -getJasmineRequireObj().buildExpectationResult = function() { - function buildExpectationResult(options) { - var messageFormatter = options.messageFormatter || function() {}, - stackFormatter = options.stackFormatter || function() {}; - - var result = { - matcherName: options.matcherName, - message: message(), - stack: stack(), - passed: options.passed - }; - - if(!result.passed) { - result.expected = options.expected; - result.actual = options.actual; - } - - return result; - - function message() { - if (options.passed) { - return 'Passed.'; - } else if (options.message) { - return options.message; - } else if (options.error) { - return messageFormatter(options.error); - } - return ''; - } - - function stack() { - if (options.passed) { - return ''; - } - - var error = options.error; - if (!error) { - try { - throw new Error(message()); - } catch (e) { - error = e; - } - } - return stackFormatter(error); - } - } - - return buildExpectationResult; -}; - -getJasmineRequireObj().formatErrorMsg = function() { - function generateErrorMsg(domain, usage) { - var usageDefinition = usage ? '\nUsage: ' + usage : ''; - - return function errorMsg(msg) { - return domain + ' : ' + msg + usageDefinition; - }; - } - - return generateErrorMsg; -}; - -getJasmineRequireObj().GlobalErrors = function(j$) { - function GlobalErrors(global) { - var handlers = []; - global = global || j$.getGlobal(); - - var onerror = function onerror() { - var handler = handlers[handlers.length - 1]; - handler.apply(null, Array.prototype.slice.call(arguments, 0)); - }; - - this.uninstall = function noop() {}; - - this.install = function install() { - if (global.process && j$.isFunction_(global.process.on)) { - var originalHandlers = global.process.listeners('uncaughtException'); - global.process.removeAllListeners('uncaughtException'); - global.process.on('uncaughtException', onerror); - - this.uninstall = function uninstall() { - global.process.removeListener('uncaughtException', onerror); - for (var i = 0; i < originalHandlers.length; i++) { - global.process.on('uncaughtException', originalHandlers[i]); - } - }; - } else { - var originalHandler = global.onerror; - global.onerror = onerror; - - this.uninstall = function uninstall() { - global.onerror = originalHandler; - }; - } - }; - - this.pushListener = function pushListener(listener) { - handlers.push(listener); - }; - - this.popListener = function popListener() { - handlers.pop(); - }; - } - - return GlobalErrors; -}; - -getJasmineRequireObj().DiffBuilder = function(j$) { - return function DiffBuilder() { - var path = new j$.ObjectPath(), - mismatches = []; - - return { - record: function (actual, expected, formatter) { - formatter = formatter || defaultFormatter; - mismatches.push(formatter(actual, expected, path)); - }, - - getMessage: function () { - return mismatches.join('\n'); - }, - - withPath: function (pathComponent, block) { - var oldPath = path; - path = path.add(pathComponent); - block(); - path = oldPath; - } - }; - - function defaultFormatter (actual, expected, path) { - return 'Expected ' + - path + (path.depth() ? ' = ' : '') + - j$.pp(actual) + - ' to equal ' + - j$.pp(expected) + - '.'; - } - }; -}; - -getJasmineRequireObj().matchersUtil = function(j$) { - // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter? - - return { - equals: equals, - - contains: function(haystack, needle, customTesters) { - customTesters = customTesters || []; - - if ((Object.prototype.toString.apply(haystack) === '[object Set]')) { - return haystack.has(needle); - } - - if ((Object.prototype.toString.apply(haystack) === '[object Array]') || - (!!haystack && !haystack.indexOf)) - { - for (var i = 0; i < haystack.length; i++) { - if (equals(haystack[i], needle, customTesters)) { - return true; - } - } - return false; - } - - return !!haystack && haystack.indexOf(needle) >= 0; - }, - - buildFailureMessage: function() { - var args = Array.prototype.slice.call(arguments, 0), - matcherName = args[0], - isNot = args[1], - actual = args[2], - expected = args.slice(3), - englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); - - var message = 'Expected ' + - j$.pp(actual) + - (isNot ? ' not ' : ' ') + - englishyPredicate; - - if (expected.length > 0) { - for (var i = 0; i < expected.length; i++) { - if (i > 0) { - message += ','; - } - message += ' ' + j$.pp(expected[i]); - } - } - - return message + '.'; - } - }; - - function isAsymmetric(obj) { - return obj && j$.isA_('Function', obj.asymmetricMatch); - } - - function asymmetricMatch(a, b, customTesters, diffBuilder) { - var asymmetricA = isAsymmetric(a), - asymmetricB = isAsymmetric(b), - result; - - if (asymmetricA && asymmetricB) { - return undefined; - } - - if (asymmetricA) { - result = a.asymmetricMatch(b, customTesters); - diffBuilder.record(a, b); - return result; - } - - if (asymmetricB) { - result = b.asymmetricMatch(a, customTesters); - diffBuilder.record(a, b); - return result; - } - } - - function equals(a, b, customTesters, diffBuilder) { - customTesters = customTesters || []; - diffBuilder = diffBuilder || j$.NullDiffBuilder(); - - return eq(a, b, [], [], customTesters, diffBuilder); - } - - // Equality function lovingly adapted from isEqual in - // [Underscore](http://underscorejs.org) - function eq(a, b, aStack, bStack, customTesters, diffBuilder) { - var result = true, i; - - var asymmetricResult = asymmetricMatch(a, b, customTesters, diffBuilder); - if (!j$.util.isUndefined(asymmetricResult)) { - return asymmetricResult; - } - - for (i = 0; i < customTesters.length; i++) { - var customTesterResult = customTesters[i](a, b); - if (!j$.util.isUndefined(customTesterResult)) { - if (!customTesterResult) { - diffBuilder.record(a, b); - } - return customTesterResult; - } - } - - if (a instanceof Error && b instanceof Error) { - result = a.message == b.message; - if (!result) { - diffBuilder.record(a, b); - } - return result; - } - - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). - if (a === b) { - result = a !== 0 || 1 / a == 1 / b; - if (!result) { - diffBuilder.record(a, b); - } - return result; - } - // A strict comparison is necessary because `null == undefined`. - if (a === null || b === null) { - result = a === b; - if (!result) { - diffBuilder.record(a, b); - } - return result; - } - var className = Object.prototype.toString.call(a); - if (className != Object.prototype.toString.call(b)) { - diffBuilder.record(a, b); - return false; - } - switch (className) { - // Strings, numbers, dates, and booleans are compared by value. - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - result = a == String(b); - if (!result) { - diffBuilder.record(a, b); - } - return result; - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for - // other numeric values. - result = a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b); - if (!result) { - diffBuilder.record(a, b); - } - return result; - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - result = +a == +b; - if (!result) { - diffBuilder.record(a, b); - } - return result; - // RegExps are compared by their source patterns and flags. - case '[object RegExp]': - return a.source == b.source && - a.global == b.global && - a.multiline == b.multiline && - a.ignoreCase == b.ignoreCase; - } - if (typeof a != 'object' || typeof b != 'object') { - diffBuilder.record(a, b); - return false; - } - - var aIsDomNode = j$.isDomNode(a); - var bIsDomNode = j$.isDomNode(b); - if (aIsDomNode && bIsDomNode) { - // At first try to use DOM3 method isEqualNode - if (a.isEqualNode) { - result = a.isEqualNode(b); - if (!result) { - diffBuilder.record(a, b); - } - return result; - } - // IE8 doesn't support isEqualNode, try to use outerHTML && innerText - var aIsElement = a instanceof Element; - var bIsElement = b instanceof Element; - if (aIsElement && bIsElement) { - result = a.outerHTML == b.outerHTML; - if (!result) { - diffBuilder.record(a, b); - } - return result; - } - if (aIsElement || bIsElement) { - diffBuilder.record(a, b); - return false; - } - result = a.innerText == b.innerText && a.textContent == b.textContent; - if (!result) { - diffBuilder.record(a, b); - } - return result; - } - if (aIsDomNode || bIsDomNode) { - diffBuilder.record(a, b); - return false; - } - - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] == a) { return bStack[length] == b; } - } - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - var size = 0; - // Recursively compare objects and arrays. - // Compare array lengths to determine if a deep comparison is necessary. - if (className == '[object Array]') { - size = a.length; - if (size !== b.length) { - diffBuilder.record(a, b); - return false; - } - - for (i = 0; i < size; i++) { - diffBuilder.withPath(i, function() { - result = eq(a[i], b[i], aStack, bStack, customTesters, diffBuilder) && result; - }); - } - if (!result) { - return false; - } - } else if (className == '[object Set]') { - if (a.size != b.size) { - diffBuilder.record(a, b); - return false; - } - var iterA = a.values(), iterB = b.values(); - var valA, valB; - do { - valA = iterA.next(); - valB = iterB.next(); - if (!eq(valA.value, valB.value, aStack, bStack, customTesters, j$.NullDiffBuilder())) { - diffBuilder.record(a, b); - return false; - } - } while (!valA.done && !valB.done); - } else { - - // Objects with different constructors are not equivalent, but `Object`s - // or `Array`s from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && - isFunction(aCtor) && isFunction(bCtor) && - a instanceof aCtor && b instanceof bCtor && - !(aCtor instanceof aCtor && bCtor instanceof bCtor)) { - - diffBuilder.record(a, b, constructorsAreDifferentFormatter); - return false; - } - } - - // Deep compare objects. - var aKeys = keys(a, className == '[object Array]'), key; - size = aKeys.length; - - // Ensure that both objects contain the same number of properties before comparing deep equality. - if (keys(b, className == '[object Array]').length !== size) { - diffBuilder.record(a, b, objectKeysAreDifferentFormatter); - return false; - } - - for (i = 0; i < size; i++) { - key = aKeys[i]; - // Deep compare each member - if (!j$.util.has(b, key)) { - diffBuilder.record(a, b, objectKeysAreDifferentFormatter); - result = false; - continue; - } - - diffBuilder.withPath(key, function() { - if(!eq(a[key], b[key], aStack, bStack, customTesters, diffBuilder)) { - result = false; - } - }); - } - - if (!result) { - return false; - } - - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - - return result; - } - - function keys(obj, isArray) { - var allKeys = Object.keys ? Object.keys(obj) : - (function(o) { - var keys = []; - for (var key in o) { - if (j$.util.has(o, key)) { - keys.push(key); - } - } - return keys; - })(obj); - - if (!isArray) { - return allKeys; - } - - if (allKeys.length === 0) { - return allKeys; - } - - var extraKeys = []; - for (var i in allKeys) { - if (!allKeys[i].match(/^[0-9]+$/)) { - extraKeys.push(allKeys[i]); - } - } - - return extraKeys; - } - - function has(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); - } - - function isFunction(obj) { - return typeof obj === 'function'; - } - - function objectKeysAreDifferentFormatter(actual, expected, path) { - var missingProperties = j$.util.objectDifference(expected, actual), - extraProperties = j$.util.objectDifference(actual, expected), - missingPropertiesMessage = formatKeyValuePairs(missingProperties), - extraPropertiesMessage = formatKeyValuePairs(extraProperties), - messages = []; - - if (!path.depth()) { - path = 'object'; - } - - if (missingPropertiesMessage.length) { - messages.push('Expected ' + path + ' to have properties' + missingPropertiesMessage); - } - - if (extraPropertiesMessage.length) { - messages.push('Expected ' + path + ' not to have properties' + extraPropertiesMessage); - } - - return messages.join('\n'); - } - - function constructorsAreDifferentFormatter(actual, expected, path) { - if (!path.depth()) { - path = 'object'; - } - - return 'Expected ' + - path + ' to be a kind of ' + - j$.fnNameFor(expected.constructor) + - ', but was ' + j$.pp(actual) + '.'; - } - - function formatKeyValuePairs(obj) { - var formatted = ''; - for (var key in obj) { - formatted += '\n ' + key + ': ' + j$.pp(obj[key]); - } - return formatted; - } -}; - -getJasmineRequireObj().NullDiffBuilder = function(j$) { - return function() { - return { - withPath: function(_, block) { - block(); - }, - record: function() {} - }; - }; -}; - -getJasmineRequireObj().ObjectPath = function(j$) { - function ObjectPath(components) { - this.components = components || []; - } - - ObjectPath.prototype.toString = function() { - if (this.components.length) { - return '$' + map(this.components, formatPropertyAccess).join(''); - } else { - return ''; - } - }; - - ObjectPath.prototype.add = function(component) { - return new ObjectPath(this.components.concat([component])); - }; - - ObjectPath.prototype.depth = function() { - return this.components.length; - }; - - function formatPropertyAccess(prop) { - if (typeof prop === 'number') { - return '[' + prop + ']'; - } - - if (isValidIdentifier(prop)) { - return '.' + prop; - } - - return '[\'' + prop + '\']'; - } - - function map(array, fn) { - var results = []; - for (var i = 0; i < array.length; i++) { - results.push(fn(array[i])); - } - return results; - } - - function isValidIdentifier(string) { - return /^[A-Za-z\$_][A-Za-z0-9\$_]*$/.test(string); - } - - return ObjectPath; -}; - -getJasmineRequireObj().toBe = function() { - /** - * {@link expect} the actual value to be `===` to the expected value. - * @function - * @name matchers#toBe - * @param {Object} expected - The expected value to compare against. - * @example - * expect(thing).toBe(realThing); - */ - function toBe() { - return { - compare: function(actual, expected) { - return { - pass: actual === expected - }; - } - }; - } - - return toBe; -}; - -getJasmineRequireObj().toBeCloseTo = function() { - /** - * {@link expect} the actual value to be within a specified precision of the expected value. - * @function - * @name matchers#toBeCloseTo - * @param {Object} expected - The expected value to compare against. - * @param {Number} [precision=2] - The number of decimal points to check. - * @example - * expect(number).toBeCloseTo(42.2, 3); - */ - function toBeCloseTo() { - return { - compare: function(actual, expected, precision) { - if (precision !== 0) { - precision = precision || 2; - } - - return { - pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) - }; - } - }; - } - - return toBeCloseTo; -}; - -getJasmineRequireObj().toBeDefined = function() { - /** - * {@link expect} the actual value to be defined. (Not `undefined`) - * @function - * @name matchers#toBeDefined - * @example - * expect(result).toBeDefined(); - */ - function toBeDefined() { - return { - compare: function(actual) { - return { - pass: (void 0 !== actual) - }; - } - }; - } - - return toBeDefined; -}; - -getJasmineRequireObj().toBeFalsy = function() { - /** - * {@link expect} the actual value to be falsy - * @function - * @name matchers#toBeFalsy - * @example - * expect(result).toBeFalsy(); - */ - function toBeFalsy() { - return { - compare: function(actual) { - return { - pass: !!!actual - }; - } - }; - } - - return toBeFalsy; -}; - -getJasmineRequireObj().toBeGreaterThan = function() { - /** - * {@link expect} the actual value to be greater than the expected value. - * @function - * @name matchers#toBeGreaterThan - * @param {Number} expected - The value to compare against. - * @example - * expect(result).toBeGreaterThan(3); - */ - function toBeGreaterThan() { - return { - compare: function(actual, expected) { - return { - pass: actual > expected - }; - } - }; - } - - return toBeGreaterThan; -}; - - -getJasmineRequireObj().toBeGreaterThanOrEqual = function() { - /** - * {@link expect} the actual value to be greater than or equal to the expected value. - * @function - * @name matchers#toBeGreaterThanOrEqual - * @param {Number} expected - The expected value to compare against. - * @example - * expect(result).toBeGreaterThanOrEqual(25); - */ - function toBeGreaterThanOrEqual() { - return { - compare: function(actual, expected) { - return { - pass: actual >= expected - }; - } - }; - } - - return toBeGreaterThanOrEqual; -}; - -getJasmineRequireObj().toBeLessThan = function() { - /** - * {@link expect} the actual value to be less than the expected value. - * @function - * @name matchers#toBeLessThan - * @param {Number} expected - The expected value to compare against. - * @example - * expect(result).toBeLessThan(0); - */ - function toBeLessThan() { - return { - - compare: function(actual, expected) { - return { - pass: actual < expected - }; - } - }; - } - - return toBeLessThan; -}; - -getJasmineRequireObj().toBeLessThanOrEqual = function() { - /** - * {@link expect} the actual value to be less than or equal to the expected value. - * @function - * @name matchers#toBeLessThanOrEqual - * @param {Number} expected - The expected value to compare against. - * @example - * expect(result).toBeLessThanOrEqual(123); - */ - function toBeLessThanOrEqual() { - return { - - compare: function(actual, expected) { - return { - pass: actual <= expected - }; - } - }; - } - - return toBeLessThanOrEqual; -}; - -getJasmineRequireObj().toBeNaN = function(j$) { - /** - * {@link expect} the actual value to be `NaN` (Not a Number). - * @function - * @name matchers#toBeNaN - * @example - * expect(thing).toBeNaN(); - */ - function toBeNaN() { - return { - compare: function(actual) { - var result = { - pass: (actual !== actual) - }; - - if (result.pass) { - result.message = 'Expected actual not to be NaN.'; - } else { - result.message = function() { return 'Expected ' + j$.pp(actual) + ' to be NaN.'; }; - } - - return result; - } - }; - } - - return toBeNaN; -}; - -getJasmineRequireObj().toBeNegativeInfinity = function(j$) { - /** - * {@link expect} the actual value to be `-Infinity` (-infinity). - * @function - * @name matchers#toBeNegativeInfinity - * @example - * expect(thing).toBeNegativeInfinity(); - */ - function toBeNegativeInfinity() { - return { - compare: function(actual) { - var result = { - pass: (actual === Number.NEGATIVE_INFINITY) - }; - - if (result.pass) { - result.message = 'Expected actual to be -Infinity.'; - } else { - result.message = function() { return 'Expected ' + j$.pp(actual) + ' not to be -Infinity.'; }; - } - - return result; - } - }; - } - - return toBeNegativeInfinity; -}; - -getJasmineRequireObj().toBeNull = function() { - /** - * {@link expect} the actual value to be `null`. - * @function - * @name matchers#toBeNull - * @example - * expect(result).toBeNull(); - */ - function toBeNull() { - return { - compare: function(actual) { - return { - pass: actual === null - }; - } - }; - } - - return toBeNull; -}; - -getJasmineRequireObj().toBePositiveInfinity = function(j$) { - /** - * {@link expect} the actual value to be `Infinity` (infinity). - * @function - * @name matchers#toBePositiveInfinity - * @example - * expect(thing).toBePositiveInfinity(); - */ - function toBePositiveInfinity() { - return { - compare: function(actual) { - var result = { - pass: (actual === Number.POSITIVE_INFINITY) - }; - - if (result.pass) { - result.message = 'Expected actual to be Infinity.'; - } else { - result.message = function() { return 'Expected ' + j$.pp(actual) + ' not to be Infinity.'; }; - } - - return result; - } - }; - } - - return toBePositiveInfinity; -}; - -getJasmineRequireObj().toBeTruthy = function() { - /** - * {@link expect} the actual value to be truthy. - * @function - * @name matchers#toBeTruthy - * @example - * expect(thing).toBeTruthy(); - */ - function toBeTruthy() { - return { - compare: function(actual) { - return { - pass: !!actual - }; - } - }; - } - - return toBeTruthy; -}; - -getJasmineRequireObj().toBeUndefined = function() { - /** - * {@link expect} the actual value to be `undefined`. - * @function - * @name matchers#toBeUndefined - * @example - * expect(result).toBeUndefined(): - */ - function toBeUndefined() { - return { - compare: function(actual) { - return { - pass: void 0 === actual - }; - } - }; - } - - return toBeUndefined; -}; - -getJasmineRequireObj().toContain = function() { - /** - * {@link expect} the actual value to contain a specific value. - * @function - * @name matchers#toContain - * @param {Object} expected - The value to look for. - * @example - * expect(array).toContain(anElement); - * expect(string).toContain(substring); - */ - function toContain(util, customEqualityTesters) { - customEqualityTesters = customEqualityTesters || []; - - return { - compare: function(actual, expected) { - - return { - pass: util.contains(actual, expected, customEqualityTesters) - }; - } - }; - } - - return toContain; -}; - -getJasmineRequireObj().toEqual = function(j$) { - /** - * {@link expect} the actual value to be equal to the expected, using deep equality comparison. - * @function - * @name matchers#toEqual - * @param {Object} expected - Expected value - * @example - * expect(bigObject).toEqual({"foo": ['bar', 'baz']}); - */ - function toEqual(util, customEqualityTesters) { - customEqualityTesters = customEqualityTesters || []; - - return { - compare: function(actual, expected) { - var result = { - pass: false - }, - diffBuilder = j$.DiffBuilder(); - - result.pass = util.equals(actual, expected, customEqualityTesters, diffBuilder); - - // TODO: only set error message if test fails - result.message = diffBuilder.getMessage(); - - return result; - } - }; - } - - return toEqual; -}; - -getJasmineRequireObj().toHaveBeenCalled = function(j$) { - - var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalled()'); - - /** - * {@link expect} the actual (a {@link Spy}) to have been called. - * @function - * @name matchers#toHaveBeenCalled - * @example - * expect(mySpy).toHaveBeenCalled(); - * expect(mySpy).not.toHaveBeenCalled(); - */ - function toHaveBeenCalled() { - return { - compare: function(actual) { - var result = {}; - - if (!j$.isSpy(actual)) { - throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); - } - - if (arguments.length > 1) { - throw new Error(getErrorMsg('Does not take arguments, use toHaveBeenCalledWith')); - } - - result.pass = actual.calls.any(); - - result.message = result.pass ? - 'Expected spy ' + actual.and.identity() + ' not to have been called.' : - 'Expected spy ' + actual.and.identity() + ' to have been called.'; - - return result; - } - }; - } - - return toHaveBeenCalled; -}; - -getJasmineRequireObj().toHaveBeenCalledBefore = function(j$) { - - var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalledBefore()'); - - /** - * {@link expect} the actual value (a {@link Spy}) to have been called before another {@link Spy}. - * @function - * @name matchers#toHaveBeenCalledBefore - * @param {Spy} expected - {@link Spy} that should have been called after the `actual` {@link Spy}. - * @example - * expect(mySpy).toHaveBeenCalledBefore(otherSpy); - */ - function toHaveBeenCalledBefore() { - return { - compare: function(firstSpy, latterSpy) { - if (!j$.isSpy(firstSpy)) { - throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(firstSpy) + '.')); - } - if (!j$.isSpy(latterSpy)) { - throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(latterSpy) + '.')); - } - - var result = { pass: false }; - - if (!firstSpy.calls.count()) { - result.message = 'Expected spy ' + firstSpy.and.identity() + ' to have been called.'; - return result; - } - if (!latterSpy.calls.count()) { - result.message = 'Expected spy ' + latterSpy.and.identity() + ' to have been called.'; - return result; - } - - var latest1stSpyCall = firstSpy.calls.mostRecent().invocationOrder; - var first2ndSpyCall = latterSpy.calls.first().invocationOrder; - - result.pass = latest1stSpyCall < first2ndSpyCall; - - if (result.pass) { - result.message = 'Expected spy ' + firstSpy.and.identity() + ' to not have been called before spy ' + latterSpy.and.identity() + ', but it was'; - } else { - var first1stSpyCall = firstSpy.calls.first().invocationOrder; - var latest2ndSpyCall = latterSpy.calls.mostRecent().invocationOrder; - - if(first1stSpyCall < first2ndSpyCall) { - result.message = 'Expected latest call to spy ' + firstSpy.and.identity() + ' to have been called before first call to spy ' + latterSpy.and.identity() + ' (no interleaved calls)'; - } else if (latest2ndSpyCall > latest1stSpyCall) { - result.message = 'Expected first call to spy ' + latterSpy.and.identity() + ' to have been called after latest call to spy ' + firstSpy.and.identity() + ' (no interleaved calls)'; - } else { - result.message = 'Expected spy ' + firstSpy.and.identity() + ' to have been called before spy ' + latterSpy.and.identity(); - } - } - - return result; - } - }; - } - - return toHaveBeenCalledBefore; -}; - -getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) { - - var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalledTimes()'); - - /** - * {@link expect} the actual (a {@link Spy}) to have been called the specified number of times. - * @function - * @name matchers#toHaveBeenCalledTimes - * @param {Number} expected - The number of invocations to look for. - * @example - * expect(mySpy).toHaveBeenCalledTimes(3); - */ - function toHaveBeenCalledTimes() { - return { - compare: function(actual, expected) { - if (!j$.isSpy(actual)) { - throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); - } - - var args = Array.prototype.slice.call(arguments, 0), - result = { pass: false }; - - if (!j$.isNumber_(expected)){ - throw new Error(getErrorMsg('The expected times failed is a required argument and must be a number.')); - } - - actual = args[0]; - var calls = actual.calls.count(); - var timesMessage = expected === 1 ? 'once' : expected + ' times'; - result.pass = calls === expected; - result.message = result.pass ? - 'Expected spy ' + actual.and.identity() + ' not to have been called ' + timesMessage + '. It was called ' + calls + ' times.' : - 'Expected spy ' + actual.and.identity() + ' to have been called ' + timesMessage + '. It was called ' + calls + ' times.'; - return result; - } - }; - } - - return toHaveBeenCalledTimes; -}; - -getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { - - var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalledWith(...arguments)'); - - /** - * {@link expect} the actual (a {@link Spy}) to have been called with particular arguments at least once. - * @function - * @name matchers#toHaveBeenCalledWith - * @param {...Object} - The arguments to look for - * @example - * expect(mySpy).toHaveBeenCalledWith('foo', 'bar', 2); - */ - function toHaveBeenCalledWith(util, customEqualityTesters) { - return { - compare: function() { - var args = Array.prototype.slice.call(arguments, 0), - actual = args[0], - expectedArgs = args.slice(1), - result = { pass: false }; - - if (!j$.isSpy(actual)) { - throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); - } - - if (!actual.calls.any()) { - result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; }; - return result; - } - - if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { - result.pass = true; - result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; }; - } else { - result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; }; - } - - return result; - } - }; - } - - return toHaveBeenCalledWith; -}; - -getJasmineRequireObj().toMatch = function(j$) { - - var getErrorMsg = j$.formatErrorMsg('', 'expect().toMatch( || )'); - - /** - * {@link expect} the actual value to match a regular expression - * @function - * @name matchers#toMatch - * @param {RegExp|String} expected - Value to look for in the string. - * @example - * expect("my string").toMatch(/string$/); - * expect("other string").toMatch("her"); - */ - function toMatch() { - return { - compare: function(actual, expected) { - if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) { - throw new Error(getErrorMsg('Expected is not a String or a RegExp')); - } - - var regexp = new RegExp(expected); - - return { - pass: regexp.test(actual) - }; - } - }; - } - - return toMatch; -}; - -getJasmineRequireObj().toThrow = function(j$) { - - var getErrorMsg = j$.formatErrorMsg('', 'expect(function() {}).toThrow()'); - - /** - * {@link expect} a function to `throw` something. - * @function - * @name matchers#toThrow - * @param {Object} [expected] - Value that should be thrown. If not provided, simply the fact that something was thrown will be checked. - * @example - * expect(function() { return 'things'; }).toThrow('foo'); - * expect(function() { return 'stuff'; }).toThrow(); - */ - function toThrow(util) { - return { - compare: function(actual, expected) { - var result = { pass: false }, - threw = false, - thrown; - - if (typeof actual != 'function') { - throw new Error(getErrorMsg('Actual is not a Function')); - } - - try { - actual(); - } catch (e) { - threw = true; - thrown = e; - } - - if (!threw) { - result.message = 'Expected function to throw an exception.'; - return result; - } - - if (arguments.length == 1) { - result.pass = true; - result.message = function() { return 'Expected function not to throw, but it threw ' + j$.pp(thrown) + '.'; }; - - return result; - } - - if (util.equals(thrown, expected)) { - result.pass = true; - result.message = function() { return 'Expected function not to throw ' + j$.pp(expected) + '.'; }; - } else { - result.message = function() { return 'Expected function to throw ' + j$.pp(expected) + ', but it threw ' + j$.pp(thrown) + '.'; }; - } - - return result; - } - }; - } - - return toThrow; -}; - -getJasmineRequireObj().toThrowError = function(j$) { - - var getErrorMsg = j$.formatErrorMsg('', 'expect(function() {}).toThrowError(, )'); - - /** - * {@link expect} a function to `throw` an `Error`. - * @function - * @name matchers#toThrowError - * @param {Error} [expected] - `Error` constructor the object that was thrown needs to be an instance of. If not provided, `Error` will be used. - * @param {RegExp|String} [message] - The message that should be set on the thrown `Error` - * @example - * expect(function() { return 'things'; }).toThrowError(MyCustomError, 'message'); - * expect(function() { return 'things'; }).toThrowError(MyCustomError, /bar/); - * expect(function() { return 'stuff'; }).toThrowError(MyCustomError); - * expect(function() { return 'other'; }).toThrowError(/foo/); - * expect(function() { return 'other'; }).toThrowError(); - */ - function toThrowError () { - return { - compare: function(actual) { - var threw = false, - pass = {pass: true}, - fail = {pass: false}, - thrown; - - if (typeof actual != 'function') { - throw new Error(getErrorMsg('Actual is not a Function')); - } - - var errorMatcher = getMatcher.apply(null, arguments); - - try { - actual(); - } catch (e) { - threw = true; - thrown = e; - } - - if (!threw) { - fail.message = 'Expected function to throw an Error.'; - return fail; - } - - // Get Error constructor of thrown - if (!isErrorObject(thrown)) { - fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; - return fail; - } - - if (errorMatcher.hasNoSpecifics()) { - pass.message = 'Expected function not to throw an Error, but it threw ' + j$.fnNameFor(thrown) + '.'; - return pass; - } - - if (errorMatcher.matches(thrown)) { - pass.message = function() { - return 'Expected function not to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() + '.'; - }; - return pass; - } else { - fail.message = function() { - return 'Expected function to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() + - ', but it threw ' + errorMatcher.thrownDescription(thrown) + '.'; - }; - return fail; - } - } - }; - - function getMatcher() { - var expected = null, - errorType = null; - - if (arguments.length == 2) { - expected = arguments[1]; - if (isAnErrorType(expected)) { - errorType = expected; - expected = null; - } - } else if (arguments.length > 2) { - errorType = arguments[1]; - expected = arguments[2]; - if (!isAnErrorType(errorType)) { - throw new Error(getErrorMsg('Expected error type is not an Error.')); - } - } - - if (expected && !isStringOrRegExp(expected)) { - if (errorType) { - throw new Error(getErrorMsg('Expected error message is not a string or RegExp.')); - } else { - throw new Error(getErrorMsg('Expected is not an Error, string, or RegExp.')); - } - } - - function messageMatch(message) { - if (typeof expected == 'string') { - return expected == message; - } else { - return expected.test(message); - } - } - - return { - errorTypeDescription: errorType ? j$.fnNameFor(errorType) : 'an exception', - thrownDescription: function(thrown) { - var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception', - thrownMessage = ''; - - if (expected) { - thrownMessage = ' with message ' + j$.pp(thrown.message); - } - - return thrownName + thrownMessage; - }, - messageDescription: function() { - if (expected === null) { - return ''; - } else if (expected instanceof RegExp) { - return ' with a message matching ' + j$.pp(expected); - } else { - return ' with message ' + j$.pp(expected); - } - }, - hasNoSpecifics: function() { - return expected === null && errorType === null; - }, - matches: function(error) { - return (errorType === null || error instanceof errorType) && - (expected === null || messageMatch(error.message)); - } - }; - } - - function isStringOrRegExp(potential) { - return potential instanceof RegExp || (typeof potential == 'string'); - } - - function isAnErrorType(type) { - if (typeof type !== 'function') { - return false; - } - - var Surrogate = function() {}; - Surrogate.prototype = type.prototype; - return isErrorObject(new Surrogate()); - } - - function isErrorObject(thrown) { - if (thrown instanceof Error) { - return true; - } - if (thrown && thrown.constructor && thrown.constructor.constructor && - (thrown instanceof (thrown.constructor.constructor('return this')()).Error)) { - return true; - } - return false; - } - } - - return toThrowError; -}; - -getJasmineRequireObj().MockDate = function() { - function MockDate(global) { - var self = this; - var currentTime = 0; - - if (!global || !global.Date) { - self.install = function() {}; - self.tick = function() {}; - self.uninstall = function() {}; - return self; - } - - var GlobalDate = global.Date; - - self.install = function(mockDate) { - if (mockDate instanceof GlobalDate) { - currentTime = mockDate.getTime(); - } else { - currentTime = new GlobalDate().getTime(); - } - - global.Date = FakeDate; - }; - - self.tick = function(millis) { - millis = millis || 0; - currentTime = currentTime + millis; - }; - - self.uninstall = function() { - currentTime = 0; - global.Date = GlobalDate; - }; - - createDateProperties(); - - return self; - - function FakeDate() { - switch(arguments.length) { - case 0: - return new GlobalDate(currentTime); - case 1: - return new GlobalDate(arguments[0]); - case 2: - return new GlobalDate(arguments[0], arguments[1]); - case 3: - return new GlobalDate(arguments[0], arguments[1], arguments[2]); - case 4: - return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3]); - case 5: - return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], - arguments[4]); - case 6: - return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], - arguments[4], arguments[5]); - default: - return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], - arguments[4], arguments[5], arguments[6]); - } - } - - function createDateProperties() { - FakeDate.prototype = GlobalDate.prototype; - - FakeDate.now = function() { - if (GlobalDate.now) { - return currentTime; - } else { - throw new Error('Browser does not support Date.now()'); - } - }; - - FakeDate.toSource = GlobalDate.toSource; - FakeDate.toString = GlobalDate.toString; - FakeDate.parse = GlobalDate.parse; - FakeDate.UTC = GlobalDate.UTC; - } - } - - return MockDate; -}; - -getJasmineRequireObj().pp = function(j$) { - - function PrettyPrinter() { - this.ppNestLevel_ = 0; - this.seen = []; - } - - function hasCustomToString(value) { - // value.toString !== Object.prototype.toString if value has no custom toString but is from another context (e.g. - // iframe, web worker) - return value.toString !== Object.prototype.toString && (value.toString() !== Object.prototype.toString.call(value)); - } - - PrettyPrinter.prototype.format = function(value) { - this.ppNestLevel_++; - try { - if (j$.util.isUndefined(value)) { - this.emitScalar('undefined'); - } else if (value === null) { - this.emitScalar('null'); - } else if (value === 0 && 1/value === -Infinity) { - this.emitScalar('-0'); - } else if (value === j$.getGlobal()) { - this.emitScalar(''); - } else if (value.jasmineToString) { - this.emitScalar(value.jasmineToString()); - } else if (typeof value === 'string') { - this.emitString(value); - } else if (j$.isSpy(value)) { - this.emitScalar('spy on ' + value.and.identity()); - } else if (value instanceof RegExp) { - this.emitScalar(value.toString()); - } else if (typeof value === 'function') { - this.emitScalar('Function'); - } else if (typeof value.nodeType === 'number') { - this.emitScalar('HTMLNode'); - } else if (value instanceof Date) { - this.emitScalar('Date(' + value + ')'); - } else if (value.toString && value.toString() == '[object Set]') { - this.emitSet(value); - } else if (value.toString && typeof value === 'object' && !j$.isArray_(value) && hasCustomToString(value)) { - this.emitScalar(value.toString()); - } else if (j$.util.arrayContains(this.seen, value)) { - this.emitScalar(''); - } else if (j$.isArray_(value) || j$.isA_('Object', value)) { - this.seen.push(value); - if (j$.isArray_(value)) { - this.emitArray(value); - } else { - this.emitObject(value); - } - this.seen.pop(); - } else { - this.emitScalar(value.toString()); - } - } finally { - this.ppNestLevel_--; - } - }; - - PrettyPrinter.prototype.iterateObject = function(obj, fn) { - for (var property in obj) { - if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } - fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && - obj.__lookupGetter__(property) !== null) : false); - } - }; - - PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; - PrettyPrinter.prototype.emitSet = j$.unimplementedMethod_; - PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_; - PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_; - PrettyPrinter.prototype.emitString = j$.unimplementedMethod_; - - function StringPrettyPrinter() { - PrettyPrinter.call(this); - - this.string = ''; - } - - j$.util.inherit(StringPrettyPrinter, PrettyPrinter); - - StringPrettyPrinter.prototype.emitScalar = function(value) { - this.append(value); - }; - - StringPrettyPrinter.prototype.emitString = function(value) { - this.append('\'' + value + '\''); - }; - - StringPrettyPrinter.prototype.emitArray = function(array) { - if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { - this.append('Array'); - return; - } - var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); - this.append('[ '); - for (var i = 0; i < length; i++) { - if (i > 0) { - this.append(', '); - } - this.format(array[i]); - } - if(array.length > length){ - this.append(', ...'); - } - - var self = this; - var first = array.length === 0; - this.iterateObject(array, function(property, isGetter) { - if (property.match(/^\d+$/)) { - return; - } - - if (first) { - first = false; - } else { - self.append(', '); - } - - self.formatProperty(array, property, isGetter); - }); - - this.append(' ]'); - }; - - StringPrettyPrinter.prototype.emitSet = function(set) { - if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { - this.append('Set'); - return; - } - this.append('Set( '); - var size = Math.min(set.size, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); - var iter = set.values(); - for (var i = 0; i < size; i++) { - if (i > 0) { - this.append(', '); - } - this.format(iter.next().value); - } - if (set.size > size){ - this.append(', ...'); - } - this.append(' )'); - }; - - StringPrettyPrinter.prototype.emitObject = function(obj) { - var ctor = obj.constructor, - constructorName; - - constructorName = typeof ctor === 'function' && obj instanceof ctor ? - j$.fnNameFor(obj.constructor) : - 'null'; - - this.append(constructorName); - - if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { - return; - } - - var self = this; - this.append('({ '); - var first = true; - - this.iterateObject(obj, function(property, isGetter) { - if (first) { - first = false; - } else { - self.append(', '); - } - - self.formatProperty(obj, property, isGetter); - }); - - this.append(' })'); - }; - - StringPrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) { - this.append(property); - this.append(': '); - if (isGetter) { - this.append(''); - } else { - this.format(obj[property]); - } - }; - - StringPrettyPrinter.prototype.append = function(value) { - this.string += value; - }; - - return function(value) { - var stringPrettyPrinter = new StringPrettyPrinter(); - stringPrettyPrinter.format(value); - return stringPrettyPrinter.string; - }; -}; - -getJasmineRequireObj().QueueRunner = function(j$) { - - function once(fn) { - var called = false; - return function() { - if (!called) { - called = true; - fn(); - } - return null; - }; - } - - function QueueRunner(attrs) { - this.queueableFns = attrs.queueableFns || []; - this.onComplete = attrs.onComplete || function() {}; - this.clearStack = attrs.clearStack || function(fn) {fn();}; - this.onException = attrs.onException || function() {}; - this.catchException = attrs.catchException || function() { return true; }; - this.userContext = attrs.userContext || {}; - this.timeout = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; - this.fail = attrs.fail || function() {}; - this.globalErrors = attrs.globalErrors || { pushListener: function() {}, popListener: function() {} }; - } - - QueueRunner.prototype.execute = function() { - this.run(this.queueableFns, 0); - }; - - QueueRunner.prototype.run = function(queueableFns, recursiveIndex) { - var length = queueableFns.length, - self = this, - iterativeIndex; - - - for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) { - var queueableFn = queueableFns[iterativeIndex]; - if (queueableFn.fn.length > 0) { - attemptAsync(queueableFn); - return; - } else { - attemptSync(queueableFn); - } - } - - this.clearStack(this.onComplete); - - function attemptSync(queueableFn) { - try { - queueableFn.fn.call(self.userContext); - } catch (e) { - handleException(e, queueableFn); - } - } - - function attemptAsync(queueableFn) { - var clearTimeout = function () { - Function.prototype.apply.apply(self.timeout.clearTimeout, [j$.getGlobal(), [timeoutId]]); - }, - handleError = function(error) { - onException(error); - next(); - }, - next = once(function () { - clearTimeout(timeoutId); - self.globalErrors.popListener(handleError); - self.run(queueableFns, iterativeIndex + 1); - }), - timeoutId; - - next.fail = function() { - self.fail.apply(null, arguments); - next(); - }; - - self.globalErrors.pushListener(handleError); - - if (queueableFn.timeout) { - timeoutId = Function.prototype.apply.apply(self.timeout.setTimeout, [j$.getGlobal(), [function() { - var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'); - onException(error); - next(); - }, queueableFn.timeout()]]); - } - - try { - queueableFn.fn.call(self.userContext, next); - } catch (e) { - handleException(e, queueableFn); - next(); - } - } - - function onException(e) { - self.onException(e); - } - - function handleException(e, queueableFn) { - onException(e); - if (!self.catchException(e)) { - //TODO: set a var when we catch an exception and - //use a finally block to close the loop in a nice way.. - throw e; - } - } - }; - - return QueueRunner; -}; - -getJasmineRequireObj().ReportDispatcher = function() { - function ReportDispatcher(methods) { - - var dispatchedMethods = methods || []; - - for (var i = 0; i < dispatchedMethods.length; i++) { - var method = dispatchedMethods[i]; - this[method] = (function(m) { - return function() { - dispatch(m, arguments); - }; - }(method)); - } - - var reporters = []; - var fallbackReporter = null; - - this.addReporter = function(reporter) { - reporters.push(reporter); - }; - - this.provideFallbackReporter = function(reporter) { - fallbackReporter = reporter; - }; - - this.clearReporters = function() { - reporters = []; - }; - - return this; - - function dispatch(method, args) { - if (reporters.length === 0 && fallbackReporter !== null) { - reporters.push(fallbackReporter); - } - for (var i = 0; i < reporters.length; i++) { - var reporter = reporters[i]; - if (reporter[method]) { - reporter[method].apply(reporter, args); - } - } - } - } - - return ReportDispatcher; -}; - - -getJasmineRequireObj().interface = function(jasmine, env) { - var jasmineInterface = { - /** - * Create a group of specs (often called a suite). - * - * Calls to `describe` can be nested within other calls to compose your suite as a tree. - * @name describe - * @function - * @global - * @param {String} description Textual description of the group - * @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs - */ - describe: function(description, specDefinitions) { - return env.describe(description, specDefinitions); - }, - - /** - * A temporarily disabled [`describe`]{@link describe} - * - * Specs within an `xdescribe` will be marked pending and not executed - * @name xdescribe - * @function - * @global - * @param {String} description Textual description of the group - * @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs - */ - xdescribe: function(description, specDefinitions) { - return env.xdescribe(description, specDefinitions); - }, - - /** - * A focused [`describe`]{@link describe} - * - * If suites or specs are focused, only those that are focused will be executed - * @see fit - * @name fdescribe - * @function - * @global - * @param {String} description Textual description of the group - * @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs - */ - fdescribe: function(description, specDefinitions) { - return env.fdescribe(description, specDefinitions); - }, - - /** - * Define a single spec. A spec should contain one or more {@link expect|expectations} that test the state of the code. - * - * A spec whose expectations all succeed will be passing and a spec with any failures will fail. - * @name it - * @function - * @global - * @param {String} description Textual description of what this spec is checking - * @param {Function} [testFunction] Function that contains the code of your test. If not provided the test will be `pending`. - * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec. - */ - it: function() { - return env.it.apply(env, arguments); - }, - - /** - * A temporarily disabled [`it`]{@link it} - * - * The spec will report as `pending` and will not be executed. - * @name xit - * @function - * @global - * @param {String} description Textual description of what this spec is checking. - * @param {Function} [testFunction] Function that contains the code of your test. Will not be executed. - */ - xit: function() { - return env.xit.apply(env, arguments); - }, - - /** - * A focused [`it`]{@link it} - * - * If suites or specs are focused, only those that are focused will be executed. - * @name fit - * @function - * @global - * @param {String} description Textual description of what this spec is checking. - * @param {Function} testFunction Function that contains the code of your test. - * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec. - */ - fit: function() { - return env.fit.apply(env, arguments); - }, - - /** - * Run some shared setup before each of the specs in the {@link describe} in which it is called. - * @name beforeEach - * @function - * @global - * @param {Function} [function] Function that contains the code to setup your specs. - * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeEach. - */ - beforeEach: function() { - return env.beforeEach.apply(env, arguments); - }, - - /** - * Run some shared teardown after each of the specs in the {@link describe} in which it is called. - * @name afterEach - * @function - * @global - * @param {Function} [function] Function that contains the code to teardown your specs. - * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterEach. - */ - afterEach: function() { - return env.afterEach.apply(env, arguments); - }, - - /** - * Run some shared setup once before all of the specs in the {@link describe} are run. - * - * _Note:_ Be careful, sharing the setup from a beforeAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail. - * @name beforeAll - * @function - * @global - * @param {Function} [function] Function that contains the code to setup your specs. - * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeAll. - */ - beforeAll: function() { - return env.beforeAll.apply(env, arguments); - }, - - /** - * Run some shared teardown once before all of the specs in the {@link describe} are run. - * - * _Note:_ Be careful, sharing the teardown from a afterAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail. - * @name afterAll - * @function - * @global - * @param {Function} [function] Function that contains the code to teardown your specs. - * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterAll. - */ - afterAll: function() { - return env.afterAll.apply(env, arguments); - }, - - /** - * Create an expectation for a spec. - * @name expect - * @function - * @global - * @param {Object} actual - Actual computed value to test expectations against. - * @return {matchers} - */ - expect: function(actual) { - return env.expect(actual); - }, - - /** - * Mark a spec as pending, expectation results will be ignored. - * @name pending - * @function - * @global - * @param {String} [message] - Reason the spec is pending. - */ - pending: function() { - return env.pending.apply(env, arguments); - }, - - /** - * Explicitly mark a spec as failed. - * @name fail - * @function - * @global - * @param {String|Error} [error] - Reason for the failure. - */ - fail: function() { - return env.fail.apply(env, arguments); - }, - - /** - * Install a spy onto an existing object. - * @name spyOn - * @function - * @global - * @param {Object} obj - The object upon which to install the {@link Spy}. - * @param {String} methodName - The name of the method to replace with a {@link Spy}. - * @returns {Spy} - */ - spyOn: function(obj, methodName) { - return env.spyOn(obj, methodName); - }, - - /** - * Install a spy on a property onto an existing object. - * @name spyOnProperty - * @function - * @global - * @param {Object} obj - The object upon which to install the {@link Spy} - * @param {String} propertyName - The name of the property to replace with a {@link Spy}. - * @param {String} [accessType=get] - The access type (get|set) of the property to {@link Spy} on. - * @returns {Spy} - */ - spyOnProperty: function(obj, methodName, accessType) { - return env.spyOnProperty(obj, methodName, accessType); - }, - - jsApiReporter: new jasmine.JsApiReporter({ - timer: new jasmine.Timer() - }), - - /** - * @namespace jasmine - */ - jasmine: jasmine - }; - - /** - * Add a custom equality tester for the current scope of specs. - * - * _Note:_ This is only callable from within a {@link beforeEach}, {@link it}, or {@link beforeAll}. - * @name jasmine.addCustomEqualityTester - * @function - * @param {Function} tester - A function which takes two arguments to compare and returns a `true` or `false` comparison result if it knows how to compare them, and `undefined` otherwise. - * @see custom_equality - */ - jasmine.addCustomEqualityTester = function(tester) { - env.addCustomEqualityTester(tester); - }; - - /** - * Add custom matchers for the current scope of specs. - * - * _Note:_ This is only callable from within a {@link beforeEach}, {@link it}, or {@link beforeAll}. - * @name jasmine.addMatchers - * @function - * @param {Object} matchers - Keys from this object will be the new matcher names. - * @see custom_matcher - */ - jasmine.addMatchers = function(matchers) { - return env.addMatchers(matchers); - }; - - /** - * Get the currently booted mock {Clock} for this Jasmine environment. - * @name jasmine.clock - * @function - * @returns {Clock} - */ - jasmine.clock = function() { - return env.clock; - }; - - return jasmineInterface; -}; - -getJasmineRequireObj().Spy = function (j$) { - - var nextOrder = (function() { - var order = 0; - - return function() { - return order++; - }; - })(); - - /** - * _Note:_ Do not construct this directly, use {@link spyOn}, {@link spyOnProperty}, {@link jasmine.createSpy}, or {@link jasmine.createSpyObj} - * @constructor - * @name Spy - */ - function Spy(name, originalFn) { - var args = buildArgs(), - /*`eval` is the only option to preserve both this and context: - - former is needed to work as expected with methods, - - latter is needed to access real spy function and allows to reduce eval'ed code to absolute minimum - More explanation here (look at comments): http://www.bennadel.com/blog/1909-javascript-function-constructor-does-not-create-a-closure.htm - */ - /* jshint evil: true */ - wrapper = eval('(0, function (' + args + ') { return spy.apply(this, Array.prototype.slice.call(arguments)); })'), - /* jshint evil: false */ - spyStrategy = new j$.SpyStrategy({ - name: name, - fn: originalFn, - getSpy: function () { - return wrapper; - } - }), - callTracker = new j$.CallTracker(), - spy = function () { - /** - * @name Spy.callData - * @property {object} object - `this` context for the invocation. - * @property {number} invocationOrder - Order of the invocation. - * @property {Array} args - The arguments passed for this invocation. - */ - var callData = { - object: this, - invocationOrder: nextOrder(), - args: Array.prototype.slice.apply(arguments) - }; - - callTracker.track(callData); - var returnValue = spyStrategy.exec.apply(this, arguments); - callData.returnValue = returnValue; - - return returnValue; - }; - - function buildArgs() { - var args = []; - - while (originalFn instanceof Function && args.length < originalFn.length) { - args.push('arg' + args.length); - } - - return args.join(', '); - } - - for (var prop in originalFn) { - if (prop === 'and' || prop === 'calls') { - throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon'); - } - - wrapper[prop] = originalFn[prop]; - } - - wrapper.and = spyStrategy; - wrapper.calls = callTracker; - - return wrapper; - } - - return Spy; -}; - -getJasmineRequireObj().SpyRegistry = function(j$) { - - var getErrorMsg = j$.formatErrorMsg('', 'spyOn(, )'); - - function SpyRegistry(options) { - options = options || {}; - var currentSpies = options.currentSpies || function() { return []; }; - - this.allowRespy = function(allow){ - this.respy = allow; - }; - - this.spyOn = function(obj, methodName) { - - if (j$.util.isUndefined(obj) || obj === null) { - throw new Error(getErrorMsg('could not find an object to spy upon for ' + methodName + '()')); - } - - if (j$.util.isUndefined(methodName) || methodName === null) { - throw new Error(getErrorMsg('No method name supplied')); - } - - if (j$.util.isUndefined(obj[methodName])) { - throw new Error(getErrorMsg(methodName + '() method does not exist')); - } - - if (obj[methodName] && j$.isSpy(obj[methodName]) ) { - if ( !!this.respy ){ - return obj[methodName]; - }else { - throw new Error(getErrorMsg(methodName + ' has already been spied upon')); - } - } - - var descriptor; - try { - descriptor = Object.getOwnPropertyDescriptor(obj, methodName); - } catch(e) { - // IE 8 doesn't support `definePropery` on non-DOM nodes - } - - if (descriptor && !(descriptor.writable || descriptor.set)) { - throw new Error(getErrorMsg(methodName + ' is not declared writable or has no setter')); - } - - var originalMethod = obj[methodName], - spiedMethod = j$.createSpy(methodName, originalMethod), - restoreStrategy; - - if (Object.prototype.hasOwnProperty.call(obj, methodName)) { - restoreStrategy = function() { - obj[methodName] = originalMethod; - }; - } else { - restoreStrategy = function() { - if (!delete obj[methodName]) { - obj[methodName] = originalMethod; - } - }; - } - - currentSpies().push({ - restoreObjectToOriginalState: restoreStrategy - }); - - obj[methodName] = spiedMethod; - - return spiedMethod; - }; - - this.spyOnProperty = function (obj, propertyName, accessType) { - accessType = accessType || 'get'; - - if (j$.util.isUndefined(obj)) { - throw new Error('spyOn could not find an object to spy upon for ' + propertyName + ''); - } - - if (j$.util.isUndefined(propertyName)) { - throw new Error('No property name supplied'); - } - - var descriptor; - try { - descriptor = j$.util.getPropertyDescriptor(obj, propertyName); - } catch(e) { - // IE 8 doesn't support `definePropery` on non-DOM nodes - } - - if (!descriptor) { - throw new Error(propertyName + ' property does not exist'); - } - - if (!descriptor.configurable) { - throw new Error(propertyName + ' is not declared configurable'); - } - - if(!descriptor[accessType]) { - throw new Error('Property ' + propertyName + ' does not have access type ' + accessType); - } - - if (j$.isSpy(descriptor[accessType])) { - //TODO?: should this return the current spy? Downside: may cause user confusion about spy state - throw new Error(propertyName + ' has already been spied upon'); - } - - var originalDescriptor = j$.util.clone(descriptor), - spy = j$.createSpy(propertyName, descriptor[accessType]), - restoreStrategy; - - if (Object.prototype.hasOwnProperty.call(obj, propertyName)) { - restoreStrategy = function() { - Object.defineProperty(obj, propertyName, originalDescriptor); - }; - } else { - restoreStrategy = function() { - delete obj[propertyName]; - }; - } - - currentSpies().push({ - restoreObjectToOriginalState: restoreStrategy - }); - - descriptor[accessType] = spy; - - Object.defineProperty(obj, propertyName, descriptor); - - return spy; - }; - - this.clearSpies = function() { - var spies = currentSpies(); - for (var i = spies.length - 1; i >= 0; i--) { - var spyEntry = spies[i]; - spyEntry.restoreObjectToOriginalState(); - } - }; - } - - return SpyRegistry; -}; - -getJasmineRequireObj().SpyStrategy = function(j$) { - - /** - * @namespace Spy#and - */ - function SpyStrategy(options) { - options = options || {}; - - var identity = options.name || 'unknown', - originalFn = options.fn || function() {}, - getSpy = options.getSpy || function() {}, - plan = function() {}; - - /** - * Return the identifying information for the spy. - * @name Spy#and#identity - * @function - * @returns {String} - */ - this.identity = function() { - return identity; - }; - - /** - * Execute the current spy strategy. - * @name Spy#and#exec - * @function - */ - this.exec = function() { - return plan.apply(this, arguments); - }; - - /** - * Tell the spy to call through to the real implementation when invoked. - * @name Spy#and#callThrough - * @function - */ - this.callThrough = function() { - plan = originalFn; - return getSpy(); - }; - - /** - * Tell the spy to return the value when invoked. - * @name Spy#and#returnValue - * @function - * @param {*} value The value to return. - */ - this.returnValue = function(value) { - plan = function() { - return value; - }; - return getSpy(); - }; - - /** - * Tell the spy to return one of the specified values (sequentially) each time the spy is invoked. - * @name Spy#and#returnValues - * @function - * @param {...*} values - Values to be returned on subsequent calls to the spy. - */ - this.returnValues = function() { - var values = Array.prototype.slice.call(arguments); - plan = function () { - return values.shift(); - }; - return getSpy(); - }; - - /** - * Tell the spy to throw an error when invoked. - * @name Spy#and#throwError - * @function - * @param {Error|String} something Thing to throw - */ - this.throwError = function(something) { - var error = (something instanceof Error) ? something : new Error(something); - plan = function() { - throw error; - }; - return getSpy(); - }; - - /** - * Tell the spy to call a fake implementation when invoked. - * @name Spy#and#callFake - * @function - * @param {Function} fn The function to invoke with the passed parameters. - */ - this.callFake = function(fn) { - if(!j$.isFunction_(fn)) { - throw new Error('Argument passed to callFake should be a function, got ' + fn); - } - plan = fn; - return getSpy(); - }; - - /** - * Tell the spy to do nothing when invoked. This is the default. - * @name Spy#and#stub - * @function - */ - this.stub = function(fn) { - plan = function() {}; - return getSpy(); - }; - } - - return SpyStrategy; -}; - -getJasmineRequireObj().Suite = function(j$) { - function Suite(attrs) { - this.env = attrs.env; - this.id = attrs.id; - this.parentSuite = attrs.parentSuite; - this.description = attrs.description; - this.expectationFactory = attrs.expectationFactory; - this.expectationResultFactory = attrs.expectationResultFactory; - this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; - - this.beforeFns = []; - this.afterFns = []; - this.beforeAllFns = []; - this.afterAllFns = []; - - this.children = []; - - this.result = { - id: this.id, - description: this.description, - fullName: this.getFullName(), - failedExpectations: [] - }; - } - - Suite.prototype.expect = function(actual) { - return this.expectationFactory(actual, this); - }; - - Suite.prototype.getFullName = function() { - var fullName = []; - for (var parentSuite = this; parentSuite; parentSuite = parentSuite.parentSuite) { - if (parentSuite.parentSuite) { - fullName.unshift(parentSuite.description); - } - } - return fullName.join(' '); - }; - - Suite.prototype.pend = function() { - this.markedPending = true; - }; - - Suite.prototype.beforeEach = function(fn) { - this.beforeFns.unshift(fn); - }; - - Suite.prototype.beforeAll = function(fn) { - this.beforeAllFns.push(fn); - }; - - Suite.prototype.afterEach = function(fn) { - this.afterFns.unshift(fn); - }; - - Suite.prototype.afterAll = function(fn) { - this.afterAllFns.unshift(fn); - }; - - Suite.prototype.addChild = function(child) { - this.children.push(child); - }; - - Suite.prototype.status = function() { - if (this.markedPending) { - return 'pending'; - } - - if (this.result.failedExpectations.length > 0) { - return 'failed'; - } else { - return 'finished'; - } - }; - - Suite.prototype.isExecutable = function() { - return !this.markedPending; - }; - - Suite.prototype.canBeReentered = function() { - return this.beforeAllFns.length === 0 && this.afterAllFns.length === 0; - }; - - Suite.prototype.getResult = function() { - this.result.status = this.status(); - return this.result; - }; - - Suite.prototype.sharedUserContext = function() { - if (!this.sharedContext) { - this.sharedContext = this.parentSuite ? clone(this.parentSuite.sharedUserContext()) : {}; - } - - return this.sharedContext; - }; - - Suite.prototype.clonedSharedUserContext = function() { - return clone(this.sharedUserContext()); - }; - - Suite.prototype.onException = function() { - if (arguments[0] instanceof j$.errors.ExpectationFailed) { - return; - } - - if(isAfterAll(this.children)) { - var data = { - matcherName: '', - passed: false, - expected: '', - actual: '', - error: arguments[0] - }; - this.result.failedExpectations.push(this.expectationResultFactory(data)); - } else { - for (var i = 0; i < this.children.length; i++) { - var child = this.children[i]; - child.onException.apply(child, arguments); - } - } - }; - - Suite.prototype.addExpectationResult = function () { - if(isAfterAll(this.children) && isFailure(arguments)){ - var data = arguments[1]; - this.result.failedExpectations.push(this.expectationResultFactory(data)); - if(this.throwOnExpectationFailure) { - throw new j$.errors.ExpectationFailed(); - } - } else { - for (var i = 0; i < this.children.length; i++) { - var child = this.children[i]; - try { - child.addExpectationResult.apply(child, arguments); - } catch(e) { - // keep going - } - } - } - }; - - function isAfterAll(children) { - return children && children[0].result.status; - } - - function isFailure(args) { - return !args[0]; - } - - function clone(obj) { - var clonedObj = {}; - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { - clonedObj[prop] = obj[prop]; - } - } - - return clonedObj; - } - - return Suite; -}; - -if (typeof window == void 0 && typeof exports == 'object') { - exports.Suite = jasmineRequire.Suite; -} - -getJasmineRequireObj().Timer = function() { - var defaultNow = (function(Date) { - return function() { return new Date().getTime(); }; - })(Date); - - function Timer(options) { - options = options || {}; - - var now = options.now || defaultNow, - startTime; - - this.start = function() { - startTime = now(); - }; - - this.elapsed = function() { - return now() - startTime; - }; - } - - return Timer; -}; - -getJasmineRequireObj().TreeProcessor = function() { - function TreeProcessor(attrs) { - var tree = attrs.tree, - runnableIds = attrs.runnableIds, - queueRunnerFactory = attrs.queueRunnerFactory, - nodeStart = attrs.nodeStart || function() {}, - nodeComplete = attrs.nodeComplete || function() {}, - orderChildren = attrs.orderChildren || function(node) { return node.children; }, - stats = { valid: true }, - processed = false, - defaultMin = Infinity, - defaultMax = 1 - Infinity; - - this.processTree = function() { - processNode(tree, false); - processed = true; - return stats; - }; - - this.execute = function(done) { - if (!processed) { - this.processTree(); - } - - if (!stats.valid) { - throw 'invalid order'; - } - - var childFns = wrapChildren(tree, 0); - - queueRunnerFactory({ - queueableFns: childFns, - userContext: tree.sharedUserContext(), - onException: function() { - tree.onException.apply(tree, arguments); - }, - onComplete: done - }); - }; - - function runnableIndex(id) { - for (var i = 0; i < runnableIds.length; i++) { - if (runnableIds[i] === id) { - return i; - } - } - } - - function processNode(node, parentEnabled) { - var executableIndex = runnableIndex(node.id); - - if (executableIndex !== undefined) { - parentEnabled = true; - } - - parentEnabled = parentEnabled && node.isExecutable(); - - if (!node.children) { - stats[node.id] = { - executable: parentEnabled && node.isExecutable(), - segments: [{ - index: 0, - owner: node, - nodes: [node], - min: startingMin(executableIndex), - max: startingMax(executableIndex) - }] - }; - } else { - var hasExecutableChild = false; - - var orderedChildren = orderChildren(node); - - for (var i = 0; i < orderedChildren.length; i++) { - var child = orderedChildren[i]; - - processNode(child, parentEnabled); - - if (!stats.valid) { - return; - } - - var childStats = stats[child.id]; - - hasExecutableChild = hasExecutableChild || childStats.executable; - } - - stats[node.id] = { - executable: hasExecutableChild - }; - - segmentChildren(node, orderedChildren, stats[node.id], executableIndex); - - if (!node.canBeReentered() && stats[node.id].segments.length > 1) { - stats = { valid: false }; - } - } - } - - function startingMin(executableIndex) { - return executableIndex === undefined ? defaultMin : executableIndex; - } - - function startingMax(executableIndex) { - return executableIndex === undefined ? defaultMax : executableIndex; - } - - function segmentChildren(node, orderedChildren, nodeStats, executableIndex) { - var currentSegment = { index: 0, owner: node, nodes: [], min: startingMin(executableIndex), max: startingMax(executableIndex) }, - result = [currentSegment], - lastMax = defaultMax, - orderedChildSegments = orderChildSegments(orderedChildren); - - function isSegmentBoundary(minIndex) { - return lastMax !== defaultMax && minIndex !== defaultMin && lastMax < minIndex - 1; - } - - for (var i = 0; i < orderedChildSegments.length; i++) { - var childSegment = orderedChildSegments[i], - maxIndex = childSegment.max, - minIndex = childSegment.min; - - if (isSegmentBoundary(minIndex)) { - currentSegment = {index: result.length, owner: node, nodes: [], min: defaultMin, max: defaultMax}; - result.push(currentSegment); - } - - currentSegment.nodes.push(childSegment); - currentSegment.min = Math.min(currentSegment.min, minIndex); - currentSegment.max = Math.max(currentSegment.max, maxIndex); - lastMax = maxIndex; - } - - nodeStats.segments = result; - } - - function orderChildSegments(children) { - var specifiedOrder = [], - unspecifiedOrder = []; - - for (var i = 0; i < children.length; i++) { - var child = children[i], - segments = stats[child.id].segments; - - for (var j = 0; j < segments.length; j++) { - var seg = segments[j]; - - if (seg.min === defaultMin) { - unspecifiedOrder.push(seg); - } else { - specifiedOrder.push(seg); - } - } - } - - specifiedOrder.sort(function(a, b) { - return a.min - b.min; - }); - - return specifiedOrder.concat(unspecifiedOrder); - } - - function executeNode(node, segmentNumber) { - if (node.children) { - return { - fn: function(done) { - nodeStart(node); - - queueRunnerFactory({ - onComplete: function() { - nodeComplete(node, node.getResult()); - done(); - }, - queueableFns: wrapChildren(node, segmentNumber), - userContext: node.sharedUserContext(), - onException: function() { - node.onException.apply(node, arguments); - } - }); - } - }; - } else { - return { - fn: function(done) { node.execute(done, stats[node.id].executable); } - }; - } - } - - function wrapChildren(node, segmentNumber) { - var result = [], - segmentChildren = stats[node.id].segments[segmentNumber].nodes; - - for (var i = 0; i < segmentChildren.length; i++) { - result.push(executeNode(segmentChildren[i].owner, segmentChildren[i].index)); - } - - if (!stats[node.id].executable) { - return result; - } - - return node.beforeAllFns.concat(result).concat(node.afterAllFns); - } - } - - return TreeProcessor; -}; - -getJasmineRequireObj().version = function() { - return '2.6.0'; -}; diff --git a/spec/lib/jasmine-2.6.0/jasmine_favicon.png b/spec/lib/jasmine-2.6.0/jasmine_favicon.png deleted file mode 100644 index 3b84583..0000000 Binary files a/spec/lib/jasmine-2.6.0/jasmine_favicon.png and /dev/null differ diff --git a/spec/spec/animator.js b/spec/spec/animator.js index a36408c..b1834b4 100644 --- a/spec/spec/animator.js +++ b/spec/spec/animator.js @@ -3,6 +3,9 @@ describe('SVG.Animator', function () { beforeEach(function () { jasmine.RequestAnimationFrame.install() SVG.Animator.timer = jasmine.RequestAnimationFrame.mockPerf + SVG.Animator.timeouts = new SVG.Queue() + SVG.Animator.frames = new SVG.Queue() + SVG.Animator.nextDraw = null }) afterEach(function () { diff --git a/spec/spec/helper.js b/spec/spec/helper.js index a77b3e7..f8992ac 100644 --- a/spec/spec/helper.js +++ b/spec/spec/helper.js @@ -1,6 +1,3 @@ -// create canavs -//var drawing, window = window, document = document, SVG = SVG - parserInDoc = false if(typeof exports === 'object'){ @@ -133,22 +130,24 @@ if(typeof exports === 'object'){ parserInDoc |= 0 drawing.id = 'drawing' -draw = SVG().addTo(drawing).size(100,100) +//draw = SVG().addTo(drawing) parser = parserInDoc ? [SVG.parser.draw.instance] : [] // raw path data svgPath = 'M88.006,61.994c3.203,0,6.216-1.248,8.481-3.514C98.752,56.215,100,53.203,100,50c0-3.204-1.248-6.216-3.513-8.481 c-2.266-2.265-5.278-3.513-8.481-3.513c-2.687,0-5.237,0.877-7.327,2.496h-7.746l5.479-5.479 c5.891-0.757,10.457-5.803,10.457-11.896c0-6.614-5.381-11.995-11.994-11.995c-6.093,0-11.14,4.567-11.896,10.457l-5.479,5.479 v-7.747c1.618-2.089,2.495-4.641,2.495-7.327c0-3.204-1.247-6.216-3.513-8.481C56.216,1.248,53.204,0,50,0 c-3.204,0-6.216,1.248-8.481,3.513c-2.265,2.265-3.513,5.277-3.513,8.481c0,2.686,0.877,5.237,2.495,7.327v7.747l-5.479-5.479 c-0.757-5.89-5.803-10.457-11.896-10.457c-6.614,0-11.995,5.381-11.995,11.995c0,6.093,4.567,11.139,10.458,11.896l5.479,5.479 h-7.747c-2.089-1.619-4.641-2.496-7.327-2.496c-3.204,0-6.216,1.248-8.481,3.513C1.248,43.784,0,46.796,0,50 c0,3.203,1.248,6.216,3.513,8.48c2.265,2.266,5.277,3.514,8.481,3.514c2.686,0,5.237-0.877,7.327-2.496h7.747l-5.479,5.479 c-5.891,0.757-10.458,5.804-10.458,11.896c0,6.614,5.381,11.994,11.995,11.994c6.093,0,11.139-4.566,11.896-10.457l5.479-5.479 v7.749c-3.63,4.7-3.291,11.497,1.018,15.806C43.784,98.752,46.796,100,50,100c3.204,0,6.216-1.248,8.481-3.514 c4.309-4.309,4.647-11.105,1.018-15.806v-7.749l5.479,5.479c0.757,5.891,5.804,10.457,11.896,10.457 c6.613,0,11.994-5.38,11.994-11.994c0-6.093-4.566-11.14-10.457-11.896l-5.479-5.479h7.746 C82.769,61.117,85.319,61.994,88.006,61.994z M76.874,68.354c4.705,0,8.52,3.814,8.52,8.521c0,4.705-3.814,8.52-8.52,8.52 s-8.52-3.814-8.52-8.52l-12.33-12.33V81.98c3.327,3.328,3.327,8.723,0,12.049c-3.327,3.328-8.722,3.328-12.049,0 c-3.327-3.326-3.327-8.721,0-12.049V64.544l-12.33,12.33c0,4.705-3.814,8.52-8.52,8.52s-8.52-3.814-8.52-8.52 c0-4.706,3.814-8.521,8.52-8.521l12.33-12.33H18.019c-3.327,3.328-8.722,3.328-12.049,0c-3.327-3.326-3.327-8.721,0-12.048 s8.722-3.327,12.049,0h17.438l-12.33-12.33c-4.706,0-8.52-3.814-8.52-8.52c0-4.706,3.814-8.52,8.52-8.52s8.52,3.814,8.52,8.52 l12.33,12.33V18.019c-3.327-3.327-3.327-8.722,0-12.049s8.722-3.327,12.049,0s3.327,8.722,0,12.049v17.438l12.33-12.33 c0-4.706,3.814-8.52,8.52-8.52s8.52,3.814,8.52,8.52c0,4.705-3.814,8.52-8.52,8.52l-12.33,12.33h17.438 c3.327-3.327,8.722-3.327,12.049,0s3.327,8.722,0,12.048c-3.327,3.328-8.722,3.328-12.049,0H64.544L76.874,68.354z' -// image url - - // lorem ipsum text loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sodales\n imperdiet auctor. Nunc ultrices lectus at erat dictum pharetra\n elementum ante posuere. Duis turpis risus, blandit nec elementum et,\n posuere eget lacus. Aliquam et risus magna, eu aliquet nibh. Fusce\n consequat mi quis purus varius sagittis euismod urna interdum.\n Curabitur aliquet orci quis felis semper vulputate. Vestibulum ac nisi\n magna, id dictum diam. Proin sed metus vel magna blandit\n sodales. Pellentesque at neque ultricies nunc euismod rutrum ut in\n lorem. Mauris euismod tellus in tellus tempus interdum. Phasellus\n mattis sapien et leo feugiat dictum. Vestibulum at volutpat velit.' beforeEach(function(){ // test for touch device this.isTouchDevice = 'ontouchstart' in document.documentElement + draw = SVG().addTo(drawing).size(100,100) +}) + +afterEach(function(){ + draw.remove() }) // strip spaces from result diff --git a/spec/spec/selector.js b/spec/spec/selector.js index 43f3823..99823cf 100644 --- a/spec/spec/selector.js +++ b/spec/spec/selector.js @@ -28,7 +28,7 @@ describe('Selector', function() { e5 = draw.rect(100, 100).addClass('selectable-element') }) it('gets all elements with a given class name', function() { - expect(SVG.find('rect.selectable-element').valueOf()).toEqual([e1, e3, e5]) + expect(SVG.find('rect.selectable-element')).toEqual([e1, e3, e5]) }) it('returns an Array', function() { expect(SVG.find('rect.selectable-element') instanceof Array).toBe(true) diff --git a/src/A.js b/src/A.js index 02a4e0b..5bd1719 100644 --- a/src/A.js +++ b/src/A.js @@ -1,8 +1,8 @@ import Container from './Container.js' -import {nodeOrNew} from './tools.js' -import {xlink} from './namespaces.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { nodeOrNew } from './tools.js' +import { xlink } from './namespaces.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class A extends Container { constructor (node) { diff --git a/src/Animator.js b/src/Animator.js index eca6ee3..b015163 100644 --- a/src/Animator.js +++ b/src/Animator.js @@ -77,8 +77,8 @@ const Animator = { // If we have remaining timeouts or frames, draw until we don't anymore Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() - ? window.requestAnimationFrame(Animator._draw) - : null + ? window.requestAnimationFrame(Animator._draw) + : null } } diff --git a/src/ArrayPolyfill.js b/src/ArrayPolyfill.js index 19c1ede..cf95d54 100644 --- a/src/ArrayPolyfill.js +++ b/src/ArrayPolyfill.js @@ -1,18 +1,18 @@ +/* eslint no-new-func: "off" */ export const subClassArray = (function () { try { // try es6 subclassing return Function('name', 'baseClass', '_constructor', [ 'baseClass = baseClass || Array', 'return {', - '[name]: class extends baseClass {', - 'constructor (...args) {', - 'super(...args)', - '_constructor && _constructor.apply(this, args)', - '}', - '}', + '[name]: class extends baseClass {', + 'constructor (...args) {', + 'super(...args)', + '_constructor && _constructor.apply(this, args)', + '}', + '}', '}[name]' ].join('\n')) - } catch (e) { // Use es5 approach return (name, baseClass = Array, _constructor) => { diff --git a/src/Bare.js b/src/Bare.js index c08d8fc..7b3be98 100644 --- a/src/Bare.js +++ b/src/Bare.js @@ -1,8 +1,7 @@ -import {nodeOrNew} from './tools.js' -import {register} from './adopter.js' +import { nodeOrNew } from './tools.js' +import { register } from './adopter.js' import Container from './Container.js' -import {registerMethods} from './methods.js' -import {extend} from './tools.js' +import { registerMethods } from './methods.js' export default class Bare extends Container { constructor (node) { diff --git a/src/Base.js b/src/Base.js index 1e76bb4..d2897a1 100644 --- a/src/Base.js +++ b/src/Base.js @@ -1,14 +1,10 @@ export default class Base { - constructor (node/*, {extensions = []}*/) { - // this.tags = [] - // - // for (let extension of extensions) { - // extension.setup.call(this, node) - // this.tags.push(extension.name) - // } - } - - is (ability) { - return this.tags.includes(ability) - } + // constructor (node/*, {extensions = []} */) { + // // this.tags = [] + // // + // // for (let extension of extensions) { + // // extension.setup.call(this, node) + // // this.tags.push(extension.name) + // // } + // } } diff --git a/src/Box.js b/src/Box.js index c2bd5d5..148beb3 100644 --- a/src/Box.js +++ b/src/Box.js @@ -1,9 +1,8 @@ import Point from './Point.js' import parser from './parser.js' -import {fullBox, domContains, isNulledBox} from './helpers.js' -import {extend} from './tools.js' -import {delimiter} from './regex.js' -import {registerMethods} from './methods.js' +import { fullBox, domContains, isNulledBox } from './helpers.js' +import { delimiter } from './regex.js' +import { registerMethods } from './methods.js' export default class Box { constructor (...args) { @@ -14,10 +13,10 @@ export default class Box { var base = [0, 0, 0, 0] source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) : Array.isArray(source) ? source - : typeof source === 'object' ? [source.left != null ? source.left - : source.x, source.top != null ? source.top : source.y, source.width, source.height] - : arguments.length === 4 ? [].slice.call(arguments) - : base + : typeof source === 'object' ? [source.left != null ? source.left + : source.x, source.top != null ? source.top : source.y, source.width, source.height] + : arguments.length === 4 ? [].slice.call(arguments) + : base this.x = source[0] this.y = source[1] @@ -82,7 +81,7 @@ export default class Box { } } -function getBox(cb) { +function getBox (cb) { let box try { diff --git a/src/Circle.js b/src/Circle.js index 9d0c4db..8879eec 100644 --- a/src/Circle.js +++ b/src/Circle.js @@ -1,9 +1,9 @@ import Shape from './Shape.js' -import {nodeOrNew, extend} from './tools.js' -import {x, y, cx, cy, width, height, size} from './circled.js' +import { nodeOrNew, extend } from './tools.js' +import { x, y, cx, cy, width, height, size } from './circled.js' import SVGNumber from './SVGNumber.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class Circle extends Shape { constructor (node) { @@ -25,7 +25,7 @@ export default class Circle extends Shape { } } -extend(Circle, {x, y, cx, cy, width, height, size}) +extend(Circle, { x, y, cx, cy, width, height, size }) registerMethods({ Element: { diff --git a/src/ClipPath.js b/src/ClipPath.js index 1801c67..2321656 100644 --- a/src/ClipPath.js +++ b/src/ClipPath.js @@ -1,9 +1,9 @@ import Container from './Container.js' -import {nodeOrNew, extend} from './tools.js' +import { nodeOrNew } from './tools.js' import find from './selector.js' -//import {remove} from './Element.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +// import {remove} from './Element.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class ClipPath extends Container { constructor (node) { @@ -19,7 +19,7 @@ export default class ClipPath extends Container { // remove clipPath from parent return super.remove() - //return remove.call(this) + // return remove.call(this) } targets () { @@ -27,12 +27,11 @@ export default class ClipPath extends Container { } } - registerMethods({ Container: { // Create clipping element - clip: function() { - return this.defs().put(new ClipPath) + clip: function () { + return this.defs().put(new ClipPath()) } }, Element: { diff --git a/src/Color.js b/src/Color.js index de65750..ed3531c 100644 --- a/src/Color.js +++ b/src/Color.js @@ -1,5 +1,3 @@ -/* globals fullHex, compToHex */ - /* Color { @@ -29,8 +27,8 @@ SVG.hsl() SVG.lab('rgb(100, 100, 100)') */ -import {isHex, isRgb, whitespace, rgb, hex} from './regex.js' -import {fullHex, compToHex} from './helpers.js' +import { isHex, isRgb, whitespace, rgb, hex } from './regex.js' +import { fullHex, compToHex } from './helpers.js' export default class Color { constructor (...args) { diff --git a/src/Controller.js b/src/Controller.js index e3f2ab9..0bf5ac0 100644 --- a/src/Controller.js +++ b/src/Controller.js @@ -1,6 +1,6 @@ -import {timeline} from './defaults.js' -import {extend} from './tools.js' +import { timeline } from './defaults.js' +import { extend } from './tools.js' /*** Base Class @@ -29,7 +29,6 @@ export let easing = { } } - export class Stepper { done () { return false } } @@ -53,7 +52,6 @@ export class Ease extends Stepper { } } - /*** Controller Types ================ diff --git a/src/Defs.js b/src/Defs.js index 8cafb49..ddcf733 100644 --- a/src/Defs.js +++ b/src/Defs.js @@ -1,6 +1,6 @@ import Container from './Container.js' -import {nodeOrNew} from './tools.js' -import {register} from './adopter.js' +import { nodeOrNew } from './tools.js' +import { register } from './adopter.js' export default class Defs extends Container { constructor (node) { diff --git a/src/Doc.js b/src/Doc.js index 3d8c18c..d2c40ea 100644 --- a/src/Doc.js +++ b/src/Doc.js @@ -1,33 +1,32 @@ import Container from './Container.js' import Defs from './Defs.js' -import { extend, nodeOrNew } from './tools.js' +import { nodeOrNew } from './tools.js' import { ns, xlink, xmlns, svgjs } from './namespaces.js' -import {adopt, register} from './adopter.js' -import {registerMethods} from './methods.js' -//import {remove, parent, doc} from './Element.js' +import { adopt, register } from './adopter.js' +import { registerMethods } from './methods.js' export default class Doc extends Container { - constructor(node) { + constructor (node) { super(nodeOrNew('svg', node), Doc) this.namespace() } - isRoot() { - return !this.node.parentNode - || !(this.node.parentNode instanceof window.SVGElement) - || this.node.parentNode.nodeName === '#document' + isRoot () { + return !this.node.parentNode || + !(this.node.parentNode instanceof window.SVGElement) || + this.node.parentNode.nodeName === '#document' } // Check if this is a root svg // If not, call docs from this element - doc() { + doc () { if (this.isRoot()) return this return super.doc() - //return doc.call(this) + // return doc.call(this) } // Add namespaces - namespace() { + namespace () { if (!this.isRoot()) return this.doc().namespace() return this .attr({ xmlns: ns, version: '1.1' }) @@ -36,7 +35,7 @@ export default class Doc extends Container { } // Creates and returns defs element - defs() { + defs () { if (!this.isRoot()) return this.doc().defs() return adopt(this.node.getElementsByTagName('defs')[0]) || @@ -44,7 +43,7 @@ export default class Doc extends Container { } // custom parent method - parent(type) { + parent (type) { if (this.isRoot()) { return this.node.parentNode.nodeName === '#document' ? null @@ -52,7 +51,7 @@ export default class Doc extends Container { } return super.parent(type) - //return parent.call(this, type) + // return parent.call(this, type) } // Removes the doc from the DOM @@ -68,7 +67,7 @@ export default class Doc extends Container { // return this // } - clear() { + clear () { // remove children while (this.node.hasChildNodes()) { this.node.removeChild(this.node.lastChild) @@ -80,7 +79,7 @@ export default class Doc extends Container { registerMethods({ Container: { // Create nested svg document - nested() { + nested () { return this.put(new Doc()) } } diff --git a/src/Dom.js b/src/Dom.js index 515c872..488f3e0 100644 --- a/src/Dom.js +++ b/src/Dom.js @@ -1,8 +1,11 @@ import EventTarget from './EventTarget.js' -import {assignNewId, adopt, makeInstance, eid} from './adopter.js' -import {map} from './utils.js' -import {matcher} from './helpers.js' -import {ns} from './namespaces.js' +import { assignNewId, adopt, makeInstance, eid } from './adopter.js' +import { map } from './utils.js' +import { matcher } from './helpers.js' +import { ns } from './namespaces.js' + +import { extend } from './tools.js' +import attr from './attr.js' export default class Dom extends EventTarget { constructor (node) { @@ -231,7 +234,4 @@ export default class Dom extends EventTarget { return this } } - -import {extend} from './tools.js' -import attr from './attr.js' -extend(Dom, {attr}) +extend(Dom, { attr }) diff --git a/src/Element.js b/src/Element.js index e7944fc..8161b6a 100644 --- a/src/Element.js +++ b/src/Element.js @@ -1,7 +1,5 @@ -import {proportionalSize, matcher, idFromReference} from './helpers.js' -import {makeInstance, root, getClass} from './adopter.js' -import {delimiter} from './regex.js' -import {ns} from './namespaces.js' +import { proportionalSize, idFromReference } from './helpers.js' +import { makeInstance, root, getClass } from './adopter.js' import SVGNumber from './SVGNumber.js' import Dom from './Dom.js' @@ -139,8 +137,6 @@ export default class Element extends Dom { } } - - // registerMethods('Element', { // x, y, cx, cy, move, center, width, height, size, clone, remove, replace, // addTo, putIn, id, inside, toString, classes, hasClass, addClass, removeClass, diff --git a/src/Ellipse.js b/src/Ellipse.js index 21a1018..2cc1d09 100644 --- a/src/Ellipse.js +++ b/src/Ellipse.js @@ -1,8 +1,8 @@ import Shape from './Shape.js' import * as circled from './circled.js' -import {extend, nodeOrNew} from './tools.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { extend, nodeOrNew } from './tools.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class Ellipse extends Shape { constructor (node) { diff --git a/src/EventTarget.js b/src/EventTarget.js index 637f7f8..e306271 100644 --- a/src/EventTarget.js +++ b/src/EventTarget.js @@ -1,9 +1,9 @@ import Base from './Base.js' -import {on, off, dispatch} from './event.js' -import {extend} from './tools.js' +import { on, off, dispatch } from './event.js' +import { extend } from './tools.js' -export default class EventTarget extends Base{ - constructor ({events = {}} = {}) { +export default class EventTarget extends Base { + constructor ({ events = {} } = {}) { super() this.events = events } @@ -58,7 +58,6 @@ export default class EventTarget extends Base{ removeEventListener () {} } - // Add events to elements const methods = [ 'click', 'dblclick', @@ -74,23 +73,22 @@ const methods = [ 'click', 'touchleave', 'touchend', 'touchcancel' ].reduce(function (last, event) { - // add event to Element - const fn = function (f) { - if (f === null) { - off(this, event) - } else { - on(this, event, f) - } - return this + // add event to Element + const fn = function (f) { + if (f === null) { + off(this, event) + } else { + on(this, event, f) } + return this + } - last[event] = fn - return last - }, {}) + last[event] = fn + return last +}, {}) extend(EventTarget, methods) - // registerMethods('EventTarget', { // on, off, dispatch, fire // }) diff --git a/src/G.js b/src/G.js index d20aba2..2532f30 100644 --- a/src/G.js +++ b/src/G.js @@ -1,7 +1,7 @@ import Container from './Container.js' -import {nodeOrNew} from './tools.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { nodeOrNew } from './tools.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class G extends Container { constructor (node) { diff --git a/src/Gradient.js b/src/Gradient.js index 0f20173..7e8075e 100644 --- a/src/Gradient.js +++ b/src/Gradient.js @@ -1,11 +1,12 @@ import Stop from './Stop.js' import Container from './Container.js' import * as gradiented from './gradiented.js' -import {nodeOrNew, extend} from './tools.js' -//import attr from './attr.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { nodeOrNew, extend } from './tools.js' +// import attr from './attr.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' import Box from './Box.js' +import { find } from './selector.js' export default class Gradient extends Container { constructor (type) { @@ -47,7 +48,7 @@ export default class Gradient extends Container { attr (a, b, c) { if (a === 'transform') a = 'gradientTransform' return super.attr(a, b, c) - //return attr.call(this, a, b, c) + // return attr.call(this, a, b, c) } targets () { diff --git a/src/HtmlNode.js b/src/HtmlNode.js index ff45984..ced223f 100644 --- a/src/HtmlNode.js +++ b/src/HtmlNode.js @@ -1,5 +1,5 @@ import Dom from './Dom.js' -import {register} from './adopter.js' +import { register } from './adopter.js' export default class HtmlNode extends Dom { constructor (node) { diff --git a/src/Image.js b/src/Image.js index ea46a57..f257492 100644 --- a/src/Image.js +++ b/src/Image.js @@ -1,10 +1,10 @@ import Shape from './Shape.js' import Pattern from './Pattern.js' -import {on, off} from './event.js' -import {nodeOrNew} from './tools.js' -import {xlink} from './namespaces.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { on, off } from './event.js' +import { nodeOrNew } from './tools.js' +import { xlink } from './namespaces.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class Image extends Shape { constructor (node) { diff --git a/src/Line.js b/src/Line.js index 660b4f5..4028e48 100644 --- a/src/Line.js +++ b/src/Line.js @@ -1,9 +1,9 @@ -import {proportionalSize} from './helpers.js' -import {nodeOrNew, extend} from './tools.js' +import { proportionalSize } from './helpers.js' +import { nodeOrNew, extend } from './tools.js' import PointArray from './PointArray.js' import Shape from './Shape.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' import * as pointed from './pointed.js' export default class Line extends Shape { @@ -55,7 +55,7 @@ registerMethods({ // 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] + , args[0] != null ? args : [0, 0, 0, 0] ) } } diff --git a/src/Marker.js b/src/Marker.js index df19f20..16b2480 100644 --- a/src/Marker.js +++ b/src/Marker.js @@ -1,7 +1,7 @@ import Container from './Container.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' -import {nodeOrNew} from './tools.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' +import { nodeOrNew } from './tools.js' export default class Marker extends Container { // Initialize node diff --git a/src/Mask.js b/src/Mask.js index 40ebce7..fb599b9 100644 --- a/src/Mask.js +++ b/src/Mask.js @@ -1,9 +1,9 @@ import Container from './Container.js' -import {nodeOrNew} from './tools.js' +import { nodeOrNew } from './tools.js' import find from './selector.js' -//import {remove} from './Element.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +// import {remove} from './Element.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class Mask extends Container { // Initialize node @@ -20,16 +20,14 @@ export default class Mask extends Container { // remove mask from parent return super.remove() - //return remove.call(this) + // return remove.call(this) } targets () { return find('svg [mask*="' + this.id() + '"]') } - } - registerMethods({ Container: { mask () { diff --git a/src/Matrix.js b/src/Matrix.js index e6d3da0..00e4448 100644 --- a/src/Matrix.js +++ b/src/Matrix.js @@ -1,10 +1,10 @@ -import {abcdef, arrayToMatrix, closeEnough, isMatrixLike} from './helpers.js' +import { abcdef, arrayToMatrix, closeEnough, isMatrixLike } from './helpers.js' import Point from './Point.js' -import {delimiter} from './regex.js' -import {radians} from './utils.js' +import { delimiter } from './regex.js' +import { radians } from './utils.js' import parser from './parser.js' import Element from './Element.js' -import {registerMethods} from './methods.js' +import { registerMethods } from './methods.js' export default class Matrix { constructor (...args) { @@ -18,11 +18,11 @@ export default class Matrix { // ensure source as object source = source instanceof Element ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(delimiter).map(parseFloat)) - : Array.isArray(source) ? arrayToMatrix(source) - : (typeof source === 'object' && isMatrixLike(source)) ? source - : (typeof source === 'object') ? new Matrix().transform(source) - : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) - : base + : Array.isArray(source) ? arrayToMatrix(source) + : (typeof source === 'object' && isMatrixLike(source)) ? source + : (typeof source === 'object') ? new Matrix().transform(source) + : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) + : base // Merge the source matrix with the base matrix this.a = source.a != null ? source.a : base.a @@ -33,7 +33,6 @@ export default class Matrix { this.f = source.f != null ? source.f : base.f } - // Clones this matrix clone () { return new Matrix(this) @@ -249,7 +248,7 @@ export default class Matrix { y = x } - let {a, b, c, d, e, f} = this + let { a, b, c, d, e, f } = this this.a = a * x this.b = b * y @@ -273,7 +272,7 @@ export default class Matrix { let cos = Math.cos(r) let sin = Math.sin(r) - let {a, b, c, d, e, f} = this + let { a, b, c, d, e, f } = this this.a = a * cos - b * sin this.b = b * cos + a * sin @@ -293,7 +292,7 @@ export default class Matrix { flipO (axis, around) { return axis === 'x' ? this.scaleO(-1, 1, around, 0) : axis === 'y' ? this.scaleO(1, -1, 0, around) - : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point + : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point } // Shear matrix @@ -302,7 +301,7 @@ export default class Matrix { } shearO (lx, cx = 0, cy = 0) { - let {a, b, c, d, e, f} = this + let { a, b, c, d, e, f } = this this.a = a + b * lx this.c = c + d * lx @@ -331,7 +330,7 @@ export default class Matrix { let lx = Math.tan(x) let ly = Math.tan(y) - let {a, b, c, d, e, f} = this + let { a, b, c, d, e, f } = this this.a = a + b * lx this.b = b + a * ly @@ -413,7 +412,6 @@ export default class Matrix { } } - // TODO: Refactor this to a static function of matrix.js static formatTransforms (o) { // Get all of the parameters required to form the matrix @@ -422,20 +420,20 @@ export default class Matrix { var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1 var skewX = o.skew && o.skew.length ? o.skew[0] : isFinite(o.skew) ? o.skew - : isFinite(o.skewX) ? o.skewX - : 0 + : isFinite(o.skewX) ? o.skewX + : 0 var skewY = o.skew && o.skew.length ? o.skew[1] : isFinite(o.skew) ? o.skew - : isFinite(o.skewY) ? o.skewY - : 0 + : isFinite(o.skewY) ? o.skewY + : 0 var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX : isFinite(o.scale) ? o.scale * flipX - : isFinite(o.scaleX) ? o.scaleX * flipX - : flipX + : isFinite(o.scaleX) ? o.scaleX * flipX + : flipX var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY - : isFinite(o.scaleY) ? o.scaleY * flipY - : flipY + : isFinite(o.scaleY) ? o.scaleY * flipY + : flipY var shear = o.shear || 0 var theta = o.rotate || o.theta || 0 var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY) diff --git a/src/Morphable.js b/src/Morphable.js index 18f5a3b..f9dd7f0 100644 --- a/src/Morphable.js +++ b/src/Morphable.js @@ -1,13 +1,10 @@ -import {extend} from './tools.js' -import {Ease} from './Controller.js' +import { extend } from './tools.js' +import { Ease } from './Controller.js' import Color from './Color.js' import SVGNumber from './SVGNumber.js' import SVGArray from './SVGArray.js' -import PointArray from './PointArray.js' import PathArray from './PathArray.js' -import Box from './Box.js' -import Matrix from './Matrix.js' -import {delimiter, pathLetters, numberAndUnit} from './regex.js' +import { delimiter, pathLetters, numberAndUnit } from './regex.js' export default class Morphable { constructor (stepper) { diff --git a/src/Path.js b/src/Path.js index 42ab411..3557e22 100644 --- a/src/Path.js +++ b/src/Path.js @@ -1,10 +1,10 @@ -import {proportionalSize} from './helpers.js' -import {nodeOrNew} from './tools.js' +import { proportionalSize } from './helpers.js' +import { nodeOrNew } from './tools.js' import Shape from './Shape.js' import PathArray from './PathArray.js' import find from './selector.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class Path extends Shape { // Initialize node diff --git a/src/PathArray.js b/src/PathArray.js index 8529bf9..5c4fa5e 100644 --- a/src/PathArray.js +++ b/src/PathArray.js @@ -1,10 +1,10 @@ -import {arrayToString, pathRegReplace} from './helpers.js' +import { arrayToString, pathRegReplace } from './helpers.js' import parser from './parser.js' -import {numbersWithDots, pathLetters, hyphen, delimiter, isPathLetter} from './regex.js' +import { numbersWithDots, pathLetters, hyphen, delimiter, isPathLetter } from './regex.js' import Point from './Point.js' import SVGArray from './SVGArray.js' -import {subClassArray} from './ArrayPolyfill.js' -import {extend} from './tools.js' +import { subClassArray } from './ArrayPolyfill.js' +import { extend } from './tools.js' const PathArray = subClassArray('PathArray', SVGArray) @@ -83,7 +83,6 @@ for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { })(mlhvqtcsaz[i].toUpperCase()) } - extend(PathArray, { // Convert array to string toString () { @@ -246,9 +245,9 @@ extend(PathArray, { array = array .replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 .replace(pathLetters, ' $& ') // put some room between letters and numbers - .replace(hyphen, '$1 -') // add space before hyphen - .trim() // trim - .split(delimiter) // split into array + .replace(hyphen, '$1 -') // add space before hyphen + .trim() // trim + .split(delimiter) // split into array } else { array = array.reduce(function (prev, curr) { return [].concat.call(prev, curr) @@ -275,9 +274,9 @@ extend(PathArray, { } result.push(pathHandlers[s].call(null, - array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), - p, p0 - ) + array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), + p, p0 + ) ) } while (len > index) diff --git a/src/Pattern.js b/src/Pattern.js index 0c26d79..6f56e58 100644 --- a/src/Pattern.js +++ b/src/Pattern.js @@ -1,9 +1,10 @@ import Container from './Container.js' -import {nodeOrNew} from './tools.js' -//import attr from './attr.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { nodeOrNew } from './tools.js' +// import attr from './attr.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' import Box from './Box.js' +import { find } from './selector.js' export default class Pattern extends Container { // Initialize node @@ -38,7 +39,7 @@ export default class Pattern extends Container { attr (a, b, c) { if (a === 'transform') a = 'patternTransform' return super.attr(a, b, c) - //return attr.call(this, a, b, c) + // return attr.call(this, a, b, c) } targets () { diff --git a/src/Point.js b/src/Point.js index 7f8e2c3..a2b119c 100644 --- a/src/Point.js +++ b/src/Point.js @@ -1,16 +1,16 @@ import parser from './parser.js' -import {registerMethods} from './methods.js' +import { registerMethods } from './methods.js' export default class Point { // Initialize constructor (x, y, base) { let source - base = base || {x: 0, y: 0} + base = base || { x: 0, y: 0 } // ensure source as object - source = Array.isArray(x) ? {x: x[0], y: x[1]} - : typeof x === 'object' ? {x: x.x, y: x.y} - : {x: x, y: y} + source = Array.isArray(x) ? { x: x[0], y: x[1] } + : typeof x === 'object' ? { x: x.x, y: x.y } + : { x: x, y: y } // merge source this.x = source.x == null ? base.x : source.x diff --git a/src/PointArray.js b/src/PointArray.js index 1bf5460..68aeddc 100644 --- a/src/PointArray.js +++ b/src/PointArray.js @@ -1,7 +1,7 @@ import SVGArray from './SVGArray.js' -import {delimiter} from './regex.js' -import {subClassArray} from './ArrayPolyfill.js' -import {extend} from './tools.js' +import { delimiter } from './regex.js' +import { subClassArray } from './ArrayPolyfill.js' +import { extend } from './tools.js' const PointArray = subClassArray('PointArray', SVGArray) @@ -115,7 +115,7 @@ extend(PointArray, { minX = Math.min(el[0], minX) minY = Math.min(el[1], minY) }) - return {x: minX, y: minY, width: maxX - minX, height: maxY - minY} + return { x: minX, y: minY, width: maxX - minX, height: maxY - minY } } }) diff --git a/src/Polygon.js b/src/Polygon.js index 1272e44..c4afac6 100644 --- a/src/Polygon.js +++ b/src/Polygon.js @@ -1,11 +1,10 @@ -import {proportionalSize} from './helpers.js' import Shape from './Shape.js' -import {nodeOrNew, extend} from './tools.js' +import { nodeOrNew, extend } from './tools.js' import * as pointed from './pointed.js' import * as poly from './poly.js' import PointArray from './PointArray.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class Polygon extends Shape { // Initialize node diff --git a/src/Polyline.js b/src/Polyline.js index d651abd..7d1664e 100644 --- a/src/Polyline.js +++ b/src/Polyline.js @@ -1,10 +1,10 @@ import Shape from './Shape.js' -import {nodeOrNew, extend} from './tools.js' +import { nodeOrNew, extend } from './tools.js' import PointArray from './PointArray.js' import * as pointed from './pointed.js' import * as poly from './poly.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class Polyline extends Shape { // Initialize node diff --git a/src/Rect.js b/src/Rect.js index 232f591..535f562 100644 --- a/src/Rect.js +++ b/src/Rect.js @@ -1,7 +1,7 @@ import Shape from './Shape.js' -import {nodeOrNew, extend} from './tools.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { nodeOrNew } from './tools.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class Rect extends Shape { // Initialize node diff --git a/src/Runner.js b/src/Runner.js index b8bafa6..00ddf97 100644 --- a/src/Runner.js +++ b/src/Runner.js @@ -1,15 +1,16 @@ -import {isMatrixLike, getOrigin} from './helpers.js' +import { isMatrixLike, getOrigin } from './helpers.js' import Matrix from './Matrix.js' -import {default as Morphable, TransformBag} from './Morphable.js' +import Morphable, { TransformBag } from './Morphable.js' import SVGNumber from './SVGNumber.js' import Timeline from './Timeline.js' -import {Controller, Ease, Stepper} from './Controller.js' -import {noop, timeline} from './defaults.js' -import {extend} from './tools.js' +import { Controller, Ease, Stepper } from './Controller.js' +import { noop, timeline } from './defaults.js' +import { extend } from './tools.js' import Animator from './Animator.js' import Point from './Point.js' -import {registerMethods} from './methods.js' +import { registerMethods } from './methods.js' import EventTarget from './EventTarget.js' +import Box from './Box.js' // FIXME: What is this doing here? // easing = { @@ -231,7 +232,7 @@ export default class Runner extends EventTarget { var endTime = t * (w + d) - w position = x <= 0 ? Math.round(f(1e-5)) : x < endTime ? f(x) - : Math.round(f(endTime - 1e-5)) + : Math.round(f(endTime - 1e-5)) return position } @@ -269,7 +270,7 @@ export default class Runner extends EventTarget { var justFinished = this._lastTime < this._time && this.time > duration this._lastTime = this._time if (justStarted) { - this.fire('start', this) + this.fire('start', this) } // Work out if the runner is finished set the done flag here so animations @@ -441,7 +442,7 @@ export default class Runner extends EventTarget { Runner.id = 0 -class FakeRunner{ +class FakeRunner { constructor (transforms = new Matrix(), id = -1, done = true) { this.transforms = transforms this.id = id @@ -601,7 +602,6 @@ registerMethods({ } }) - extend(Runner, { attr (a, v) { return this.styleAttr('attr', a, v) @@ -707,9 +707,9 @@ extend(Runner, { // on this runner. We are absolute. We dont need these! if (!relative) this.clearTransform() - let {x, y} = new Point(origin).transform(element._currentTransform(this)) + let { x, y } = new Point(origin).transform(element._currentTransform(this)) - let target = new Matrix({...transforms, origin: [x, y]}) + let target = new Matrix({ ...transforms, origin: [x, y] }) let start = this._isDeclarative && current ? current : startTransform @@ -762,7 +762,7 @@ extend(Runner, { } // overwrite the old transformations with the new ones - transforms = {...newTransforms, origin} + transforms = { ...newTransforms, origin } } this.queue(setup, run, retarget) diff --git a/src/SVGArray.js b/src/SVGArray.js index a442aad..247f0b2 100644 --- a/src/SVGArray.js +++ b/src/SVGArray.js @@ -1,7 +1,6 @@ -/* global arrayClone */ -import {delimiter} from './regex.js' -import {subClassArray} from './ArrayPolyfill.js' -import {extend} from './tools.js' +import { delimiter } from './regex.js' +import { subClassArray } from './ArrayPolyfill.js' +import { extend } from './tools.js' const SVGArray = subClassArray('SVGArray', Array, function (...args) { this.init(...args) @@ -11,7 +10,7 @@ export default SVGArray extend(SVGArray, { init (...args) { - //this.splice(0, this.length) + // this.splice(0, this.length) this.length = 0 this.push(...this.parse(...args)) }, @@ -37,7 +36,7 @@ extend(SVGArray, { // Parse whitespace separated string parse (array = []) { - //array = array.valueOf() + // array = array.valueOf() // If already is an array, no need to parse it if (array instanceof Array) return array @@ -51,7 +50,7 @@ extend(SVGArray, { toSet () { return new Set(this) - }, + } }) // export default class SVGArray extends BaseArray { diff --git a/src/SVGNumber.js b/src/SVGNumber.js index e07b521..095e2e7 100644 --- a/src/SVGNumber.js +++ b/src/SVGNumber.js @@ -1,4 +1,4 @@ -import {numberAndUnit} from './regex.js' +import { numberAndUnit } from './regex.js' // Module for unit convertions export default class SVGNumber { @@ -45,7 +45,7 @@ export default class SVGNumber { toString () { return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 - : this.value + : this.value ) + this.unit } @@ -53,7 +53,6 @@ export default class SVGNumber { return this.toString() } - toArray () { return [this.value, this.unit] } diff --git a/src/Stop.js b/src/Stop.js index 7db6027..df33dbf 100644 --- a/src/Stop.js +++ b/src/Stop.js @@ -1,7 +1,7 @@ import Element from './Element.js' import SVGNumber from './SVGNumber.js' -import {nodeOrNew} from './tools.js' -import {register} from './adopter.js' +import { nodeOrNew } from './tools.js' +import { register } from './adopter.js' export default class Stop extends Element { constructor (node) { diff --git a/src/Symbol.js b/src/Symbol.js index 22d85da..9efb86c 100644 --- a/src/Symbol.js +++ b/src/Symbol.js @@ -1,7 +1,7 @@ import Container from './Container.js' -import {nodeOrNew} from './tools.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { nodeOrNew } from './tools.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class Symbol extends Container { // Initialize node diff --git a/src/Text.js b/src/Text.js index 55fed22..1b4c442 100644 --- a/src/Text.js +++ b/src/Text.js @@ -1,19 +1,19 @@ import Shape from './Shape.js' import SVGNumber from './SVGNumber.js' -import {nodeOrNew, extend} from './tools.js' -import {attrs} from './defaults.js' +import { nodeOrNew, extend } from './tools.js' +import { attrs } from './defaults.js' import * as textable from './textable.js' -import {register, adopt} from './adopter.js' -import {registerMethods} from './methods.js' +import { register, adopt } from './adopter.js' +import { registerMethods } from './methods.js' export default class Text extends Shape { // Initialize node constructor (node) { super(nodeOrNew('text', node), Text) - 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 + 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']) diff --git a/src/TextPath.js b/src/TextPath.js index df5b690..ce5115b 100644 --- a/src/TextPath.js +++ b/src/TextPath.js @@ -1,10 +1,10 @@ import Path from './Path.js' import Text from './Text.js' import PathArray from './PathArray.js' -import {nodeOrNew} from './tools.js' -import {xlink} from './namespaces.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { nodeOrNew } from './tools.js' +import { xlink } from './namespaces.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class TextPath extends Text { // Initialize node @@ -44,7 +44,7 @@ registerMethods({ } }, Text: { - // Create path for text to run on + // Create path for text to run on path: function (track) { var path = new TextPath() diff --git a/src/Timeline.js b/src/Timeline.js index e6e9e43..c5ce9d3 100644 --- a/src/Timeline.js +++ b/src/Timeline.js @@ -1,5 +1,5 @@ import Animator from './Animator.js' -import {registerMethods} from './methods.js' +import { registerMethods } from './methods.js' var time = window.performance || Date @@ -7,7 +7,7 @@ var makeSchedule = function (runnerInfo) { var start = runnerInfo.start var duration = runnerInfo.runner.duration() var end = start + duration - return {start: start, duration: duration, end: end, runner: runnerInfo.runner} + return { start: start, duration: duration, end: end, runner: runnerInfo.runner } } export default class Timeline { diff --git a/src/Tspan.js b/src/Tspan.js index 148fb16..f3a9469 100644 --- a/src/Tspan.js +++ b/src/Tspan.js @@ -1,8 +1,8 @@ import Text from './Text.js' -import {nodeOrNew, extend} from './tools.js' +import { nodeOrNew, extend } from './tools.js' import * as textable from './textable.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' export default class Tspan extends Text { // Initialize node diff --git a/src/Use.js b/src/Use.js index 7769929..5d4b5f4 100644 --- a/src/Use.js +++ b/src/Use.js @@ -1,8 +1,8 @@ import Shape from './Shape.js' -import {xlink} from './namespaces.js' -import {register} from './adopter.js' -import {registerMethods} from './methods.js' -import {nodeOrNew} from './tools.js' +import { xlink } from './namespaces.js' +import { register } from './adopter.js' +import { registerMethods } from './methods.js' +import { nodeOrNew } from './tools.js' export default class Use extends Shape { constructor (node) { diff --git a/src/adopter.js b/src/adopter.js index 61b1e83..ed692b8 100644 --- a/src/adopter.js +++ b/src/adopter.js @@ -1,6 +1,6 @@ import Base from './Base.js' -import {capitalize} from './helpers.js' -import {makeNode} from './tools.js' +import { capitalize } from './helpers.js' +import { makeNode } from './tools.js' const elements = {} export const root = Symbol('root') @@ -30,7 +30,6 @@ export function makeInstance (element) { return element } - // Adopt existing svg elements export function adopt (node) { // check for presence of node @@ -66,7 +65,7 @@ export function register (element, name = element.name, asRoot = false) { return element } -export function getClass(name) { +export function getClass (name) { return elements[name] } diff --git a/src/arrange.js b/src/arrange.js index d0a5b23..169cf93 100644 --- a/src/arrange.js +++ b/src/arrange.js @@ -1,5 +1,5 @@ // ### This module adds backward / forward functionality to elements. -import {registerMethods} from './methods.js' +import { registerMethods } from './methods.js' // Get all siblings, including myself export function siblings () { @@ -30,7 +30,7 @@ export function forward () { p.removeElement(this).add(this, i) // make sure defs node is always at the top - if (typeof p.isRoot == 'function' && p.isRoot()) { + if (typeof p.isRoot === 'function' && p.isRoot()) { p.node.appendChild(p.defs().node) } @@ -56,7 +56,7 @@ export function front () { p.node.appendChild(this.node) // Make sure defs node is always at the top - if (typeof p.isRoot == 'function' && p.isRoot()) { + if (typeof p.isRoot === 'function' && p.isRoot()) { p.node.appendChild(p.defs().node) } diff --git a/src/attr.js b/src/attr.js index c44fa68..cccc340 100644 --- a/src/attr.js +++ b/src/attr.js @@ -1,9 +1,9 @@ -import {isNumber, isImage} from './regex.js' -import {attrs as defaults} from './defaults.js' +import { isNumber, isImage } from './regex.js' +import { attrs as defaults } from './defaults.js' import Color from './Color.js' import SVGArray from './SVGArray.js' import SVGNumber from './SVGNumber.js' -//import {registerMethods} from './methods.js' +// import {registerMethods} from './methods.js' // Set svg element attribute export default function attr (attr, val, ns) { @@ -26,14 +26,14 @@ export default function attr (attr, val, ns) { // apply every attribute individually if an object is passed for (val in attr) this.attr(val, attr[val]) } else if (val === null) { - // remove value + // remove value this.node.removeAttribute(attr) } else if (val == null) { // act as a getter if the first and only argument is not an object val = this.node.getAttribute(attr) return val == null ? defaults[attr] // FIXME: do we need to return defaults? : isNumber.test(val) ? parseFloat(val) - : val + : val } else { // convert image fill and stroke to patterns if (attr === 'fill' || attr === 'stroke') { @@ -44,7 +44,7 @@ export default function attr (attr, val, ns) { // FIXME: This is fine, but what about the lines above? // How does attr know about image()? - while (typeof val.attrHook == 'function') { + while (typeof val.attrHook === 'function') { val = val.attrHook(this, attr) } @@ -80,4 +80,4 @@ export default function attr (attr, val, ns) { return this } -//registerMethods('Element', {attr}) +// registerMethods('Element', {attr}) diff --git a/src/circled.js b/src/circled.js index 70fafef..7df7a5b 100644 --- a/src/circled.js +++ b/src/circled.js @@ -1,5 +1,5 @@ // FIXME: import this to runner -import {proportionalSize} from './helpers.js' +import { proportionalSize } from './helpers.js' import SVGNumber from './SVGNumber.js' // Radius x value diff --git a/src/classHandling.js b/src/classHandling.js index 27bf11a..fd148b7 100644 --- a/src/classHandling.js +++ b/src/classHandling.js @@ -1,5 +1,5 @@ -import {registerMethods} from './methods.js' -import {delimiter} from './regex.js' +import { registerMethods } from './methods.js' +import { delimiter } from './regex.js' // Return array of classes on the node function classes () { diff --git a/src/classes.js b/src/classes.js index 283baaa..a4cc758 100644 --- a/src/classes.js +++ b/src/classes.js @@ -1,47 +1,47 @@ -export {default as EventTarget} from './EventTarget.js' -export {default as Dom} from './Dom.js' -export {default as Element} from './Element.js' -export {default as Shape} from './Shape.js' -export {default as Container} from './Container.js' -export {default as HtmlNode} from './HtmlNode.js' -export {default as Doc} from './Doc.js' -export {default as Defs} from './Defs.js' -export {default as G} from './G.js' -export {default as Animator} from './Animator.js' -export {default as Bare} from './Bare.js' -export {default as Circle} from './Circle.js' -export {default as ClipPath} from './ClipPath.js' -export {default as A} from './A.js' -export {default as Ellipse} from './Ellipse.js' -export {default as Stop} from './Stop.js' -export {default as Gradient} from './Gradient.js' -export {default as Image} from './Image.js' -export {default as Line} from './Line.js' -export {default as Marker} from './Marker.js' -export {default as Mask} from './Mask.js' -export {default as Path} from './Path.js' -export {default as Pattern} from './Pattern.js' -export {default as Polygon} from './Polygon.js' -export {default as Polyline} from './Polyline.js' -export {default as Rect} from './Rect.js' -export {default as Symbol} from './Symbol.js' -export {default as Text} from './Text.js' -export {default as TextPath} from './TextPath.js' -export {default as Tspan} from './Tspan.js' -export {default as Use} from './Use.js' -export {default as SVGNumber} from './SVGNumber.js' -export {default as SVGArray} from './SVGArray.js' -export {default as PathArray} from './PathArray.js' -export {default as PointArray} from './PointArray.js' -export {default as Matrix} from './Matrix.js' -export {default as Point} from './Point.js' -export {default as Box} from './Box.js' -export {default as Color} from './Color.js' -export {default as Morphable} from './Morphable.js' -export {default as Queue} from './Queue.js' -export {default as Runner} from './Runner.js' -export {default as Timeline} from './Timeline.js' -export {Controller, Ease, PID, Spring} from './Controller.js' +export { default as EventTarget } from './EventTarget.js' +export { default as Dom } from './Dom.js' +export { default as Element } from './Element.js' +export { default as Shape } from './Shape.js' +export { default as Container } from './Container.js' +export { default as HtmlNode } from './HtmlNode.js' +export { default as Doc } from './Doc.js' +export { default as Defs } from './Defs.js' +export { default as G } from './G.js' +export { default as Animator } from './Animator.js' +export { default as Bare } from './Bare.js' +export { default as Circle } from './Circle.js' +export { default as ClipPath } from './ClipPath.js' +export { default as A } from './A.js' +export { default as Ellipse } from './Ellipse.js' +export { default as Stop } from './Stop.js' +export { default as Gradient } from './Gradient.js' +export { default as Image } from './Image.js' +export { default as Line } from './Line.js' +export { default as Marker } from './Marker.js' +export { default as Mask } from './Mask.js' +export { default as Path } from './Path.js' +export { default as Pattern } from './Pattern.js' +export { default as Polygon } from './Polygon.js' +export { default as Polyline } from './Polyline.js' +export { default as Rect } from './Rect.js' +export { default as Symbol } from './Symbol.js' +export { default as Text } from './Text.js' +export { default as TextPath } from './TextPath.js' +export { default as Tspan } from './Tspan.js' +export { default as Use } from './Use.js' +export { default as SVGNumber } from './SVGNumber.js' +export { default as SVGArray } from './SVGArray.js' +export { default as PathArray } from './PathArray.js' +export { default as PointArray } from './PointArray.js' +export { default as Matrix } from './Matrix.js' +export { default as Point } from './Point.js' +export { default as Box } from './Box.js' +export { default as Color } from './Color.js' +export { default as Morphable } from './Morphable.js' +export { default as Queue } from './Queue.js' +export { default as Runner } from './Runner.js' +export { default as Timeline } from './Timeline.js' +export { Controller, Ease, PID, Spring } from './Controller.js' // export {default as Animator} from './Animator.js' // export {default as SVGArray} from './SVGArray.js' diff --git a/src/containers.js b/src/containers.js index 675c307..02869e4 100644 --- a/src/containers.js +++ b/src/containers.js @@ -1,15 +1,15 @@ -export {default as Bare} from './Bare.js' -export {default as ClipPath} from './ClipPath.js' -export {default as Defs} from './Defs.js' -export {default as Doc} from './Doc.js' -export {default as Gradient} from './Gradient.js' -export {default as G} from './G.js' -export {default as A} from './A.js' -export {default as Marker} from './Marker.js' -export {default as Mask} from './Mask.js' -export {default as Pattern} from './Pattern.js' -export {default as Symbol} from './Symbol.js' +export { default as Bare } from './Bare.js' +export { default as ClipPath } from './ClipPath.js' +export { default as Defs } from './Defs.js' +export { default as Doc } from './Doc.js' +export { default as Gradient } from './Gradient.js' +export { default as G } from './G.js' +export { default as A } from './A.js' +export { default as Marker } from './Marker.js' +export { default as Mask } from './Mask.js' +export { default as Pattern } from './Pattern.js' +export { default as Symbol } from './Symbol.js' -export {default as Text} from './Text.js' -export {default as Tspan} from './Tspan.js' -export {default as TextPath} from './TextPath.js' +export { default as Text } from './Text.js' +export { default as Tspan } from './Tspan.js' +export { default as TextPath } from './TextPath.js' diff --git a/src/css.js b/src/css.js index b581d71..a7d38a6 100644 --- a/src/css.js +++ b/src/css.js @@ -1,21 +1,20 @@ -import {camelCase} from './helpers.js' -import {isBlank} from './regex.js' -import {registerMethods} from './methods.js' +import { camelCase } from './helpers.js' +import { isBlank } from './regex.js' +import { registerMethods } from './methods.js' // FIXME: We dont need exports - // Dynamic style generator +// Dynamic style generator export function css (style, val) { let ret = {} - let i if (arguments.length === 0) { // get full style as object this.node.style.cssText.split(/\s*;\s*/) .filter(function (el) { return !!el.length }) .forEach(function (el) { - let t = el.split(/\s*:\s*/) - ret[t[0]] = t[1] - }) + let t = el.split(/\s*:\s*/) + ret[t[0]] = t[1] + }) return ret } @@ -36,7 +35,7 @@ export function css (style, val) { // set styles in object if (typeof style === 'object') { - for (name in style) { + for (let name in style) { // set empty string if null/undefined/'' was given this.node.style[camelCase(name)] = (style[name] == null || isBlank.test(style[name])) ? '' : style[name] @@ -53,17 +52,17 @@ export function css (style, val) { return this } - // Show element +// Show element export function show () { return this.css('display', '') } - // Hide element +// Hide element export function hide () { return this.css('display', 'none') } - // Is element visible? +// Is element visible? export function visible () { return this.css('display') !== 'none' } diff --git a/src/data.js b/src/data.js index 6374987..ce50abb 100644 --- a/src/data.js +++ b/src/data.js @@ -1,4 +1,4 @@ -import {registerMethods} from './methods.js' +import { registerMethods } from './methods.js' // Store data values on svg nodes export function data (a, v, r) { @@ -15,12 +15,12 @@ export function data (a, v, r) { } else { this.attr('data-' + a, v === null ? null - : r === true || typeof v === 'string' || typeof v === 'number' ? v - : JSON.stringify(v) + : r === true || typeof v === 'string' || typeof v === 'number' ? v + : JSON.stringify(v) ) } return this } -registerMethods('Dom', {data}) +registerMethods('Dom', { data }) diff --git a/src/elements.js b/src/elements.js index c251f25..b09d6e8 100644 --- a/src/elements.js +++ b/src/elements.js @@ -1,25 +1,25 @@ -export {default as Bare} from './Bare.js' -export {default as Circle} from './Circle.js' -export {default as ClipPath} from './ClipPath.js' -export {default as Defs} from './Defs.js' -export {default as Doc} from './Doc.js' -export {default as Ellipse} from './Ellipse.js' -export {default as Gradient} from './Gradient.js' -export {default as G} from './G.js' -export {default as HtmlNode} from './HtmlNode.js' -export {default as A} from './A.js' -export {default as Image} from './Image.js' -export {default as Line} from './Line.js' -export {default as Marker} from './Marker.js' -export {default as Mask} from './Mask.js' -export {default as Path} from './Path.js' -export {default as Pattern} from './Pattern.js' -export {default as Polygon} from './Polygon.js' -export {default as Polyline} from './Polyline.js' -export {default as Rect} from './Rect.js' -export {default as Stop} from './Stop.js' -export {default as Symbol} from './Symbol.js' -export {default as Text} from './Text.js' -export {default as TextPath} from './TextPath.js' -export {default as Tspan} from './Tspan.js' -export {default as Use} from './Use.js' +export { default as Bare } from './Bare.js' +export { default as Circle } from './Circle.js' +export { default as ClipPath } from './ClipPath.js' +export { default as Defs } from './Defs.js' +export { default as Doc } from './Doc.js' +export { default as Ellipse } from './Ellipse.js' +export { default as Gradient } from './Gradient.js' +export { default as G } from './G.js' +export { default as HtmlNode } from './HtmlNode.js' +export { default as A } from './A.js' +export { default as Image } from './Image.js' +export { default as Line } from './Line.js' +export { default as Marker } from './Marker.js' +export { default as Mask } from './Mask.js' +export { default as Path } from './Path.js' +export { default as Pattern } from './Pattern.js' +export { default as Polygon } from './Polygon.js' +export { default as Polyline } from './Polyline.js' +export { default as Rect } from './Rect.js' +export { default as Stop } from './Stop.js' +export { default as Symbol } from './Symbol.js' +export { default as Text } from './Text.js' +export { default as TextPath } from './TextPath.js' +export { default as Tspan } from './Tspan.js' +export { default as Use } from './Use.js' diff --git a/src/elemnts-svg.js b/src/elemnts-svg.js index 5ee97b7..b5b2542 100644 --- a/src/elemnts-svg.js +++ b/src/elemnts-svg.js @@ -1,63 +1,68 @@ - // Import raw svg - svg: function (svg, fn = false) { - var well, len - - // act as getter if no svg string is given - if(svg == null || svg === true || typeof svg == 'function') { - // write svgjs data to the dom - this.writeDataToDom() - let current = this - - // An export modifier was passed - if (typeof svg == 'function') { - // Juggle arguments - [fn, svg] = [svg, fn] - - // If the user wants outerHTML we need to process this node, too - if (!svg) { - current = fn(current) - - // The user does not want this node? Well, then he gets nothing - if (current === false) return '' - } +import { ns } from './namespaces.js' - // Deep loop through all children and apply modifier - current.each(function () { - let result = fn(this) +/* eslint no-unused-vars: "off" */ +var a = { + // Import raw svg + svg (svg, fn = false) { + var well, len, fragment - // If modifier returns false, discard node - if (result === false) { - this.remove() + // act as getter if no svg string is given + if (svg == null || svg === true || typeof svg === 'function') { + // write svgjs data to the dom + this.writeDataToDom() + let current = this - // If modifier returns new node, use it - } else if (result !== this) { - this.replace(result) - } - }, true) + // An export modifier was passed + if (typeof svg === 'function') { + // Juggle arguments + [fn, svg] = [svg, fn] + + // If the user wants outerHTML we need to process this node, too + if (!svg) { + current = fn(current) + + // The user does not want this node? Well, then he gets nothing + if (current === false) return '' } - // Return outer or inner content - return svg - ? current.node.innerHTML - : current.node.outerHTML + // Deep loop through all children and apply modifier + current.each(function () { + let result = fn(this) + + // If modifier returns false, discard node + if (result === false) { + this.remove() + + // If modifier returns new node, use it + } else if (result !== this) { + this.replace(result) + } + }, true) } - // Act as setter if we got a string + // Return outer or inner content + return svg + ? current.node.innerHTML + : current.node.outerHTML + } - // Create temporary holder - well = document.createElementNS(SVG.ns, 'svg') - fragment = document.createDocumentFragment() + // Act as setter if we got a string - // Dump raw svg - well.innerHTML = svg + // Create temporary holder + well = document.createElementNS(ns, 'svg') + fragment = document.createDocumentFragment() - // Transplant nodes into the fragment - for (len = well.children.length; len--;) { - fragment.appendChild(well.firstElementChild) - } + // Dump raw svg + well.innerHTML = svg + + // Transplant nodes into the fragment + for (len = well.children.length; len--;) { + fragment.appendChild(well.firstElementChild) + } - // Add the whole fragment at once - this.node.appendChild(fragment) + // Add the whole fragment at once + this.node.appendChild(fragment) - return this - }, + return this + } +} diff --git a/src/event.js b/src/event.js index 2aa9daf..8cd4188 100644 --- a/src/event.js +++ b/src/event.js @@ -1,6 +1,5 @@ -import {delimiter} from './regex.js' -import {registerMethods} from './methods.js' -import {makeInstance} from './adopter.js' +import { delimiter } from './regex.js' +import { makeInstance } from './adopter.js' let listenerId = 0 @@ -125,7 +124,7 @@ export function dispatch (node, event, data) { if (event instanceof window.Event) { n.dispatchEvent(event) } else { - event = new window.CustomEvent(event, {detail: data, cancelable: true}) + event = new window.CustomEvent(event, { detail: data, cancelable: true }) n.dispatchEvent(event) } return event diff --git a/src/helpers.js b/src/helpers.js index 2248ea9..9bf393c 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -1,4 +1,4 @@ -import {dots, reference} from './regex.js' +import { dots, reference } from './regex.js' export function isNulledBox (box) { return !box.w && !box.h && !box.x && !box.y @@ -188,10 +188,10 @@ export function getOrigin (o, element) { // Calculate the transformed x and y coordinates let bx = string.includes('left') ? x : string.includes('right') ? x + width - : x + width / 2 + : x + width / 2 let by = string.includes('top') ? y : string.includes('bottom') ? y + height - : y + height / 2 + : y + height / 2 // Set the bounds eg : "bottom-left", "Top right", "middle" etc... ox = o.ox != null ? o.ox : bx diff --git a/src/memory.js b/src/memory.js index a94f0e2..3f81c6f 100644 --- a/src/memory.js +++ b/src/memory.js @@ -1,5 +1,4 @@ -import {registerMethods} from './methods.js' -import {registerConstructor} from './methods.js' +import { registerMethods } from './methods.js' // export const name = 'Memory' // @@ -25,7 +24,7 @@ export function remember (k, v) { return this } - // Erase a given memory +// Erase a given memory export function forget () { if (arguments.length === 0) { this._memory = {} @@ -37,10 +36,10 @@ export function forget () { return this } - // return local memory object +// return local memory object export function memory () { return (this._memory = this._memory || {}) } -registerMethods('Dom', {remember, forget, memory}) -//registerConstructor('Memory', setup) +registerMethods('Dom', { remember, forget, memory }) +// registerConstructor('Memory', setup) diff --git a/src/methods.js b/src/methods.js index 4eb92b9..f926598 100644 --- a/src/methods.js +++ b/src/methods.js @@ -9,7 +9,7 @@ export function registerMethods (name, m) { return } - if (typeof name == 'object') { + if (typeof name === 'object') { for (let [_name, _m] of Object.entries(name)) { registerMethods(_name, _m) } @@ -24,15 +24,14 @@ export function getMethodsFor (name) { } // FIXME: save memory? -export function cleanMethods () { - methods = {} -} - +// export function cleanMethods () { +// methods = {} +// } export function registerConstructor (name, setup) { constructors[name] = setup } export function getConstructor (name) { - return constructors[name] ? {setup: constructors[name], name} : {} + return constructors[name] ? { setup: constructors[name], name } : {} } diff --git a/src/parser.js b/src/parser.js index 9a64dbc..aa58db4 100644 --- a/src/parser.js +++ b/src/parser.js @@ -1,7 +1,6 @@ import Doc from './Doc.js' export default function parser () { - // Reuse cached element if possible if (!parser.nodes) { let svg = new Doc().size(2, 0).css({ @@ -14,7 +13,7 @@ export default function parser () { let path = svg.path().node - parser.nodes = {svg, path} + parser.nodes = { svg, path } } if (!parser.nodes.svg.node.parentNode) { diff --git a/src/poly.js b/src/poly.js index 937247a..269b0c9 100644 --- a/src/poly.js +++ b/src/poly.js @@ -1,6 +1,6 @@ // Add polygon-specific functions import PointArray from './PointArray.js' -import {proportionalSize} from './helpers.js' +import { proportionalSize } from './helpers.js' // Get array export function array () { @@ -11,7 +11,7 @@ export function array () { export function plot (p) { return (p == null) ? this.array() : this.clear().attr('points', typeof p === 'string' ? p - : (this._array = new PointArray(p))) + : (this._array = new PointArray(p))) } // Clear array cache diff --git a/src/selector.js b/src/selector.js index c6717fb..6ee1207 100644 --- a/src/selector.js +++ b/src/selector.js @@ -1,7 +1,6 @@ -import {idFromReference} from './helpers.js' -import {map} from './utils.js' -import {adopt} from './adopter.js' -import {registerMethods} from './methods.js' +import { map } from './utils.js' +import { adopt } from './adopter.js' +import { registerMethods } from './methods.js' // // Method for getting an element by id // SVG.get = function (id) { @@ -37,4 +36,4 @@ export function find (query) { return baseFind(query, this.node) } -registerMethods('Dom', {find}) +registerMethods('Dom', { find }) diff --git a/src/set.js b/src/set.js index 5352570..c755c2c 100644 --- a/src/set.js +++ b/src/set.js @@ -1,4 +1,5 @@ -SVG.Set = class extends Set { +/* eslint no-unused-vars: "off" */ +class SVGSet extends Set { // constructor (arr) { // super(arr) // } diff --git a/src/sugar.js b/src/sugar.js index 6465985..7d34cee 100644 --- a/src/sugar.js +++ b/src/sugar.js @@ -4,7 +4,7 @@ import SVGNumber from './SVGNumber.js' import Matrix from './Matrix.js' import Point from './Point.js' import Element from './Element.js' -import {registerMethods} from './methods.js' +import { registerMethods } from './methods.js' // Define list of available attributes for stroke and fill var sugar = { @@ -55,18 +55,18 @@ registerMethods(['Element', 'Runner'], { // Map rotation to transform rotate: function (angle, cx, cy) { - return this.transform({rotate: angle, ox: cx, oy: cy}, true) + return this.transform({ rotate: angle, ox: cx, oy: cy }, true) }, // Map skew to transform skew: function (x, y, cx, cy) { return arguments.length === 1 || arguments.length === 3 - ? this.transform({skew: x, ox: y, oy: cx}, true) - : this.transform({skew: [x, y], ox: cx, oy: cy}, true) + ? this.transform({ skew: x, ox: y, oy: cx }, true) + : this.transform({ skew: [x, y], ox: cx, oy: cy }, true) }, shear: function (lam, cx, cy) { - return this.transform({shear: lam, ox: cx, oy: cy}, true) + return this.transform({ shear: lam, ox: cx, oy: cy }, true) }, // Map scale to transform @@ -90,13 +90,13 @@ registerMethods(['Element', 'Runner'], { flip: function (direction, around) { var directionString = typeof direction === 'string' ? direction : isFinite(direction) ? 'both' - : 'both' + : 'both' var origin = (direction === 'both' && isFinite(around)) ? [around, around] : (direction === 'x') ? [around, 0] - : (direction === 'y') ? [0, around] - : isFinite(direction) ? [direction, direction] - : [0, 0] - this.transform({flip: directionString, origin: origin}, true) + : (direction === 'y') ? [0, around] + : isFinite(direction) ? [direction, direction] + : [0, 0] + this.transform({ flip: directionString, origin: origin }, true) }, // Opacity @@ -149,11 +149,11 @@ registerMethods(['Element', 'Runner'], { } return a === 'leading' - ? this.leading(v) + ? this.leading(v) : a === 'anchor' ? this.attr('text-anchor', v) - : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style' - ? this.attr('font-' + a, v) - : this.attr(a, v) + : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style' + ? this.attr('font-' + a, v) + : this.attr(a, v) } }) diff --git a/src/svg.js b/src/svg.js index 7cfbbc8..a7e92d0 100644 --- a/src/svg.js +++ b/src/svg.js @@ -1,9 +1,6 @@ -import {makeInstance} from './adopter.js' import * as Classes from './classes.js' import * as adopter from './adopter.js' import * as tools from './tools.js' -import * as containers from './containers.js' -import * as elements from './elements.js' import './attr.js' import './arrange.js' import './data.js' @@ -13,13 +10,24 @@ import './css.js' import './transform.js' import './memory.js' import './sugar.js' -import {getMethodsFor, getConstructor} from './methods.js' -import {registerMorphableType, makeMorphable} from './Morphable.js' -const extend = tools.extend +import { getMethodsFor } from './methods.js' +import { registerMorphableType, makeMorphable, TransformBag, ObjectBag, NonMorphable } from './Morphable.js' import './EventTarget.js' import './Element.js' +import * as utils from './utils.js' + +import * as regex from './regex.js' + +// satisfy tests, fix later +import * as ns from './namespaces.js' +import { easing } from './Controller.js' +import * as events from './event.js' +import parser from './parser.js' +import * as defaults from './defaults.js' +const extend = tools.extend + extend([ Classes.Doc, Classes.Symbol, @@ -56,7 +64,7 @@ extend(Classes.EventTarget, getMethodsFor('EventTarget')) extend(Classes.Dom, getMethodsFor('Dom')) extend(Classes.Element, getMethodsFor('Element')) extend(Classes.Shape, getMethodsFor('Shape')) -//extend(Classes.Element, getConstructor('Memory')) +// extend(Classes.Element, getConstructor('Memory')) extend(Classes.Container, getMethodsFor('Container')) registerMorphableType([ @@ -73,34 +81,21 @@ makeMorphable() // The main wrapping element export default function SVG (element) { - return makeInstance(element) + return adopter.makeInstance(element) } Object.assign(SVG, Classes) Object.assign(SVG, tools) Object.assign(SVG, adopter) - -import * as utils from './utils.js' SVG.utils = utils - -import * as regex from './regex.js' SVG.regex = regex - - -// satisfy tests, fix later -import * as ns from './namespaces.js' SVG.get = SVG SVG.find = find Object.assign(SVG, ns) -import {easing} from './Controller.js' SVG.easing = easing -import * as events from './event.js' Object.assign(SVG, events) -import {TransformBag, ObjectBag, NonMorphable} from './Morphable.js' SVG.TransformBag = TransformBag SVG.ObjectBag = ObjectBag SVG.NonMorphable = NonMorphable -import parser from './parser.js' SVG.parser = parser -import * as defaults from './defaults.js' SVG.defaults = defaults diff --git a/src/tools.js b/src/tools.js index 898f016..14e19a3 100644 --- a/src/tools.js +++ b/src/tools.js @@ -1,5 +1,5 @@ -import {ns} from './namespaces.js' -import {capitalize} from './helpers.js' +import { ns } from './namespaces.js' +import { getClass } from './adopter.js' export function nodeOrNew (name, node) { return node || makeNode(name) @@ -39,6 +39,7 @@ export function invent (config) { // Inherit prototype if (config.inherit) { + /* eslint new-cap: "off" */ initializer.prototype = new config.inherit() initializer.prototype.constructor = initializer } @@ -49,7 +50,7 @@ export function invent (config) { } // Attach construct method to parent - if (config.construct) { extend(config.parent || Container, config.construct) } + if (config.construct) { extend(config.parent || getClass('Container'), config.construct) } return initializer } diff --git a/src/transform.js b/src/transform.js index 907bbfa..ff3364e 100644 --- a/src/transform.js +++ b/src/transform.js @@ -1,7 +1,7 @@ -import {arrayToMatrix, getOrigin, isMatrixLike} from './helpers.js' +import { arrayToMatrix, getOrigin, isMatrixLike } from './helpers.js' import Matrix from './Matrix.js' -import {delimiter, transforms} from './regex.js' -import {registerMethods} from './methods.js' +import { delimiter, transforms } from './regex.js' +import { registerMethods } from './methods.js' // Reset all transformations export function untransform () { @@ -58,7 +58,7 @@ export function transform (o, relative) { if (!isMatrixLike(o)) { // Set the origin according to the defined transform - o = {...o, origin: getOrigin(o, this)} + o = { ...o, origin: getOrigin(o, this) } } // The user can pass a boolean, an Element or an Matrix or nothing diff --git a/src/umd.js b/src/umd.js deleted file mode 100644 index bb8e300..0000000 --- a/src/umd.js +++ /dev/null @@ -1,28 +0,0 @@ - -(function(root, factory) { - /* istanbul ignore next */ - if (typeof define === 'function' && define.amd) { - define(function(){ - return factory(root, root.document) - }) - } else if (typeof exports === 'object') { - module.exports = root.document ? factory(root, root.document) : function(w){ return factory(w, w.document) } - } else { - root.SVG = factory(root, root.document) - } -}(typeof window !== "undefined" ? window : this, function(window, document) { - -// Check that our browser supports svg -var supported = !! document.createElementNS && - !! document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect - -// If we don't support svg, just exit without doing anything -if (!supported) - return {supported: false} - -// Otherwise, the library will be here -<%= contents %> - -return SVG - -})); -- cgit v1.2.3 From 9f2696e8a2cf7e4eebc1cc7e31027fe2070094fa Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Mon, 5 Nov 2018 21:53:40 +0100 Subject: removed unused comments and files --- dist/svg.js | 7355 ++++++++++++++++++++++++---------------------------- dist/svg.min.js | 2 +- src/ClipPath.js | 1 - src/Doc.js | 15 - src/Dom.js | 3 +- src/Element.js | 9 - src/EventTarget.js | 10 +- src/Gradient.js | 1 - src/Mask.js | 1 - src/PathArray.js | 217 -- src/Pattern.js | 1 - src/PointArray.js | 124 - src/SVGArray.js | 50 - src/attr.js | 2 - src/classes.js | 91 +- src/containers.js | 15 - src/elements.js | 25 - src/event.js | 12 - src/memory.js | 7 +- src/methods.js | 5 - src/selector.js | 23 - 21 files changed, 3471 insertions(+), 4498 deletions(-) delete mode 100644 src/containers.js delete mode 100644 src/elements.js (limited to 'src') diff --git a/dist/svg.js b/dist/svg.js index 3b71aea..946db81 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -6,7 +6,7 @@ * @copyright Wout Fierens * @license MIT * -* BUILT: Mon Nov 05 2018 18:59:11 GMT+0100 (GMT+01:00) +* BUILT: Mon Nov 05 2018 21:52:42 GMT+0100 (GMT+01:00) */; var SVG = (function () { 'use strict'; @@ -216,8 +216,157 @@ var SVG = (function () { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } - var Base = function Base() { - _classCallCheck(this, Base); + var Queue = + /*#__PURE__*/ + function () { + function Queue() { + _classCallCheck(this, Queue); + + this._first = null; + this._last = null; + } + + _createClass(Queue, [{ + key: "push", + value: function push(value) { + // An item stores an id and the provided value + var item = value.next ? value : { + value: value, + next: null, + prev: null // Deal with the queue being empty or populated + + }; + + if (this._last) { + item.prev = this._last; + this._last.next = item; + this._last = item; + } else { + this._last = item; + this._first = item; + } // Update the length and return the current item + + + return item; + } + }, { + key: "shift", + value: function shift() { + // Check if we have a value + var remove = this._first; + if (!remove) return null; // If we do, remove it and relink things + + this._first = remove.next; + if (this._first) this._first.prev = null; + this._last = this._first ? this._last : null; + return remove.value; + } // Shows us the first item in the list + + }, { + key: "first", + value: function first() { + return this._first && this._first.value; + } // Shows us the last item in the list + + }, { + key: "last", + value: function last() { + return this._last && this._last.value; + } // Removes the item that was returned from the push + + }, { + key: "remove", + value: function remove(item) { + // Relink the previous item + if (item.prev) item.prev.next = item.next; + if (item.next) item.next.prev = item.prev; + if (item === this._last) this._last = item.prev; + if (item === this._first) this._first = item.next; // Invalidate item + + item.prev = null; + item.next = null; + } + }]); + + return Queue; + }(); + + var Animator = { + nextDraw: null, + frames: new Queue(), + timeouts: new Queue(), + timer: window.performance || window.Date, + transforms: [], + frame: function frame(fn) { + // Store the node + var node = Animator.frames.push({ + run: fn + }); // Request an animation frame if we don't have one + + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw); + } // Return the node so we can remove it easily + + + return node; + }, + transform_frame: function transform_frame(fn, id) { + Animator.transforms[id] = fn; + }, + timeout: function timeout(fn, delay) { + delay = delay || 0; // Work out when the event should fire + + var time = Animator.timer.now() + delay; // Add the timeout to the end of the queue + + var node = Animator.timeouts.push({ + run: fn, + time: time + }); // Request another animation frame if we need one + + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw); + } + + return node; + }, + cancelFrame: function cancelFrame(node) { + Animator.frames.remove(node); + }, + clearTimeout: function clearTimeout(node) { + Animator.timeouts.remove(node); + }, + _draw: function _draw(now) { + // Run all the timeouts we can run, if they are not ready yet, add them + // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) + var nextTimeout = null; + var lastTimeout = Animator.timeouts.last(); + + while (nextTimeout = Animator.timeouts.shift()) { + // Run the timeout if its time, or push it to the end + if (now >= nextTimeout.time) { + nextTimeout.run(); + } else { + Animator.timeouts.push(nextTimeout); + } // If we hit the last item, we should stop shifting out more items + + + if (nextTimeout === lastTimeout) break; + } // Run all of the animation frames + + + var nextFrame = null; + var lastFrame = Animator.frames.last(); + + while (nextFrame !== lastFrame && (nextFrame = Animator.frames.shift())) { + nextFrame.run(); + } + + Animator.transforms.forEach(function (el) { + el(); + }); // If we have remaining timeouts or frames, draw until we don't anymore + + Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() ? window.requestAnimationFrame(Animator._draw) : null; + } }; // Parse unit value @@ -282,6 +431,47 @@ var SVG = (function () { dots: dots }); + /* eslint no-new-func: "off" */ + var subClassArray = function () { + try { + // try es6 subclassing + return Function('name', 'baseClass', '_constructor', ['baseClass = baseClass || Array', 'return {', '[name]: class extends baseClass {', 'constructor (...args) {', 'super(...args)', '_constructor && _constructor.apply(this, args)', '}', '}', '}[name]'].join('\n')); + } catch (e) { + // Use es5 approach + return function (name) { + var baseClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Array; + + var _constructor = arguments.length > 2 ? arguments[2] : undefined; + + var Arr = function Arr() { + baseClass.apply(this, arguments); + _constructor && _constructor.apply(this, arguments); + }; + + Arr.prototype = Object.create(baseClass.prototype); + Arr.prototype.constructor = Arr; + return Arr; + }; + } + }(); + + // Default namespaces + var ns = 'http://www.w3.org/2000/svg'; + var xmlns = 'http://www.w3.org/2000/xmlns/'; + var xlink = 'http://www.w3.org/1999/xlink'; + var svgjs = 'http://svgjs.com/svgjs'; + + var ns$1 = /*#__PURE__*/Object.freeze({ + ns: ns, + xmlns: xmlns, + xlink: xlink, + svgjs: svgjs + }); + + var Base = function Base() { + _classCallCheck(this, Base); + }; + function isNulledBox(box) { return !box.w && !box.h && !box.x && !box.y; } @@ -447,104 +637,34 @@ var SVG = (function () { return [ox, oy]; } - // Default namespaces - var ns = 'http://www.w3.org/2000/svg'; - var xmlns = 'http://www.w3.org/2000/xmlns/'; - var xlink = 'http://www.w3.org/1999/xlink'; - var svgjs = 'http://svgjs.com/svgjs'; - - var ns$1 = /*#__PURE__*/Object.freeze({ - ns: ns, - xmlns: xmlns, - xlink: xlink, - svgjs: svgjs - }); - - function nodeOrNew(name, node) { - return node || makeNode(name); - } // Method for element creation + var elements = {}; + var root = Symbol('root'); + function makeInstance(element) { + if (element instanceof Base) return element; - function makeNode(name) { - // create element - return document.createElementNS(ns, name); - } // Method for extending objects + if (_typeof(element) === 'object') { + return adopt(element); + } - function extend(modules, methods) { - var key, i; - modules = Array.isArray(modules) ? modules : [modules]; + if (element == null) { + return new elements[root](); + } - for (i = modules.length - 1; i >= 0; i--) { - for (key in methods) { - modules[i].prototype[key] = methods[key]; - } + if (typeof element === 'string' && element.charAt(0) !== '<') { + return adopt(document.querySelector(element)); } - } // FIXME: enhanced constructors here - function addFactory(modules, methods) { - extend(modules, methods); - } // Invent new element + var node = makeNode('svg'); + node.innerHTML = element; // We can use firstChild here because we know, + // that the first char is < and thus an element - function invent(config) { - // Create element initializer - var initializer = typeof config.create === 'function' ? config.create : function (node) { - config.inherit.call(this, node || makeNode(config.create)); - }; // Inherit prototype + element = adopt(node.firstChild); + return element; + } // Adopt existing svg elements - if (config.inherit) { - /* eslint new-cap: "off" */ - initializer.prototype = new config.inherit(); - initializer.prototype.constructor = initializer; - } // Extend with methods - - - if (config.extend) { - extend(initializer, config.extend); - } // Attach construct method to parent - - - if (config.construct) { - extend(config.parent || getClass('Container'), config.construct); - } - - return initializer; - } - - var tools = /*#__PURE__*/Object.freeze({ - nodeOrNew: nodeOrNew, - makeNode: makeNode, - extend: extend, - addFactory: addFactory, - invent: invent - }); - - var elements = {}; - var root = Symbol('root'); - function makeInstance(element) { - if (element instanceof Base) return element; - - if (_typeof(element) === 'object') { - return adopt(element); - } - - if (element == null) { - return new elements[root](); - } - - if (typeof element === 'string' && element.charAt(0) !== '<') { - return adopt(document.querySelector(element)); - } - - var node = makeNode('svg'); - node.innerHTML = element; // We can use firstChild here because we know, - // that the first char is < and thus an element - - element = adopt(node.firstChild); - return element; - } // Adopt existing svg elements - - function adopt(node) { - // check for presence of node - if (!node) return null; // make sure a node isn't already adopted + function adopt(node) { + // check for presence of node + if (!node) return null; // make sure a node isn't already adopted if (node.instance instanceof Base) return node.instance; @@ -607,6 +727,196 @@ var SVG = (function () { assignNewId: assignNewId }); + function nodeOrNew(name, node) { + return node || makeNode(name); + } // Method for element creation + + function makeNode(name) { + // create element + return document.createElementNS(ns, name); + } // Method for extending objects + + function extend(modules, methods) { + var key, i; + modules = Array.isArray(modules) ? modules : [modules]; + + for (i = modules.length - 1; i >= 0; i--) { + for (key in methods) { + modules[i].prototype[key] = methods[key]; + } + } + } // FIXME: enhanced constructors here + + function addFactory(modules, methods) { + extend(modules, methods); + } // Invent new element + + function invent(config) { + // Create element initializer + var initializer = typeof config.create === 'function' ? config.create : function (node) { + config.inherit.call(this, node || makeNode(config.create)); + }; // Inherit prototype + + if (config.inherit) { + /* eslint new-cap: "off" */ + initializer.prototype = new config.inherit(); + initializer.prototype.constructor = initializer; + } // Extend with methods + + + if (config.extend) { + extend(initializer, config.extend); + } // Attach construct method to parent + + + if (config.construct) { + extend(config.parent || getClass('Container'), config.construct); + } + + return initializer; + } + + var tools = /*#__PURE__*/Object.freeze({ + nodeOrNew: nodeOrNew, + makeNode: makeNode, + extend: extend, + addFactory: addFactory, + invent: invent + }); + + var SVGArray = subClassArray('SVGArray', Array, function () { + this.init.apply(this, arguments); + }); + extend(SVGArray, { + init: function init() { + this.length = 0; + this.push.apply(this, _toConsumableArray(this.parse.apply(this, arguments))); + }, + toArray: function toArray() { + return Array.prototype.concat.apply([], this); + }, + toString: function toString() { + return this.join(' '); + }, + // Flattens the array if needed + valueOf: function valueOf() { + var ret = []; + ret.push.apply(ret, _toConsumableArray(this)); + return ret; + }, + // Parse whitespace separated string + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + // If already is an array, no need to parse it + if (array instanceof Array) return array; + return array.trim().split(delimiter).map(parseFloat); + }, + clone: function clone() { + return new this.constructor(this); + }, + toSet: function toSet() { + return new Set(this); + } + }); + + var SVGNumber = + /*#__PURE__*/ + function () { + // Initialize + function SVGNumber() { + _classCallCheck(this, SVGNumber); + + this.init.apply(this, arguments); + } + + _createClass(SVGNumber, [{ + key: "init", + value: function init(value, unit) { + unit = Array.isArray(value) ? value[1] : unit; + value = Array.isArray(value) ? value[0] : value; // initialize defaults + + this.value = 0; + this.unit = unit || ''; // parse value + + if (typeof value === 'number') { + // ensure a valid numeric value + this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; + } else if (typeof value === 'string') { + unit = value.match(numberAndUnit); + + if (unit) { + // make value numeric + this.value = parseFloat(unit[1]); // normalize + + if (unit[5] === '%') { + this.value /= 100; + } else if (unit[5] === 's') { + this.value *= 1000; + } // store unit + + + this.unit = unit[5]; + } + } else { + if (value instanceof SVGNumber) { + this.value = value.valueOf(); + this.unit = value.unit; + } + } + } + }, { + key: "toString", + value: function toString() { + return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; + } + }, { + key: "toJSON", + value: function toJSON() { + return this.toString(); + } + }, { + key: "toArray", + value: function toArray() { + return [this.value, this.unit]; + } + }, { + key: "valueOf", + value: function valueOf() { + return this.value; + } // Add number + + }, { + key: "plus", + value: function plus(number) { + number = new SVGNumber(number); + return new SVGNumber(this + number, this.unit || number.unit); + } // Subtract number + + }, { + key: "minus", + value: function minus(number) { + number = new SVGNumber(number); + return new SVGNumber(this - number, this.unit || number.unit); + } // Multiply number + + }, { + key: "times", + value: function times(number) { + number = new SVGNumber(number); + return new SVGNumber(this * number, this.unit || number.unit); + } // Divide number + + }, { + key: "divide", + value: function divide(number) { + number = new SVGNumber(number); + return new SVGNumber(this / number, this.unit || number.unit); + } + }]); + + return SVGNumber; + }(); + var listenerId = 0; function getEvents(node) { @@ -630,11 +940,7 @@ var SVG = (function () { var bag = getEvents(node); var n = getEventTarget(node); // events can be an array of events or a string of events - events = Array.isArray(events) ? events : events.split(delimiter); // ensure instance object for nodes which are not adopted - // n.instance = n.instance || {events: {}} - // pull event handlers from the element - // var bag = n.instance.events - // add id to listener + events = Array.isArray(events) ? events : events.split(delimiter); // add id to listener if (!listener._svgjsListenerId) { listener._svgjsListenerId = ++listenerId; @@ -655,16 +961,12 @@ var SVG = (function () { function off(node, events, listener, options) { var bag = getEvents(node); - var n = getEventTarget(node); // we cannot remove an event if its not an svg.js instance - // if (!n.instance) return - // listener can be a function or a number + var n = getEventTarget(node); // listener can be a function or a number if (typeof listener === 'function') { listener = listener._svgjsListenerId; if (!listener) return; - } // pull event handlers from the element - // var bag = n.instance.events - // events can be an array of events or a string or undefined + } // events can be an array of events or a string or undefined events = Array.isArray(events) ? events : (events || '').split(delimiter); @@ -739,17 +1041,67 @@ var SVG = (function () { dispatch: dispatch }); - var EventTarget = - /*#__PURE__*/ - function (_Base) { - _inherits(EventTarget, _Base); - - function EventTarget() { - var _this; - - var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, - _ref$events = _ref.events, - events = _ref$events === void 0 ? {} : _ref$events; + var methods = {}; + function registerMethods(name, m) { + if (Array.isArray(name)) { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = name[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var _name = _step.value; + registerMethods(_name, m); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + return; + } + + if (_typeof(name) === 'object') { + var _arr = Object.entries(name); + + for (var _i = 0; _i < _arr.length; _i++) { + var _arr$_i = _slicedToArray(_arr[_i], 2), + _name2 = _arr$_i[0], + _m = _arr$_i[1]; + + registerMethods(_name2, _m); + } + + return; + } + + methods[name] = Object.assign(methods[name] || {}, m); + } + function getMethodsFor(name) { + return methods[name] || {}; + } + + var EventTarget = + /*#__PURE__*/ + function (_Base) { + _inherits(EventTarget, _Base); + + function EventTarget() { + var _this; + + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + _ref$events = _ref.events, + events = _ref$events === void 0 ? {} : _ref$events; _classCallCheck(this, EventTarget); @@ -821,7 +1173,7 @@ var SVG = (function () { return EventTarget; }(Base); // Add events to elements - var methods = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove', 'mouseenter', 'mouseleave', 'touchstart', 'touchmove', 'touchleave', 'touchend', 'touchcancel'].reduce(function (last, event) { + var methods$1 = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove', 'mouseenter', 'mouseleave', 'touchstart', 'touchmove', 'touchleave', 'touchend', 'touchcancel'].reduce(function (last, event) { // add event to Element var fn = function fn(f) { if (f === null) { @@ -836,11 +1188,7 @@ var SVG = (function () { last[event] = fn; return last; }, {}); - extend(EventTarget, methods); // registerMethods('EventTarget', { - // on, off, dispatch, fire - // }) - // - // registerConstructor('EventTarget', setup) + registerMethods('Element', methods$1); // Map function function map(array, block) { @@ -1039,209 +1387,6 @@ var SVG = (function () { return Color; }(); - /* eslint no-new-func: "off" */ - var subClassArray = function () { - try { - // try es6 subclassing - return Function('name', 'baseClass', '_constructor', ['baseClass = baseClass || Array', 'return {', '[name]: class extends baseClass {', 'constructor (...args) {', 'super(...args)', '_constructor && _constructor.apply(this, args)', '}', '}', '}[name]'].join('\n')); - } catch (e) { - // Use es5 approach - return function (name) { - var baseClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Array; - - var _constructor = arguments.length > 2 ? arguments[2] : undefined; - - var Arr = function Arr() { - baseClass.apply(this, arguments); - _constructor && _constructor.apply(this, arguments); - }; - - Arr.prototype = Object.create(baseClass.prototype); - Arr.prototype.constructor = Arr; - return Arr; - }; - } - }(); - - var SVGArray = subClassArray('SVGArray', Array, function () { - this.init.apply(this, arguments); - }); - extend(SVGArray, { - init: function init() { - // this.splice(0, this.length) - this.length = 0; - this.push.apply(this, _toConsumableArray(this.parse.apply(this, arguments))); - }, - toArray: function toArray() { - // const ret = [] - // ret.push(...this) - // return ret - return Array.prototype.concat.apply([], this); - }, - toString: function toString() { - return this.join(' '); - }, - // Flattens the array if needed - valueOf: function valueOf() { - var ret = []; - ret.push.apply(ret, _toConsumableArray(this)); - return ret; // return this.toArray() - }, - // Parse whitespace separated string - parse: function parse() { - var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - // array = array.valueOf() - // If already is an array, no need to parse it - if (array instanceof Array) return array; - return array.trim().split(delimiter).map(parseFloat); - }, - clone: function clone() { - return new this.constructor(this); - }, - toSet: function toSet() { - return new Set(this); - } - }); // export default class SVGArray extends BaseArray { - // constructor (...args) { - // super() - // this.init(...args) - // } - // - // init (array, fallback = []) { - // //this.splice(0, this.length) - // this.length = 0 - // this.push(...this.parse(array || fallback)) - // } - // - // toArray () { - // return [].concat(this) - // } - // - // toString () { - // return this.join(' ') - // } - // - // valueOf () { - // return this.toArray() - // } - // - // // Parse whitespace separated string - // parse (array) { - // array = array.valueOf() - // - // // if already is an array, no need to parse it - // if (Array.isArray(array)) return array - // - // return array.trim().split(delimiter).map(parseFloat) - // } - // - // clone () { - // return new this.constructor(this) - // } - // - // toSet () { - // return new Set(this) - // } - // } - - var SVGNumber = - /*#__PURE__*/ - function () { - // Initialize - function SVGNumber() { - _classCallCheck(this, SVGNumber); - - this.init.apply(this, arguments); - } - - _createClass(SVGNumber, [{ - key: "init", - value: function init(value, unit) { - unit = Array.isArray(value) ? value[1] : unit; - value = Array.isArray(value) ? value[0] : value; // initialize defaults - - this.value = 0; - this.unit = unit || ''; // parse value - - if (typeof value === 'number') { - // ensure a valid numeric value - this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; - } else if (typeof value === 'string') { - unit = value.match(numberAndUnit); - - if (unit) { - // make value numeric - this.value = parseFloat(unit[1]); // normalize - - if (unit[5] === '%') { - this.value /= 100; - } else if (unit[5] === 's') { - this.value *= 1000; - } // store unit - - - this.unit = unit[5]; - } - } else { - if (value instanceof SVGNumber) { - this.value = value.valueOf(); - this.unit = value.unit; - } - } - } - }, { - key: "toString", - value: function toString() { - return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; - } - }, { - key: "toJSON", - value: function toJSON() { - return this.toString(); - } - }, { - key: "toArray", - value: function toArray() { - return [this.value, this.unit]; - } - }, { - key: "valueOf", - value: function valueOf() { - return this.value; - } // Add number - - }, { - key: "plus", - value: function plus(number) { - number = new SVGNumber(number); - return new SVGNumber(this + number, this.unit || number.unit); - } // Subtract number - - }, { - key: "minus", - value: function minus(number) { - number = new SVGNumber(number); - return new SVGNumber(this - number, this.unit || number.unit); - } // Multiply number - - }, { - key: "times", - value: function times(number) { - number = new SVGNumber(number); - return new SVGNumber(this * number, this.unit || number.unit); - } // Divide number - - }, { - key: "divide", - value: function divide(number) { - number = new SVGNumber(number); - return new SVGNumber(this / number, this.unit || number.unit); - } - }]); - - return SVGNumber; - }(); - // Set svg element attribute function attr(attr, val, ns) { @@ -1331,7 +1476,7 @@ var SVG = (function () { } return this; - } // registerMethods('Element', {attr}) + } var Dom = /*#__PURE__*/ @@ -1534,7 +1679,7 @@ var SVG = (function () { }, { key: "replace", value: function replace(element) { - // FIXME: after might not be available here + // FIXME: after() might not be available here this.after(element).remove(); return element; } // Return id on string conversion @@ -1737,21 +1882,7 @@ var SVG = (function () { }]); return Element; - }(Dom); // registerMethods('Element', { - - var Shape = - /*#__PURE__*/ - function (_Element) { - _inherits(Shape, _Element); - - function Shape() { - _classCallCheck(this, Shape); - - return _possibleConstructorReturn(this, _getPrototypeOf(Shape).apply(this, arguments)); - } - - return Shape; - }(Element); + }(Dom); var Container = /*#__PURE__*/ @@ -1790,31 +1921,51 @@ var SVG = (function () { return Container; }(Element); - var HtmlNode = + var Bare = /*#__PURE__*/ - function (_Dom) { - _inherits(HtmlNode, _Dom); + function (_Container) { + _inherits(Bare, _Container); - function HtmlNode(node) { - _classCallCheck(this, HtmlNode); + function Bare(node) { + _classCallCheck(this, Bare); - return _possibleConstructorReturn(this, _getPrototypeOf(HtmlNode).call(this, node, HtmlNode)); + return _possibleConstructorReturn(this, _getPrototypeOf(Bare).call(this, nodeOrNew(node, typeof node === 'string' ? null : node), Bare)); } - return HtmlNode; - }(Dom); - register(HtmlNode); - - var Defs = - /*#__PURE__*/ - function (_Container) { - _inherits(Defs, _Container); + _createClass(Bare, [{ + key: "words", + value: function words(text) { + // remove contents + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } // create text node - function Defs(node) { - _classCallCheck(this, Defs); - return _possibleConstructorReturn(this, _getPrototypeOf(Defs).call(this, nodeOrNew('defs', node), Defs)); - } + this.node.appendChild(document.createTextNode(text)); + return this; + } + }]); + + return Bare; + }(Container); + register(Bare); + registerMethods('Container', { + // Create an element that is not described by SVG.js + element: function element(node, inherit) { + return this.put(new Bare(node, inherit)); + } + }); + + var Defs = + /*#__PURE__*/ + function (_Container) { + _inherits(Defs, _Container); + + function Defs(node) { + _classCallCheck(this, Defs); + + return _possibleConstructorReturn(this, _getPrototypeOf(Defs).call(this, nodeOrNew('defs', node), Defs)); + } _createClass(Defs, [{ key: "flatten", @@ -1832,56 +1983,6 @@ var SVG = (function () { }(Container); register(Defs); - var methods$1 = {}; - function registerMethods(name, m) { - if (Array.isArray(name)) { - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = name[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var _name = _step.value; - registerMethods(_name, m); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - return; - } - - if (_typeof(name) === 'object') { - var _arr = Object.entries(name); - - for (var _i = 0; _i < _arr.length; _i++) { - var _arr$_i = _slicedToArray(_arr[_i], 2), - _name2 = _arr$_i[0], - _m = _arr$_i[1]; - - registerMethods(_name2, _m); - } - - return; - } - - methods$1[name] = Object.assign(methods$1[name] || {}, m); - } - function getMethodsFor(name) { - return methods$1[name] || {}; - } // FIXME: save memory? - var Doc$1 = /*#__PURE__*/ function (_Container) { @@ -1910,7 +2011,7 @@ var SVG = (function () { key: "doc", value: function doc() { if (this.isRoot()) return this; - return _get(_getPrototypeOf(Doc.prototype), "doc", this).call(this); // return doc.call(this) + return _get(_getPrototypeOf(Doc.prototype), "doc", this).call(this); } // Add namespaces }, { @@ -1937,20 +2038,8 @@ var SVG = (function () { return this.node.parentNode.nodeName === '#document' ? null : adopt(this.node.parentNode); } - return _get(_getPrototypeOf(Doc.prototype), "parent", this).call(this, type); // return parent.call(this, type) - } // Removes the doc from the DOM - // remove() { - // if (!this.isRoot()) { - // return super.remove() - // } - // - // if (this.parent()) { - // this.parent().remove(this) - // } - // - // return this - // } - + return _get(_getPrototypeOf(Doc.prototype), "parent", this).call(this, type); + } }, { key: "clear", value: function clear() { @@ -1975,216 +2064,231 @@ var SVG = (function () { }); register(Doc$1, 'Doc', true); - var G = - /*#__PURE__*/ - function (_Container) { - _inherits(G, _Container); - - function G(node) { - _classCallCheck(this, G); - - return _possibleConstructorReturn(this, _getPrototypeOf(G).call(this, nodeOrNew('g', node), G)); + function parser() { + // Reuse cached element if possible + if (!parser.nodes) { + var svg = new Doc$1().size(2, 0).css({ + opacity: 0, + position: 'absolute', + left: '-100%', + top: '-100%', + overflow: 'hidden' + }); + var path = svg.path().node; + parser.nodes = { + svg: svg, + path: path + }; } - return G; - }(Container); - registerMethods({ - Element: { - // Create a group element - group: function group() { - return this.put(new G()); - } + if (!parser.nodes.svg.node.parentNode) { + var b = document.body || document.documentElement; + parser.nodes.svg.addTo(b); } - }); - register(G); - var Queue = + return parser.nodes; + } + + var Point = /*#__PURE__*/ function () { - function Queue() { - _classCallCheck(this, Queue); - - this._first = null; - this._last = null; - } - - _createClass(Queue, [{ - key: "push", - value: function push(value) { - // An item stores an id and the provided value - var item = value.next ? value : { - value: value, - next: null, - prev: null // Deal with the queue being empty or populated + // Initialize + function Point(x, y, base) { + _classCallCheck(this, Point); - }; + var source; + base = base || { + x: 0, + y: 0 // ensure source as object - if (this._last) { - item.prev = this._last; - this._last.next = item; - this._last = item; - } else { - this._last = item; - this._first = item; - } // Update the length and return the current item + }; + source = Array.isArray(x) ? { + x: x[0], + y: x[1] + } : _typeof(x) === 'object' ? { + x: x.x, + y: x.y + } : { + x: x, + y: y // merge source + }; + this.x = source.x == null ? base.x : source.x; + this.y = source.y == null ? base.y : source.y; + } // Clone point - return item; - } - }, { - key: "shift", - value: function shift() { - // Check if we have a value - var remove = this._first; - if (!remove) return null; // If we do, remove it and relink things - this._first = remove.next; - if (this._first) this._first.prev = null; - this._last = this._first ? this._last : null; - return remove.value; - } // Shows us the first item in the list + _createClass(Point, [{ + key: "clone", + value: function clone() { + return new Point(this); + } // Convert to native SVGPoint }, { - key: "first", - value: function first() { - return this._first && this._first.value; - } // Shows us the last item in the list + key: "native", + value: function native() { + // create new point + var point = parser().svg.node.createSVGPoint(); // update with current values - }, { - key: "last", - value: function last() { - return this._last && this._last.value; - } // Removes the item that was returned from the push + point.x = this.x; + point.y = this.y; + return point; + } // transform point with matrix }, { - key: "remove", - value: function remove(item) { - // Relink the previous item - if (item.prev) item.prev.next = item.next; - if (item.next) item.next.prev = item.prev; - if (item === this._last) this._last = item.prev; - if (item === this._first) this._first = item.next; // Invalidate item + key: "transform", + value: function transform(m) { + // Perform the matrix multiplication + var x = m.a * this.x + m.c * this.y + m.e; + var y = m.b * this.x + m.d * this.y + m.f; // Return the required point - item.prev = null; - item.next = null; + return new Point(x, y); } }]); - return Queue; + return Point; }(); + registerMethods({ + Element: { + // Get point + point: function point(x, y) { + return new Point(x, y).transform(this.screenCTM().inverse()); + } + } + }); - var Animator = { - nextDraw: null, - frames: new Queue(), - timeouts: new Queue(), - timer: window.performance || window.Date, - transforms: [], - frame: function frame(fn) { - // Store the node - var node = Animator.frames.push({ - run: fn - }); // Request an animation frame if we don't have one + var Box = + /*#__PURE__*/ + function () { + function Box() { + _classCallCheck(this, Box); - if (Animator.nextDraw === null) { - Animator.nextDraw = window.requestAnimationFrame(Animator._draw); - } // Return the node so we can remove it easily + this.init.apply(this, arguments); + } + _createClass(Box, [{ + key: "init", + value: function init(source) { + var base = [0, 0, 0, 0]; + source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) : Array.isArray(source) ? source : _typeof(source) === 'object' ? [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] : arguments.length === 4 ? [].slice.call(arguments) : base; + this.x = source[0]; + this.y = source[1]; + this.width = source[2]; + this.height = source[3]; // add center, right, bottom... - return node; - }, - transform_frame: function transform_frame(fn, id) { - Animator.transforms[id] = fn; - }, - timeout: function timeout(fn, delay) { - delay = delay || 0; // Work out when the event should fire - - var time = Animator.timer.now() + delay; // Add the timeout to the end of the queue - - var node = Animator.timeouts.push({ - run: fn, - time: time - }); // Request another animation frame if we need one + fullBox(this); + } // Merge rect box with another, return a new instance - if (Animator.nextDraw === null) { - Animator.nextDraw = window.requestAnimationFrame(Animator._draw); + }, { + key: "merge", + value: function merge(box) { + var x = Math.min(this.x, box.x); + var y = Math.min(this.y, box.y); + var width = Math.max(this.x + this.width, box.x + box.width) - x; + var height = Math.max(this.y + this.height, box.y + box.height) - y; + return new Box(x, y, width, height); } + }, { + key: "transform", + value: function transform(m) { + var xMin = Infinity; + var xMax = -Infinity; + var yMin = Infinity; + var yMax = -Infinity; + var pts = [new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2)]; + pts.forEach(function (p) { + p = p.transform(m); + xMin = Math.min(xMin, p.x); + xMax = Math.max(xMax, p.x); + yMin = Math.min(yMin, p.y); + yMax = Math.max(yMax, p.y); + }); + return new Box(xMin, yMin, xMax - xMin, yMax - yMin); + } + }, { + key: "addOffset", + value: function addOffset() { + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset; + this.y += window.pageYOffset; + return this; + } + }, { + key: "toString", + value: function toString() { + return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height; + } + }, { + key: "toArray", + value: function toArray() { + return [this.x, this.y, this.width, this.height]; + } + }]); - return node; - }, - cancelFrame: function cancelFrame(node) { - Animator.frames.remove(node); - }, - clearTimeout: function clearTimeout(node) { - Animator.timeouts.remove(node); - }, - _draw: function _draw(now) { - // Run all the timeouts we can run, if they are not ready yet, add them - // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) - var nextTimeout = null; - var lastTimeout = Animator.timeouts.last(); - - while (nextTimeout = Animator.timeouts.shift()) { - // Run the timeout if its time, or push it to the end - if (now >= nextTimeout.time) { - nextTimeout.run(); - } else { - Animator.timeouts.push(nextTimeout); - } // If we hit the last item, we should stop shifting out more items + return Box; + }(); + function getBox(cb) { + var box; - if (nextTimeout === lastTimeout) break; - } // Run all of the animation frames + try { + box = cb(this.node); + if (isNulledBox(box) && !domContains(this.node)) { + throw new Error('Element not in the dom'); + } + } catch (e) { + try { + var clone = this.clone(parser().svg).show(); + box = cb(clone.node); + clone.remove(); + } catch (e) { + console.warn('Getting a bounding box of this element is not possible'); + } + } - var nextFrame = null; - var lastFrame = Animator.frames.last(); + return box; + } - while (nextFrame !== lastFrame && (nextFrame = Animator.frames.shift())) { - nextFrame.run(); + registerMethods({ + Element: { + // Get bounding box + bbox: function bbox() { + return new Box(getBox.call(this, function (node) { + return node.getBBox(); + })); + }, + rbox: function rbox(el) { + var box = new Box(getBox.call(this, function (node) { + return node.getBoundingClientRect(); + })); + if (el) return box.transform(el.screenCTM().inverse()); + return box.addOffset(); } + }, + viewbox: { + viewbox: function viewbox(x, y, width, height) { + // act as getter + if (x == null) return new Box(this.attr('viewBox')); // act as setter - Animator.transforms.forEach(function (el) { - el(); - }); // If we have remaining timeouts or frames, draw until we don't anymore - - Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() ? window.requestAnimationFrame(Animator._draw) : null; + return this.attr('viewBox', new Box(x, y, width, height)); + } } - }; + }); - var Bare = + var Shape = /*#__PURE__*/ - function (_Container) { - _inherits(Bare, _Container); + function (_Element) { + _inherits(Shape, _Element); - function Bare(node) { - _classCallCheck(this, Bare); + function Shape() { + _classCallCheck(this, Shape); - return _possibleConstructorReturn(this, _getPrototypeOf(Bare).call(this, nodeOrNew(node, typeof node === 'string' ? null : node), Bare)); + return _possibleConstructorReturn(this, _getPrototypeOf(Shape).apply(this, arguments)); } - _createClass(Bare, [{ - key: "words", - value: function words(text) { - // remove contents - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild); - } // create text node - - - this.node.appendChild(document.createTextNode(text)); - return this; - } - }]); - - return Bare; - }(Container); - register(Bare); - registerMethods('Container', { - // Create an element that is not described by SVG.js - element: function element(node, inherit) { - return this.put(new Bare(node, inherit)); - } - }); + return Shape; + }(Element); // FIXME: import this to runner @@ -2288,28 +2392,6 @@ var SVG = (function () { }); register(Circle); - // SVG.get = function (id) { - // var node = document.getElementById(idFromReference(id) || id) - // 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.$$ = function (query, parent) { - // return SVG.utils.map((parent || document).querySelectorAll(query), function (node) { - // return SVG.adopt(node) - // }) - // } - // - // SVG.$ = function (query, parent) { - // return SVG.adopt((parent || document).querySelector(query)) - // } - function baseFind(query, parent) { return map((parent || document).querySelectorAll(query), function (node) { return adopt(node); @@ -2343,7 +2425,7 @@ var SVG = (function () { el.unclip(); }); // remove clipPath from parent - return _get(_getPrototypeOf(ClipPath.prototype), "remove", this).call(this); // return remove.call(this) + return _get(_getPrototypeOf(ClipPath.prototype), "remove", this).call(this); } }, { key: "targets", @@ -2380,56 +2462,235 @@ var SVG = (function () { }); register(ClipPath); - var A = - /*#__PURE__*/ - function (_Container) { - _inherits(A, _Container); - - function A(node) { - _classCallCheck(this, A); - - return _possibleConstructorReturn(this, _getPrototypeOf(A).call(this, nodeOrNew('a', node), A)); - } // Link url + /*** + Base Class + ========== + The base stepper class that will be + ***/ + function makeSetterGetter(k, f) { + return function (v) { + if (v == null) return this[v]; + this[k] = v; + if (f) f.call(this); + return this; + }; + } - _createClass(A, [{ - key: "to", - value: function to(url) { - return this.attr('href', url, xlink); - } // Link target attribute + var easing = { + '-': function _(pos) { + return pos; + }, + '<>': function _(pos) { + return -Math.cos(pos * Math.PI) / 2 + 0.5; + }, + '>': function _(pos) { + return Math.sin(pos * Math.PI / 2); + }, + '<': function _(pos) { + return -Math.cos(pos * Math.PI / 2) + 1; + }, + bezier: function bezier(t0, x0, t1, x1) { + return function (t) {// TODO: FINISH + }; + } + }; + var Stepper = + /*#__PURE__*/ + function () { + function Stepper() { + _classCallCheck(this, Stepper); + } - }, { - key: "target", - value: function target(_target) { - return this.attr('target', _target); + _createClass(Stepper, [{ + key: "done", + value: function done() { + return false; } }]); - return A; - }(Container); - registerMethods({ - Container: { - // Create a hyperlink element - link: function link(url) { - return this.put(new A()).to(url); - } - }, - Element: { - // Create a hyperlink element - linkTo: function linkTo(url) { - var link = new A(); + return Stepper; + }(); + /*** + Easing Functions + ================ + ***/ - if (typeof url === 'function') { - url.call(link, link); - } else { - link.to(url); + var Ease = + /*#__PURE__*/ + function (_Stepper) { + _inherits(Ease, _Stepper); + + function Ease(fn) { + var _this; + + _classCallCheck(this, Ease); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Ease).call(this)); + _this.ease = easing[fn || timeline.ease] || fn; + return _this; + } + + _createClass(Ease, [{ + key: "step", + value: function step(from, to, pos) { + if (typeof from !== 'number') { + return pos < 1 ? from : to; } - return this.parent().put(link).put(this); + return from + (to - from) * this.ease(pos); + } + }]); + + return Ease; + }(Stepper); + /*** + Controller Types + ================ + ***/ + + var Controller = + /*#__PURE__*/ + function (_Stepper2) { + _inherits(Controller, _Stepper2); + + function Controller(fn) { + var _this2; + + _classCallCheck(this, Controller); + + _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Controller).call(this)); + _this2.stepper = fn; + return _this2; + } + + _createClass(Controller, [{ + key: "step", + value: function step(current, target, dt, c) { + return this.stepper(current, target, dt, c); + } + }, { + key: "done", + value: function done(c) { + return c.done; } + }]); + + return Controller; + }(Stepper); + + function recalculate() { + // Apply the default parameters + var duration = (this._duration || 500) / 1000; + var overshoot = this._overshoot || 0; // Calculate the PID natural response + + var eps = 1e-10; + var pi = Math.PI; + var os = Math.log(overshoot / 100 + eps); + var zeta = -os / Math.sqrt(pi * pi + os * os); + var wn = 3.9 / (zeta * duration); // Calculate the Spring values + + this.d = 2 * zeta * wn; + this.k = wn * wn; + } + + var Spring = + /*#__PURE__*/ + function (_Controller) { + _inherits(Spring, _Controller); + + function Spring(duration, overshoot) { + var _this3; + + _classCallCheck(this, Spring); + + _this3 = _possibleConstructorReturn(this, _getPrototypeOf(Spring).call(this)); + + _this3.duration(duration || 500).overshoot(overshoot || 0); + + return _this3; } + + _createClass(Spring, [{ + key: "step", + value: function step(current, target, dt, c) { + if (typeof current === 'string') return current; + c.done = dt === Infinity; + if (dt === Infinity) return target; + if (dt === 0) return current; + if (dt > 100) dt = 16; + dt /= 1000; // Get the previous velocity + + var velocity = c.velocity || 0; // Apply the control to get the new position and store it + + var acceleration = -this.d * velocity - this.k * (current - target); + var newPosition = current + velocity * dt + acceleration * dt * dt / 2; // Store the velocity + + c.velocity = velocity + acceleration * dt; // Figure out if we have converged, and if so, pass the value + + c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002; + return c.done ? target : newPosition; + } + }]); + + return Spring; + }(Controller); + extend(Spring, { + duration: makeSetterGetter('_duration', recalculate), + overshoot: makeSetterGetter('_overshoot', recalculate) + }); + var PID = + /*#__PURE__*/ + function (_Controller2) { + _inherits(PID, _Controller2); + + function PID(p, i, d, windup) { + var _this4; + + _classCallCheck(this, PID); + + _this4 = _possibleConstructorReturn(this, _getPrototypeOf(PID).call(this)); + p = p == null ? 0.1 : p; + i = i == null ? 0.01 : i; + d = d == null ? 0 : d; + windup = windup == null ? 1000 : windup; + + _this4.p(p).i(i).d(d).windup(windup); + + return _this4; + } + + _createClass(PID, [{ + key: "step", + value: function step(current, target, dt, c) { + if (typeof current === 'string') return current; + c.done = dt === Infinity; + if (dt === Infinity) return target; + if (dt === 0) return current; + var p = target - current; + var i = (c.integral || 0) + p * dt; + var d = (p - (c.error || 0)) / dt; + var windup = this.windup; // antiwindup + + if (windup !== false) { + i = Math.max(-windup, Math.min(i, windup)); + } + + c.error = p; + c.integral = i; + c.done = Math.abs(p) < 0.001; + return c.done ? target : current + (this.P * p + this.I * i + this.D * d); + } + }]); + + return PID; + }(Controller); + extend(PID, { + windup: makeSetterGetter('windup'), + p: makeSetterGetter('P'), + i: makeSetterGetter('I'), + d: makeSetterGetter('D') }); - register(A); var Ellipse = /*#__PURE__*/ @@ -2513,240 +2774,198 @@ var SVG = (function () { to: to }); - function parser() { - // Reuse cached element if possible - if (!parser.nodes) { - var svg = new Doc$1().size(2, 0).css({ - opacity: 0, - position: 'absolute', - left: '-100%', - top: '-100%', - overflow: 'hidden' - }); - var path = svg.path().node; - parser.nodes = { - svg: svg, - path: path - }; - } - - if (!parser.nodes.svg.node.parentNode) { - var b = document.body || document.documentElement; - parser.nodes.svg.addTo(b); - } - - return parser.nodes; - } - - var Point = + var Gradient = /*#__PURE__*/ - function () { - // Initialize - function Point(x, y, base) { - _classCallCheck(this, Point); - - var source; - base = base || { - x: 0, - y: 0 // ensure source as object + function (_Container) { + _inherits(Gradient, _Container); - }; - source = Array.isArray(x) ? { - x: x[0], - y: x[1] - } : _typeof(x) === 'object' ? { - x: x.x, - y: x.y - } : { - x: x, - y: y // merge source + function Gradient(type) { + _classCallCheck(this, Gradient); - }; - this.x = source.x == null ? base.x : source.x; - this.y = source.y == null ? base.y : source.y; - } // Clone point + return _possibleConstructorReturn(this, _getPrototypeOf(Gradient).call(this, nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type), Gradient)); + } // Add a color stop - _createClass(Point, [{ - key: "clone", - value: function clone() { - return new Point(this); - } // Convert to native SVGPoint + _createClass(Gradient, [{ + key: "stop", + value: function stop(offset, color, opacity) { + return this.put(new Stop()).update(offset, color, opacity); + } // Update gradient }, { - key: "native", - value: function native() { - // create new point - var point = parser().svg.node.createSVGPoint(); // update with current values + key: "update", + value: function update(block) { + // remove all stops + this.clear(); // invoke passed block - point.x = this.x; - point.y = this.y; - return point; - } // transform point with matrix + if (typeof block === 'function') { + block.call(this, this); + } + + return this; + } // Return the fill id }, { - key: "transform", - value: function transform(m) { - // Perform the matrix multiplication - var x = m.a * this.x + m.c * this.y + m.e; - var y = m.b * this.x + m.d * this.y + m.f; // Return the required point + key: "url", + value: function url() { + return 'url(#' + this.id() + ')'; + } // Alias string convertion to fill - return new Point(x, y); + }, { + key: "toString", + value: function toString() { + return this.url(); + } // custom attr to handle transform + + }, { + key: "attr", + value: function attr(a, b, c) { + if (a === 'transform') a = 'gradientTransform'; + return _get(_getPrototypeOf(Gradient.prototype), "attr", this).call(this, a, b, c); + } + }, { + key: "targets", + value: function targets() { + return find('svg [fill*="' + this.id() + '"]'); + } + }, { + key: "bbox", + value: function bbox() { + return new Box(); } }]); - return Point; - }(); + return Gradient; + }(Container); + extend(Gradient, gradiented); + registerMethods({ + Container: { + // Create gradient element in defs + gradient: function gradient(type, block) { + return this.defs().gradient(type, block); + } + }, + // define gradient + Defs: { + gradient: function gradient(type, block) { + return this.put(new Gradient(type)).update(block); + } + } + }); + register(Gradient); + + var G = + /*#__PURE__*/ + function (_Container) { + _inherits(G, _Container); + + function G(node) { + _classCallCheck(this, G); + + return _possibleConstructorReturn(this, _getPrototypeOf(G).call(this, nodeOrNew('g', node), G)); + } + + return G; + }(Container); registerMethods({ Element: { - // Get point - point: function point(x, y) { - return new Point(x, y).transform(this.screenCTM().inverse()); + // Create a group element + group: function group() { + return this.put(new G()); } } }); + register(G); - var Box = + var HtmlNode = /*#__PURE__*/ - function () { - function Box() { - _classCallCheck(this, Box); + function (_Dom) { + _inherits(HtmlNode, _Dom); - this.init.apply(this, arguments); + function HtmlNode(node) { + _classCallCheck(this, HtmlNode); + + return _possibleConstructorReturn(this, _getPrototypeOf(HtmlNode).call(this, node, HtmlNode)); } - _createClass(Box, [{ - key: "init", - value: function init(source) { - var base = [0, 0, 0, 0]; - source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) : Array.isArray(source) ? source : _typeof(source) === 'object' ? [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] : arguments.length === 4 ? [].slice.call(arguments) : base; - this.x = source[0]; - this.y = source[1]; - this.width = source[2]; - this.height = source[3]; // add center, right, bottom... + return HtmlNode; + }(Dom); + register(HtmlNode); - fullBox(this); - } // Merge rect box with another, return a new instance + var A = + /*#__PURE__*/ + function (_Container) { + _inherits(A, _Container); - }, { - key: "merge", - value: function merge(box) { - var x = Math.min(this.x, box.x); - var y = Math.min(this.y, box.y); - var width = Math.max(this.x + this.width, box.x + box.width) - x; - var height = Math.max(this.y + this.height, box.y + box.height) - y; - return new Box(x, y, width, height); - } - }, { - key: "transform", - value: function transform(m) { - var xMin = Infinity; - var xMax = -Infinity; - var yMin = Infinity; - var yMax = -Infinity; - var pts = [new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2)]; - pts.forEach(function (p) { - p = p.transform(m); - xMin = Math.min(xMin, p.x); - xMax = Math.max(xMax, p.x); - yMin = Math.min(yMin, p.y); - yMax = Math.max(yMax, p.y); - }); - return new Box(xMin, yMin, xMax - xMin, yMax - yMin); - } - }, { - key: "addOffset", - value: function addOffset() { - // offset by window scroll position, because getBoundingClientRect changes when window is scrolled - this.x += window.pageXOffset; - this.y += window.pageYOffset; - return this; - } - }, { - key: "toString", - value: function toString() { - return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height; - } - }, { - key: "toArray", - value: function toArray() { - return [this.x, this.y, this.width, this.height]; - } - }]); + function A(node) { + _classCallCheck(this, A); - return Box; - }(); + return _possibleConstructorReturn(this, _getPrototypeOf(A).call(this, nodeOrNew('a', node), A)); + } // Link url - function getBox(cb) { - var box; - try { - box = cb(this.node); + _createClass(A, [{ + key: "to", + value: function to(url) { + return this.attr('href', url, xlink); + } // Link target attribute - if (isNulledBox(box) && !domContains(this.node)) { - throw new Error('Element not in the dom'); - } - } catch (e) { - try { - var clone = this.clone(parser().svg).show(); - box = cb(clone.node); - clone.remove(); - } catch (e) { - console.warn('Getting a bounding box of this element is not possible'); + }, { + key: "target", + value: function target(_target) { + return this.attr('target', _target); } - } - - return box; - } + }]); + return A; + }(Container); registerMethods({ - Element: { - // Get bounding box - bbox: function bbox() { - return new Box(getBox.call(this, function (node) { - return node.getBBox(); - })); - }, - rbox: function rbox(el) { - var box = new Box(getBox.call(this, function (node) { - return node.getBoundingClientRect(); - })); - if (el) return box.transform(el.screenCTM().inverse()); - return box.addOffset(); + Container: { + // Create a hyperlink element + link: function link(url) { + return this.put(new A()).to(url); } }, - viewbox: { - viewbox: function viewbox(x, y, width, height) { - // act as getter - if (x == null) return new Box(this.attr('viewBox')); // act as setter + Element: { + // Create a hyperlink element + linkTo: function linkTo(url) { + var link = new A(); - return this.attr('viewBox', new Box(x, y, width, height)); + if (typeof url === 'function') { + url.call(link, link); + } else { + link.to(url); + } + + return this.parent().put(link).put(this); } } }); + register(A); - var Gradient = + var Pattern = /*#__PURE__*/ function (_Container) { - _inherits(Gradient, _Container); + _inherits(Pattern, _Container); - function Gradient(type) { - _classCallCheck(this, Gradient); + // Initialize node + function Pattern(node) { + _classCallCheck(this, Pattern); - return _possibleConstructorReturn(this, _getPrototypeOf(Gradient).call(this, nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type), Gradient)); - } // Add a color stop + return _possibleConstructorReturn(this, _getPrototypeOf(Pattern).call(this, nodeOrNew('pattern', node), Pattern)); + } // Return the fill id - _createClass(Gradient, [{ - key: "stop", - value: function stop(offset, color, opacity) { - return this.put(new Stop()).update(offset, color, opacity); - } // Update gradient + _createClass(Pattern, [{ + key: "url", + value: function url() { + return 'url(#' + this.id() + ')'; + } // Update pattern by rebuilding }, { key: "update", value: function update(block) { - // remove all stops + // remove content this.clear(); // invoke passed block if (typeof block === 'function') { @@ -2754,12 +2973,6 @@ var SVG = (function () { } return this; - } // Return the fill id - - }, { - key: "url", - value: function url() { - return 'url(#' + this.id() + ')'; } // Alias string convertion to fill }, { @@ -2771,8 +2984,8 @@ var SVG = (function () { }, { key: "attr", value: function attr(a, b, c) { - if (a === 'transform') a = 'gradientTransform'; - return _get(_getPrototypeOf(Gradient.prototype), "attr", this).call(this, a, b, c); // return attr.call(this, a, b, c) + if (a === 'transform') a = 'patternTransform'; + return _get(_getPrototypeOf(Pattern.prototype), "attr", this).call(this, a, b, c); } }, { key: "targets", @@ -2786,82 +2999,7 @@ var SVG = (function () { } }]); - return Gradient; - }(Container); - extend(Gradient, gradiented); - registerMethods({ - Container: { - // Create gradient element in defs - gradient: function gradient(type, block) { - return this.defs().gradient(type, block); - } - }, - // define gradient - Defs: { - gradient: function gradient(type, block) { - return this.put(new Gradient(type)).update(block); - } - } - }); - register(Gradient); - - var Pattern = - /*#__PURE__*/ - function (_Container) { - _inherits(Pattern, _Container); - - // Initialize node - function Pattern(node) { - _classCallCheck(this, Pattern); - - return _possibleConstructorReturn(this, _getPrototypeOf(Pattern).call(this, nodeOrNew('pattern', node), Pattern)); - } // Return the fill id - - - _createClass(Pattern, [{ - key: "url", - value: function url() { - return 'url(#' + this.id() + ')'; - } // Update pattern by rebuilding - - }, { - key: "update", - value: function update(block) { - // remove content - this.clear(); // invoke passed block - - if (typeof block === 'function') { - block.call(this, this); - } - - return this; - } // Alias string convertion to fill - - }, { - key: "toString", - value: function toString() { - return this.url(); - } // custom attr to handle transform - - }, { - key: "attr", - value: function attr(a, b, c) { - if (a === 'transform') a = 'patternTransform'; - return _get(_getPrototypeOf(Pattern.prototype), "attr", this).call(this, a, b, c); // return attr.call(this, a, b, c) - } - }, { - key: "targets", - value: function targets() { - return find('svg [fill*="' + this.id() + '"]'); - } - }, { - key: "bbox", - value: function bbox() { - return new Box(); - } - }]); - - return Pattern; + return Pattern; }(Container); registerMethods({ Container: { @@ -3056,129 +3194,7 @@ var SVG = (function () { height: maxY - minY }; } - }); // export default class PointArray extends SVGArray { - // constructor (array, fallback = [[0, 0]]) { - // super(array, fallback) - // } - // - // // Convert array to string - // toString () { - // // convert to a poly point string - // for (var i = 0, il = this.length, array = []; i < il; i++) { - // array.push(this[i].join(',')) - // } - // - // return array.join(' ') - // } - // - // // toArray () { - // // return this.reduce(function (prev, curr) { - // // return [].concat.call(prev, curr) - // // }, []) - // // } - // - // // Convert array to line object - // toLine () { - // return { - // x1: this[0][0], - // y1: this[0][1], - // x2: this[1][0], - // y2: this[1][1] - // } - // } - // - // // Get morphed array at given position - // at (pos) { - // // make sure a destination is defined - // if (!this.destination) return this - // - // // generate morphed point string - // for (var i = 0, il = this.length, array = []; i < il; i++) { - // array.push([ - // this[i][0] + (this.destination[i][0] - this[i][0]) * pos, - // this[i][1] + (this.destination[i][1] - this[i][1]) * pos - // ]) - // } - // - // return new PointArray(array) - // } - // - // // Parse point string and flat array - // parse (array) { - // var points = [] - // - // array = array.valueOf() - // - // // if it is an array - // if (Array.isArray(array)) { - // // and it is not flat, there is no need to parse it - // if (Array.isArray(array[0])) { - // return array - // } - // } else { // Else, it is considered as a string - // // parse points - // array = array.trim().split(delimiter).map(parseFloat) - // } - // - // // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints - // // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. - // if (array.length % 2 !== 0) array.pop() - // - // // wrap points in two-tuples and parse points as floats - // for (var i = 0, len = array.length; i < len; i = i + 2) { - // points.push([ array[i], array[i + 1] ]) - // } - // - // return points - // } - // - // // Move point string - // move (x, y) { - // var box = this.bbox() - // - // // get relative offset - // x -= box.x - // y -= box.y - // - // // move every point - // if (!isNaN(x) && !isNaN(y)) { - // for (var i = this.length - 1; i >= 0; i--) { - // this[i] = [this[i][0] + x, this[i][1] + y] - // } - // } - // - // return this - // } - // - // // Resize poly string - // size (width, height) { - // var i - // var box = this.bbox() - // - // // recalculate position of all points according to new size - // for (i = this.length - 1; i >= 0; i--) { - // if (box.width) this[i][0] = ((this[i][0] - box.x) * width) / box.width + box.x - // if (box.height) this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y - // } - // - // return this - // } - // - // // Get bounding box of points - // bbox () { - // var maxX = -Infinity - // var maxY = -Infinity - // var minX = Infinity - // var minY = Infinity - // this.forEach(function (el) { - // maxX = Math.max(el[0], maxX) - // maxY = Math.max(el[1], maxY) - // minX = Math.min(el[0], minX) - // minY = Math.min(el[1], minY) - // }) - // return {x: minX, y: minY, width: maxX - minX, height: maxY - minY} - // } - // } + }); var MorphArray = PointArray; // Move by left top corner over x-axis @@ -3382,7 +3398,7 @@ var SVG = (function () { el.unmask(); }); // remove mask from parent - return _get(_getPrototypeOf(Mask.prototype), "remove", this).call(this); // return remove.call(this) + return _get(_getPrototypeOf(Mask.prototype), "remove", this).call(this); } }, { key: "targets", @@ -3418,3409 +3434,2924 @@ var SVG = (function () { }); register(Mask); - var PathArray = subClassArray('PathArray', SVGArray); - var pathHandlers = { - M: function M(c, p, p0) { - p.x = p0.x = c[0]; - p.y = p0.y = c[1]; - return ['M', p.x, p.y]; - }, - L: function L(c, p) { - p.x = c[0]; - p.y = c[1]; - return ['L', c[0], c[1]]; - }, - H: function H(c, p) { - p.x = c[0]; - return ['H', c[0]]; - }, - V: function V(c, p) { - p.y = c[0]; - return ['V', c[0]]; - }, - C: function C(c, p) { - p.x = c[4]; - p.y = c[5]; - return ['C', c[0], c[1], c[2], c[3], c[4], c[5]]; - }, - S: function S(c, p) { - p.x = c[2]; - p.y = c[3]; - return ['S', c[0], c[1], c[2], c[3]]; - }, - Q: function Q(c, p) { - p.x = c[2]; - p.y = c[3]; - return ['Q', c[0], c[1], c[2], c[3]]; - }, - T: function T(c, p) { - p.x = c[0]; - p.y = c[1]; - return ['T', c[0], c[1]]; - }, - Z: function Z(c, p, p0) { - p.x = p0.x; - p.y = p0.y; - return ['Z']; - }, - A: function A(c, p) { - p.x = c[5]; - p.y = c[6]; - return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]]; - } - }; - var mlhvqtcsaz = 'mlhvqtcsaz'.split(''); + var Matrix = + /*#__PURE__*/ + function () { + function Matrix() { + _classCallCheck(this, Matrix); - for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { - pathHandlers[mlhvqtcsaz[i]] = function (i) { - return function (c, p, p0) { - if (i === 'H') c[0] = c[0] + p.x;else if (i === 'V') c[0] = c[0] + p.y;else if (i === 'A') { - c[5] = c[5] + p.x; - c[6] = c[6] + p.y; - } else { - for (var j = 0, jl = c.length; j < jl; ++j) { - c[j] = c[j] + (j % 2 ? p.y : p.x); - } - } - return pathHandlers[i](c, p, p0); - }; - }(mlhvqtcsaz[i].toUpperCase()); - } + this.init.apply(this, arguments); + } // Initialize - extend(PathArray, { - // Convert array to string - toString: function toString() { - return arrayToString(this); - }, - // Move path string - move: function move(x, y) { - // get bounding box of current situation - var box = this.bbox(); // get relative offset - x -= box.x; - y -= box.y; + _createClass(Matrix, [{ + key: "init", + value: function init(source) { + var base = arrayToMatrix([1, 0, 0, 1, 0, 0]); // ensure source as object - if (!isNaN(x) && !isNaN(y)) { - // move every point - for (var l, i = this.length - 1; i >= 0; i--) { - l = this[i][0]; + source = source instanceof Element ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? arrayToMatrix(source) : _typeof(source) === 'object' && isMatrixLike(source) ? source : _typeof(source) === 'object' ? new Matrix().transform(source) : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) : base; // Merge the source matrix with the base matrix - if (l === 'M' || l === 'L' || l === 'T') { - this[i][1] += x; - this[i][2] += y; - } else if (l === 'H') { - this[i][1] += x; - } else if (l === 'V') { - this[i][1] += y; - } else if (l === 'C' || l === 'S' || l === 'Q') { - this[i][1] += x; - this[i][2] += y; - this[i][3] += x; - this[i][4] += y; + this.a = source.a != null ? source.a : base.a; + this.b = source.b != null ? source.b : base.b; + this.c = source.c != null ? source.c : base.c; + this.d = source.d != null ? source.d : base.d; + this.e = source.e != null ? source.e : base.e; + this.f = source.f != null ? source.f : base.f; + } // Clones this matrix - if (l === 'C') { - this[i][5] += x; - this[i][6] += y; - } - } else if (l === 'A') { - this[i][6] += x; - this[i][7] += y; - } - } - } + }, { + key: "clone", + value: function clone() { + return new Matrix(this); + } // Transform a matrix into another matrix by manipulating the space - return this; - }, - // Resize path string - size: function size(width, height) { - // get bounding box of current situation - var box = this.bbox(); - var i, l; // recalculate position of all points according to new size + }, { + key: "transform", + value: function transform(o) { + // Check if o is a matrix and then left multiply it directly + if (isMatrixLike(o)) { + var matrix = new Matrix(o); + return matrix.multiplyO(this); + } // Get the proposed transformations and the current transformations - for (i = this.length - 1; i >= 0; i--) { - l = this[i][0]; - if (l === 'M' || l === 'L' || l === 'T') { - this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; - this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; - } else if (l === 'H') { - this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; - } else if (l === 'V') { - this[i][1] = (this[i][1] - box.y) * height / box.height + box.y; - } else if (l === 'C' || l === 'S' || l === 'Q') { - this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; - this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; - this[i][3] = (this[i][3] - box.x) * width / box.width + box.x; - this[i][4] = (this[i][4] - box.y) * height / box.height + box.y; + var t = Matrix.formatTransforms(o); + var current = this; - if (l === 'C') { - this[i][5] = (this[i][5] - box.x) * width / box.width + box.x; - this[i][6] = (this[i][6] - box.y) * height / box.height + box.y; - } - } else if (l === 'A') { - // resize radii - this[i][1] = this[i][1] * width / box.width; - this[i][2] = this[i][2] * height / box.height; // move position values + var _transform = new Point(t.ox, t.oy).transform(current), + ox = _transform.x, + oy = _transform.y; // Construct the resulting matrix - this[i][6] = (this[i][6] - box.x) * width / box.width + box.x; - this[i][7] = (this[i][7] - box.y) * height / box.height + box.y; - } - } - return this; - }, - // Test if the passed path array use the same path data commands as this path array - equalCommands: function equalCommands(pathArray) { - var i, il, equalCommands; - pathArray = new PathArray(pathArray); - equalCommands = this.length === pathArray.length; + var transformer = new Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy); // If we want the origin at a particular place, we force it there - for (i = 0, il = this.length; equalCommands && i < il; i++) { - equalCommands = this[i][0] === pathArray[i][0]; - } - - return equalCommands; - }, - // Make path array morphable - morph: function morph(pathArray) { - pathArray = new PathArray(pathArray); - - if (this.equalCommands(pathArray)) { - this.destination = pathArray; - } else { - this.destination = null; - } - - return this; - }, - // Get morphed path array at given position - at: function at(pos) { - // make sure a destination is defined - if (!this.destination) return this; - var sourceArray = this; - var destinationArray = this.destination.value; - var array = []; - var pathArray = new PathArray(); - var i, il, j, jl; // Animate has specified in the SVG spec - // See: https://www.w3.org/TR/SVG11/paths.html#PathElement + if (isFinite(t.px) || isFinite(t.py)) { + var origin = new Point(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px) - for (i = 0, il = sourceArray.length; i < il; i++) { - array[i] = [sourceArray[i][0]]; + var dx = t.px ? t.px - origin.x : 0; + var dy = t.py ? t.py - origin.y : 0; + transformer.translateO(dx, dy); + } // Translate now after positioning - for (j = 1, jl = sourceArray[i].length; j < jl; j++) { - array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos; - } // For the two flags of the elliptical arc command, the SVG spec say: - // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true - // Elliptical arc command as an array followed by corresponding indexes: - // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] - // 0 1 2 3 4 5 6 7 + transformer.translateO(t.tx, t.ty); + return transformer; + } // Applies a matrix defined by its affine parameters - if (array[i][0] === 'A') { - array[i][4] = +(array[i][4] !== 0); - array[i][5] = +(array[i][5] !== 0); - } - } // Directly modify the value of a path array, this is done this way for performance + }, { + key: "compose", + value: function compose(o) { + if (o.origin) { + o.originX = o.origin[0]; + o.originY = o.origin[1]; + } // Get the parameters - pathArray.value = array; - return pathArray; - }, - // Absolutize and parse path to array - parse: function parse() { - var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [['M', 0, 0]]; - // if it's already a patharray, no need to parse it - if (array instanceof PathArray) return array; // prepare for parsing + var ox = o.originX || 0; + var oy = o.originY || 0; + var sx = o.scaleX || 1; + var sy = o.scaleY || 1; + var lam = o.shear || 0; + var theta = o.rotate || 0; + var tx = o.translateX || 0; + var ty = o.translateY || 0; // Apply the standard matrix - var s; - var paramCnt = { - 'M': 2, - 'L': 2, - 'H': 1, - 'V': 1, - 'C': 6, - 'S': 4, - 'Q': 4, - 'T': 2, - 'A': 7, - 'Z': 0 - }; + var result = new Matrix().translateO(-ox, -oy).scaleO(sx, sy).shearO(lam).rotateO(theta).translateO(tx, ty).lmultiplyO(this).translateO(ox, oy); + return result; + } // Decomposes this matrix into its affine parameters - if (typeof array === 'string') { - array = array.replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 - .replace(pathLetters, ' $& ') // put some room between letters and numbers - .replace(hyphen, '$1 -') // add space before hyphen - .trim() // trim - .split(delimiter); // split into array - } else { - array = array.reduce(function (prev, curr) { - return [].concat.call(prev, curr); - }, []); - } // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] + }, { + key: "decompose", + value: function decompose() { + var cx = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var cy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + // Get the parameters from the matrix + var a = this.a; + var b = this.b; + var c = this.c; + var d = this.d; + var e = this.e; + var f = this.f; // Figure out if the winding direction is clockwise or counterclockwise + var determinant = a * d - b * c; + var ccw = determinant > 0 ? 1 : -1; // Since we only shear in x, we can use the x basis to get the x scale + // and the rotation of the resulting matrix - var result = []; - var p = new Point(); - var p0 = new Point(); - var index = 0; - var len = array.length; + var sx = ccw * Math.sqrt(a * a + b * b); + var thetaRad = Math.atan2(ccw * b, ccw * a); + var theta = 180 / Math.PI * thetaRad; + var ct = Math.cos(thetaRad); + var st = Math.sin(thetaRad); // We can then solve the y basis vector simultaneously to get the other + // two affine parameters directly from these parameters - do { - // Test if we have a path letter - if (isPathLetter.test(array[index])) { - s = array[index]; - ++index; // If last letter was a move command and we got no new, it defaults to [L]ine - } else if (s === 'M') { - s = 'L'; - } else if (s === 'm') { - s = 'l'; - } + var lam = (a * c + b * d) / determinant; + var sy = c * sx / (lam * a - b) || d * sx / (lam * b + a); // Use the translations - result.push(pathHandlers[s].call(null, array.slice(index, index = index + paramCnt[s.toUpperCase()]).map(parseFloat), p, p0)); - } while (len > index); + var tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy); + var ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy); // Construct the decomposition and return it - return result; - }, - // Get bounding box of path - bbox: function bbox() { - parser().path.setAttribute('d', this.toString()); - return parser.nodes.path.getBBox(); - } - }); // export default class PathArray extends SVGArray { - // constructor (array, fallback = [['M', 0, 0]]) { - // super(array, fallback) - // } - // - // // Convert array to string - // toString () { - // return arrayToString(this) - // } - // - // toArray () { - // return this.reduce(function (prev, curr) { - // return [].concat.call(prev, curr) - // }, []) - // } - // - // // Move path string - // move (x, y) { - // // get bounding box of current situation - // var box = this.bbox() - // - // // get relative offset - // x -= box.x - // y -= box.y - // - // if (!isNaN(x) && !isNaN(y)) { - // // move every point - // for (var l, i = this.length - 1; i >= 0; i--) { - // l = this[i][0] - // - // if (l === 'M' || l === 'L' || l === 'T') { - // this[i][1] += x - // this[i][2] += y - // } else if (l === 'H') { - // this[i][1] += x - // } else if (l === 'V') { - // this[i][1] += y - // } else if (l === 'C' || l === 'S' || l === 'Q') { - // this[i][1] += x - // this[i][2] += y - // this[i][3] += x - // this[i][4] += y - // - // if (l === 'C') { - // this[i][5] += x - // this[i][6] += y - // } - // } else if (l === 'A') { - // this[i][6] += x - // this[i][7] += y - // } - // } - // } - // - // return this - // } - // - // // Resize path string - // size (width, height) { - // // get bounding box of current situation - // var box = this.bbox() - // var i, l - // - // // recalculate position of all points according to new size - // for (i = this.length - 1; i >= 0; i--) { - // l = this[i][0] - // - // if (l === 'M' || l === 'L' || l === 'T') { - // this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x - // this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y - // } else if (l === 'H') { - // this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x - // } else if (l === 'V') { - // this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y - // } else if (l === 'C' || l === 'S' || l === 'Q') { - // this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x - // this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y - // this[i][3] = ((this[i][3] - box.x) * width) / box.width + box.x - // this[i][4] = ((this[i][4] - box.y) * height) / box.height + box.y - // - // if (l === 'C') { - // this[i][5] = ((this[i][5] - box.x) * width) / box.width + box.x - // this[i][6] = ((this[i][6] - box.y) * height) / box.height + box.y - // } - // } else if (l === 'A') { - // // resize radii - // this[i][1] = (this[i][1] * width) / box.width - // this[i][2] = (this[i][2] * height) / box.height - // - // // move position values - // this[i][6] = ((this[i][6] - box.x) * width) / box.width + box.x - // this[i][7] = ((this[i][7] - box.y) * height) / box.height + box.y - // } - // } - // - // return this - // } - // - // // Test if the passed path array use the same path data commands as this path array - // equalCommands (pathArray) { - // var i, il, equalCommands - // - // pathArray = new PathArray(pathArray) - // - // equalCommands = this.length === pathArray.value.length - // for (i = 0, il = this.length; equalCommands && i < il; i++) { - // equalCommands = this[i][0] === pathArray.value[i][0] - // } - // - // return equalCommands - // } - // - // // Make path array morphable - // morph (pathArray) { - // pathArray = new PathArray(pathArray) - // - // if (this.equalCommands(pathArray)) { - // this.destination = pathArray - // } else { - // this.destination = null - // } - // - // return this - // } - // - // // Get morphed path array at given position - // at (pos) { - // // make sure a destination is defined - // if (!this.destination) return this - // - // var sourceArray = this - // var destinationArray = this.destination.value - // var array = [] - // var pathArray = new PathArray() - // var i, il, j, jl - // - // // Animate has specified in the SVG spec - // // See: https://www.w3.org/TR/SVG11/paths.html#PathElement - // for (i = 0, il = sourceArray.length; i < il; i++) { - // array[i] = [sourceArray[i][0]] - // for (j = 1, jl = sourceArray[i].length; j < jl; j++) { - // array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos - // } - // // For the two flags of the elliptical arc command, the SVG spec say: - // // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true - // // Elliptical arc command as an array followed by corresponding indexes: - // // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] - // // 0 1 2 3 4 5 6 7 - // if (array[i][0] === 'A') { - // array[i][4] = +(array[i][4] !== 0) - // array[i][5] = +(array[i][5] !== 0) - // } - // } - // - // // Directly modify the value of a path array, this is done this way for performance - // pathArray.value = array - // return pathArray - // } - // - // // Absolutize and parse path to array - // parse (array) { - // // if it's already a patharray, no need to parse it - // if (array instanceof PathArray) return array.valueOf() - // - // // prepare for parsing - // var s - // var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 } - // - // if (typeof array === 'string') { - // array = array - // .replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 - // .replace(pathLetters, ' $& ') // put some room between letters and numbers - // .replace(hyphen, '$1 -') // add space before hyphen - // .trim() // trim - // .split(delimiter) // split into array - // } else { - // array = array.reduce(function (prev, curr) { - // return [].concat.call(prev, curr) - // }, []) - // } - // - // // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] - // var result = [] - // var p = new Point() - // var p0 = new Point() - // var index = 0 - // var len = array.length - // - // do { - // // Test if we have a path letter - // if (isPathLetter.test(array[index])) { - // s = array[index] - // ++index - // // If last letter was a move command and we got no new, it defaults to [L]ine - // } else if (s === 'M') { - // s = 'L' - // } else if (s === 'm') { - // s = 'l' - // } - // - // result.push(pathHandlers[s].call(null, - // array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), - // p, p0 - // ) - // ) - // } while (len > index) - // - // return result - // } - // - // // Get bounding box of path - // bbox () { - // parser().path.setAttribute('d', this.toString()) - // return parser.nodes.path.getBBox() - // } - // } + return { + // Return the affine parameters + scaleX: sx, + scaleY: sy, + shear: lam, + rotate: theta, + translateX: tx, + translateY: ty, + originX: cx, + originY: cy, + // Return the matrix parameters + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + }; + } // Left multiplies by the given matrix - var Path = - /*#__PURE__*/ - function (_Shape) { - _inherits(Path, _Shape); + }, { + key: "multiply", + value: function multiply(matrix) { + return this.clone().multiplyO(matrix); + } + }, { + key: "multiplyO", + value: function multiplyO(matrix) { + // Get the matrices + var l = this; + var r = matrix instanceof Matrix ? matrix : new Matrix(matrix); + return Matrix.matrixMultiply(l, r, this); + } + }, { + key: "lmultiply", + value: function lmultiply(matrix) { + return this.clone().lmultiplyO(matrix); + } + }, { + key: "lmultiplyO", + value: function lmultiplyO(matrix) { + var r = this; + var l = matrix instanceof Matrix ? matrix : new Matrix(matrix); + return Matrix.matrixMultiply(l, r, this); + } // Inverses matrix - // Initialize node - function Path(node) { - _classCallCheck(this, Path); + }, { + key: "inverseO", + value: function inverseO() { + // Get the current parameters out of the matrix + var a = this.a; + var b = this.b; + var c = this.c; + var d = this.d; + var e = this.e; + var f = this.f; // Invert the 2x2 matrix in the top left - return _possibleConstructorReturn(this, _getPrototypeOf(Path).call(this, nodeOrNew('path', node), Path)); - } // Get array + var det = a * d - b * c; + if (!det) throw new Error('Cannot invert ' + this); // Calculate the top 2x2 matrix + var na = d / det; + var nb = -b / det; + var nc = -c / det; + var nd = a / det; // Apply the inverted matrix to the top right - _createClass(Path, [{ - key: "array", - value: function array() { - return this._array || (this._array = new PathArray(this.attr('d'))); - } // Plot new path + var ne = -(na * e + nc * f); + var nf = -(nb * e + nd * f); // Construct the inverted matrix + this.a = na; + this.b = nb; + this.c = nc; + this.d = nd; + this.e = ne; + this.f = nf; + return this; + } }, { - key: "plot", - value: function plot(d) { - return d == null ? this.array() : this.clear().attr('d', typeof d === 'string' ? d : this._array = new PathArray(d)); - } // Clear array cache + key: "inverse", + value: function inverse() { + return this.clone().inverseO(); + } // Translate matrix }, { - key: "clear", - value: function clear() { - delete this._array; + key: "translate", + value: function translate(x, y) { + return this.clone().translateO(x, y); + } + }, { + key: "translateO", + value: function translateO(x, y) { + this.e += x || 0; + this.f += y || 0; return this; - } // Move by left top corner + } // Scale matrix }, { - key: "move", - value: function move(x, y) { - return this.attr('d', this.array().move(x, y)); - } // Move by left top corner over x-axis + key: "scale", + value: function scale(x, y, cx, cy) { + var _this$clone; + return (_this$clone = this.clone()).scaleO.apply(_this$clone, arguments); + } }, { - key: "x", - value: function x(_x) { - return _x == null ? this.bbox().x : this.move(_x, this.bbox().y); - } // Move by left top corner over y-axis + key: "scaleO", + value: function scaleO(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; - }, { - key: "y", - value: function y(_y) { - return _y == null ? this.bbox().y : this.move(this.bbox().x, _y); - } // Set element size to given width and height + // Support uniform scaling + if (arguments.length === 3) { + cy = cx; + cx = y; + y = x; + } - }, { - key: "size", - value: function size(width, height) { - var p = proportionalSize(this, width, height); - return this.attr('d', this.array().size(p.width, p.height)); - } // Set width of element + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a * x; + this.b = b * y; + this.c = c * x; + this.d = d * y; + this.e = e * x - cx * x + cx; + this.f = f * y - cy * y + cy; + return this; + } // Rotate matrix }, { - key: "width", - value: function width(_width) { - return _width == null ? this.bbox().width : this.size(_width, this.bbox().height); - } // Set height of element + key: "rotate", + value: function rotate(r, cx, cy) { + return this.clone().rotateO(r, cx, cy); + } + }, { + key: "rotateO", + value: function rotateO(r) { + var cx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + // Convert degrees to radians + r = radians(r); + var cos = Math.cos(r); + var sin = Math.sin(r); + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a * cos - b * sin; + this.b = b * cos + a * sin; + this.c = c * cos - d * sin; + this.d = d * cos + c * sin; + this.e = e * cos - f * sin + cy * sin - cx * cos + cx; + this.f = f * cos + e * sin - cx * sin - cy * cos + cy; + return this; + } // Flip matrix on x or y, at a given offset }, { - key: "height", - value: function height(_height) { - return _height == null ? this.bbox().height : this.size(this.bbox().width, _height); + key: "flip", + value: function flip(axis, around) { + return this.clone().flipO(axis, around); } }, { - key: "targets", - value: function targets() { - return baseFind('svg textpath [href*="' + this.id() + '"]'); + key: "flipO", + value: function flipO(axis, around) { + return axis === 'x' ? this.scaleO(-1, 1, around, 0) : axis === 'y' ? this.scaleO(1, -1, 0, around) : this.scaleO(-1, -1, axis, around || axis); // Define an x, y flip point + } // Shear matrix + + }, { + key: "shear", + value: function shear(a, cx, cy) { + return this.clone().shearO(a, cx, cy); } - }]); + }, { + key: "shearO", + value: function shearO(lx) { + var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a + b * lx; + this.c = c + d * lx; + this.e = e + f * lx - cy * lx; + return this; + } // Skew Matrix - return Path; - }(Shape); // Define morphable array - Path.prototype.MorphArray = PathArray; // Add parent method + }, { + key: "skew", + value: function skew(x, y, cx, cy) { + var _this$clone2; - registerMethods({ - Container: { - // Create a wrapped path element - path: function path(d) { - // make sure plot is called as a setter - return this.put(new Path()).plot(d || new PathArray()); + return (_this$clone2 = this.clone()).skewO.apply(_this$clone2, arguments); } - } - }); - register(Path); + }, { + key: "skewO", + value: function skewO(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; - // Add polygon-specific functions + // support uniformal skew + if (arguments.length === 3) { + cy = cx; + cx = y; + y = x; + } // Convert degrees to radians - function array() { - return this._array || (this._array = new PointArray(this.attr('points'))); - } // Plot new path - function plot(p) { - return p == null ? this.array() : this.clear().attr('points', typeof p === 'string' ? p : this._array = new PointArray(p)); - } // Clear array cache + x = radians(x); + y = radians(y); + var lx = Math.tan(x); + var ly = Math.tan(y); + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a + b * lx; + this.b = b + a * ly; + this.c = c + d * lx; + this.d = d + c * ly; + this.e = e + f * lx - cy * lx; + this.f = f + e * ly - cx * ly; + return this; + } // SkewX - function clear() { - delete this._array; - return this; - } // Move by left top corner + }, { + key: "skewX", + value: function skewX(x, cx, cy) { + return this.skew(x, 0, cx, cy); + } + }, { + key: "skewXO", + value: function skewXO(x, cx, cy) { + return this.skewO(x, 0, cx, cy); + } // SkewY - function move(x, y) { - return this.attr('points', this.array().move(x, y)); - } // Set element size to given width and height + }, { + key: "skewY", + value: function skewY(y, cx, cy) { + return this.skew(0, y, cx, cy); + } + }, { + key: "skewYO", + value: function skewYO(y, cx, cy) { + return this.skewO(0, y, cx, cy); + } // Transform around a center point - function size$1(width, height) { - var p = proportionalSize(this, width, height); - return this.attr('points', this.array().size(p.width, p.height)); - } + }, { + key: "aroundO", + value: function aroundO(cx, cy, matrix) { + var dx = cx || 0; + var dy = cy || 0; + return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy); + } + }, { + key: "around", + value: function around(cx, cy, matrix) { + return this.clone().aroundO(cx, cy, matrix); + } // Convert to native SVGMatrix - var poly = /*#__PURE__*/Object.freeze({ - array: array, - plot: plot, - clear: clear, - move: move, - size: size$1 - }); + }, { + key: "native", + value: function native() { + // create new matrix + var matrix = parser().svg.node.createSVGMatrix(); // update with current values - var Polygon = - /*#__PURE__*/ - function (_Shape) { - _inherits(Polygon, _Shape); + for (var i = abcdef.length - 1; i >= 0; i--) { + matrix[abcdef[i]] = this[abcdef[i]]; + } - // Initialize node - function Polygon(node) { - _classCallCheck(this, Polygon); + return matrix; + } // Check if two matrices are equal - return _possibleConstructorReturn(this, _getPrototypeOf(Polygon).call(this, nodeOrNew('polygon', node), Polygon)); - } + }, { + key: "equals", + value: function equals(other) { + var comp = new Matrix(other); + return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f); + } // Convert matrix to string - return Polygon; - }(Shape); - registerMethods({ - Container: { - // Create a wrapped polygon element - polygon: function polygon(p) { - // make sure plot is called as a setter - return this.put(new Polygon()).plot(p || new PointArray()); + }, { + key: "toString", + value: function toString() { + return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'; } - } - }); - extend(Polygon, pointed); - extend(Polygon, poly); - register(Polygon); - - var Polyline = - /*#__PURE__*/ - function (_Shape) { - _inherits(Polyline, _Shape); - - // Initialize node - function Polyline(node) { - _classCallCheck(this, Polyline); - - return _possibleConstructorReturn(this, _getPrototypeOf(Polyline).call(this, nodeOrNew('polyline', node), Polyline)); - } - - return Polyline; - }(Shape); - registerMethods({ - Container: { - // Create a wrapped polygon element - polyline: function polyline(p) { - // make sure plot is called as a setter - return this.put(new Polyline()).plot(p || new PointArray()); + }, { + key: "toArray", + value: function toArray() { + return [this.a, this.b, this.c, this.d, this.e, this.f]; } - } - }); - extend(Polyline, pointed); - extend(Polyline, poly); - register(Polyline); - - var Rect = - /*#__PURE__*/ - function (_Shape) { - _inherits(Rect, _Shape); - - // Initialize node - function Rect(node) { - _classCallCheck(this, Rect); - - return _possibleConstructorReturn(this, _getPrototypeOf(Rect).call(this, nodeOrNew('rect', node), Rect)); - } // FIXME: unify with circle - // Radius x value + }, { + key: "valueOf", + value: function valueOf() { + return { + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + }; + } // TODO: Refactor this to a static function of matrix.js + }], [{ + key: "formatTransforms", + value: function formatTransforms(o) { + // Get all of the parameters required to form the matrix + var flipBoth = o.flip === 'both' || o.flip === true; + var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1; + var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1; + var skewX = o.skew && o.skew.length ? o.skew[0] : isFinite(o.skew) ? o.skew : isFinite(o.skewX) ? o.skewX : 0; + var skewY = o.skew && o.skew.length ? o.skew[1] : isFinite(o.skew) ? o.skew : isFinite(o.skewY) ? o.skewY : 0; + var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX : isFinite(o.scale) ? o.scale * flipX : isFinite(o.scaleX) ? o.scaleX * flipX : flipX; + var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY; + var shear = o.shear || 0; + var theta = o.rotate || o.theta || 0; + var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY); + var ox = origin.x; + var oy = origin.y; + var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY); + var px = position.x; + var py = position.y; + var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY); + var tx = translate.x; + var ty = translate.y; + var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY); + var rx = relative.x; + var ry = relative.y; // Populate all of the values - _createClass(Rect, [{ - key: "rx", - value: function rx(_rx) { - return this.attr('rx', _rx); - } // Radius y value + return { + scaleX: scaleX, + scaleY: scaleY, + skewX: skewX, + skewY: skewY, + shear: shear, + theta: theta, + rx: rx, + ry: ry, + tx: tx, + ty: ty, + ox: ox, + oy: oy, + px: px, + py: py + }; + } // left matrix, right matrix, target matrix which is overwritten }, { - key: "ry", - value: function ry(_ry) { - return this.attr('ry', _ry); + key: "matrixMultiply", + value: function matrixMultiply(l, r, o) { + // Work out the product directly + var a = l.a * r.a + l.c * r.b; + var b = l.b * r.a + l.d * r.b; + var c = l.a * r.c + l.c * r.d; + var d = l.b * r.c + l.d * r.d; + var e = l.e + l.a * r.e + l.c * r.f; + var f = l.f + l.b * r.e + l.d * r.f; // make sure to use local variables because l/r and o could be the same + + o.a = a; + o.b = b; + o.c = c; + o.d = d; + o.e = e; + o.f = f; + return o; } }]); - return Rect; - }(Shape); + return Matrix; + }(); registerMethods({ - Container: { - // Create a rect element - rect: function rect(width, height) { - return this.put(new Rect()).size(width, height); + Element: { + // Get current matrix + ctm: function ctm() { + return new Matrix(this.node.getCTM()); + }, + // Get current screen matrix + screenCTM: function screenCTM() { + /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 + This is needed because FF does not return the transformation matrix + for the inner coordinate system when getScreenCTM() is called on nested svgs. + However all other Browsers do that */ + if (typeof this.isRoot === 'function' && !this.isRoot()) { + var rect = this.rect(1, 1); + var m = rect.node.getScreenCTM(); + rect.remove(); + return new Matrix(m); + } + + return new Matrix(this.node.getScreenCTM()); } } }); - register(Rect); - - var _Symbol = - /*#__PURE__*/ - function (_Container) { - _inherits(_Symbol, _Container); - - // Initialize node - function _Symbol(node) { - _classCallCheck(this, _Symbol); - return _possibleConstructorReturn(this, _getPrototypeOf(_Symbol).call(this, nodeOrNew('symbol', node), _Symbol)); + var PathArray = subClassArray('PathArray', SVGArray); + var pathHandlers = { + M: function M(c, p, p0) { + p.x = p0.x = c[0]; + p.y = p0.y = c[1]; + return ['M', p.x, p.y]; + }, + L: function L(c, p) { + p.x = c[0]; + p.y = c[1]; + return ['L', c[0], c[1]]; + }, + H: function H(c, p) { + p.x = c[0]; + return ['H', c[0]]; + }, + V: function V(c, p) { + p.y = c[0]; + return ['V', c[0]]; + }, + C: function C(c, p) { + p.x = c[4]; + p.y = c[5]; + return ['C', c[0], c[1], c[2], c[3], c[4], c[5]]; + }, + S: function S(c, p) { + p.x = c[2]; + p.y = c[3]; + return ['S', c[0], c[1], c[2], c[3]]; + }, + Q: function Q(c, p) { + p.x = c[2]; + p.y = c[3]; + return ['Q', c[0], c[1], c[2], c[3]]; + }, + T: function T(c, p) { + p.x = c[0]; + p.y = c[1]; + return ['T', c[0], c[1]]; + }, + Z: function Z(c, p, p0) { + p.x = p0.x; + p.y = p0.y; + return ['Z']; + }, + A: function A(c, p) { + p.x = c[5]; + p.y = c[6]; + return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]]; } + }; + var mlhvqtcsaz = 'mlhvqtcsaz'.split(''); - return _Symbol; - }(Container); - registerMethods({ - Container: { - symbol: function symbol() { - return this.put(new _Symbol()); - } - } - }); - register(_Symbol); + for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { + pathHandlers[mlhvqtcsaz[i]] = function (i) { + return function (c, p, p0) { + if (i === 'H') c[0] = c[0] + p.x;else if (i === 'V') c[0] = c[0] + p.y;else if (i === 'A') { + c[5] = c[5] + p.x; + c[6] = c[6] + p.y; + } else { + for (var j = 0, jl = c.length; j < jl; ++j) { + c[j] = c[j] + (j % 2 ? p.y : p.x); + } + } + return pathHandlers[i](c, p, p0); + }; + }(mlhvqtcsaz[i].toUpperCase()); + } - // Create plain text node - function plain(text) { - // clear if build mode is disabled - if (this._build === false) { - this.clear(); - } // create text node + extend(PathArray, { + // Convert array to string + toString: function toString() { + return arrayToString(this); + }, + // Move path string + move: function move(x, y) { + // get bounding box of current situation + var box = this.bbox(); // get relative offset + x -= box.x; + y -= box.y; - this.node.appendChild(document.createTextNode(text)); - return this; - } // FIXME: Does this also work for textpath? - // Get length of text element + if (!isNaN(x) && !isNaN(y)) { + // move every point + for (var l, i = this.length - 1; i >= 0; i--) { + l = this[i][0]; - function length() { - return this.node.getComputedTextLength(); - } + if (l === 'M' || l === 'L' || l === 'T') { + this[i][1] += x; + this[i][2] += y; + } else if (l === 'H') { + this[i][1] += x; + } else if (l === 'V') { + this[i][1] += y; + } else if (l === 'C' || l === 'S' || l === 'Q') { + this[i][1] += x; + this[i][2] += y; + this[i][3] += x; + this[i][4] += y; - var textable = /*#__PURE__*/Object.freeze({ - plain: plain, - length: length - }); + if (l === 'C') { + this[i][5] += x; + this[i][6] += y; + } + } else if (l === 'A') { + this[i][6] += x; + this[i][7] += y; + } + } + } - var Text = - /*#__PURE__*/ - function (_Shape) { - _inherits(Text, _Shape); + return this; + }, + // Resize path string + size: function size(width, height) { + // get bounding box of current situation + var box = this.bbox(); + var i, l; // recalculate position of all points according to new size - // Initialize node - function Text(node) { - var _this; + for (i = this.length - 1; i >= 0; i--) { + l = this[i][0]; - _classCallCheck(this, Text); + if (l === 'M' || l === 'L' || l === 'T') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; + } else if (l === 'H') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + } else if (l === 'V') { + this[i][1] = (this[i][1] - box.y) * height / box.height + box.y; + } else if (l === 'C' || l === 'S' || l === 'Q') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; + this[i][3] = (this[i][3] - box.x) * width / box.width + box.x; + this[i][4] = (this[i][4] - box.y) * height / box.height + box.y; - _this = _possibleConstructorReturn(this, _getPrototypeOf(Text).call(this, nodeOrNew('text', node), Text)); - _this.dom.leading = new SVGNumber(1.3); // store leading value for rebuilding + if (l === 'C') { + this[i][5] = (this[i][5] - box.x) * width / box.width + box.x; + this[i][6] = (this[i][6] - box.y) * height / box.height + box.y; + } + } else if (l === 'A') { + // resize radii + this[i][1] = this[i][1] * width / box.width; + this[i][2] = this[i][2] * height / box.height; // move position values - _this._rebuild = true; // enable automatic updating of dy values + this[i][6] = (this[i][6] - box.x) * width / box.width + box.x; + this[i][7] = (this[i][7] - box.y) * height / box.height + box.y; + } + } - _this._build = false; // disable build mode for adding multiple lines - // set default font + return this; + }, + // Test if the passed path array use the same path data commands as this path array + equalCommands: function equalCommands(pathArray) { + var i, il, equalCommands; + pathArray = new PathArray(pathArray); + equalCommands = this.length === pathArray.length; - _this.attr('font-family', attrs['font-family']); + for (i = 0, il = this.length; equalCommands && i < il; i++) { + equalCommands = this[i][0] === pathArray[i][0]; + } - return _this; - } // Move over x-axis + return equalCommands; + }, + // Make path array morphable + morph: function morph(pathArray) { + pathArray = new PathArray(pathArray); + if (this.equalCommands(pathArray)) { + this.destination = pathArray; + } else { + this.destination = null; + } - _createClass(Text, [{ - key: "x", - value: function x(_x) { - // act as getter - if (_x == null) { - return this.attr('x'); - } + return this; + }, + // Get morphed path array at given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; + var sourceArray = this; + var destinationArray = this.destination.value; + var array = []; + var pathArray = new PathArray(); + var i, il, j, jl; // Animate has specified in the SVG spec + // See: https://www.w3.org/TR/SVG11/paths.html#PathElement - return this.attr('x', _x); - } // Move over y-axis + for (i = 0, il = sourceArray.length; i < il; i++) { + array[i] = [sourceArray[i][0]]; - }, { - key: "y", - value: function y(_y) { - var oy = this.attr('y'); - var o = typeof oy === 'number' ? oy - this.bbox().y : 0; // act as getter + for (j = 1, jl = sourceArray[i].length; j < jl; j++) { + array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos; + } // For the two flags of the elliptical arc command, the SVG spec say: + // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true + // Elliptical arc command as an array followed by corresponding indexes: + // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // 0 1 2 3 4 5 6 7 - if (_y == null) { - return typeof oy === 'number' ? oy - o : oy; - } - return this.attr('y', typeof _y === 'number' ? _y + o : _y); - } // Move center over x-axis + if (array[i][0] === 'A') { + array[i][4] = +(array[i][4] !== 0); + array[i][5] = +(array[i][5] !== 0); + } + } // Directly modify the value of a path array, this is done this way for performance - }, { - key: "cx", - value: function cx(x) { - return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2); - } // Move center over y-axis - }, { - key: "cy", - value: function cy(y) { - return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2); - } // Set the text content + pathArray.value = array; + return pathArray; + }, + // Absolutize and parse path to array + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [['M', 0, 0]]; + // if it's already a patharray, no need to parse it + if (array instanceof PathArray) return array; // prepare for parsing - }, { - key: "text", - value: function text(_text) { - // act as getter - if (_text === undefined) { - // FIXME use children() or each() - var children = this.node.childNodes; - var firstLine = 0; - _text = ''; + var s; + var paramCnt = { + 'M': 2, + 'L': 2, + 'H': 1, + 'V': 1, + 'C': 6, + 'S': 4, + 'Q': 4, + 'T': 2, + 'A': 7, + 'Z': 0 + }; - 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; - continue; - } // add newline if its not the first child and newLined is set to true + if (typeof array === 'string') { + array = array.replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 + .replace(pathLetters, ' $& ') // put some room between letters and numbers + .replace(hyphen, '$1 -') // add space before hyphen + .trim() // trim + .split(delimiter); // split into array + } else { + array = array.reduce(function (prev, curr) { + return [].concat.call(prev, curr); + }, []); + } // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] - if (i !== firstLine && children[i].nodeType !== 3 && adopt(children[i]).dom.newLined === true) { - _text += '\n'; - } // add content of this node + var result = []; + var p = new Point(); + var p0 = new Point(); + var index = 0; + var len = array.length; + do { + // Test if we have a path letter + if (isPathLetter.test(array[index])) { + s = array[index]; + ++index; // If last letter was a move command and we got no new, it defaults to [L]ine + } else if (s === 'M') { + s = 'L'; + } else if (s === 'm') { + s = 'l'; + } - _text += children[i].textContent; - } + result.push(pathHandlers[s].call(null, array.slice(index, index = index + paramCnt[s.toUpperCase()]).map(parseFloat), p, p0)); + } while (len > index); - return _text; - } // remove existing content + return result; + }, + // Get bounding box of path + bbox: function bbox() { + parser().path.setAttribute('d', this.toString()); + return parser.nodes.path.getBBox(); + } + }); + var Morphable = + /*#__PURE__*/ + function () { + function Morphable(stepper) { + _classCallCheck(this, Morphable); - this.clear().build(true); + // FIXME: the default stepper does not know about easing + this._stepper = stepper || new Ease('-'); + this._from = null; + this._to = null; + this._type = null; + this._context = null; + this._morphObj = null; + } - if (typeof _text === 'function') { - // call block - _text.call(this, this); - } else { - // store text and make sure text is not blank - _text = _text.split('\n'); // build new lines - - 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(); - } // Set / get leading + _createClass(Morphable, [{ + key: "from", + value: function from(val) { + if (val == null) { + return this._from; + } + this._from = this._set(val); + return this; + } }, { - key: "leading", - value: function leading(value) { - // act as getter - if (value == null) { - return this.dom.leading; - } // act as setter - - - this.dom.leading = new SVGNumber(value); - return this.rebuild(); - } // Rebuild appearance type + key: "to", + value: function to(val) { + if (val == null) { + return this._to; + } + this._to = this._set(val); + return this; + } }, { - key: "rebuild", - value: function rebuild(_rebuild) { - // store new rebuild flag if given - if (typeof _rebuild === 'boolean') { - this._rebuild = _rebuild; - } // define position of all lines + key: "type", + value: function type(_type) { + // getter + if (_type == null) { + return this._type; + } // setter - if (this._rebuild) { - var self = this; - var blankLineOffset = 0; - var dy = this.dom.leading * new SVGNumber(this.attr('font-size')); - this.each(function () { - if (this.dom.newLined) { - this.attr('x', self.attr('x')); + this._type = _type; + return this; + } + }, { + key: "_set", + value: function _set$$1(value) { + if (!this._type) { + var type = _typeof(value); - if (this.text() === '\n') { - blankLineOffset += dy; - } else { - this.attr('dy', dy + blankLineOffset); - blankLineOffset = 0; - } + if (type === 'number') { + this.type(SVGNumber); + } else if (type === 'string') { + if (Color.isColor(value)) { + this.type(Color); + } else if (delimiter.test(value)) { + this.type(pathLetters.test(value) ? PathArray : SVGArray); + } else if (numberAndUnit.test(value)) { + this.type(SVGNumber); + } else { + this.type(NonMorphable); } - }); - this.fire('rebuild'); + } else if (morphableTypes.indexOf(value.constructor) > -1) { + this.type(value.constructor); + } else if (Array.isArray(value)) { + this.type(SVGArray); + } else if (type === 'object') { + this.type(ObjectBag); + } else { + this.type(NonMorphable); + } } - return this; - } // Enable / disable build mode - + var result = new this._type(value).toArray(); + this._morphObj = this._morphObj || new this._type(); + this._context = this._context || Array.apply(null, Array(result.length)).map(Object); + return result; + } }, { - key: "build", - value: function build(_build) { - this._build = !!_build; + key: "stepper", + value: function stepper(_stepper) { + if (_stepper == null) return this._stepper; + this._stepper = _stepper; return this; - } // overwrite method from parent to set data properly - + } }, { - key: "setData", - value: function setData(o) { - this.dom = o; - this.dom.leading = new SVGNumber(o.leading || 1.3); - return this; + key: "done", + value: function done() { + var complete = this._context.map(this._stepper.done).reduce(function (last, curr) { + return last && curr; + }, true); + + return complete; } - }]); + }, { + key: "at", + value: function at(pos) { + var _this = this; - return Text; - }(Shape); - extend(Text, textable); - registerMethods({ - Container: { - // Create text element - text: function text(_text2) { - return this.put(new Text()).text(_text2); - }, - // Create plain text element - plain: function plain$$1(text) { - return this.put(new Text()).plain(text); + return this._morphObj.fromArray(this._from.map(function (i, index) { + return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context); + })); } - } - }); - register(Text); + }]); - var TextPath = + return Morphable; + }(); + var NonMorphable = /*#__PURE__*/ - function (_Text) { - _inherits(TextPath, _Text); - - // Initialize node - function TextPath(node) { - _classCallCheck(this, TextPath); - - return _possibleConstructorReturn(this, _getPrototypeOf(TextPath).call(this, nodeOrNew('textPath', node), TextPath)); - } // return the array of the path track element - + function () { + function NonMorphable() { + _classCallCheck(this, NonMorphable); - _createClass(TextPath, [{ - key: "array", - value: function array() { - var track = this.track(); - return track ? track.array() : null; - } // Plot path if any + this.init.apply(this, arguments); + } + _createClass(NonMorphable, [{ + key: "init", + value: function init(val) { + val = Array.isArray(val) ? val[0] : val; + this.value = val; + } }, { - key: "plot", - value: function plot(d) { - var track = this.track(); - var pathArray = null; - - if (track) { - pathArray = track.plot(d); - } - - return d == null ? pathArray : this; - } // Get the path element - + key: "valueOf", + value: function valueOf() { + return this.value; + } }, { - key: "track", - value: function track() { - return this.reference('href'); + key: "toArray", + value: function toArray() { + return [this.value]; } }]); - return TextPath; - }(Text); - registerMethods({ - Container: { - textPath: function textPath(text, path) { - return this.defs().path(path).text(text).addTo(this); - } - }, - Text: { - // Create path for text to run on - path: function path(track) { - var path = new TextPath(); // if d is a path, reuse it - - if (!(track instanceof Path)) { - // create path element - track = this.doc().defs().path(track); - } // link textPath to path and add content + return NonMorphable; + }(); + var TransformBag = + /*#__PURE__*/ + function () { + function TransformBag() { + _classCallCheck(this, TransformBag); + this.init.apply(this, arguments); + } - path.attr('href', '#' + track, xlink); // add textPath element as child node and return textPath + _createClass(TransformBag, [{ + key: "init", + value: function init(obj) { + if (Array.isArray(obj)) { + obj = { + scaleX: obj[0], + scaleY: obj[1], + shear: obj[2], + rotate: obj[3], + translateX: obj[4], + translateY: obj[5], + originX: obj[6], + originY: obj[7] + }; + } - return this.put(path); - }, - // FIXME: make this plural? - // Get the textPath children - textPath: function textPath() { - return this.find('textPath'); + Object.assign(this, TransformBag.defaults, obj); } - }, - Path: { - // creates a textPath from this path - text: function text(_text) { - if (_text instanceof Text) { - var txt = _text.text(); + }, { + key: "toArray", + value: function toArray() { + var v = this; + return [v.scaleX, v.scaleY, v.shear, v.rotate, v.translateX, v.translateY, v.originX, v.originY]; + } + }]); - return _text.clear().path(this).text(txt); + return TransformBag; + }(); + TransformBag.defaults = { + scaleX: 1, + scaleY: 1, + shear: 0, + rotate: 0, + translateX: 0, + translateY: 0, + originX: 0, + originY: 0 + }; + var ObjectBag = + /*#__PURE__*/ + function () { + function ObjectBag() { + _classCallCheck(this, ObjectBag); + + this.init.apply(this, arguments); + } + + _createClass(ObjectBag, [{ + key: "init", + value: function init(objOrArr) { + this.values = []; + + if (Array.isArray(objOrArr)) { + this.values = objOrArr; + return; } - return this.parent().put(new Text()).path(this).text(_text); - } // FIXME: Maybe add `targets` to get all textPaths associated with this path + var entries = Object.entries(objOrArr || {}).sort(function (a, b) { + return a[0] - b[0]; + }); + this.values = entries.reduce(function (last, curr) { + return last.concat(curr); + }, []); + } + }, { + key: "valueOf", + value: function valueOf() { + var obj = {}; + var arr = this.values; - } - }); - TextPath.prototype.MorphArray = PathArray; - register(TextPath); + for (var i = 0, len = arr.length; i < len; i += 2) { + obj[arr[i]] = arr[i + 1]; + } - var Tspan = + return obj; + } + }, { + key: "toArray", + value: function toArray() { + return this.values; + } + }]); + + return ObjectBag; + }(); + var morphableTypes = [NonMorphable, TransformBag, ObjectBag]; + function registerMorphableType() { + var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + morphableTypes.push.apply(morphableTypes, _toConsumableArray([].concat(type))); + } + function makeMorphable() { + extend(morphableTypes, { + to: function to(val, args) { + return new Morphable().type(this.constructor).from(this.valueOf()).to(val, args); + }, + fromArray: function fromArray(arr) { + this.init(arr); + return this; + } + }); + } + + var Path = /*#__PURE__*/ - function (_Text) { - _inherits(Tspan, _Text); + function (_Shape) { + _inherits(Path, _Shape); // Initialize node - function Tspan(node) { - _classCallCheck(this, Tspan); + function Path(node) { + _classCallCheck(this, Path); - return _possibleConstructorReturn(this, _getPrototypeOf(Tspan).call(this, nodeOrNew('tspan', node), Tspan)); - } // Set text content + return _possibleConstructorReturn(this, _getPrototypeOf(Path).call(this, nodeOrNew('path', node), Path)); + } // Get array - _createClass(Tspan, [{ - key: "text", - value: function text(_text) { - if (_text == null) return this.node.textContent + (this.dom.newLined ? '\n' : ''); - typeof _text === 'function' ? _text.call(this, this) : this.plain(_text); - return this; - } // Shortcut dx + _createClass(Path, [{ + key: "array", + value: function array() { + return this._array || (this._array = new PathArray(this.attr('d'))); + } // Plot new path }, { - key: "dx", - value: function dx(_dx) { - return this.attr('dx', _dx); - } // Shortcut dy + key: "plot", + value: function plot(d) { + return d == null ? this.array() : this.clear().attr('d', typeof d === 'string' ? d : this._array = new PathArray(d)); + } // Clear array cache }, { - key: "dy", - value: function dy(_dy) { - return this.attr('dy', _dy); - } // Create new line + key: "clear", + value: function clear() { + delete this._array; + return this; + } // Move by left top corner }, { - key: "newLine", - value: function newLine() { - // fetch text parent - var t = this.parent(Text); // mark new line - - this.dom.newLined = true; // apply new position + key: "move", + value: function move(x, y) { + return this.attr('d', this.array().move(x, y)); + } // Move by left top corner over x-axis - return this.dy(t.dom.leading * t.attr('font-size')).attr('x', t.x()); - } - }]); + }, { + key: "x", + value: function x(_x) { + return _x == null ? this.bbox().x : this.move(_x, this.bbox().y); + } // Move by left top corner over y-axis - return Tspan; - }(Text); - extend(Tspan, textable); - registerMethods({ - Tspan: { - tspan: function tspan(text) { - var tspan = new Tspan(); // clear if build mode is disabled + }, { + key: "y", + value: function y(_y) { + return _y == null ? this.bbox().y : this.move(this.bbox().x, _y); + } // Set element size to given width and height - if (!this._build) { - this.clear(); - } // add new tspan + }, { + key: "size", + value: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.attr('d', this.array().size(p.width, p.height)); + } // Set width of element + }, { + key: "width", + value: function width(_width) { + return _width == null ? this.bbox().width : this.size(_width, this.bbox().height); + } // Set height of element - this.node.appendChild(tspan.node); - return tspan.text(text); + }, { + key: "height", + value: function height(_height) { + return _height == null ? this.bbox().height : this.size(this.bbox().width, _height); } - } - }); - register(Tspan); - - var Use = - /*#__PURE__*/ - function (_Shape) { - _inherits(Use, _Shape); - - function Use(node) { - _classCallCheck(this, Use); - - return _possibleConstructorReturn(this, _getPrototypeOf(Use).call(this, nodeOrNew('use', node), Use)); - } // Use element as a reference - - - _createClass(Use, [{ - key: "element", - value: function element(_element, file) { - // Set lined element - return this.attr('href', (file || '') + '#' + _element, xlink); + }, { + key: "targets", + value: function targets() { + return baseFind('svg textpath [href*="' + this.id() + '"]'); } }]); - return Use; - }(Shape); + return Path; + }(Shape); // Define morphable array + Path.prototype.MorphArray = PathArray; // Add parent method + registerMethods({ Container: { - // Create a use element - use: function use(element, file) { - return this.put(new Use()).element(element, file); + // Create a wrapped path element + path: function path(d) { + // make sure plot is called as a setter + return this.put(new Path()).plot(d || new PathArray()); } } }); - register(Use); - - var Matrix = - /*#__PURE__*/ - function () { - function Matrix() { - _classCallCheck(this, Matrix); + register(Path); - this.init.apply(this, arguments); - } // Initialize + // Add polygon-specific functions + function array() { + return this._array || (this._array = new PointArray(this.attr('points'))); + } // Plot new path - _createClass(Matrix, [{ - key: "init", - value: function init(source) { - var base = arrayToMatrix([1, 0, 0, 1, 0, 0]); // ensure source as object + function plot(p) { + return p == null ? this.array() : this.clear().attr('points', typeof p === 'string' ? p : this._array = new PointArray(p)); + } // Clear array cache - source = source instanceof Element ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? arrayToMatrix(source) : _typeof(source) === 'object' && isMatrixLike(source) ? source : _typeof(source) === 'object' ? new Matrix().transform(source) : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) : base; // Merge the source matrix with the base matrix + function clear() { + delete this._array; + return this; + } // Move by left top corner - this.a = source.a != null ? source.a : base.a; - this.b = source.b != null ? source.b : base.b; - this.c = source.c != null ? source.c : base.c; - this.d = source.d != null ? source.d : base.d; - this.e = source.e != null ? source.e : base.e; - this.f = source.f != null ? source.f : base.f; - } // Clones this matrix + function move(x, y) { + return this.attr('points', this.array().move(x, y)); + } // Set element size to given width and height - }, { - key: "clone", - value: function clone() { - return new Matrix(this); - } // Transform a matrix into another matrix by manipulating the space + function size$1(width, height) { + var p = proportionalSize(this, width, height); + return this.attr('points', this.array().size(p.width, p.height)); + } - }, { - key: "transform", - value: function transform(o) { - // Check if o is a matrix and then left multiply it directly - if (isMatrixLike(o)) { - var matrix = new Matrix(o); - return matrix.multiplyO(this); - } // Get the proposed transformations and the current transformations + var poly = /*#__PURE__*/Object.freeze({ + array: array, + plot: plot, + clear: clear, + move: move, + size: size$1 + }); + var Polygon = + /*#__PURE__*/ + function (_Shape) { + _inherits(Polygon, _Shape); - var t = Matrix.formatTransforms(o); - var current = this; + // Initialize node + function Polygon(node) { + _classCallCheck(this, Polygon); - var _transform = new Point(t.ox, t.oy).transform(current), - ox = _transform.x, - oy = _transform.y; // Construct the resulting matrix + return _possibleConstructorReturn(this, _getPrototypeOf(Polygon).call(this, nodeOrNew('polygon', node), Polygon)); + } + return Polygon; + }(Shape); + registerMethods({ + Container: { + // Create a wrapped polygon element + polygon: function polygon(p) { + // make sure plot is called as a setter + return this.put(new Polygon()).plot(p || new PointArray()); + } + } + }); + extend(Polygon, pointed); + extend(Polygon, poly); + register(Polygon); - var transformer = new Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy); // If we want the origin at a particular place, we force it there + var Polyline = + /*#__PURE__*/ + function (_Shape) { + _inherits(Polyline, _Shape); - if (isFinite(t.px) || isFinite(t.py)) { - var origin = new Point(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px) + // Initialize node + function Polyline(node) { + _classCallCheck(this, Polyline); - var dx = t.px ? t.px - origin.x : 0; - var dy = t.py ? t.py - origin.y : 0; - transformer.translateO(dx, dy); - } // Translate now after positioning + return _possibleConstructorReturn(this, _getPrototypeOf(Polyline).call(this, nodeOrNew('polyline', node), Polyline)); + } + return Polyline; + }(Shape); + registerMethods({ + Container: { + // Create a wrapped polygon element + polyline: function polyline(p) { + // make sure plot is called as a setter + return this.put(new Polyline()).plot(p || new PointArray()); + } + } + }); + extend(Polyline, pointed); + extend(Polyline, poly); + register(Polyline); - transformer.translateO(t.tx, t.ty); - return transformer; - } // Applies a matrix defined by its affine parameters + var Rect = + /*#__PURE__*/ + function (_Shape) { + _inherits(Rect, _Shape); - }, { - key: "compose", - value: function compose(o) { - if (o.origin) { - o.originX = o.origin[0]; - o.originY = o.origin[1]; - } // Get the parameters + // Initialize node + function Rect(node) { + _classCallCheck(this, Rect); + return _possibleConstructorReturn(this, _getPrototypeOf(Rect).call(this, nodeOrNew('rect', node), Rect)); + } // FIXME: unify with circle + // Radius x value - var ox = o.originX || 0; - var oy = o.originY || 0; - var sx = o.scaleX || 1; - var sy = o.scaleY || 1; - var lam = o.shear || 0; - var theta = o.rotate || 0; - var tx = o.translateX || 0; - var ty = o.translateY || 0; // Apply the standard matrix - var result = new Matrix().translateO(-ox, -oy).scaleO(sx, sy).shearO(lam).rotateO(theta).translateO(tx, ty).lmultiplyO(this).translateO(ox, oy); - return result; - } // Decomposes this matrix into its affine parameters + _createClass(Rect, [{ + key: "rx", + value: function rx(_rx) { + return this.attr('rx', _rx); + } // Radius y value }, { - key: "decompose", - value: function decompose() { - var cx = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; - var cy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - // Get the parameters from the matrix - var a = this.a; - var b = this.b; - var c = this.c; - var d = this.d; - var e = this.e; - var f = this.f; // Figure out if the winding direction is clockwise or counterclockwise - - var determinant = a * d - b * c; - var ccw = determinant > 0 ? 1 : -1; // Since we only shear in x, we can use the x basis to get the x scale - // and the rotation of the resulting matrix + key: "ry", + value: function ry(_ry) { + return this.attr('ry', _ry); + } + }]); - var sx = ccw * Math.sqrt(a * a + b * b); - var thetaRad = Math.atan2(ccw * b, ccw * a); - var theta = 180 / Math.PI * thetaRad; - var ct = Math.cos(thetaRad); - var st = Math.sin(thetaRad); // We can then solve the y basis vector simultaneously to get the other - // two affine parameters directly from these parameters + return Rect; + }(Shape); + registerMethods({ + Container: { + // Create a rect element + rect: function rect(width, height) { + return this.put(new Rect()).size(width, height); + } + } + }); + register(Rect); - var lam = (a * c + b * d) / determinant; - var sy = c * sx / (lam * a - b) || d * sx / (lam * b + a); // Use the translations + var time = window.performance || Date; - var tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy); - var ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy); // Construct the decomposition and return it + var makeSchedule = function makeSchedule(runnerInfo) { + var start = runnerInfo.start; + var duration = runnerInfo.runner.duration(); + var end = start + duration; + return { + start: start, + duration: duration, + end: end, + runner: runnerInfo.runner + }; + }; - return { - // Return the affine parameters - scaleX: sx, - scaleY: sy, - shear: lam, - rotate: theta, - translateX: tx, - translateY: ty, - originX: cx, - originY: cy, - // Return the matrix parameters - a: this.a, - b: this.b, - c: this.c, - d: this.d, - e: this.e, - f: this.f - }; - } // Left multiplies by the given matrix + var Timeline = + /*#__PURE__*/ + function () { + // Construct a new timeline on the given element + function Timeline() { + _classCallCheck(this, Timeline); - }, { - key: "multiply", - value: function multiply(matrix) { - return this.clone().multiplyO(matrix); - } - }, { - key: "multiplyO", - value: function multiplyO(matrix) { - // Get the matrices - var l = this; - var r = matrix instanceof Matrix ? matrix : new Matrix(matrix); - return Matrix.matrixMultiply(l, r, this); - } - }, { - key: "lmultiply", - value: function lmultiply(matrix) { - return this.clone().lmultiplyO(matrix); - } - }, { - key: "lmultiplyO", - value: function lmultiplyO(matrix) { - var r = this; - var l = matrix instanceof Matrix ? matrix : new Matrix(matrix); - return Matrix.matrixMultiply(l, r, this); - } // Inverses matrix + this._timeSource = function () { + return time.now(); + }; - }, { - key: "inverseO", - value: function inverseO() { - // Get the current parameters out of the matrix - var a = this.a; - var b = this.b; - var c = this.c; - var d = this.d; - var e = this.e; - var f = this.f; // Invert the 2x2 matrix in the top left + this._dispatcher = document.createElement('div'); // Store the timing variables - var det = a * d - b * c; - if (!det) throw new Error('Cannot invert ' + this); // Calculate the top 2x2 matrix + this._startTime = 0; + this._speed = 1.0; // Play control variables control how the animation proceeds - var na = d / det; - var nb = -b / det; - var nc = -c / det; - var nd = a / det; // Apply the inverted matrix to the top right + this._reverse = false; + this._persist = 0; // Keep track of the running animations and their starting parameters - var ne = -(na * e + nc * f); - var nf = -(nb * e + nd * f); // Construct the inverted matrix + this._nextFrame = null; + this._paused = false; + this._runners = []; + this._order = []; + this._time = 0; + this._lastSourceTime = 0; + this._lastStepTime = 0; + } - this.a = na; - this.b = nb; - this.c = nc; - this.d = nd; - this.e = ne; - this.f = nf; - return this; - } - }, { - key: "inverse", - value: function inverse() { - return this.clone().inverseO(); - } // Translate matrix - - }, { - key: "translate", - value: function translate(x, y) { - return this.clone().translateO(x, y); + _createClass(Timeline, [{ + key: "getEventTarget", + value: function getEventTarget() { + return this._dispatcher; } - }, { - key: "translateO", - value: function translateO(x, y) { - this.e += x || 0; - this.f += y || 0; - return this; - } // Scale matrix + /** + * + */ + // schedules a runner on the timeline }, { - key: "scale", - value: function scale(x, y, cx, cy) { - var _this$clone; + key: "schedule", + value: function schedule(runner, delay, when) { + if (runner == null) { + return this._runners.map(makeSchedule).sort(function (a, b) { + return a.start - b.start || a.duration - b.duration; + }); + } - return (_this$clone = this.clone()).scaleO.apply(_this$clone, arguments); - } - }, { - key: "scaleO", - value: function scaleO(x) { - var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; - var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + if (!this.active()) { + this._step(); - // Support uniform scaling - if (arguments.length === 3) { - cy = cx; - cx = y; - y = x; - } + if (when == null) { + when = 'now'; + } + } // The start time for the next animation can either be given explicitly, + // derived from the current timeline time or it can be relative to the + // last start time to chain animations direclty - var a = this.a, - b = this.b, - c = this.c, - d = this.d, - e = this.e, - f = this.f; - this.a = a * x; - this.b = b * y; - this.c = c * x; - this.d = d * y; - this.e = e * x - cx * x + cx; - this.f = f * y - cy * y + cy; - return this; - } // Rotate matrix - }, { - key: "rotate", - value: function rotate(r, cx, cy) { - return this.clone().rotateO(r, cx, cy); - } - }, { - key: "rotateO", - value: function rotateO(r) { - var cx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - // Convert degrees to radians - r = radians(r); - var cos = Math.cos(r); - var sin = Math.sin(r); - var a = this.a, - b = this.b, - c = this.c, - d = this.d, - e = this.e, - f = this.f; - this.a = a * cos - b * sin; - this.b = b * cos + a * sin; - this.c = c * cos - d * sin; - this.d = d * cos + c * sin; - this.e = e * cos - f * sin + cy * sin - cx * cos + cx; - this.f = f * cos + e * sin - cx * sin - cy * cos + cy; - return this; - } // Flip matrix on x or y, at a given offset + var absoluteStartTime = 0; + delay = delay || 0; // Work out when to start the animation - }, { - key: "flip", - value: function flip(axis, around) { - return this.clone().flipO(axis, around); - } - }, { - key: "flipO", - value: function flipO(axis, around) { - return axis === 'x' ? this.scaleO(-1, 1, around, 0) : axis === 'y' ? this.scaleO(1, -1, 0, around) : this.scaleO(-1, -1, axis, around || axis); // Define an x, y flip point - } // Shear matrix + if (when == null || when === 'last' || when === 'after') { + // Take the last time and increment + absoluteStartTime = this._startTime; + } else if (when === 'absolute' || when === 'start') { + absoluteStartTime = delay; + delay = 0; + } else if (when === 'now') { + absoluteStartTime = this._time; + } else if (when === 'relative') { + var runnerInfo = this._runners[runner.id]; - }, { - key: "shear", - value: function shear(a, cx, cy) { - return this.clone().shearO(a, cx, cy); - } - }, { - key: "shearO", - value: function shearO(lx) { - var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var a = this.a, - b = this.b, - c = this.c, - d = this.d, - e = this.e, - f = this.f; - this.a = a + b * lx; - this.c = c + d * lx; - this.e = e + f * lx - cy * lx; - return this; - } // Skew Matrix + if (runnerInfo) { + absoluteStartTime = runnerInfo.start + delay; + delay = 0; + } + } else { + throw new Error('Invalid value for the "when" parameter'); + } // Manage runner - }, { - key: "skew", - value: function skew(x, y, cx, cy) { - var _this$clone2; - return (_this$clone2 = this.clone()).skewO.apply(_this$clone2, arguments); - } - }, { - key: "skewO", - value: function skewO(x) { - var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; - var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + runner.unschedule(); + runner.timeline(this); + runner.time(-delay); // Save startTime for next runner - // support uniformal skew - if (arguments.length === 3) { - cy = cx; - cx = y; - y = x; - } // Convert degrees to radians + this._startTime = absoluteStartTime + runner.duration() + delay; // Save runnerInfo + this._runners[runner.id] = { + persist: this.persist(), + runner: runner, + start: absoluteStartTime // Save order and continue - x = radians(x); - y = radians(y); - var lx = Math.tan(x); - var ly = Math.tan(y); - var a = this.a, - b = this.b, - c = this.c, - d = this.d, - e = this.e, - f = this.f; - this.a = a + b * lx; - this.b = b + a * ly; - this.c = c + d * lx; - this.d = d + c * ly; - this.e = e + f * lx - cy * lx; - this.f = f + e * ly - cx * ly; - return this; - } // SkewX + }; - }, { - key: "skewX", - value: function skewX(x, cx, cy) { - return this.skew(x, 0, cx, cy); - } - }, { - key: "skewXO", - value: function skewXO(x, cx, cy) { - return this.skewO(x, 0, cx, cy); - } // SkewY + this._order.push(runner.id); - }, { - key: "skewY", - value: function skewY(y, cx, cy) { - return this.skew(0, y, cx, cy); - } - }, { - key: "skewYO", - value: function skewYO(y, cx, cy) { - return this.skewO(0, y, cx, cy); - } // Transform around a center point + this._continue(); - }, { - key: "aroundO", - value: function aroundO(cx, cy, matrix) { - var dx = cx || 0; - var dy = cy || 0; - return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy); - } - }, { - key: "around", - value: function around(cx, cy, matrix) { - return this.clone().aroundO(cx, cy, matrix); - } // Convert to native SVGMatrix + return this; + } // Remove the runner from this timeline }, { - key: "native", - value: function native() { - // create new matrix - var matrix = parser().svg.node.createSVGMatrix(); // update with current values + key: "unschedule", + value: function unschedule(runner) { + var index = this._order.indexOf(runner.id); - for (var i = abcdef.length - 1; i >= 0; i--) { - matrix[abcdef[i]] = this[abcdef[i]]; - } + if (index < 0) return this; + delete this._runners[runner.id]; - return matrix; - } // Check if two matrices are equal + this._order.splice(index, 1); + runner.timeline(null); + return this; + } }, { - key: "equals", - value: function equals(other) { - var comp = new Matrix(other); - return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f); - } // Convert matrix to string - + key: "play", + value: function play() { + // Now make sure we are not paused and continue the animation + this._paused = false; + return this._continue(); + } }, { - key: "toString", - value: function toString() { - return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'; + key: "pause", + value: function pause() { + // Cancel the next animation frame and pause + this._nextFrame = null; + this._paused = true; + return this; } }, { - key: "toArray", - value: function toArray() { - return [this.a, this.b, this.c, this.d, this.e, this.f]; + key: "stop", + value: function stop() { + // Cancel the next animation frame and go to start + this.seek(-this._time); + return this.pause(); } }, { - key: "valueOf", - value: function valueOf() { - return { - a: this.a, - b: this.b, - c: this.c, - d: this.d, - e: this.e, - f: this.f - }; - } // TODO: Refactor this to a static function of matrix.js - - }], [{ - key: "formatTransforms", - value: function formatTransforms(o) { - // Get all of the parameters required to form the matrix - var flipBoth = o.flip === 'both' || o.flip === true; - var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1; - var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1; - var skewX = o.skew && o.skew.length ? o.skew[0] : isFinite(o.skew) ? o.skew : isFinite(o.skewX) ? o.skewX : 0; - var skewY = o.skew && o.skew.length ? o.skew[1] : isFinite(o.skew) ? o.skew : isFinite(o.skewY) ? o.skewY : 0; - var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX : isFinite(o.scale) ? o.scale * flipX : isFinite(o.scaleX) ? o.scaleX * flipX : flipX; - var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY; - var shear = o.shear || 0; - var theta = o.rotate || o.theta || 0; - var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY); - var ox = origin.x; - var oy = origin.y; - var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY); - var px = position.x; - var py = position.y; - var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY); - var tx = translate.x; - var ty = translate.y; - var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY); - var rx = relative.x; - var ry = relative.y; // Populate all of the values - - return { - scaleX: scaleX, - scaleY: scaleY, - skewX: skewX, - skewY: skewY, - shear: shear, - theta: theta, - rx: rx, - ry: ry, - tx: tx, - ty: ty, - ox: ox, - oy: oy, - px: px, - py: py - }; - } // left matrix, right matrix, target matrix which is overwritten - + key: "finish", + value: function finish() { + this.seek(Infinity); + return this.pause(); + } }, { - key: "matrixMultiply", - value: function matrixMultiply(l, r, o) { - // Work out the product directly - var a = l.a * r.a + l.c * r.b; - var b = l.b * r.a + l.d * r.b; - var c = l.a * r.c + l.c * r.d; - var d = l.b * r.c + l.d * r.d; - var e = l.e + l.a * r.e + l.c * r.f; - var f = l.f + l.b * r.e + l.d * r.f; // make sure to use local variables because l/r and o could be the same - - o.a = a; - o.b = b; - o.c = c; - o.d = d; - o.e = e; - o.f = f; - return o; + key: "speed", + value: function speed(_speed) { + if (_speed == null) return this._speed; + this._speed = _speed; + return this; } - }]); - - return Matrix; - }(); - registerMethods({ - Element: { - // Get current matrix - ctm: function ctm() { - return new Matrix(this.node.getCTM()); - }, - // Get current screen matrix - screenCTM: function screenCTM() { - /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 - This is needed because FF does not return the transformation matrix - for the inner coordinate system when getScreenCTM() is called on nested svgs. - However all other Browsers do that */ - if (typeof this.isRoot === 'function' && !this.isRoot()) { - var rect = this.rect(1, 1); - var m = rect.node.getScreenCTM(); - rect.remove(); - return new Matrix(m); - } - - return new Matrix(this.node.getScreenCTM()); + }, { + key: "reverse", + value: function reverse(yes) { + var currentSpeed = this.speed(); + if (yes == null) return this.speed(-currentSpeed); + var positive = Math.abs(currentSpeed); + return this.speed(yes ? positive : -positive); } - } - }); - - /*** - Base Class - ========== - The base stepper class that will be - ***/ - - function makeSetterGetter(k, f) { - return function (v) { - if (v == null) return this[v]; - this[k] = v; - if (f) f.call(this); - return this; - }; - } - - var easing = { - '-': function _(pos) { - return pos; - }, - '<>': function _(pos) { - return -Math.cos(pos * Math.PI) / 2 + 0.5; - }, - '>': function _(pos) { - return Math.sin(pos * Math.PI / 2); - }, - '<': function _(pos) { - return -Math.cos(pos * Math.PI / 2) + 1; - }, - bezier: function bezier(t0, x0, t1, x1) { - return function (t) {// TODO: FINISH - }; - } - }; - var Stepper = - /*#__PURE__*/ - function () { - function Stepper() { - _classCallCheck(this, Stepper); - } - - _createClass(Stepper, [{ - key: "done", - value: function done() { - return false; + }, { + key: "seek", + value: function seek(dt) { + this._time += dt; + return this._continue(); } - }]); - - return Stepper; - }(); - /*** - Easing Functions - ================ - ***/ - - var Ease = - /*#__PURE__*/ - function (_Stepper) { - _inherits(Ease, _Stepper); - - function Ease(fn) { - var _this; - - _classCallCheck(this, Ease); - - _this = _possibleConstructorReturn(this, _getPrototypeOf(Ease).call(this)); - _this.ease = easing[fn || timeline.ease] || fn; - return _this; - } - - _createClass(Ease, [{ - key: "step", - value: function step(from, to, pos) { - if (typeof from !== 'number') { - return pos < 1 ? from : to; - } - - return from + (to - from) * this.ease(pos); + }, { + key: "time", + value: function time(_time) { + if (_time == null) return this._time; + this._time = _time; + return this; } - }]); - - return Ease; - }(Stepper); - /*** - Controller Types - ================ - ***/ - - var Controller = - /*#__PURE__*/ - function (_Stepper2) { - _inherits(Controller, _Stepper2); - - function Controller(fn) { - var _this2; - - _classCallCheck(this, Controller); - - _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Controller).call(this)); - _this2.stepper = fn; - return _this2; - } - - _createClass(Controller, [{ - key: "step", - value: function step(current, target, dt, c) { - return this.stepper(current, target, dt, c); + }, { + key: "persist", + value: function persist(dtOrForever) { + if (dtOrForever == null) return this._persist; + this._persist = dtOrForever; + return this; } }, { - key: "done", - value: function done(c) { - return c.done; + key: "source", + value: function source(fn) { + if (fn == null) return this._timeSource; + this._timeSource = fn; + return this; } - }]); + }, { + key: "_step", + value: function _step() { + // If the timeline is paused, just do nothing + if (this._paused) return; // Get the time delta from the last time and update the time + // TODO: Deal with window.blur window.focus to pause animations - return Controller; - }(Stepper); + var time = this._timeSource(); - function recalculate() { - // Apply the default parameters - var duration = (this._duration || 500) / 1000; - var overshoot = this._overshoot || 0; // Calculate the PID natural response + var dtSource = time - this._lastSourceTime; + var dtTime = this._speed * dtSource + (this._time - this._lastStepTime); + this._lastSourceTime = time; // Update the time - var eps = 1e-10; - var pi = Math.PI; - var os = Math.log(overshoot / 100 + eps); - var zeta = -os / Math.sqrt(pi * pi + os * os); - var wn = 3.9 / (zeta * duration); // Calculate the Spring values + this._time += dtTime; + this._lastStepTime = this._time; // this.fire('time', this._time) + // Run all of the runners directly - this.d = 2 * zeta * wn; - this.k = wn * wn; - } + var runnersLeft = false; - var Spring = - /*#__PURE__*/ - function (_Controller) { - _inherits(Spring, _Controller); + for (var i = 0, len = this._order.length; i < len; i++) { + // Get and run the current runner and ignore it if its inactive + var runnerInfo = this._runners[this._order[i]]; + var runner = runnerInfo.runner; + var dt = dtTime; // Make sure that we give the actual difference + // between runner start time and now - function Spring(duration, overshoot) { - var _this3; + var dtToStart = this._time - runnerInfo.start; // Dont run runner if not started yet - _classCallCheck(this, Spring); + if (dtToStart < 0) { + runnersLeft = true; + continue; + } else if (dtToStart < dt) { + // Adjust dt to make sure that animation is on point + dt = dtToStart; + } - _this3 = _possibleConstructorReturn(this, _getPrototypeOf(Spring).call(this)); + if (!runner.active()) continue; // If this runner is still going, signal that we need another animation + // frame, otherwise, remove the completed runner - _this3.duration(duration || 500).overshoot(overshoot || 0); + var finished = runner.step(dt).done; - return _this3; - } + if (!finished) { + runnersLeft = true; // continue + } else if (runnerInfo.persist !== true) { + // runner is finished. And runner might get removed + // TODO: Figure out end time of runner + var endTime = runner.duration() - runner.time() + this._time; - _createClass(Spring, [{ - key: "step", - value: function step(current, target, dt, c) { - if (typeof current === 'string') return current; - c.done = dt === Infinity; - if (dt === Infinity) return target; - if (dt === 0) return current; - if (dt > 100) dt = 16; - dt /= 1000; // Get the previous velocity + if (endTime + this._persist < this._time) { + // Delete runner and correct index + delete this._runners[this._order[i]]; + this._order.splice(i--, 1) && --len; + runner.timeline(null); + } + } + } // Get the next animation frame to keep the simulation going - var velocity = c.velocity || 0; // Apply the control to get the new position and store it - var acceleration = -this.d * velocity - this.k * (current - target); - var newPosition = current + velocity * dt + acceleration * dt * dt / 2; // Store the velocity + if (runnersLeft) { + this._nextFrame = Animator.frame(this._step.bind(this)); + } else { + this._nextFrame = null; + } - c.velocity = velocity + acceleration * dt; // Figure out if we have converged, and if so, pass the value + return this; + } // Checks if we are running and continues the animation - c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002; - return c.done ? target : newPosition; + }, { + key: "_continue", + value: function _continue() { + if (this._paused) return this; + + if (!this._nextFrame) { + this._nextFrame = Animator.frame(this._step.bind(this)); + } + + return this; + } + }, { + key: "active", + value: function active() { + return !!this._nextFrame; } }]); - return Spring; - }(Controller); - extend(Spring, { - duration: makeSetterGetter('_duration', recalculate), - overshoot: makeSetterGetter('_overshoot', recalculate) + return Timeline; + }(); + registerMethods({ + Element: { + timeline: function timeline() { + this._timeline = this._timeline || new Timeline(); + return this._timeline; + } + } }); - var PID = + + // easing = { + // '-': function (pos) { return pos }, + // '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, + // '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, + // '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } + // } + + var Runner = /*#__PURE__*/ - function (_Controller2) { - _inherits(PID, _Controller2); + function (_EventTarget) { + _inherits(Runner, _EventTarget); - function PID(p, i, d, windup) { - var _this4; + function Runner(options) { + var _this; - _classCallCheck(this, PID); + _classCallCheck(this, Runner); - _this4 = _possibleConstructorReturn(this, _getPrototypeOf(PID).call(this)); - p = p == null ? 0.1 : p; - i = i == null ? 0.01 : i; - d = d == null ? 0 : d; - windup = windup == null ? 1000 : windup; + _this = _possibleConstructorReturn(this, _getPrototypeOf(Runner).call(this)); // Store a unique id on the runner, so that we can identify it later - _this4.p(p).i(i).d(d).windup(windup); + _this.id = Runner.id++; // Ensure a default value - return _this4; - } + options = options == null ? timeline.duration : options; // Ensure that we get a controller - _createClass(PID, [{ - key: "step", - value: function step(current, target, dt, c) { - if (typeof current === 'string') return current; - c.done = dt === Infinity; - if (dt === Infinity) return target; - if (dt === 0) return current; - var p = target - current; - var i = (c.integral || 0) + p * dt; - var d = (p - (c.error || 0)) / dt; - var windup = this.windup; // antiwindup + options = typeof options === 'function' ? new Controller(options) : options; // Declare all of the variables - if (windup !== false) { - i = Math.max(-windup, Math.min(i, windup)); - } + _this._element = null; + _this._timeline = null; + _this.done = false; + _this._queue = []; // Work out the stepper and the duration + + _this._duration = typeof options === 'number' && options; + _this._isDeclarative = options instanceof Controller; + _this._stepper = _this._isDeclarative ? options : new Ease(); // We copy the current values from the timeline because they can change - c.error = p; - c.integral = i; - c.done = Math.abs(p) < 0.001; - return c.done ? target : current + (this.P * p + this.I * i + this.D * d); - } - }]); + _this._history = {}; // Store the state of the runner - return PID; - }(Controller); - extend(PID, { - windup: makeSetterGetter('windup'), - p: makeSetterGetter('P'), - i: makeSetterGetter('I'), - d: makeSetterGetter('D') - }); + _this.enabled = true; + _this._time = 0; + _this._last = 0; // Save transforms applied to this runner - var Morphable = - /*#__PURE__*/ - function () { - function Morphable(stepper) { - _classCallCheck(this, Morphable); + _this.transforms = new Matrix(); + _this.transformId = 1; // Looping variables - // FIXME: the default stepper does not know about easing - this._stepper = stepper || new Ease('-'); - this._from = null; - this._to = null; - this._type = null; - this._context = null; - this._morphObj = null; + _this._haveReversed = false; + _this._reverse = false; + _this._loopsDone = 0; + _this._swing = false; + _this._wait = 0; + _this._times = 1; + return _this; } + /* + Runner Definitions + ================== + These methods help us define the runtime behaviour of the Runner or they + help us make new runners from the current runner + */ - _createClass(Morphable, [{ - key: "from", - value: function from(val) { - if (val == null) { - return this._from; - } - this._from = this._set(val); + _createClass(Runner, [{ + key: "element", + value: function element(_element) { + if (_element == null) return this._element; + this._element = _element; + + _element._prepareRunner(); + return this; } }, { - key: "to", - value: function to(val) { - if (val == null) { - return this._to; - } - - this._to = this._set(val); + key: "timeline", + value: function timeline$$1(_timeline) { + // check explicitly for undefined so we can set the timeline to null + if (typeof _timeline === 'undefined') return this._timeline; + this._timeline = _timeline; return this; } }, { - key: "type", - value: function type(_type) { - // getter - if (_type == null) { - return this._type; - } // setter - - - this._type = _type; - return this; + key: "animate", + value: function animate(duration, delay, when) { + var o = Runner.sanitise(duration, delay, when); + var runner = new Runner(o.duration); + if (this._timeline) runner.timeline(this._timeline); + if (this._element) runner.element(this._element); + return runner.loop(o).schedule(delay, when); } }, { - key: "_set", - value: function _set$$1(value) { - if (!this._type) { - var type = _typeof(value); + key: "schedule", + value: function schedule(timeline$$1, delay, when) { + // The user doesn't need to pass a timeline if we already have one + if (!(timeline$$1 instanceof Timeline)) { + when = delay; + delay = timeline$$1; + timeline$$1 = this.timeline(); + } // If there is no timeline, yell at the user... - if (type === 'number') { - this.type(SVGNumber); - } else if (type === 'string') { - if (Color.isColor(value)) { - this.type(Color); - } else if (delimiter.test(value)) { - this.type(pathLetters.test(value) ? PathArray : SVGArray); - } else if (numberAndUnit.test(value)) { - this.type(SVGNumber); - } else { - this.type(NonMorphable); - } - } else if (morphableTypes.indexOf(value.constructor) > -1) { - this.type(value.constructor); - } else if (Array.isArray(value)) { - this.type(SVGArray); - } else if (type === 'object') { - this.type(ObjectBag); - } else { - this.type(NonMorphable); - } - } - var result = new this._type(value).toArray(); - this._morphObj = this._morphObj || new this._type(); - this._context = this._context || Array.apply(null, Array(result.length)).map(Object); - return result; + if (!timeline$$1) { + throw Error('Runner cannot be scheduled without timeline'); + } // Schedule the runner on the timeline provided + + + timeline$$1.schedule(this, delay, when); + return this; } }, { - key: "stepper", - value: function stepper(_stepper) { - if (_stepper == null) return this._stepper; - this._stepper = _stepper; + key: "unschedule", + value: function unschedule() { + var timeline$$1 = this.timeline(); + timeline$$1 && timeline$$1.unschedule(this); return this; } }, { - key: "done", - value: function done() { - var complete = this._context.map(this._stepper.done).reduce(function (last, curr) { - return last && curr; - }, true); + key: "loop", + value: function loop(times, swing, wait) { + // Deal with the user passing in an object + if (_typeof(times) === 'object') { + swing = times.swing; + wait = times.wait; + times = times.times; + } // Sanitise the values and store them - return complete; + + this._times = times || Infinity; + this._swing = swing || false; + this._wait = wait || 0; + return this; } }, { - key: "at", - value: function at(pos) { - var _this = this; - - return this._morphObj.fromArray(this._from.map(function (i, index) { - return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context); - })); + key: "delay", + value: function delay(_delay) { + return this.animate(0, _delay); } - }]); - - return Morphable; - }(); - var NonMorphable = - /*#__PURE__*/ - function () { - function NonMorphable() { - _classCallCheck(this, NonMorphable); + /* + Basic Functionality + =================== + These methods allow us to attach basic functions to the runner directly + */ - this.init.apply(this, arguments); - } + }, { + key: "queue", + value: function queue(initFn, runFn, isTransform) { + this._queue.push({ + initialiser: initFn || noop, + runner: runFn || noop, + isTransform: isTransform, + initialised: false, + finished: false + }); - _createClass(NonMorphable, [{ - key: "init", - value: function init(val) { - val = Array.isArray(val) ? val[0] : val; - this.value = val; + var timeline$$1 = this.timeline(); + timeline$$1 && this.timeline()._continue(); + return this; } }, { - key: "valueOf", - value: function valueOf() { - return this.value; + key: "during", + value: function during(fn) { + return this.queue(null, fn); } }, { - key: "toArray", - value: function toArray() { - return [this.value]; + key: "after", + value: function after(fn) { + return this.on('finish', fn); } - }]); - - return NonMorphable; - }(); - var TransformBag = - /*#__PURE__*/ - function () { - function TransformBag() { - _classCallCheck(this, TransformBag); + /* + Runner animation methods + ======================== + Control how the animation plays + */ - this.init.apply(this, arguments); - } + }, { + key: "time", + value: function time(_time) { + if (_time == null) { + return this._time; + } - _createClass(TransformBag, [{ - key: "init", - value: function init(obj) { - if (Array.isArray(obj)) { - obj = { - scaleX: obj[0], - scaleY: obj[1], - shear: obj[2], - rotate: obj[3], - translateX: obj[4], - translateY: obj[5], - originX: obj[6], - originY: obj[7] - }; + var dt = _time - this._time; + this.step(dt); + return this; + } + }, { + key: "duration", + value: function duration() { + return this._times * (this._wait + this._duration) - this._wait; + } + }, { + key: "loops", + value: function loops(p) { + var loopDuration = this._duration + this._wait; + + if (p == null) { + var loopsDone = Math.floor(this._time / loopDuration); + var relativeTime = this._time - loopsDone * loopDuration; + var position = relativeTime / this._duration; + return Math.min(loopsDone + position, this._times); } - Object.assign(this, TransformBag.defaults, obj); + var whole = Math.floor(p); + var partial = p % 1; + var time = loopDuration * whole + this._duration * partial; + return this.time(time); } }, { - key: "toArray", - value: function toArray() { - var v = this; - return [v.scaleX, v.scaleY, v.shear, v.rotate, v.translateX, v.translateY, v.originX, v.originY]; - } - }]); + key: "position", + value: function position(p) { + // Get all of the variables we need + var x = this._time; + var d = this._duration; + var w = this._wait; + var t = this._times; + var s = this._swing; + var r = this._reverse; + var position; - return TransformBag; - }(); - TransformBag.defaults = { - scaleX: 1, - scaleY: 1, - shear: 0, - rotate: 0, - translateX: 0, - translateY: 0, - originX: 0, - originY: 0 - }; - var ObjectBag = - /*#__PURE__*/ - function () { - function ObjectBag() { - _classCallCheck(this, ObjectBag); + if (p == null) { + /* + This function converts a time to a position in the range [0, 1] + The full explanation can be found in this desmos demonstration + https://www.desmos.com/calculator/u4fbavgche + The logic is slightly simplified here because we can use booleans + */ + // Figure out the value without thinking about the start or end time + var f = function f(x) { + var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)); + var backwards = swinging && !r || !swinging && r; + var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards; + var clipped = Math.max(Math.min(uncliped, 1), 0); + return clipped; + }; // Figure out the value by incorporating the start time - this.init.apply(this, arguments); - } - _createClass(ObjectBag, [{ - key: "init", - value: function init(objOrArr) { - this.values = []; + var endTime = t * (w + d) - w; + position = x <= 0 ? Math.round(f(1e-5)) : x < endTime ? f(x) : Math.round(f(endTime - 1e-5)); + return position; + } // Work out the loops done and add the position to the loops done - if (Array.isArray(objOrArr)) { - this.values = objOrArr; - return; - } - var entries = Object.entries(objOrArr || {}).sort(function (a, b) { - return a[0] - b[0]; - }); - this.values = entries.reduce(function (last, curr) { - return last.concat(curr); - }, []); + var loopsDone = Math.floor(this.loops()); + var swingForward = s && loopsDone % 2 === 0; + var forwards = swingForward && !r || r && swingForward; + position = loopsDone + (forwards ? p : 1 - p); + return this.loops(position); } }, { - key: "valueOf", - value: function valueOf() { - var obj = {}; - var arr = this.values; - - for (var i = 0, len = arr.length; i < len; i += 2) { - obj[arr[i]] = arr[i + 1]; + key: "progress", + value: function progress(p) { + if (p == null) { + return Math.min(1, this._time / this.duration()); } - return obj; + return this.time(p * this.duration()); } }, { - key: "toArray", - value: function toArray() { - return this.values; - } - }]); + key: "step", + value: function step(dt) { + // If we are inactive, this stepper just gets skipped + if (!this.enabled) return this; // Update the time and get the new position - return ObjectBag; - }(); - var morphableTypes = [NonMorphable, TransformBag, ObjectBag]; - function registerMorphableType() { - var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - morphableTypes.push.apply(morphableTypes, _toConsumableArray([].concat(type))); - } - function makeMorphable() { - extend(morphableTypes, { - to: function to(val, args) { - return new Morphable().type(this.constructor).from(this.valueOf()).to(val, args); - }, - fromArray: function fromArray(arr) { - this.init(arr); - return this; - } - }); - } + dt = dt == null ? 16 : dt; + this._time += dt; + var position = this.position(); // Figure out if we need to run the stepper in this frame - var time = window.performance || Date; + var running = this._lastPosition !== position && this._time >= 0; + this._lastPosition = position; // Figure out if we just started - var makeSchedule = function makeSchedule(runnerInfo) { - var start = runnerInfo.start; - var duration = runnerInfo.runner.duration(); - var end = start + duration; - return { - start: start, - duration: duration, - end: end, - runner: runnerInfo.runner - }; - }; + var duration = this.duration(); + var justStarted = this._lastTime < 0 && this._time > 0; + var justFinished = this._lastTime < this._time && this.time > duration; + this._lastTime = this._time; - var Timeline = - /*#__PURE__*/ - function () { - // Construct a new timeline on the given element - function Timeline() { - _classCallCheck(this, Timeline); + if (justStarted) { + this.fire('start', this); + } // Work out if the runner is finished set the done flag here so animations + // know, that they are running in the last step (this is good for + // transformations which can be merged) - this._timeSource = function () { - return time.now(); - }; - this._dispatcher = document.createElement('div'); // Store the timing variables + var declarative = this._isDeclarative; + this.done = !declarative && !justFinished && this._time >= duration; // Call initialise and the run function - this._startTime = 0; - this._speed = 1.0; // Play control variables control how the animation proceeds + if (running || declarative) { + this._initialise(running); // clear the transforms on this runner so they dont get added again and again - this._reverse = false; - this._persist = 0; // Keep track of the running animations and their starting parameters - this._nextFrame = null; - this._paused = false; - this._runners = []; - this._order = []; - this._time = 0; - this._lastSourceTime = 0; - this._lastStepTime = 0; - } + this.transforms = new Matrix(); - _createClass(Timeline, [{ - key: "getEventTarget", - value: function getEventTarget() { - return this._dispatcher; - } - /** - * - */ - // schedules a runner on the timeline + var converged = this._run(declarative ? dt : position); - }, { - key: "schedule", - value: function schedule(runner, delay, when) { - if (runner == null) { - return this._runners.map(makeSchedule).sort(function (a, b) { - return a.start - b.start || a.duration - b.duration; - }); + this.fire('step', this); + } // correct the done flag here + // declaritive animations itself know when they converged + + + this.done = this.done || converged && declarative; + + if (this.done) { + this.fire('finish', this); } - if (!this.active()) { - this._step(); + return this; + } + }, { + key: "finish", + value: function finish() { + return this.step(Infinity); + } + }, { + key: "reverse", + value: function reverse(_reverse) { + this._reverse = _reverse == null ? !this._reverse : _reverse; + return this; + } + }, { + key: "ease", + value: function ease(fn) { + this._stepper = new Ease(fn); + return this; + } + }, { + key: "active", + value: function active(enabled) { + if (enabled == null) return this.enabled; + this.enabled = enabled; + return this; + } + /* + Private Methods + =============== + Methods that shouldn't be used externally + */ + // Save a morpher to the morpher list so that we can retarget it later - if (when == null) { - when = 'now'; - } - } // The start time for the next animation can either be given explicitly, - // derived from the current timeline time or it can be relative to the - // last start time to chain animations direclty + }, { + key: "_rememberMorpher", + value: function _rememberMorpher(method, morpher) { + this._history[method] = { + morpher: morpher, + caller: this._queue[this._queue.length - 1] + }; + } // Try to set the target for a morpher if the morpher exists, otherwise + // do nothing and return false + }, { + key: "_tryRetarget", + value: function _tryRetarget(method, target) { + if (this._history[method]) { + // if the last method wasnt even initialised, throw it away + if (!this._history[method].caller.initialised) { + var index = this._queue.indexOf(this._history[method].caller); - var absoluteStartTime = 0; - delay = delay || 0; // Work out when to start the animation + this._queue.splice(index, 1); - if (when == null || when === 'last' || when === 'after') { - // Take the last time and increment - absoluteStartTime = this._startTime; - } else if (when === 'absolute' || when === 'start') { - absoluteStartTime = delay; - delay = 0; - } else if (when === 'now') { - absoluteStartTime = this._time; - } else if (when === 'relative') { - var runnerInfo = this._runners[runner.id]; + return false; + } // for the case of transformations, we use the special retarget function + // which has access to the outer scope - if (runnerInfo) { - absoluteStartTime = runnerInfo.start + delay; - delay = 0; - } - } else { - throw new Error('Invalid value for the "when" parameter'); - } // Manage runner + if (this._history[method].caller.isTransform) { + this._history[method].caller.isTransform(target); // for everything else a simple morpher change is sufficient - runner.unschedule(); - runner.timeline(this); - runner.time(-delay); // Save startTime for next runner + } else { + this._history[method].morpher.to(target); + } - this._startTime = absoluteStartTime + runner.duration() + delay; // Save runnerInfo + this._history[method].caller.finished = false; + var timeline$$1 = this.timeline(); + timeline$$1 && timeline$$1._continue(); + return true; + } - this._runners[runner.id] = { - persist: this.persist(), - runner: runner, - start: absoluteStartTime // Save order and continue + return false; + } // Run each initialise function in the runner if required - }; + }, { + key: "_initialise", + value: function _initialise(running) { + // If we aren't running, we shouldn't initialise when not declarative + if (!running && !this._isDeclarative) return; // Loop through all of the initialisers - this._order.push(runner.id); + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current initialiser + var current = this._queue[i]; // Determine whether we need to initialise - this._continue(); + var needsIt = this._isDeclarative || !current.initialised && running; + running = !current.finished; // Call the initialiser if we need to - return this; - } // Remove the runner from this timeline + if (needsIt && running) { + current.initialiser.call(this); + current.initialised = true; + } + } + } // Run each run function for the position or dt given }, { - key: "unschedule", - value: function unschedule(runner) { - var index = this._order.indexOf(runner.id); + key: "_run", + value: function _run(positionOrDt) { + // Run all of the _queue directly + var allfinished = true; - if (index < 0) return this; - delete this._runners[runner.id]; + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current function to run + var current = this._queue[i]; // Run the function if its not finished, we keep track of the finished + // flag for the sake of declarative _queue - this._order.splice(index, 1); + var converged = current.runner.call(this, positionOrDt); + current.finished = current.finished || converged === true; + allfinished = allfinished && current.finished; + } // We report when all of the constructors are finished - runner.timeline(null); - return this; - } - }, { - key: "play", - value: function play() { - // Now make sure we are not paused and continue the animation - this._paused = false; - return this._continue(); + + return allfinished; } }, { - key: "pause", - value: function pause() { - // Cancel the next animation frame and pause - this._nextFrame = null; - this._paused = true; + key: "addTransform", + value: function addTransform(transform, index) { + this.transforms.lmultiplyO(transform); return this; } }, { - key: "stop", - value: function stop() { - // Cancel the next animation frame and go to start - this.seek(-this._time); - return this.pause(); - } - }, { - key: "finish", - value: function finish() { - this.seek(Infinity); - return this.pause(); - } - }, { - key: "speed", - value: function speed(_speed) { - if (_speed == null) return this._speed; - this._speed = _speed; + key: "clearTransform", + value: function clearTransform() { + this.transforms = new Matrix(); return this; } - }, { - key: "reverse", - value: function reverse(yes) { - var currentSpeed = this.speed(); - if (yes == null) return this.speed(-currentSpeed); - var positive = Math.abs(currentSpeed); - return this.speed(yes ? positive : -positive); - } - }, { - key: "seek", - value: function seek(dt) { - this._time += dt; - return this._continue(); + }], [{ + key: "sanitise", + value: function sanitise(duration, delay, when) { + // Initialise the default parameters + var times = 1; + var swing = false; + var wait = 0; + duration = duration || timeline.duration; + delay = delay || timeline.delay; + when = when || 'last'; // If we have an object, unpack the values + + if (_typeof(duration) === 'object' && !(duration instanceof Stepper)) { + delay = duration.delay || delay; + when = duration.when || when; + swing = duration.swing || swing; + times = duration.times || times; + wait = duration.wait || wait; + duration = duration.duration || timeline.duration; + } + + return { + duration: duration, + delay: delay, + swing: swing, + times: times, + wait: wait, + when: when + }; } - }, { - key: "time", - value: function time(_time) { - if (_time == null) return this._time; - this._time = _time; + }]); + + return Runner; + }(EventTarget); + Runner.id = 0; + + var FakeRunner = function FakeRunner() { + var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix(); + var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; + var done = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + + _classCallCheck(this, FakeRunner); + + this.transforms = transforms; + this.id = id; + this.done = done; + }; + + extend([Runner, FakeRunner], { + mergeWith: function mergeWith(runner) { + return new FakeRunner(runner.transforms.lmultiply(this.transforms), runner.id); + } + }); // FakeRunner.emptyRunner = new FakeRunner() + + var lmultiply = function lmultiply(last, curr) { + return last.lmultiplyO(curr); + }; + + var getRunnerTransform = function getRunnerTransform(runner) { + return runner.transforms; + }; + + function mergeTransforms() { + // Find the matrix to apply to the element and apply it + var runners = this._transformationRunners.runners; + var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix()); + this.transform(netTransform); + + this._transformationRunners.merge(); + + if (this._transformationRunners.length() === 1) { + this._frameId = null; + } + } + + var RunnerArray = + /*#__PURE__*/ + function () { + function RunnerArray() { + _classCallCheck(this, RunnerArray); + + this.runners = []; + this.ids = []; + } + + _createClass(RunnerArray, [{ + key: "add", + value: function add(runner) { + if (this.runners.includes(runner)) return; + var id = runner.id + 1; + var leftSibling = this.ids.reduce(function (last, curr) { + if (curr > last && curr < id) return curr; + return last; + }, 0); + var index = this.ids.indexOf(leftSibling) + 1; + this.ids.splice(index, 0, id); + this.runners.splice(index, 0, runner); return this; } }, { - key: "persist", - value: function persist(dtOrForever) { - if (dtOrForever == null) return this._persist; - this._persist = dtOrForever; - return this; + key: "getByID", + value: function getByID(id) { + return this.runners[this.ids.indexOf(id + 1)]; } }, { - key: "source", - value: function source(fn) { - if (fn == null) return this._timeSource; - this._timeSource = fn; + key: "remove", + value: function remove(id) { + var index = this.ids.indexOf(id + 1); + this.ids.splice(index, 1); + this.runners.splice(index, 1); return this; } }, { - key: "_step", - value: function _step() { - // If the timeline is paused, just do nothing - if (this._paused) return; // Get the time delta from the last time and update the time - // TODO: Deal with window.blur window.focus to pause animations - - var time = this._timeSource(); - - var dtSource = time - this._lastSourceTime; - var dtTime = this._speed * dtSource + (this._time - this._lastStepTime); - this._lastSourceTime = time; // Update the time - - this._time += dtTime; - this._lastStepTime = this._time; // this.fire('time', this._time) - // Run all of the runners directly - - var runnersLeft = false; - - for (var i = 0, len = this._order.length; i < len; i++) { - // Get and run the current runner and ignore it if its inactive - var runnerInfo = this._runners[this._order[i]]; - var runner = runnerInfo.runner; - var dt = dtTime; // Make sure that we give the actual difference - // between runner start time and now - - var dtToStart = this._time - runnerInfo.start; // Dont run runner if not started yet - - if (dtToStart < 0) { - runnersLeft = true; - continue; - } else if (dtToStart < dt) { - // Adjust dt to make sure that animation is on point - dt = dtToStart; - } - - if (!runner.active()) continue; // If this runner is still going, signal that we need another animation - // frame, otherwise, remove the completed runner - - var finished = runner.step(dt).done; + key: "merge", + value: function merge() { + var _this2 = this; - if (!finished) { - runnersLeft = true; // continue - } else if (runnerInfo.persist !== true) { - // runner is finished. And runner might get removed - // TODO: Figure out end time of runner - var endTime = runner.duration() - runner.time() + this._time; + var lastRunner = null; + this.runners.forEach(function (runner, i) { + if (lastRunner && runner.done && lastRunner.done) { + _this2.remove(runner.id); - if (endTime + this._persist < this._time) { - // Delete runner and correct index - delete this._runners[this._order[i]]; - this._order.splice(i--, 1) && --len; - runner.timeline(null); - } + _this2.edit(lastRunner.id, runner.mergeWith(lastRunner)); } - } // Get the next animation frame to keep the simulation going - - - if (runnersLeft) { - this._nextFrame = Animator.frame(this._step.bind(this)); - } else { - this._nextFrame = null; - } + lastRunner = runner; + }); return this; - } // Checks if we are running and continues the animation - + } }, { - key: "_continue", - value: function _continue() { - if (this._paused) return this; - - if (!this._nextFrame) { - this._nextFrame = Animator.frame(this._step.bind(this)); - } - + key: "edit", + value: function edit(id, newRunner) { + var index = this.ids.indexOf(id + 1); + this.ids.splice(index, 1, id); + this.runners.splice(index, 1, newRunner); return this; } }, { - key: "active", - value: function active() { - return !!this._nextFrame; + key: "length", + value: function length() { + return this.ids.length; + } + }, { + key: "clearBefore", + value: function clearBefore(id) { + var deleteCnt = this.ids.indexOf(id + 1) || 1; + this.ids.splice(0, deleteCnt, 0); + this.runners.splice(0, deleteCnt, new FakeRunner()); + return this; } }]); - return Timeline; + return RunnerArray; }(); + + var frameId = 0; registerMethods({ Element: { - timeline: function timeline() { - this._timeline = this._timeline || new Timeline(); - return this._timeline; + animate: function animate(duration, delay, when) { + var o = Runner.sanitise(duration, delay, when); + var timeline$$1 = this.timeline(); + return new Runner(o.duration).loop(o).element(this).timeline(timeline$$1).schedule(delay, when); + }, + delay: function delay(by, when) { + return this.animate(0, by, when); + }, + // this function searches for all runners on the element and deletes the ones + // which run before the current one. This is because absolute transformations + // overwfrite anything anyway so there is no need to waste time computing + // other runners + _clearTransformRunnersBefore: function _clearTransformRunnersBefore(currentRunner) { + this._transformationRunners.clearBefore(currentRunner.id); + }, + _currentTransform: function _currentTransform(current) { + return this._transformationRunners.runners // we need the equal sign here to make sure, that also transformations + // on the same runner which execute before the current transformation are + // taken into account + .filter(function (runner) { + return runner.id <= current.id; + }).map(getRunnerTransform).reduce(lmultiply, new Matrix()); + }, + addRunner: function addRunner(runner) { + this._transformationRunners.add(runner); + + Animator.transform_frame(mergeTransforms.bind(this), this._frameId); + }, + _prepareRunner: function _prepareRunner() { + if (this._frameId == null) { + this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix(this))); + this._frameId = frameId++; + } } } }); + extend(Runner, { + attr: function attr(a, v) { + return this.styleAttr('attr', a, v); + }, + // Add animatable styles + css: function css(s, v) { + return this.styleAttr('css', s, v); + }, + styleAttr: function styleAttr(type, name, val) { + // apply attributes individually + if (_typeof(name) === 'object') { + for (var key in val) { + this.styleAttr(type, key, val[key]); + } + } - // easing = { - // '-': function (pos) { return pos }, - // '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, - // '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, - // '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } - // } - - var Runner = - /*#__PURE__*/ - function (_EventTarget) { - _inherits(Runner, _EventTarget); - - function Runner(options) { - var _this; - - _classCallCheck(this, Runner); - - _this = _possibleConstructorReturn(this, _getPrototypeOf(Runner).call(this)); // Store a unique id on the runner, so that we can identify it later - - _this.id = Runner.id++; // Ensure a default value - - options = options == null ? timeline.duration : options; // Ensure that we get a controller - - options = typeof options === 'function' ? new Controller(options) : options; // Declare all of the variables - - _this._element = null; - _this._timeline = null; - _this.done = false; - _this._queue = []; // Work out the stepper and the duration - - _this._duration = typeof options === 'number' && options; - _this._isDeclarative = options instanceof Controller; - _this._stepper = _this._isDeclarative ? options : new Ease(); // We copy the current values from the timeline because they can change - - _this._history = {}; // Store the state of the runner - - _this.enabled = true; - _this._time = 0; - _this._last = 0; // Save transforms applied to this runner + var morpher = new Morphable(this._stepper).to(val); + this.queue(function () { + morpher = morpher.from(this.element()[type](name)); + }, function (pos) { + this.element()[type](name, morpher.at(pos)); + return morpher.done(); + }); + return this; + }, + zoom: function zoom(level, point) { + var morpher = new Morphable(this._stepper).to(new SVGNumber(level)); + this.queue(function () { + morpher = morpher.from(this.zoom()); + }, function (pos) { + this.element().zoom(morpher.at(pos), point); + return morpher.done(); + }); + return this; + }, - _this.transforms = new Matrix(); - _this.transformId = 1; // Looping variables + /** + ** absolute transformations + **/ + // + // M v -----|-----(D M v = F v)------|-----> T v + // + // 1. define the final state (T) and decompose it (once) + // t = [tx, ty, the, lam, sy, sx] + // 2. on every frame: pull the current state of all previous transforms + // (M - m can change) + // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] + // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) + // - Note F(0) = M + // - Note F(1) = T + // 4. Now you get the delta matrix as a result: D = F * inv(M) + transform: function transform(transforms, relative, affine) { + // If we have a declarative function, we should retarget it if possible + relative = transforms.relative || relative; - _this._haveReversed = false; - _this._reverse = false; - _this._loopsDone = 0; - _this._swing = false; - _this._wait = 0; - _this._times = 1; - return _this; - } - /* - Runner Definitions - ================== - These methods help us define the runtime behaviour of the Runner or they - help us make new runners from the current runner - */ + if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { + return this; + } // Parse the parameters - _createClass(Runner, [{ - key: "element", - value: function element(_element) { - if (_element == null) return this._element; - this._element = _element; + var isMatrix = isMatrixLike(transforms); + affine = transforms.affine != null ? transforms.affine : affine != null ? affine : !isMatrix; // Create a morepher and set its type - _element._prepareRunner(); + var morpher = new Morphable().type(affine ? TransformBag : Matrix).stepper(this._stepper); + var origin; + var element; + var current; + var currentAngle; + var startTransform; - return this; - } - }, { - key: "timeline", - value: function timeline$$1(_timeline) { - // check explicitly for undefined so we can set the timeline to null - if (typeof _timeline === 'undefined') return this._timeline; - this._timeline = _timeline; - return this; - } - }, { - key: "animate", - value: function animate(duration, delay, when) { - var o = Runner.sanitise(duration, delay, when); - var runner = new Runner(o.duration); - if (this._timeline) runner.timeline(this._timeline); - if (this._element) runner.element(this._element); - return runner.loop(o).schedule(delay, when); - } - }, { - key: "schedule", - value: function schedule(timeline$$1, delay, when) { - // The user doesn't need to pass a timeline if we already have one - if (!(timeline$$1 instanceof Timeline)) { - when = delay; - delay = timeline$$1; - timeline$$1 = this.timeline(); - } // If there is no timeline, yell at the user... + function setup() { + // make sure element and origin is defined + element = element || this.element(); + origin = origin || getOrigin(transforms, element); + startTransform = new Matrix(relative ? undefined : element); // add the runner to the element so it can merge transformations + element.addRunner(this); // Deactivate all transforms that have run so far if we are absolute - if (!timeline$$1) { - throw Error('Runner cannot be scheduled without timeline'); - } // Schedule the runner on the timeline provided + if (!relative) { + element._clearTransformRunnersBefore(this); + } + } + function run(pos) { + // clear all other transforms before this in case something is saved + // on this runner. We are absolute. We dont need these! + if (!relative) this.clearTransform(); - timeline$$1.schedule(this, delay, when); - return this; - } - }, { - key: "unschedule", - value: function unschedule() { - var timeline$$1 = this.timeline(); - timeline$$1 && timeline$$1.unschedule(this); - return this; - } - }, { - key: "loop", - value: function loop(times, swing, wait) { - // Deal with the user passing in an object - if (_typeof(times) === 'object') { - swing = times.swing; - wait = times.wait; - times = times.times; - } // Sanitise the values and store them + var _transform = new Point(origin).transform(element._currentTransform(this)), + x = _transform.x, + y = _transform.y; + var target = new Matrix(_objectSpread({}, transforms, { + origin: [x, y] + })); + var start = this._isDeclarative && current ? current : startTransform; - this._times = times || Infinity; - this._swing = swing || false; - this._wait = wait || 0; - return this; - } - }, { - key: "delay", - value: function delay(_delay) { - return this.animate(0, _delay); - } - /* - Basic Functionality - =================== - These methods allow us to attach basic functions to the runner directly - */ + if (affine) { + target = target.decompose(x, y); + start = start.decompose(x, y); // Get the current and target angle as it was set - }, { - key: "queue", - value: function queue(initFn, runFn, isTransform) { - this._queue.push({ - initialiser: initFn || noop, - runner: runFn || noop, - isTransform: isTransform, - initialised: false, - finished: false - }); + var rTarget = target.rotate; + var rCurrent = start.rotate; // Figure out the shortest path to rotate directly - var timeline$$1 = this.timeline(); - timeline$$1 && this.timeline()._continue(); - return this; - } - }, { - key: "during", - value: function during(fn) { - return this.queue(null, fn); - } - }, { - key: "after", - value: function after(fn) { - return this.on('finish', fn); - } - /* - Runner animation methods - ======================== - Control how the animation plays - */ + var possibilities = [rTarget - 360, rTarget, rTarget + 360]; + var distances = possibilities.map(function (a) { + return Math.abs(a - rCurrent); + }); + var shortest = Math.min.apply(Math, _toConsumableArray(distances)); + var index = distances.indexOf(shortest); + target.rotate = possibilities[index]; + } - }, { - key: "time", - value: function time(_time) { - if (_time == null) { - return this._time; + if (relative) { + // we have to be careful here not to overwrite the rotation + // with the rotate method of Matrix + if (!isMatrix) { + target.rotate = transforms.rotate || 0; + } + + if (this._isDeclarative && currentAngle) { + start.rotate = currentAngle; + } } - var dt = _time - this._time; - this.step(dt); - return this; - } - }, { - key: "duration", - value: function duration() { - return this._times * (this._wait + this._duration) - this._wait; + morpher.from(start); + morpher.to(target); + var affineParameters = morpher.at(pos); + currentAngle = affineParameters.rotate; + current = new Matrix(affineParameters); + this.addTransform(current); + return morpher.done(); } - }, { - key: "loops", - value: function loops(p) { - var loopDuration = this._duration + this._wait; - if (p == null) { - var loopsDone = Math.floor(this._time / loopDuration); - var relativeTime = this._time - loopsDone * loopDuration; - var position = relativeTime / this._duration; - return Math.min(loopsDone + position, this._times); - } + function retarget(newTransforms) { + // only get a new origin if it changed since the last call + if ((newTransforms.origin || 'center').toString() !== (transforms.origin || 'center').toString()) { + origin = getOrigin(transforms, element); + } // overwrite the old transformations with the new ones - var whole = Math.floor(p); - var partial = p % 1; - var time = loopDuration * whole + this._duration * partial; - return this.time(time); + + transforms = _objectSpread({}, newTransforms, { + origin: origin + }); } - }, { - key: "position", - value: function position(p) { - // Get all of the variables we need - var x = this._time; - var d = this._duration; - var w = this._wait; - var t = this._times; - var s = this._swing; - var r = this._reverse; - var position; - if (p == null) { - /* - This function converts a time to a position in the range [0, 1] - The full explanation can be found in this desmos demonstration - https://www.desmos.com/calculator/u4fbavgche - The logic is slightly simplified here because we can use booleans - */ - // Figure out the value without thinking about the start or end time - var f = function f(x) { - var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)); - var backwards = swinging && !r || !swinging && r; - var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards; - var clipped = Math.max(Math.min(uncliped, 1), 0); - return clipped; - }; // Figure out the value by incorporating the start time + this.queue(setup, run, retarget); + this._isDeclarative && this._rememberMorpher('transform', morpher); + return this; + }, + // Animatable x-axis + x: function x(_x, relative) { + return this._queueNumber('x', _x); + }, + // Animatable y-axis + y: function y(_y) { + return this._queueNumber('y', _y); + }, + dx: function dx(x) { + return this._queueNumberDelta('dx', x); + }, + dy: function dy(y) { + return this._queueNumberDelta('dy', y); + }, + _queueNumberDelta: function _queueNumberDelta(method, to) { + to = new SVGNumber(to); // Try to change the target if we have this method already registerd + if (this._tryRetargetDelta(method, to)) return this; // Make a morpher and queue the animation - var endTime = t * (w + d) - w; - position = x <= 0 ? Math.round(f(1e-5)) : x < endTime ? f(x) : Math.round(f(endTime - 1e-5)); - return position; - } // Work out the loops done and add the position to the loops done + var morpher = new Morphable(this._stepper).to(to); + this.queue(function () { + var from = this.element()[method](); + morpher.from(from); + morpher.to(from + to); + }, function (pos) { + this.element()[method](morpher.at(pos)); + return morpher.done(); + }); // Register the morpher so that if it is changed again, we can retarget it + this._rememberMorpher(method, morpher); - var loopsDone = Math.floor(this.loops()); - var swingForward = s && loopsDone % 2 === 0; - var forwards = swingForward && !r || r && swingForward; - position = loopsDone + (forwards ? p : 1 - p); - return this.loops(position); - } - }, { - key: "progress", - value: function progress(p) { - if (p == null) { - return Math.min(1, this._time / this.duration()); - } + return this; + }, + _queueObject: function _queueObject(method, to) { + // Try to change the target if we have this method already registerd + if (this._tryRetarget(method, to)) return this; // Make a morpher and queue the animation - return this.time(p * this.duration()); - } - }, { - key: "step", - value: function step(dt) { - // If we are inactive, this stepper just gets skipped - if (!this.enabled) return this; // Update the time and get the new position + var morpher = new Morphable(this._stepper).to(to); + this.queue(function () { + morpher.from(this.element()[method]()); + }, function (pos) { + this.element()[method](morpher.at(pos)); + return morpher.done(); + }); // Register the morpher so that if it is changed again, we can retarget it - dt = dt == null ? 16 : dt; - this._time += dt; - var position = this.position(); // Figure out if we need to run the stepper in this frame + this._rememberMorpher(method, morpher); - var running = this._lastPosition !== position && this._time >= 0; - this._lastPosition = position; // Figure out if we just started + return this; + }, + _queueNumber: function _queueNumber(method, value) { + return this._queueObject(method, new SVGNumber(value)); + }, + // Animatable center x-axis + cx: function cx(x) { + return this._queueNumber('cx', x); + }, + // Animatable center y-axis + cy: function cy(y) { + return this._queueNumber('cy', y); + }, + // Add animatable move + move: function move(x, y) { + return this.x(x).y(y); + }, + // Add animatable center + center: function center(x, y) { + return this.cx(x).cy(y); + }, + // Add animatable size + size: function size(width, height) { + // animate bbox based size for all other elements + var box; - var duration = this.duration(); - var justStarted = this._lastTime < 0 && this._time > 0; - var justFinished = this._lastTime < this._time && this.time > duration; - this._lastTime = this._time; + if (!width || !height) { + box = this._element.bbox(); + } - if (justStarted) { - this.fire('start', this); - } // Work out if the runner is finished set the done flag here so animations - // know, that they are running in the last step (this is good for - // transformations which can be merged) + if (!width) { + width = box.width / box.height * height; + } + if (!height) { + height = box.height / box.width * width; + } - var declarative = this._isDeclarative; - this.done = !declarative && !justFinished && this._time >= duration; // Call initialise and the run function + return this.width(width).height(height); + }, + // Add animatable width + width: function width(_width) { + return this._queueNumber('width', _width); + }, + // Add animatable height + height: function height(_height) { + return this._queueNumber('height', _height); + }, + // Add animatable plot + plot: function plot(a, b, c, d) { + // Lines can be plotted with 4 arguments + if (arguments.length === 4) { + return this.plot([a, b, c, d]); + } // FIXME: this needs to be rewritten such that the element is only accesed + // in the init function - if (running || declarative) { - this._initialise(running); // clear the transforms on this runner so they dont get added again and again + return this._queueObject('plot', new this._element.MorphArray(a)); + /* + var morpher = this._element.morphArray().to(a) + this.queue(function () { + morpher.from(this._element.array()) + }, function (pos) { + this._element.plot(morpher.at(pos)) + }) + return this + */ + }, + // Add leading method + leading: function leading(value) { + return this._queueNumber('leading', value); + }, + // Add animatable viewbox + viewbox: function viewbox(x, y, width, height) { + return this._queueObject('viewbox', new Box(x, y, width, height)); + }, + update: function update(o) { + if (_typeof(o) !== 'object') { + return this.update({ + offset: arguments[0], + color: arguments[1], + opacity: arguments[2] + }); + } - this.transforms = new Matrix(); + 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', o.offset); + return this; + } + }); - var converged = this._run(declarative ? dt : position); + var _Symbol = + /*#__PURE__*/ + function (_Container) { + _inherits(_Symbol, _Container); - this.fire('step', this); - } // correct the done flag here - // declaritive animations itself know when they converged + // Initialize node + function _Symbol(node) { + _classCallCheck(this, _Symbol); + return _possibleConstructorReturn(this, _getPrototypeOf(_Symbol).call(this, nodeOrNew('symbol', node), _Symbol)); + } - this.done = this.done || converged && declarative; + return _Symbol; + }(Container); + registerMethods({ + Container: { + symbol: function symbol() { + return this.put(new _Symbol()); + } + } + }); + register(_Symbol); - if (this.done) { - this.fire('finish', this); - } + // Create plain text node + function plain(text) { + // clear if build mode is disabled + if (this._build === false) { + this.clear(); + } // create text node - return this; - } - }, { - key: "finish", - value: function finish() { - return this.step(Infinity); - } - }, { - key: "reverse", - value: function reverse(_reverse) { - this._reverse = _reverse == null ? !this._reverse : _reverse; - return this; - } - }, { - key: "ease", - value: function ease(fn) { - this._stepper = new Ease(fn); - return this; - } - }, { - key: "active", - value: function active(enabled) { - if (enabled == null) return this.enabled; - this.enabled = enabled; - return this; - } - /* - Private Methods - =============== - Methods that shouldn't be used externally - */ - // Save a morpher to the morpher list so that we can retarget it later - }, { - key: "_rememberMorpher", - value: function _rememberMorpher(method, morpher) { - this._history[method] = { - morpher: morpher, - caller: this._queue[this._queue.length - 1] - }; - } // Try to set the target for a morpher if the morpher exists, otherwise - // do nothing and return false + this.node.appendChild(document.createTextNode(text)); + return this; + } // FIXME: Does this also work for textpath? + // Get length of text element - }, { - key: "_tryRetarget", - value: function _tryRetarget(method, target) { - if (this._history[method]) { - // if the last method wasnt even initialised, throw it away - if (!this._history[method].caller.initialised) { - var index = this._queue.indexOf(this._history[method].caller); + function length() { + return this.node.getComputedTextLength(); + } - this._queue.splice(index, 1); + var textable = /*#__PURE__*/Object.freeze({ + plain: plain, + length: length + }); - return false; - } // for the case of transformations, we use the special retarget function - // which has access to the outer scope + var Text = + /*#__PURE__*/ + function (_Shape) { + _inherits(Text, _Shape); + // Initialize node + function Text(node) { + var _this; - if (this._history[method].caller.isTransform) { - this._history[method].caller.isTransform(target); // for everything else a simple morpher change is sufficient + _classCallCheck(this, Text); - } else { - this._history[method].morpher.to(target); - } + _this = _possibleConstructorReturn(this, _getPrototypeOf(Text).call(this, nodeOrNew('text', node), Text)); + _this.dom.leading = new SVGNumber(1.3); // store leading value for rebuilding - this._history[method].caller.finished = false; - var timeline$$1 = this.timeline(); - timeline$$1 && timeline$$1._continue(); - return true; - } + _this._rebuild = true; // enable automatic updating of dy values - return false; - } // Run each initialise function in the runner if required + _this._build = false; // disable build mode for adding multiple lines + // set default font - }, { - key: "_initialise", - value: function _initialise(running) { - // If we aren't running, we shouldn't initialise when not declarative - if (!running && !this._isDeclarative) return; // Loop through all of the initialisers + _this.attr('font-family', attrs['font-family']); - for (var i = 0, len = this._queue.length; i < len; ++i) { - // Get the current initialiser - var current = this._queue[i]; // Determine whether we need to initialise + return _this; + } // Move over x-axis - var needsIt = this._isDeclarative || !current.initialised && running; - running = !current.finished; // Call the initialiser if we need to - if (needsIt && running) { - current.initialiser.call(this); - current.initialised = true; - } + _createClass(Text, [{ + key: "x", + value: function x(_x) { + // act as getter + if (_x == null) { + return this.attr('x'); } - } // Run each run function for the position or dt given + + return this.attr('x', _x); + } // Move over y-axis }, { - key: "_run", - value: function _run(positionOrDt) { - // Run all of the _queue directly - var allfinished = true; + key: "y", + value: function y(_y) { + var oy = this.attr('y'); + var o = typeof oy === 'number' ? oy - this.bbox().y : 0; // act as getter - for (var i = 0, len = this._queue.length; i < len; ++i) { - // Get the current function to run - var current = this._queue[i]; // Run the function if its not finished, we keep track of the finished - // flag for the sake of declarative _queue + if (_y == null) { + return typeof oy === 'number' ? oy - o : oy; + } - var converged = current.runner.call(this, positionOrDt); - current.finished = current.finished || converged === true; - allfinished = allfinished && current.finished; - } // We report when all of the constructors are finished + return this.attr('y', typeof _y === 'number' ? _y + o : _y); + } // Move center over x-axis + }, { + key: "cx", + value: function cx(x) { + return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2); + } // Move center over y-axis - return allfinished; - } }, { - key: "addTransform", - value: function addTransform(transform, index) { - this.transforms.lmultiplyO(transform); - return this; - } + key: "cy", + value: function cy(y) { + return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2); + } // Set the text content + }, { - key: "clearTransform", - value: function clearTransform() { - this.transforms = new Matrix(); - return this; - } - }], [{ - key: "sanitise", - value: function sanitise(duration, delay, when) { - // Initialise the default parameters - var times = 1; - var swing = false; - var wait = 0; - duration = duration || timeline.duration; - delay = delay || timeline.delay; - when = when || 'last'; // If we have an object, unpack the values + key: "text", + value: function text(_text) { + // act as getter + if (_text === undefined) { + // FIXME use children() or each() + var children = this.node.childNodes; + var firstLine = 0; + _text = ''; - if (_typeof(duration) === 'object' && !(duration instanceof Stepper)) { - delay = duration.delay || delay; - when = duration.when || when; - swing = duration.swing || swing; - times = duration.times || times; - wait = duration.wait || wait; - duration = duration.duration || timeline.duration; - } + 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; + continue; + } // add newline if its not the first child and newLined is set to true - return { - duration: duration, - delay: delay, - swing: swing, - times: times, - wait: wait, - when: when - }; - } - }]); - return Runner; - }(EventTarget); - Runner.id = 0; + if (i !== firstLine && children[i].nodeType !== 3 && adopt(children[i]).dom.newLined === true) { + _text += '\n'; + } // add content of this node - var FakeRunner = function FakeRunner() { - var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix(); - var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; - var done = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; - _classCallCheck(this, FakeRunner); + _text += children[i].textContent; + } - this.transforms = transforms; - this.id = id; - this.done = done; - }; + return _text; + } // remove existing content - extend([Runner, FakeRunner], { - mergeWith: function mergeWith(runner) { - return new FakeRunner(runner.transforms.lmultiply(this.transforms), runner.id); - } - }); // FakeRunner.emptyRunner = new FakeRunner() - var lmultiply = function lmultiply(last, curr) { - return last.lmultiplyO(curr); - }; + this.clear().build(true); - var getRunnerTransform = function getRunnerTransform(runner) { - return runner.transforms; - }; + if (typeof _text === 'function') { + // call block + _text.call(this, this); + } else { + // store text and make sure text is not blank + _text = _text.split('\n'); // build new lines - function mergeTransforms() { - // Find the matrix to apply to the element and apply it - var runners = this._transformationRunners.runners; - var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix()); - this.transform(netTransform); + for (var j = 0, jl = _text.length; j < jl; j++) { + this.tspan(_text[j]).newLine(); + } + } // disable build mode and rebuild lines - this._transformationRunners.merge(); - if (this._transformationRunners.length() === 1) { - this._frameId = null; - } - } + return this.build(false).rebuild(); + } // Set / get leading - var RunnerArray = - /*#__PURE__*/ - function () { - function RunnerArray() { - _classCallCheck(this, RunnerArray); + }, { + key: "leading", + value: function leading(value) { + // act as getter + if (value == null) { + return this.dom.leading; + } // act as setter - this.runners = []; - this.ids = []; - } - _createClass(RunnerArray, [{ - key: "add", - value: function add(runner) { - if (this.runners.includes(runner)) return; - var id = runner.id + 1; - var leftSibling = this.ids.reduce(function (last, curr) { - if (curr > last && curr < id) return curr; - return last; - }, 0); - var index = this.ids.indexOf(leftSibling) + 1; - this.ids.splice(index, 0, id); - this.runners.splice(index, 0, runner); - return this; - } - }, { - key: "getByID", - value: function getByID(id) { - return this.runners[this.ids.indexOf(id + 1)]; - } - }, { - key: "remove", - value: function remove(id) { - var index = this.ids.indexOf(id + 1); - this.ids.splice(index, 1); - this.runners.splice(index, 1); - return this; - } + this.dom.leading = new SVGNumber(value); + return this.rebuild(); + } // Rebuild appearance type + }, { - key: "merge", - value: function merge() { - var _this2 = this; + key: "rebuild", + value: function rebuild(_rebuild) { + // store new rebuild flag if given + if (typeof _rebuild === 'boolean') { + this._rebuild = _rebuild; + } // define position of all lines - var lastRunner = null; - this.runners.forEach(function (runner, i) { - if (lastRunner && runner.done && lastRunner.done) { - _this2.remove(runner.id); - _this2.edit(lastRunner.id, runner.mergeWith(lastRunner)); - } + if (this._rebuild) { + var self = this; + var blankLineOffset = 0; + var dy = this.dom.leading * new SVGNumber(this.attr('font-size')); + this.each(function () { + if (this.dom.newLined) { + this.attr('x', self.attr('x')); + + if (this.text() === '\n') { + blankLineOffset += dy; + } else { + this.attr('dy', dy + blankLineOffset); + blankLineOffset = 0; + } + } + }); + this.fire('rebuild'); + } - lastRunner = runner; - }); - return this; - } - }, { - key: "edit", - value: function edit(id, newRunner) { - var index = this.ids.indexOf(id + 1); - this.ids.splice(index, 1, id); - this.runners.splice(index, 1, newRunner); return this; - } + } // Enable / disable build mode + }, { - key: "length", - value: function length() { - return this.ids.length; - } + key: "build", + value: function build(_build) { + this._build = !!_build; + return this; + } // overwrite method from parent to set data properly + }, { - key: "clearBefore", - value: function clearBefore(id) { - var deleteCnt = this.ids.indexOf(id + 1) || 1; - this.ids.splice(0, deleteCnt, 0); - this.runners.splice(0, deleteCnt, new FakeRunner()); + key: "setData", + value: function setData(o) { + this.dom = o; + this.dom.leading = new SVGNumber(o.leading || 1.3); return this; } }]); - return RunnerArray; - }(); - - var frameId = 0; + return Text; + }(Shape); + extend(Text, textable); registerMethods({ - Element: { - animate: function animate(duration, delay, when) { - var o = Runner.sanitise(duration, delay, when); - var timeline$$1 = this.timeline(); - return new Runner(o.duration).loop(o).element(this).timeline(timeline$$1).schedule(delay, when); - }, - delay: function delay(by, when) { - return this.animate(0, by, when); - }, - // this function searches for all runners on the element and deletes the ones - // which run before the current one. This is because absolute transformations - // overwfrite anything anyway so there is no need to waste time computing - // other runners - _clearTransformRunnersBefore: function _clearTransformRunnersBefore(currentRunner) { - this._transformationRunners.clearBefore(currentRunner.id); - }, - _currentTransform: function _currentTransform(current) { - return this._transformationRunners.runners // we need the equal sign here to make sure, that also transformations - // on the same runner which execute before the current transformation are - // taken into account - .filter(function (runner) { - return runner.id <= current.id; - }).map(getRunnerTransform).reduce(lmultiply, new Matrix()); - }, - addRunner: function addRunner(runner) { - this._transformationRunners.add(runner); - - Animator.transform_frame(mergeTransforms.bind(this), this._frameId); + Container: { + // Create text element + text: function text(_text2) { + return this.put(new Text()).text(_text2); }, - _prepareRunner: function _prepareRunner() { - if (this._frameId == null) { - this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix(this))); - this._frameId = frameId++; - } + // Create plain text element + plain: function plain$$1(text) { + return this.put(new Text()).plain(text); } } }); - extend(Runner, { - attr: function attr(a, v) { - return this.styleAttr('attr', a, v); - }, - // Add animatable styles - css: function css(s, v) { - return this.styleAttr('css', s, v); - }, - styleAttr: function styleAttr(type, name, val) { - // apply attributes individually - if (_typeof(name) === 'object') { - for (var key in val) { - this.styleAttr(type, key, val[key]); - } - } + register(Text); - var morpher = new Morphable(this._stepper).to(val); - this.queue(function () { - morpher = morpher.from(this.element()[type](name)); - }, function (pos) { - this.element()[type](name, morpher.at(pos)); - return morpher.done(); - }); - return this; - }, - zoom: function zoom(level, point) { - var morpher = new Morphable(this._stepper).to(new SVGNumber(level)); - this.queue(function () { - morpher = morpher.from(this.zoom()); - }, function (pos) { - this.element().zoom(morpher.at(pos), point); - return morpher.done(); - }); - return this; - }, + var TextPath = + /*#__PURE__*/ + function (_Text) { + _inherits(TextPath, _Text); - /** - ** absolute transformations - **/ - // - // M v -----|-----(D M v = F v)------|-----> T v - // - // 1. define the final state (T) and decompose it (once) - // t = [tx, ty, the, lam, sy, sx] - // 2. on every frame: pull the current state of all previous transforms - // (M - m can change) - // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] - // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) - // - Note F(0) = M - // - Note F(1) = T - // 4. Now you get the delta matrix as a result: D = F * inv(M) - transform: function transform(transforms, relative, affine) { - // If we have a declarative function, we should retarget it if possible - relative = transforms.relative || relative; + // Initialize node + function TextPath(node) { + _classCallCheck(this, TextPath); - if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { - return this; - } // Parse the parameters + return _possibleConstructorReturn(this, _getPrototypeOf(TextPath).call(this, nodeOrNew('textPath', node), TextPath)); + } // return the array of the path track element - var isMatrix = isMatrixLike(transforms); - affine = transforms.affine != null ? transforms.affine : affine != null ? affine : !isMatrix; // Create a morepher and set its type + _createClass(TextPath, [{ + key: "array", + value: function array() { + var track = this.track(); + return track ? track.array() : null; + } // Plot path if any - var morpher = new Morphable().type(affine ? TransformBag : Matrix).stepper(this._stepper); - var origin; - var element; - var current; - var currentAngle; - var startTransform; + }, { + key: "plot", + value: function plot(d) { + var track = this.track(); + var pathArray = null; - function setup() { - // make sure element and origin is defined - element = element || this.element(); - origin = origin || getOrigin(transforms, element); - startTransform = new Matrix(relative ? undefined : element); // add the runner to the element so it can merge transformations + if (track) { + pathArray = track.plot(d); + } - element.addRunner(this); // Deactivate all transforms that have run so far if we are absolute + return d == null ? pathArray : this; + } // Get the path element - if (!relative) { - element._clearTransformRunnersBefore(this); - } + }, { + key: "track", + value: function track() { + return this.reference('href'); } + }]); - function run(pos) { - // clear all other transforms before this in case something is saved - // on this runner. We are absolute. We dont need these! - if (!relative) this.clearTransform(); + return TextPath; + }(Text); + registerMethods({ + Container: { + textPath: function textPath(text, path) { + return this.defs().path(path).text(text).addTo(this); + } + }, + Text: { + // Create path for text to run on + path: function path(track) { + var path = new TextPath(); // if d is a path, reuse it - var _transform = new Point(origin).transform(element._currentTransform(this)), - x = _transform.x, - y = _transform.y; + if (!(track instanceof Path)) { + // create path element + track = this.doc().defs().path(track); + } // link textPath to path and add content - var target = new Matrix(_objectSpread({}, transforms, { - origin: [x, y] - })); - var start = this._isDeclarative && current ? current : startTransform; - if (affine) { - target = target.decompose(x, y); - start = start.decompose(x, y); // Get the current and target angle as it was set + path.attr('href', '#' + track, xlink); // add textPath element as child node and return textPath - var rTarget = target.rotate; - var rCurrent = start.rotate; // Figure out the shortest path to rotate directly + return this.put(path); + }, + // FIXME: make this plural? + // Get the textPath children + textPath: function textPath() { + return this.find('textPath'); + } + }, + Path: { + // creates a textPath from this path + text: function text(_text) { + if (_text instanceof Text) { + var txt = _text.text(); - var possibilities = [rTarget - 360, rTarget, rTarget + 360]; - var distances = possibilities.map(function (a) { - return Math.abs(a - rCurrent); - }); - var shortest = Math.min.apply(Math, _toConsumableArray(distances)); - var index = distances.indexOf(shortest); - target.rotate = possibilities[index]; + return _text.clear().path(this).text(txt); } - if (relative) { - // we have to be careful here not to overwrite the rotation - // with the rotate method of Matrix - if (!isMatrix) { - target.rotate = transforms.rotate || 0; - } + return this.parent().put(new Text()).path(this).text(_text); + } // FIXME: Maybe add `targets` to get all textPaths associated with this path - if (this._isDeclarative && currentAngle) { - start.rotate = currentAngle; - } - } + } + }); + TextPath.prototype.MorphArray = PathArray; + register(TextPath); - morpher.from(start); - morpher.to(target); - var affineParameters = morpher.at(pos); - currentAngle = affineParameters.rotate; - current = new Matrix(affineParameters); - this.addTransform(current); - return morpher.done(); - } + var Tspan = + /*#__PURE__*/ + function (_Text) { + _inherits(Tspan, _Text); + + // Initialize node + function Tspan(node) { + _classCallCheck(this, Tspan); - function retarget(newTransforms) { - // only get a new origin if it changed since the last call - if ((newTransforms.origin || 'center').toString() !== (transforms.origin || 'center').toString()) { - origin = getOrigin(transforms, element); - } // overwrite the old transformations with the new ones + return _possibleConstructorReturn(this, _getPrototypeOf(Tspan).call(this, nodeOrNew('tspan', node), Tspan)); + } // Set text content - transforms = _objectSpread({}, newTransforms, { - origin: origin - }); - } + _createClass(Tspan, [{ + key: "text", + value: function text(_text) { + if (_text == null) return this.node.textContent + (this.dom.newLined ? '\n' : ''); + typeof _text === 'function' ? _text.call(this, this) : this.plain(_text); + return this; + } // Shortcut dx - this.queue(setup, run, retarget); - this._isDeclarative && this._rememberMorpher('transform', morpher); - return this; - }, - // Animatable x-axis - x: function x(_x, relative) { - return this._queueNumber('x', _x); - }, - // Animatable y-axis - y: function y(_y) { - return this._queueNumber('y', _y); - }, - dx: function dx(x) { - return this._queueNumberDelta('dx', x); - }, - dy: function dy(y) { - return this._queueNumberDelta('dy', y); - }, - _queueNumberDelta: function _queueNumberDelta(method, to) { - to = new SVGNumber(to); // Try to change the target if we have this method already registerd + }, { + key: "dx", + value: function dx(_dx) { + return this.attr('dx', _dx); + } // Shortcut dy - if (this._tryRetargetDelta(method, to)) return this; // Make a morpher and queue the animation + }, { + key: "dy", + value: function dy(_dy) { + return this.attr('dy', _dy); + } // Create new line - var morpher = new Morphable(this._stepper).to(to); - this.queue(function () { - var from = this.element()[method](); - morpher.from(from); - morpher.to(from + to); - }, function (pos) { - this.element()[method](morpher.at(pos)); - return morpher.done(); - }); // Register the morpher so that if it is changed again, we can retarget it + }, { + key: "newLine", + value: function newLine() { + // fetch text parent + var t = this.parent(Text); // mark new line - this._rememberMorpher(method, morpher); + this.dom.newLined = true; // apply new position - return this; - }, - _queueObject: function _queueObject(method, to) { - // Try to change the target if we have this method already registerd - if (this._tryRetarget(method, to)) return this; // Make a morpher and queue the animation + return this.dy(t.dom.leading * t.attr('font-size')).attr('x', t.x()); + } + }]); - var morpher = new Morphable(this._stepper).to(to); - this.queue(function () { - morpher.from(this.element()[method]()); - }, function (pos) { - this.element()[method](morpher.at(pos)); - return morpher.done(); - }); // Register the morpher so that if it is changed again, we can retarget it + return Tspan; + }(Text); + extend(Tspan, textable); + registerMethods({ + Tspan: { + tspan: function tspan(text) { + var tspan = new Tspan(); // clear if build mode is disabled - this._rememberMorpher(method, morpher); + if (!this._build) { + this.clear(); + } // add new tspan - return this; - }, - _queueNumber: function _queueNumber(method, value) { - return this._queueObject(method, new SVGNumber(value)); - }, - // Animatable center x-axis - cx: function cx(x) { - return this._queueNumber('cx', x); - }, - // Animatable center y-axis - cy: function cy(y) { - return this._queueNumber('cy', y); - }, - // Add animatable move - move: function move(x, y) { - return this.x(x).y(y); - }, - // Add animatable center - center: function center(x, y) { - return this.cx(x).cy(y); - }, - // Add animatable size - size: function size(width, height) { - // animate bbox based size for all other elements - var box; - if (!width || !height) { - box = this._element.bbox(); + this.node.appendChild(tspan.node); + return tspan.text(text); } + } + }); + register(Tspan); - if (!width) { - width = box.width / box.height * height; - } + var Use = + /*#__PURE__*/ + function (_Shape) { + _inherits(Use, _Shape); - if (!height) { - height = box.height / box.width * width; - } + function Use(node) { + _classCallCheck(this, Use); - return this.width(width).height(height); - }, - // Add animatable width - width: function width(_width) { - return this._queueNumber('width', _width); - }, - // Add animatable height - height: function height(_height) { - return this._queueNumber('height', _height); - }, - // Add animatable plot - plot: function plot(a, b, c, d) { - // Lines can be plotted with 4 arguments - if (arguments.length === 4) { - return this.plot([a, b, c, d]); - } // FIXME: this needs to be rewritten such that the element is only accesed - // in the init function + return _possibleConstructorReturn(this, _getPrototypeOf(Use).call(this, nodeOrNew('use', node), Use)); + } // Use element as a reference - return this._queueObject('plot', new this._element.MorphArray(a)); - /* - var morpher = this._element.morphArray().to(a) - this.queue(function () { - morpher.from(this._element.array()) - }, function (pos) { - this._element.plot(morpher.at(pos)) - }) - return this - */ - }, - // Add leading method - leading: function leading(value) { - return this._queueNumber('leading', value); - }, - // Add animatable viewbox - viewbox: function viewbox(x, y, width, height) { - return this._queueObject('viewbox', new Box(x, y, width, height)); - }, - update: function update(o) { - if (_typeof(o) !== 'object') { - return this.update({ - offset: arguments[0], - color: arguments[1], - opacity: arguments[2] - }); + _createClass(Use, [{ + key: "element", + value: function element(_element, file) { + // Set lined element + return this.attr('href', (file || '') + '#' + _element, xlink); } + }]); - 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', o.offset); - return this; + return Use; + }(Shape); + registerMethods({ + Container: { + // Create a use element + use: function use(element, file) { + return this.put(new Use()).element(element, file); + } } }); + register(Use); + - // export {default as SVGArray} from './SVGArray.js' - // export {default as Bare} from './Bare.js' - // export {default as Box} from './Box.js' - // export {default as Circle} from './Circle.js' - // export {default as ClipPath} from './ClipPath.js' - // export {default as Color} from './Color.js' - // export {default as Container} from './Container.js' - // export {Controller, Ease, PID, Spring} from './Controller.js' - // export {default as Defs} from './Defs.js' - // export {default as Doc} from './Doc.js' - // export {default as Element} from './Element.js' - // export {default as Ellipse} from './Ellipse.js' - // export {default as EventTarget} from './EventTarget.js' - // export {default as Gradient} from './Gradient.js' - // export {default as G} from './G.js' - // export {default as HtmlNode} from './HtmlNode.js' - // export {default as A} from './A.js' - // export {default as Image} from './Image.js' - // export {default as Line} from './Line.js' - // export {default as Marker} from './Marker.js' - // export {default as Mask} from './Mask.js' - // export {default as Matrix} from './Matrix.js' - // export {default as Morphable} from './Morphable.js' - // export {default as SVGNumber} from './SVGNumber.js' - // export {default as Path} from './Path.js' - // export {default as PathArray} from './PathArray.js' - // export {default as Pattern} from './Pattern.js' - // export {default as Point} from './Point.js' - // export {default as PointArray} from './PointArray.js' - // export {default as Polygon} from './Polygon.js' - // export {default as Polyline} from './Polyline.js' - // export {default as Queue} from './Queue.js' - // export {default as Rect} from './Rect.js' - // export {default as Runner} from './Runner.js' - // export {default as Shape} from './Shape.js' - // export {default as Stop} from './Stop.js' - // export {default as Symbol} from './Symbol.js' - // export {default as Text} from './Text.js' - // export {default as TextPath} from './TextPath.js' - // export {default as Timeline} from './Timeline.js' - // export {default as Use} from './Use.js' var Classes = /*#__PURE__*/Object.freeze({ - EventTarget: EventTarget, - Dom: Dom, - Element: Element, - Shape: Shape, - Container: Container, - HtmlNode: HtmlNode, - Doc: Doc$1, - Defs: Defs, - G: G, Animator: Animator, + SVGArray: SVGArray, Bare: Bare, + Box: Box, Circle: Circle, ClipPath: ClipPath, - A: A, + Color: Color, + Container: Container, + Controller: Controller, + Ease: Ease, + PID: PID, + Spring: Spring, + Defs: Defs, + Doc: Doc$1, + Dom: Dom, + Element: Element, Ellipse: Ellipse, - Stop: Stop, + EventTarget: EventTarget, Gradient: Gradient, + G: G, + HtmlNode: HtmlNode, + A: A, Image: Image, Line: Line, Marker: Marker, Mask: Mask, + Matrix: Matrix, + Morphable: Morphable, + SVGNumber: SVGNumber, Path: Path, + PathArray: PathArray, Pattern: Pattern, + Point: Point, + PointArray: PointArray, Polygon: Polygon, Polyline: Polyline, + Queue: Queue, Rect: Rect, + Runner: Runner, + Shape: Shape, + Stop: Stop, Symbol: _Symbol, Text: Text, TextPath: TextPath, - Tspan: Tspan, - Use: Use, - SVGNumber: SVGNumber, - SVGArray: SVGArray, - PathArray: PathArray, - PointArray: PointArray, - Matrix: Matrix, - Point: Point, - Box: Box, - Color: Color, - Morphable: Morphable, - Queue: Queue, - Runner: Runner, Timeline: Timeline, - Controller: Controller, - Ease: Ease, - PID: PID, - Spring: Spring + Tspan: Tspan, + Use: Use }); // ### This module adds backward / forward functionality to elements. @@ -7125,10 +6656,6 @@ var SVG = (function () { transform: transform }); - // - // export function setup (node) { - // this._memory = {} - // } // Remember arbitrary data function remember(k, v) { @@ -7167,7 +6694,7 @@ var SVG = (function () { remember: remember, forget: forget, memory: memory - }); // registerConstructor('Memory', setup) + }); var sugar = { stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], diff --git a/dist/svg.min.js b/dist/svg.min.js index 7f3eb18..001199b 100644 --- a/dist/svg.min.js +++ b/dist/svg.min.js @@ -1 +1 @@ -var SVG=function(){"use strict";function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;n",delay:0},kt={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},bt=Object.freeze({noop:gt,timeline:wt,attrs:kt}),xt=function(){function t(){o(this,t),this.init.apply(this,arguments)}return a(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?k.test(t)?(i=p.exec(t.replace(g,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):w.test(t)&&(i=y.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+z(Math.round(this.r))+z(Math.round(this.g))+z(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",w.test(t)||k.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}(),_t=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1n.x&&e>n.y&&t=e.time?e.run():Ft.timeouts.push(e),e!==n););for(var i=null,r=Ft.frames.last();i!==r&&(i=Ft.frames.shift());)i.run();Ft.transforms.forEach(function(t){t()}),Ft.nextDraw=Ft.timeouts.first()||Ft.frames.first()?window.requestAnimationFrame(Ft._draw):null}},It=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q(t,"string"==typeof t?null:t),e))}return r(e,Tt),a(e,[{key:"words",value:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(document.createTextNode(t)),this}}]),e}();function Xt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function Yt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function Ht(t){return null==t?this.attr("cx"):this.attr("cx",t)}function Gt(t){return null==t?this.attr("cy"):this.attr("cy",t)}function Vt(t){return null==t?2*this.rx():this.rx(new At(t).divide(2))}function Bt(t){return null==t?2*this.ry():this.ry(new At(t).divide(2))}function Qt(t,e){var n=R(this,t,e);return this.rx(new At(n.width).divide(2)).ry(new At(n.height).divide(2))}et(It),Pt("Container",{element:function(t,e){return this.put(new It(t,e))}});var Ut=Object.freeze({rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)},x:Xt,y:Yt,cx:Ht,cy:Gt,width:Vt,height:Bt,size:Qt}),$t=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("circle",t),e))}return r(e,St),a(e,[{key:"radius",value:function(t){return this.attr("r",t)}},{key:"rx",value:function(t){return this.attr("r",t)}},{key:"ry",value:function(t){return this.rx(t)}}]),e}();function Wt(t,e){return yt((e||document).querySelectorAll(t),function(t){return tt(t)})}function Jt(t){return Wt(t,this.node)}$($t,{x:Xt,y:Yt,cx:Ht,cy:Gt,width:Vt,height:Bt,size:Qt}),Pt({Element:{circle:function(t){return this.put(new $t).radius(new At(t).divide(2)).move(0,0)}}}),et($t),Pt("Dom",{find:Jt});var Zt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("clipPath",t),e))}return r(e,Tt),a(e,[{key:"remove",value:function(){return this.targets().forEach(function(t){t.unclip()}),c(u(e.prototype),"remove",this).call(this)}},{key:"targets",value:function(){return Wt('svg [clip-path*="'+this.id()+'"]')}}]),e}();Pt({Container:{clip:function(){return this.defs().put(new Zt)}},Element:{clipWith:function(t){var e=t instanceof Zt?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.id()+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}}),et(Zt);var Kt=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("a",t),e))}return r(e,Tt),a(e,[{key:"to",value:function(t){return this.attr("href",t,G)}},{key:"target",value:function(t){return this.attr("target",t)}}]),e}();Pt({Container:{link:function(t){return this.put(new Kt).to(t)}},Element:{linkTo:function(t){var e=new Kt;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}}),et(Kt);var te=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("ellipse",t),e))}return r(e,St),e}();$(te,Ut),Pt("Container",{ellipse:function(t,e){return this.put(new te).size(t,e).move(0,0)}}),et(te);var ee=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("stop",t),e))}return r(e,Mt),a(e,[{key:"update",value:function(t){return("number"==typeof t||t instanceof At)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new At(t.offset)),this}}]),e}();et(ee);var ne=Object.freeze({from:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({fx:new At(t),fy:new At(e)}):this.attr({x1:new At(t),y1:new At(e)})},to:function(t,e){return"radialGradient"===(this._element||this).type?this.attr({cx:new At(t),cy:new At(e)}):this.attr({x2:new At(t),y2:new At(e)})}});function ie(){if(!ie.nodes){var t=(new Rt).size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"}),e=t.path().node;ie.nodes={svg:t,path:e}}if(!ie.nodes.svg.node.parentNode){var n=document.body||document.documentElement;ie.nodes.svg.addTo(n)}return ie.nodes}var re=function(){function r(t,e,n){var i;o(this,r),n=n||{x:0,y:0},i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"===l(t)?{x:t.x,y:t.y}:{x:t,y:e},this.x=null==i.x?n.x:i.x,this.y=null==i.y?n.y:i.y}return a(r,[{key:"clone",value:function(){return new r(this)}},{key:"native",value:function(){var t=ie().svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t}},{key:"transform",value:function(t){return new r(t.a*this.x+t.c*this.y+t.e,t.b*this.x+t.d*this.y+t.f)}}]),r}();Pt({Element:{point:function(t,e){return new re(t,e).transform(this.screenCTM().inverse())}}});var se=function(){function u(){o(this,u),this.init.apply(this,arguments)}return a(u,[{key:"init",value:function(t){var e;t="string"==typeof t?t.split(C).map(parseFloat):Array.isArray(t)?t:"object"===l(t)?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):[0,0,0,0],this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],null==(e=this).x&&(e.x=0,e.y=0,e.width=0,e.height=0),e.w=e.width,e.h=e.height,e.x2=e.x+e.width,e.y2=e.y+e.height,e.cx=e.x+e.width/2,e.cy=e.y+e.height/2}},{key:"merge",value:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new u(e,n,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-n)}},{key:"transform",value:function(e){var n=1/0,i=-1/0,r=1/0,s=-1/0;return[new re(this.x,this.y),new re(this.x2,this.y),new re(this.x,this.y2),new re(this.x2,this.y2)].forEach(function(t){t=t.transform(e),n=Math.min(n,t.x),i=Math.max(i,t.x),r=Math.min(r,t.y),s=Math.max(s,t.y)}),new u(n,r,i-n,s-r)}},{key:"addOffset",value:function(){return this.x+=window.pageXOffset,this.y+=window.pageYOffset,this}},{key:"toString",value:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}},{key:"toArray",value:function(){return[this.x,this.y,this.width,this.height]}}]),u}();function ue(e){var n,t,i;try{if(n=e(this.node),!((i=n).w||i.h||i.x||i.y||(t=this.node,(document.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===document}).call(document.documentElement,t))))throw new Error("Element not in the dom")}catch(t){try{var r=this.clone(ie().svg).show();n=e(r.node),r.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return n}Pt({Element:{bbox:function(){return new se(ue.call(this,function(t){return t.getBBox()}))},rbox:function(t){var e=new se(ue.call(this,function(t){return t.getBoundingClientRect()}));return t?e.transform(t.screenCTM().inverse()):e.addOffset()}},viewbox:{viewbox:function(t,e,n,i){return null==t?new se(this.attr("viewBox")):this.attr("viewBox",new se(t,e,n,i))}}});var oe=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q(t+"Gradient","string"==typeof t?null:t),i))}return r(i,Tt),a(i,[{key:"stop",value:function(t,e,n){return this.put(new ee).update(t,e,n)}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="gradientTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return Jt('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new se}}]),i}();$(oe,ne),Pt({Container:{gradient:function(t,e){return this.defs().gradient(t,e)}},Defs:{gradient:function(t,e){return this.put(new oe(t)).update(e)}}}),et(oe);var ae=function(t){function i(t){return o(this,i),h(this,u(i).call(this,Q("pattern",t),i))}return r(i,Tt),a(i,[{key:"url",value:function(){return"url(#"+this.id()+")"}},{key:"update",value:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}},{key:"toString",value:function(){return this.url()}},{key:"attr",value:function(t,e,n){return"transform"===t&&(t="patternTransform"),c(u(i.prototype),"attr",this).call(this,t,e,n)}},{key:"targets",value:function(){return Jt('svg [fill*="'+this.id()+'"]')}},{key:"bbox",value:function(){return new se}}]),i}();Pt({Container:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}},Defs:{pattern:function(t,e,n){return this.put(new ae).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}}),et(ae);var he=function(t){function e(t){return o(this,e),h(this,u(e).call(this,Q("image",t),e))}return r(e,St),a(e,[{key:"load",value:function(n,i){if(!n)return this;var r=new window.Image;return lt(r,"load",function(t){var e=this.parent(ae);0===this.width()&&0===this.height()&&this.size(r.width,r.height),e instanceof ae&&0===e.width()&&0===e.height()&&e.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:r.width,height:r.height,ratio:r.width/r.height,url:n})},this),lt(r,"load error",function(){ct(r)}),this.attr("href",r.src=n,G)}},{key:"attrHook",value:function(t){var e=this;return t.doc().defs().pattern(0,0,function(t){t.add(e)})}}]),e}();Pt({Container:{image:function(t,e){return this.put(new he).size(0,0).load(t,e)}}}),et(he);var le=_t("PointArray",Ot);$(le,{toString:function(){for(var t=0,e=this.length,n=[];t":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},ze=function(){function t(){o(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),Re=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).ease=Pe[t||wt.ease]||t,e}return r(n,ze),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),qe=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).stepper=t,e}return r(n,ze),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function Le(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var Fe=function(t){function i(t,e){var n;return o(this,i),(n=h(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,qe),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i;this._lastTime=this._time,r&&this.fire("start",this);var u=this._isDeclarative;if(this.done=!u&&!s&&this._time>=i,n||u){this._initialise(n),this.transforms=new Ne;var o=this._run(u?t:e);this.fire("step",this)}return this.done=this.done||o&&u,this.done&&this.fire("finish",this),this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new Re(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e=e.time?e.run():d.timeouts.push(e),e!==n););for(var i=null,r=d.frames.last();i!==r&&(i=d.frames.shift());)i.run();d.transforms.forEach(function(t){t()}),d.nextDraw=d.timeouts.first()||d.frames.first()?window.requestAnimationFrame(d._draw):null}},v=/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,y=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,p=/rgb\((\d+),(\d+),(\d+)\)/,m=/(#[a-z0-9\-_]+)/i,e=/\)\s*,?\s*/,g=/\s/g,w=/^#[a-f0-9]{3,6}$/i,k=/^rgb\(/,b=/^(\s+)?$/,x=/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,A=/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,C=/[\s,]+/,j=/([^e])-/gi,M=/[MLHVCSQTAZ]/gi,S=/[MLHVCSQTAZ]/i,T=/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,E=/\./g,N=Object.freeze({numberAndUnit:v,hex:y,rgb:p,reference:m,transforms:e,whitespace:g,isHex:w,isRgb:k,isCss:/[^:]+:[^;]+;?/,isBlank:b,isNumber:x,isPercent:/^-?[\d.]+%$/,isImage:A,delimiter:C,hyphen:j,pathLetters:M,isPathLetter:S,numbersWithDots:T,dots:E}),D=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1",delay:0},Mt={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},St=Object.freeze({noop:Ct,timeline:jt,attrs:Mt}),Tt=function(){function t(){o(this,t),this.init.apply(this,arguments)}return a(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?k.test(t)?(i=p.exec(t.replace(g,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):w.test(t)&&(i=y.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+H(Math.round(this.r))+H(Math.round(this.g))+H(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",w.test(t)||k.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}();var Et=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this,t))).node=t,e.type=t.nodeName,e}return r(n,xt),a(n,[{key:"add",value:function(t,e){return t=Z(t),null==e?this.node.appendChild(t.node):t.node!==this.node.childNodes[e]&&this.node.insertBefore(t.node,this.node.childNodes[e]),this}},{key:"addTo",value:function(t){return Z(t).put(this)}},{key:"children",value:function(){return _t(this.node.children,function(t){return K(t)})}},{key:"clear",value:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return delete this._defs,this}},{key:"clone",value:function(t){this.writeDataToDom();var e=rt(this.node.cloneNode(!0));return t?t.add(e):this.after(e),e}},{key:"each",value:function(t,e){var n,i,r=this.children();for(n=0,i=r.length;nn.x&&e>n.y&&t":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},ie=function(){function t(){o(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),re=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).ease=ne[t||jt.ease]||t,e}return r(n,ie),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),se=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).stepper=t,e}return r(n,ie),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function ue(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var oe=function(t){function i(t,e){var n;return o(this,i),(n=h(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,se),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i;this._lastTime=this._time,r&&this.fire("start",this);var u=this._isDeclarative;if(this.done=!u&&!s&&this._time>=i,n||u){this._initialise(n),this.transforms=new Oe;var o=this._run(u?t:e);this.fire("step",this)}return this.done=this.done||o&&u,this.done&&this.fire("finish",this),this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new re(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e= 0; i--) { -// l = this[i][0] -// -// if (l === 'M' || l === 'L' || l === 'T') { -// this[i][1] += x -// this[i][2] += y -// } else if (l === 'H') { -// this[i][1] += x -// } else if (l === 'V') { -// this[i][1] += y -// } else if (l === 'C' || l === 'S' || l === 'Q') { -// this[i][1] += x -// this[i][2] += y -// this[i][3] += x -// this[i][4] += y -// -// if (l === 'C') { -// this[i][5] += x -// this[i][6] += y -// } -// } else if (l === 'A') { -// this[i][6] += x -// this[i][7] += y -// } -// } -// } -// -// return this -// } -// -// // Resize path string -// size (width, height) { -// // get bounding box of current situation -// var box = this.bbox() -// var i, l -// -// // recalculate position of all points according to new size -// for (i = this.length - 1; i >= 0; i--) { -// l = this[i][0] -// -// if (l === 'M' || l === 'L' || l === 'T') { -// this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x -// this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y -// } else if (l === 'H') { -// this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x -// } else if (l === 'V') { -// this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y -// } else if (l === 'C' || l === 'S' || l === 'Q') { -// this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x -// this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y -// this[i][3] = ((this[i][3] - box.x) * width) / box.width + box.x -// this[i][4] = ((this[i][4] - box.y) * height) / box.height + box.y -// -// if (l === 'C') { -// this[i][5] = ((this[i][5] - box.x) * width) / box.width + box.x -// this[i][6] = ((this[i][6] - box.y) * height) / box.height + box.y -// } -// } else if (l === 'A') { -// // resize radii -// this[i][1] = (this[i][1] * width) / box.width -// this[i][2] = (this[i][2] * height) / box.height -// -// // move position values -// this[i][6] = ((this[i][6] - box.x) * width) / box.width + box.x -// this[i][7] = ((this[i][7] - box.y) * height) / box.height + box.y -// } -// } -// -// return this -// } -// -// // Test if the passed path array use the same path data commands as this path array -// equalCommands (pathArray) { -// var i, il, equalCommands -// -// pathArray = new PathArray(pathArray) -// -// equalCommands = this.length === pathArray.value.length -// for (i = 0, il = this.length; equalCommands && i < il; i++) { -// equalCommands = this[i][0] === pathArray.value[i][0] -// } -// -// return equalCommands -// } -// -// // Make path array morphable -// morph (pathArray) { -// pathArray = new PathArray(pathArray) -// -// if (this.equalCommands(pathArray)) { -// this.destination = pathArray -// } else { -// this.destination = null -// } -// -// return this -// } -// -// // Get morphed path array at given position -// at (pos) { -// // make sure a destination is defined -// if (!this.destination) return this -// -// var sourceArray = this -// var destinationArray = this.destination.value -// var array = [] -// var pathArray = new PathArray() -// var i, il, j, jl -// -// // Animate has specified in the SVG spec -// // See: https://www.w3.org/TR/SVG11/paths.html#PathElement -// for (i = 0, il = sourceArray.length; i < il; i++) { -// array[i] = [sourceArray[i][0]] -// for (j = 1, jl = sourceArray[i].length; j < jl; j++) { -// array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos -// } -// // For the two flags of the elliptical arc command, the SVG spec say: -// // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true -// // Elliptical arc command as an array followed by corresponding indexes: -// // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] -// // 0 1 2 3 4 5 6 7 -// if (array[i][0] === 'A') { -// array[i][4] = +(array[i][4] !== 0) -// array[i][5] = +(array[i][5] !== 0) -// } -// } -// -// // Directly modify the value of a path array, this is done this way for performance -// pathArray.value = array -// return pathArray -// } -// -// // Absolutize and parse path to array -// parse (array) { -// // if it's already a patharray, no need to parse it -// if (array instanceof PathArray) return array.valueOf() -// -// // prepare for parsing -// var s -// var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 } -// -// if (typeof array === 'string') { -// array = array -// .replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 -// .replace(pathLetters, ' $& ') // put some room between letters and numbers -// .replace(hyphen, '$1 -') // add space before hyphen -// .trim() // trim -// .split(delimiter) // split into array -// } else { -// array = array.reduce(function (prev, curr) { -// return [].concat.call(prev, curr) -// }, []) -// } -// -// // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] -// var result = [] -// var p = new Point() -// var p0 = new Point() -// var index = 0 -// var len = array.length -// -// do { -// // Test if we have a path letter -// if (isPathLetter.test(array[index])) { -// s = array[index] -// ++index -// // If last letter was a move command and we got no new, it defaults to [L]ine -// } else if (s === 'M') { -// s = 'L' -// } else if (s === 'm') { -// s = 'l' -// } -// -// result.push(pathHandlers[s].call(null, -// array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), -// p, p0 -// ) -// ) -// } while (len > index) -// -// return result -// } -// -// // Get bounding box of path -// bbox () { -// parser().path.setAttribute('d', this.toString()) -// return parser.nodes.path.getBBox() -// } -// } diff --git a/src/Pattern.js b/src/Pattern.js index 6f56e58..4a3e1ad 100644 --- a/src/Pattern.js +++ b/src/Pattern.js @@ -39,7 +39,6 @@ export default class Pattern extends Container { attr (a, b, c) { if (a === 'transform') a = 'patternTransform' return super.attr(a, b, c) - // return attr.call(this, a, b, c) } targets () { diff --git a/src/PointArray.js b/src/PointArray.js index 68aeddc..42299e0 100644 --- a/src/PointArray.js +++ b/src/PointArray.js @@ -118,127 +118,3 @@ extend(PointArray, { return { x: minX, y: minY, width: maxX - minX, height: maxY - minY } } }) - -// export default class PointArray extends SVGArray { -// constructor (array, fallback = [[0, 0]]) { -// super(array, fallback) -// } -// -// // Convert array to string -// toString () { -// // convert to a poly point string -// for (var i = 0, il = this.length, array = []; i < il; i++) { -// array.push(this[i].join(',')) -// } -// -// return array.join(' ') -// } -// -// // toArray () { -// // return this.reduce(function (prev, curr) { -// // return [].concat.call(prev, curr) -// // }, []) -// // } -// -// // Convert array to line object -// toLine () { -// return { -// x1: this[0][0], -// y1: this[0][1], -// x2: this[1][0], -// y2: this[1][1] -// } -// } -// -// // Get morphed array at given position -// at (pos) { -// // make sure a destination is defined -// if (!this.destination) return this -// -// // generate morphed point string -// for (var i = 0, il = this.length, array = []; i < il; i++) { -// array.push([ -// this[i][0] + (this.destination[i][0] - this[i][0]) * pos, -// this[i][1] + (this.destination[i][1] - this[i][1]) * pos -// ]) -// } -// -// return new PointArray(array) -// } -// -// // Parse point string and flat array -// parse (array) { -// var points = [] -// -// array = array.valueOf() -// -// // if it is an array -// if (Array.isArray(array)) { -// // and it is not flat, there is no need to parse it -// if (Array.isArray(array[0])) { -// return array -// } -// } else { // Else, it is considered as a string -// // parse points -// array = array.trim().split(delimiter).map(parseFloat) -// } -// -// // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints -// // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. -// if (array.length % 2 !== 0) array.pop() -// -// // wrap points in two-tuples and parse points as floats -// for (var i = 0, len = array.length; i < len; i = i + 2) { -// points.push([ array[i], array[i + 1] ]) -// } -// -// return points -// } -// -// // Move point string -// move (x, y) { -// var box = this.bbox() -// -// // get relative offset -// x -= box.x -// y -= box.y -// -// // move every point -// if (!isNaN(x) && !isNaN(y)) { -// for (var i = this.length - 1; i >= 0; i--) { -// this[i] = [this[i][0] + x, this[i][1] + y] -// } -// } -// -// return this -// } -// -// // Resize poly string -// size (width, height) { -// var i -// var box = this.bbox() -// -// // recalculate position of all points according to new size -// for (i = this.length - 1; i >= 0; i--) { -// if (box.width) this[i][0] = ((this[i][0] - box.x) * width) / box.width + box.x -// if (box.height) this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y -// } -// -// return this -// } -// -// // Get bounding box of points -// bbox () { -// var maxX = -Infinity -// var maxY = -Infinity -// var minX = Infinity -// var minY = Infinity -// this.forEach(function (el) { -// maxX = Math.max(el[0], maxX) -// maxY = Math.max(el[1], maxY) -// minX = Math.min(el[0], minX) -// minY = Math.min(el[1], minY) -// }) -// return {x: minX, y: minY, width: maxX - minX, height: maxY - minY} -// } -// } diff --git a/src/SVGArray.js b/src/SVGArray.js index 247f0b2..351e166 100644 --- a/src/SVGArray.js +++ b/src/SVGArray.js @@ -10,15 +10,11 @@ export default SVGArray extend(SVGArray, { init (...args) { - // this.splice(0, this.length) this.length = 0 this.push(...this.parse(...args)) }, toArray () { - // const ret = [] - // ret.push(...this) - // return ret return Array.prototype.concat.apply([], this) }, @@ -31,13 +27,10 @@ extend(SVGArray, { const ret = [] ret.push(...this) return ret - // return this.toArray() }, // Parse whitespace separated string parse (array = []) { - // array = array.valueOf() - // If already is an array, no need to parse it if (array instanceof Array) return array @@ -52,46 +45,3 @@ extend(SVGArray, { return new Set(this) } }) - -// export default class SVGArray extends BaseArray { -// constructor (...args) { -// super() -// this.init(...args) -// } -// -// init (array, fallback = []) { -// //this.splice(0, this.length) -// this.length = 0 -// this.push(...this.parse(array || fallback)) -// } -// -// toArray () { -// return [].concat(this) -// } -// -// toString () { -// return this.join(' ') -// } -// -// valueOf () { -// return this.toArray() -// } -// -// // Parse whitespace separated string -// parse (array) { -// array = array.valueOf() -// -// // if already is an array, no need to parse it -// if (Array.isArray(array)) return array -// -// return array.trim().split(delimiter).map(parseFloat) -// } -// -// clone () { -// return new this.constructor(this) -// } -// -// toSet () { -// return new Set(this) -// } -// } diff --git a/src/attr.js b/src/attr.js index cccc340..f3aa230 100644 --- a/src/attr.js +++ b/src/attr.js @@ -79,5 +79,3 @@ export default function attr (attr, val, ns) { return this } - -// registerMethods('Element', {attr}) diff --git a/src/classes.js b/src/classes.js index a4cc758..8e1b866 100644 --- a/src/classes.js +++ b/src/classes.js @@ -1,87 +1,44 @@ -export { default as EventTarget } from './EventTarget.js' -export { default as Dom } from './Dom.js' -export { default as Element } from './Element.js' -export { default as Shape } from './Shape.js' -export { default as Container } from './Container.js' -export { default as HtmlNode } from './HtmlNode.js' -export { default as Doc } from './Doc.js' -export { default as Defs } from './Defs.js' -export { default as G } from './G.js' export { default as Animator } from './Animator.js' +export { default as SVGArray } from './SVGArray.js' export { default as Bare } from './Bare.js' +export { default as Box } from './Box.js' export { default as Circle } from './Circle.js' export { default as ClipPath } from './ClipPath.js' -export { default as A } from './A.js' +export { default as Color } from './Color.js' +export { default as Container } from './Container.js' +export { Controller, Ease, PID, Spring } from './Controller.js' +export { default as Defs } from './Defs.js' +export { default as Doc } from './Doc.js' +export { default as Dom } from './Dom.js' +export { default as Element } from './Element.js' export { default as Ellipse } from './Ellipse.js' -export { default as Stop } from './Stop.js' +export { default as EventTarget } from './EventTarget.js' export { default as Gradient } from './Gradient.js' +export { default as G } from './G.js' +export { default as HtmlNode } from './HtmlNode.js' +export { default as A } from './A.js' export { default as Image } from './Image.js' export { default as Line } from './Line.js' export { default as Marker } from './Marker.js' export { default as Mask } from './Mask.js' +export { default as Matrix } from './Matrix.js' +export { default as Morphable } from './Morphable.js' +export { default as SVGNumber } from './SVGNumber.js' export { default as Path } from './Path.js' +export { default as PathArray } from './PathArray.js' export { default as Pattern } from './Pattern.js' +export { default as Point } from './Point.js' +export { default as PointArray } from './PointArray.js' export { default as Polygon } from './Polygon.js' export { default as Polyline } from './Polyline.js' +export { default as Queue } from './Queue.js' export { default as Rect } from './Rect.js' +export { default as Runner } from './Runner.js' +export { default as Shape } from './Shape.js' +export { default as Stop } from './Stop.js' export { default as Symbol } from './Symbol.js' export { default as Text } from './Text.js' export { default as TextPath } from './TextPath.js' +export { default as Timeline } from './Timeline.js' export { default as Tspan } from './Tspan.js' export { default as Use } from './Use.js' -export { default as SVGNumber } from './SVGNumber.js' -export { default as SVGArray } from './SVGArray.js' -export { default as PathArray } from './PathArray.js' -export { default as PointArray } from './PointArray.js' -export { default as Matrix } from './Matrix.js' -export { default as Point } from './Point.js' -export { default as Box } from './Box.js' -export { default as Color } from './Color.js' -export { default as Morphable } from './Morphable.js' -export { default as Queue } from './Queue.js' -export { default as Runner } from './Runner.js' -export { default as Timeline } from './Timeline.js' -export { Controller, Ease, PID, Spring } from './Controller.js' - -// export {default as Animator} from './Animator.js' -// export {default as SVGArray} from './SVGArray.js' -// export {default as Bare} from './Bare.js' -// export {default as Box} from './Box.js' -// export {default as Circle} from './Circle.js' -// export {default as ClipPath} from './ClipPath.js' -// export {default as Color} from './Color.js' -// export {default as Container} from './Container.js' -// export {Controller, Ease, PID, Spring} from './Controller.js' -// export {default as Defs} from './Defs.js' -// export {default as Doc} from './Doc.js' -// export {default as Element} from './Element.js' -// export {default as Ellipse} from './Ellipse.js' -// export {default as EventTarget} from './EventTarget.js' -// export {default as Gradient} from './Gradient.js' -// export {default as G} from './G.js' -// export {default as HtmlNode} from './HtmlNode.js' -// export {default as A} from './A.js' -// export {default as Image} from './Image.js' -// export {default as Line} from './Line.js' -// export {default as Marker} from './Marker.js' -// export {default as Mask} from './Mask.js' -// export {default as Matrix} from './Matrix.js' -// export {default as Morphable} from './Morphable.js' -// export {default as SVGNumber} from './SVGNumber.js' -// export {default as Path} from './Path.js' -// export {default as PathArray} from './PathArray.js' -// export {default as Pattern} from './Pattern.js' -// export {default as Point} from './Point.js' -// export {default as PointArray} from './PointArray.js' -// export {default as Polygon} from './Polygon.js' -// export {default as Polyline} from './Polyline.js' -// export {default as Queue} from './Queue.js' -// export {default as Rect} from './Rect.js' -// export {default as Runner} from './Runner.js' -// export {default as Shape} from './Shape.js' -// export {default as Stop} from './Stop.js' -// export {default as Symbol} from './Symbol.js' -// export {default as Text} from './Text.js' -// export {default as TextPath} from './TextPath.js' -// export {default as Timeline} from './Timeline.js' -// export {default as Use} from './Use.js' diff --git a/src/containers.js b/src/containers.js deleted file mode 100644 index 02869e4..0000000 --- a/src/containers.js +++ /dev/null @@ -1,15 +0,0 @@ -export { default as Bare } from './Bare.js' -export { default as ClipPath } from './ClipPath.js' -export { default as Defs } from './Defs.js' -export { default as Doc } from './Doc.js' -export { default as Gradient } from './Gradient.js' -export { default as G } from './G.js' -export { default as A } from './A.js' -export { default as Marker } from './Marker.js' -export { default as Mask } from './Mask.js' -export { default as Pattern } from './Pattern.js' -export { default as Symbol } from './Symbol.js' - -export { default as Text } from './Text.js' -export { default as Tspan } from './Tspan.js' -export { default as TextPath } from './TextPath.js' diff --git a/src/elements.js b/src/elements.js deleted file mode 100644 index b09d6e8..0000000 --- a/src/elements.js +++ /dev/null @@ -1,25 +0,0 @@ -export { default as Bare } from './Bare.js' -export { default as Circle } from './Circle.js' -export { default as ClipPath } from './ClipPath.js' -export { default as Defs } from './Defs.js' -export { default as Doc } from './Doc.js' -export { default as Ellipse } from './Ellipse.js' -export { default as Gradient } from './Gradient.js' -export { default as G } from './G.js' -export { default as HtmlNode } from './HtmlNode.js' -export { default as A } from './A.js' -export { default as Image } from './Image.js' -export { default as Line } from './Line.js' -export { default as Marker } from './Marker.js' -export { default as Mask } from './Mask.js' -export { default as Path } from './Path.js' -export { default as Pattern } from './Pattern.js' -export { default as Polygon } from './Polygon.js' -export { default as Polyline } from './Polyline.js' -export { default as Rect } from './Rect.js' -export { default as Stop } from './Stop.js' -export { default as Symbol } from './Symbol.js' -export { default as Text } from './Text.js' -export { default as TextPath } from './TextPath.js' -export { default as Tspan } from './Tspan.js' -export { default as Use } from './Use.js' diff --git a/src/event.js b/src/event.js index 8cd4188..d3cf26d 100644 --- a/src/event.js +++ b/src/event.js @@ -27,12 +27,6 @@ export function on (node, events, listener, binding, options) { // events can be an array of events or a string of events events = Array.isArray(events) ? events : events.split(delimiter) - // ensure instance object for nodes which are not adopted - // n.instance = n.instance || {events: {}} - - // pull event handlers from the element - // var bag = n.instance.events - // add id to listener if (!listener._svgjsListenerId) { listener._svgjsListenerId = ++listenerId @@ -59,18 +53,12 @@ export function off (node, events, listener, options) { var bag = getEvents(node) var n = getEventTarget(node) - // we cannot remove an event if its not an svg.js instance - // if (!n.instance) return - // listener can be a function or a number if (typeof listener === 'function') { listener = listener._svgjsListenerId if (!listener) return } - // pull event handlers from the element - // var bag = n.instance.events - // events can be an array of events or a string or undefined events = Array.isArray(events) ? events : (events || '').split(delimiter) diff --git a/src/memory.js b/src/memory.js index 3f81c6f..9c826a2 100644 --- a/src/memory.js +++ b/src/memory.js @@ -1,10 +1,6 @@ import { registerMethods } from './methods.js' -// export const name = 'Memory' -// -// export function setup (node) { -// this._memory = {} -// } +// FIXME: We need a constructor to set this up // Remember arbitrary data export function remember (k, v) { @@ -42,4 +38,3 @@ export function memory () { } registerMethods('Dom', { remember, forget, memory }) -// registerConstructor('Memory', setup) diff --git a/src/methods.js b/src/methods.js index f926598..2373445 100644 --- a/src/methods.js +++ b/src/methods.js @@ -23,11 +23,6 @@ export function getMethodsFor (name) { return methods[name] || {} } -// FIXME: save memory? -// export function cleanMethods () { -// methods = {} -// } - export function registerConstructor (name, setup) { constructors[name] = setup } diff --git a/src/selector.js b/src/selector.js index 6ee1207..7208153 100644 --- a/src/selector.js +++ b/src/selector.js @@ -2,29 +2,6 @@ import { map } from './utils.js' import { adopt } from './adopter.js' import { registerMethods } from './methods.js' -// // Method for getting an element by id -// SVG.get = function (id) { -// var node = document.getElementById(idFromReference(id) || id) -// 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.$$ = function (query, parent) { -// return SVG.utils.map((parent || document).querySelectorAll(query), function (node) { -// return SVG.adopt(node) -// }) -// } -// -// SVG.$ = function (query, parent) { -// return SVG.adopt((parent || document).querySelector(query)) -// } - export default function baseFind (query, parent) { return map((parent || document).querySelectorAll(query), function (node) { return adopt(node) -- cgit v1.2.3 From a0b13ebcacfd74b9f521110c7225bb404325bcd3 Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Tue, 6 Nov 2018 13:48:05 +0100 Subject: reordered modules, add es6 build --- .gitignore | 3 +- dist/svg.es6.js | 6682 +++++++++++++++++++++++++++++ dist/svg.js | 8481 ++++++++++++++++++------------------- dist/svg.min.js | 2 +- package.json | 3 +- rollup.config.js | 14 + src/A.js | 44 - src/Animator.js | 85 - src/ArrayPolyfill.js | 30 - src/Bare.js | 31 - src/Base.js | 10 - src/Box.js | 127 - src/Circle.js | 41 - src/ClipPath.js | 59 - src/Color.js | 130 - src/Container.js | 26 - src/Controller.js | 174 - src/Defs.js | 14 - src/Doc.js | 73 - src/Dom.js | 238 -- src/Element.js | 138 - src/Ellipse.js | 22 - src/EventTarget.js | 90 - src/G.js | 21 - src/Gradient.js | 79 - src/HtmlNode.js | 10 - src/Image.js | 69 - src/Line.js | 64 - src/Marker.js | 82 - src/Mask.js | 59 - src/Matrix.js | 502 --- src/Morphable.js | 240 -- src/Path.js | 82 - src/PathArray.js | 291 -- src/Pattern.js | 73 - src/Point.js | 54 - src/PointArray.js | 120 - src/Polygon.js | 28 - src/Polyline.js | 28 - src/Queue.js | 59 - src/Rect.js | 33 - src/Runner.js | 936 ---- src/SVGArray.js | 47 - src/SVGNumber.js | 87 - src/Shape.js | 2 - src/Stop.js | 30 - src/Symbol.js | 21 - src/Text.js | 178 - src/TextPath.js | 84 - src/Timeline.js | 271 -- src/Tspan.js | 65 - src/Use.js | 28 - src/adopter.js | 92 - src/animation/Animator.js | 85 + src/animation/Controller.js | 173 + src/animation/Queue.js | 59 + src/animation/Runner.js | 928 ++++ src/animation/Timeline.js | 271 ++ src/arrange.js | 99 - src/attr.js | 81 - src/circled.js | 64 - src/classHandling.js | 44 - src/classes.js | 44 - src/css.js | 72 - src/data.js | 26 - src/defaults.js | 48 - src/elements/A.js | 43 + src/elements/Bare.js | 30 + src/elements/Circle.js | 40 + src/elements/ClipPath.js | 57 + src/elements/Container.js | 27 + src/elements/Defs.js | 13 + src/elements/Doc.js | 72 + src/elements/Dom.js | 242 ++ src/elements/Element.js | 142 + src/elements/Ellipse.js | 21 + src/elements/G.js | 20 + src/elements/Gradient.js | 77 + src/elements/HtmlNode.js | 10 + src/elements/Image.js | 68 + src/elements/Line.js | 63 + src/elements/Marker.js | 81 + src/elements/Mask.js | 57 + src/elements/Path.js | 81 + src/elements/Pattern.js | 71 + src/elements/Polygon.js | 27 + src/elements/Polyline.js | 27 + src/elements/Rect.js | 32 + src/elements/Shape.js | 3 + src/elements/Stop.js | 29 + src/elements/Symbol.js | 20 + src/elements/Text.js | 177 + src/elements/TextPath.js | 83 + src/elements/Tspan.js | 64 + src/elements/Use.js | 27 + src/event.js | 119 - src/gradiented.js | 14 - src/helpers.js | 206 - src/main.js | 163 + src/memory.js | 40 - src/methods.js | 32 - src/modules/core/attr.js | 80 + src/modules/core/circled.js | 64 + src/modules/core/defaults.js | 48 + src/modules/core/event.js | 119 + src/modules/core/gradiented.js | 14 + src/modules/core/namespaces.js | 5 + src/modules/core/parser.js | 26 + src/modules/core/pointed.js | 25 + src/modules/core/poly.js | 31 + src/modules/core/regex.js | 58 + src/modules/core/selector.js | 16 + src/modules/core/textable.js | 18 + src/modules/optional/arrange.js | 98 + src/modules/optional/class.js | 44 + src/modules/optional/css.js | 71 + src/modules/optional/data.js | 26 + src/modules/optional/memory.js | 39 + src/modules/optional/sugar.js | 159 + src/modules/optional/transform.js | 72 + src/namespaces.js | 5 - src/parser.js | 25 - src/pointed.js | 25 - src/poly.js | 32 - src/regex.js | 58 - src/selector.js | 16 - src/set.js | 18 - src/sugar.js | 159 - src/svg.js | 101 +- src/textable.js | 18 - src/tools.js | 56 - src/transform.js | 72 - src/types/ArrayPolyfill.js | 30 + src/types/Base.js | 10 + src/types/Box.js | 147 + src/types/Color.js | 146 + src/types/EventTarget.js | 90 + src/types/Matrix.js | 522 +++ src/types/Morphable.js | 244 ++ src/types/PathArray.js | 337 ++ src/types/Point.js | 54 + src/types/PointArray.js | 120 + src/types/SVGArray.js | 47 + src/types/SVGNumber.js | 87 + src/types/set.js | 18 + src/utils.js | 40 - src/utils/adopter.js | 115 + src/utils/methods.js | 32 + src/utils/utils.js | 96 + 149 files changed, 17398 insertions(+), 10859 deletions(-) create mode 100644 dist/svg.es6.js delete mode 100644 src/A.js delete mode 100644 src/Animator.js delete mode 100644 src/ArrayPolyfill.js delete mode 100644 src/Bare.js delete mode 100644 src/Base.js delete mode 100644 src/Box.js delete mode 100644 src/Circle.js delete mode 100644 src/ClipPath.js delete mode 100644 src/Color.js delete mode 100644 src/Container.js delete mode 100644 src/Controller.js delete mode 100644 src/Defs.js delete mode 100644 src/Doc.js delete mode 100644 src/Dom.js delete mode 100644 src/Element.js delete mode 100644 src/Ellipse.js delete mode 100644 src/EventTarget.js delete mode 100644 src/G.js delete mode 100644 src/Gradient.js delete mode 100644 src/HtmlNode.js delete mode 100644 src/Image.js delete mode 100644 src/Line.js delete mode 100644 src/Marker.js delete mode 100644 src/Mask.js delete mode 100644 src/Matrix.js delete mode 100644 src/Morphable.js delete mode 100644 src/Path.js delete mode 100644 src/PathArray.js delete mode 100644 src/Pattern.js delete mode 100644 src/Point.js delete mode 100644 src/PointArray.js delete mode 100644 src/Polygon.js delete mode 100644 src/Polyline.js delete mode 100644 src/Queue.js delete mode 100644 src/Rect.js delete mode 100644 src/Runner.js delete mode 100644 src/SVGArray.js delete mode 100644 src/SVGNumber.js delete mode 100644 src/Shape.js delete mode 100644 src/Stop.js delete mode 100644 src/Symbol.js delete mode 100644 src/Text.js delete mode 100644 src/TextPath.js delete mode 100644 src/Timeline.js delete mode 100644 src/Tspan.js delete mode 100644 src/Use.js delete mode 100644 src/adopter.js create mode 100644 src/animation/Animator.js create mode 100644 src/animation/Controller.js create mode 100644 src/animation/Queue.js create mode 100644 src/animation/Runner.js create mode 100644 src/animation/Timeline.js delete mode 100644 src/arrange.js delete mode 100644 src/attr.js delete mode 100644 src/circled.js delete mode 100644 src/classHandling.js delete mode 100644 src/classes.js delete mode 100644 src/css.js delete mode 100644 src/data.js delete mode 100644 src/defaults.js create mode 100644 src/elements/A.js create mode 100644 src/elements/Bare.js create mode 100644 src/elements/Circle.js create mode 100644 src/elements/ClipPath.js create mode 100644 src/elements/Container.js create mode 100644 src/elements/Defs.js create mode 100644 src/elements/Doc.js create mode 100644 src/elements/Dom.js create mode 100644 src/elements/Element.js create mode 100644 src/elements/Ellipse.js create mode 100644 src/elements/G.js create mode 100644 src/elements/Gradient.js create mode 100644 src/elements/HtmlNode.js create mode 100644 src/elements/Image.js create mode 100644 src/elements/Line.js create mode 100644 src/elements/Marker.js create mode 100644 src/elements/Mask.js create mode 100644 src/elements/Path.js create mode 100644 src/elements/Pattern.js create mode 100644 src/elements/Polygon.js create mode 100644 src/elements/Polyline.js create mode 100644 src/elements/Rect.js create mode 100644 src/elements/Shape.js create mode 100644 src/elements/Stop.js create mode 100644 src/elements/Symbol.js create mode 100644 src/elements/Text.js create mode 100644 src/elements/TextPath.js create mode 100644 src/elements/Tspan.js create mode 100644 src/elements/Use.js delete mode 100644 src/event.js delete mode 100644 src/gradiented.js delete mode 100644 src/helpers.js create mode 100644 src/main.js delete mode 100644 src/memory.js delete mode 100644 src/methods.js create mode 100644 src/modules/core/attr.js create mode 100644 src/modules/core/circled.js create mode 100644 src/modules/core/defaults.js create mode 100644 src/modules/core/event.js create mode 100644 src/modules/core/gradiented.js create mode 100644 src/modules/core/namespaces.js create mode 100644 src/modules/core/parser.js create mode 100644 src/modules/core/pointed.js create mode 100644 src/modules/core/poly.js create mode 100644 src/modules/core/regex.js create mode 100644 src/modules/core/selector.js create mode 100644 src/modules/core/textable.js create mode 100644 src/modules/optional/arrange.js create mode 100644 src/modules/optional/class.js create mode 100644 src/modules/optional/css.js create mode 100644 src/modules/optional/data.js create mode 100644 src/modules/optional/memory.js create mode 100644 src/modules/optional/sugar.js create mode 100644 src/modules/optional/transform.js delete mode 100644 src/namespaces.js delete mode 100644 src/parser.js delete mode 100644 src/pointed.js delete mode 100644 src/poly.js delete mode 100644 src/regex.js delete mode 100644 src/selector.js delete mode 100644 src/set.js delete mode 100644 src/sugar.js delete mode 100644 src/textable.js delete mode 100644 src/tools.js delete mode 100644 src/transform.js create mode 100644 src/types/ArrayPolyfill.js create mode 100644 src/types/Base.js create mode 100644 src/types/Box.js create mode 100644 src/types/Color.js create mode 100644 src/types/EventTarget.js create mode 100644 src/types/Matrix.js create mode 100644 src/types/Morphable.js create mode 100644 src/types/PathArray.js create mode 100644 src/types/Point.js create mode 100644 src/types/PointArray.js create mode 100644 src/types/SVGArray.js create mode 100644 src/types/SVGNumber.js create mode 100644 src/types/set.js delete mode 100644 src/utils.js create mode 100644 src/utils/adopter.js create mode 100644 src/utils/methods.js create mode 100644 src/utils/utils.js (limited to 'src') diff --git a/.gitignore b/.gitignore index f58d182..ebf7883 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store .idea +.importjs.js public site/ bleed/ @@ -10,4 +11,4 @@ src/index.js node_modules/ .vscode/ coverage/ -fonts/ \ No newline at end of file +fonts/ diff --git a/dist/svg.es6.js b/dist/svg.es6.js new file mode 100644 index 0000000..6188915 --- /dev/null +++ b/dist/svg.es6.js @@ -0,0 +1,6682 @@ +/*! +* svg.js - A lightweight library for manipulating and animating SVG. +* @version 3.0.0 +* https://svgdotjs.github.io/ +* +* @copyright Wout Fierens +* @license MIT +* +* BUILT: Tue Nov 06 2018 13:43:56 GMT+0100 (GMT+01:00) +*/; +function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); +} + +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } +} + +function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; +} + +function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +} + +function _objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + var ownKeys = Object.keys(source); + + if (typeof Object.getOwnPropertySymbols === 'function') { + ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + + ownKeys.forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } + + return target; +} + +function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); +} + +function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); +} + +function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); +} + +function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; +} + +function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); +} + +function _superPropBase(object, property) { + while (!Object.prototype.hasOwnProperty.call(object, property)) { + object = _getPrototypeOf(object); + if (object === null) break; + } + + return object; +} + +function _get(target, property, receiver) { + if (typeof Reflect !== "undefined" && Reflect.get) { + _get = Reflect.get; + } else { + _get = function _get(target, property, receiver) { + var base = _superPropBase(target, property); + + if (!base) return; + var desc = Object.getOwnPropertyDescriptor(base, property); + + if (desc.get) { + return desc.get.call(receiver); + } + + return desc.value; + }; + } + + return _get(target, property, receiver || target); +} + +function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); +} + +function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); +} + +function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } +} + +function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; +} + +function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); +} + +function _iterableToArrayLimit(arr, i) { + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; +} + +function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); +} + +function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); +} + +var methods = {}; +function registerMethods(name, m) { + if (Array.isArray(name)) { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = name[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var _name = _step.value; + registerMethods(_name, m); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + return; + } + + if (_typeof(name) === 'object') { + var _arr = Object.entries(name); + + for (var _i = 0; _i < _arr.length; _i++) { + var _arr$_i = _slicedToArray(_arr[_i], 2), + _name2 = _arr$_i[0], + _m = _arr$_i[1]; + + registerMethods(_name2, _m); + } + + return; + } + + methods[name] = Object.assign(methods[name] || {}, m); +} +function getMethodsFor(name) { + return methods[name] || {}; +} + +function siblings() { + return this.parent().children(); +} // Get the curent position siblings + +function position() { + return this.parent().index(this); +} // Get the next element (will return null if there is none) + +function next() { + return this.siblings()[this.position() + 1]; +} // Get the next element (will return null if there is none) + +function prev() { + return this.siblings()[this.position() - 1]; +} // Send given element one step forward + +function forward() { + var i = this.position() + 1; + 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); + } + + return this; +} // Send given element one step backward + +function backward() { + var i = this.position(); + + if (i > 0) { + this.parent().removeElement(this).add(this, i - 1); + } + + return this; +} // Send given element all the way to the front + +function front() { + var p = this.parent(); // Move node forward + + p.node.appendChild(this.node); // Make sure defs node is always at the top + + if (typeof p.isRoot === 'function' && p.isRoot()) { + p.node.appendChild(p.defs().node); + } + + return this; +} // Send given element all the way to the back + +function back() { + if (this.position() > 0) { + this.parent().removeElement(this).add(this, 0); + } + + return this; +} // Inserts a given element before the targeted element + +function before(element) { + element.remove(); + var i = this.position(); + this.parent().add(element, i); + return this; +} // Inserts a given element after the targeted element + +function after(element) { + element.remove(); + var i = this.position(); + this.parent().add(element, i + 1); + return this; +} +registerMethods('Dom', { + siblings: siblings, + position: position, + next: next, + prev: prev, + forward: forward, + backward: backward, + front: front, + back: back, + before: before, + after: after +}); + +// Parse unit value +var numberAndUnit = /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i; // Parse hex value + +var hex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i; // Parse rgb value + +var rgb = /rgb\((\d+),(\d+),(\d+)\)/; // Parse reference id + +var reference = /(#[a-z0-9\-_]+)/i; // splits a transformation chain + +var transforms = /\)\s*,?\s*/; // Whitespace + +var whitespace = /\s/g; // Test hex value + +var isHex = /^#[a-f0-9]{3,6}$/i; // Test rgb value + +var isRgb = /^rgb\(/; // Test css declaration + +var isBlank = /^(\s+)?$/; // Test for numeric string + +var isNumber = /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i; // Test for percent value + +var isImage = /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i; // split at whitespace and comma + +var delimiter = /[\s,]+/; // The following regex are used to parse the d attribute of a path +// Matches all hyphens which are not after an exponent + +var hyphen = /([^e])-/gi; // Replaces and tests for all path letters + +var pathLetters = /[MLHVCSQTAZ]/gi; // yes we need this one, too + +var isPathLetter = /[MLHVCSQTAZ]/i; // matches 0.154.23.45 + +var numbersWithDots = /((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi; // matches . + +var dots = /\./g; + +function classes() { + var attr = this.attr('class'); + return attr == null ? [] : attr.trim().split(delimiter); +} // Return true if class exists on the node, false otherwise + + +function hasClass(name) { + return this.classes().indexOf(name) !== -1; +} // Add class to the node + + +function addClass(name) { + if (!this.hasClass(name)) { + var array = this.classes(); + array.push(name); + this.attr('class', array.join(' ')); + } + + return this; +} // Remove class from the node + + +function removeClass(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 + + +function toggleClass(name) { + return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); +} + +registerMethods('Dom', { + classes: classes, + hasClass: hasClass, + addClass: addClass, + removeClass: removeClass, + toggleClass: toggleClass +}); + +// Map function +function map(array, block) { + var i; + var il = array.length; + var result = []; + + for (i = 0; i < il; i++) { + result.push(block(array[i])); + } + + return result; +} // Filter function + +function filter(array, block) { + var i; + var il = array.length; + var result = []; + + for (i = 0; i < il; i++) { + if (block(array[i])) { + result.push(array[i]); + } + } + + return result; +} // Degrees to radians + +function radians(d) { + return d % 360 * Math.PI / 180; +} // Radians to degrees + +function degrees(r) { + return r * 180 / Math.PI % 360; +} // Convert dash-separated-string to camelCase + +function camelCase(s) { + return s.toLowerCase().replace(/-(.)/g, function (m, g) { + return g.toUpperCase(); + }); +} // Capitalize first letter of a string + +function capitalize(s) { + return s.charAt(0).toUpperCase() + s.slice(1); +} // Calculate proportional width and height values when necessary + +function proportionalSize(element, width, height) { + if (width == null || height == null) { + var box = element.bbox(); + + if (width == null) { + width = box.width / box.height * height; + } else if (height == null) { + height = box.height / box.width * width; + } + } + + return { + width: width, + height: height + }; +} +function getOrigin(o, element) { + // Allow origin or around as the names + var origin = o.origin; // o.around == null ? o.origin : o.around + + var ox, oy; // Allow the user to pass a string to rotate around a given point + + if (typeof origin === 'string' || origin == null) { + // Get the bounding box of the element with no transformations applied + var string = (origin || 'center').toLowerCase().trim(); + + var _element$bbox = element.bbox(), + height = _element$bbox.height, + width = _element$bbox.width, + x = _element$bbox.x, + y = _element$bbox.y; // Calculate the transformed x and y coordinates + + + var bx = string.includes('left') ? x : string.includes('right') ? x + width : x + width / 2; + var by = string.includes('top') ? y : string.includes('bottom') ? y + height : y + height / 2; // Set the bounds eg : "bottom-left", "Top right", "middle" etc... + + ox = o.ox != null ? o.ox : bx; + oy = o.oy != null ? o.oy : by; + } else { + ox = origin[0]; + oy = origin[1]; + } // Return the origin as it is if it wasn't a string + + + return [ox, oy]; +} + +function css(style, val) { + var ret = {}; + + if (arguments.length === 0) { + // get full style as object + this.node.style.cssText.split(/\s*;\s*/).filter(function (el) { + return !!el.length; + }).forEach(function (el) { + var t = el.split(/\s*:\s*/); + ret[t[0]] = t[1]; + }); + return ret; + } + + if (arguments.length < 2) { + // get style properties in the array + if (Array.isArray(style)) { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = style[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var name = _step.value; + var cased = camelCase(name); + ret[cased] = this.node.style[cased]; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + return ret; + } // get style for property + + + if (typeof style === 'string') { + return this.node.style[camelCase(style)]; + } // set styles in object + + + if (_typeof(style) === 'object') { + for (var _name in style) { + // set empty string if null/undefined/'' was given + this.node.style[camelCase(_name)] = style[_name] == null || isBlank.test(style[_name]) ? '' : style[_name]; + } + } + } // set style for property + + + if (arguments.length === 2) { + this.node.style[camelCase(style)] = val == null || isBlank.test(val) ? '' : val; + } + + return this; +} // Show element + +function show() { + return this.css('display', ''); +} // Hide element + +function hide() { + return this.css('display', 'none'); +} // Is element visible? + +function visible() { + return this.css('display') !== 'none'; +} +registerMethods('Dom', { + css: css, + show: show, + hide: hide, + visible: visible +}); + +function data(a, v, r) { + if (_typeof(a) === 'object') { + for (v in a) { + this.data(v, a[v]); + } + } else if (arguments.length < 2) { + try { + return JSON.parse(this.attr('data-' + a)); + } catch (e) { + return this.attr('data-' + a); + } + } else { + this.attr('data-' + a, v === null ? null : r === true || typeof v === 'string' || typeof v === 'number' ? v : JSON.stringify(v)); + } + + return this; +} +registerMethods('Dom', { + data: data +}); + +// Remember arbitrary data + +function remember(k, v) { + // remember every item in an object individually + if (_typeof(arguments[0]) === 'object') { + for (var key in k) { + this.remember(key, k[key]); + } + } else if (arguments.length === 1) { + // retrieve memory + return this.memory()[k]; + } else { + // store memory + this.memory()[k] = v; + } + + return this; +} // Erase a given memory + +function forget() { + if (arguments.length === 0) { + this._memory = {}; + } else { + for (var i = arguments.length - 1; i >= 0; i--) { + delete this.memory()[arguments[i]]; + } + } + + return this; +} // return local memory object + +function memory() { + return this._memory = this._memory || {}; +} +registerMethods('Dom', { + remember: remember, + forget: forget, + memory: memory +}); + +function fullHex(hex$$1) { + return hex$$1.length === 4 ? ['#', hex$$1.substring(1, 2), hex$$1.substring(1, 2), hex$$1.substring(2, 3), hex$$1.substring(2, 3), hex$$1.substring(3, 4), hex$$1.substring(3, 4)].join('') : hex$$1; +} // Component to hex value + + +function compToHex(comp) { + var hex$$1 = comp.toString(16); + return hex$$1.length === 1 ? '0' + hex$$1 : hex$$1; +} + +var Color = +/*#__PURE__*/ +function () { + function Color() { + _classCallCheck(this, Color); + + this.init.apply(this, arguments); + } + + _createClass(Color, [{ + key: "init", + value: function init(color, g, b) { + var match; // initialize defaults + + this.r = 0; + this.g = 0; + this.b = 0; + if (!color) return; // parse color + + if (typeof color === 'string') { + if (isRgb.test(color)) { + // get rgb values + match = rgb.exec(color.replace(whitespace, '')); // parse numeric values + + this.r = parseInt(match[1]); + this.g = parseInt(match[2]); + this.b = parseInt(match[3]); + } else if (isHex.test(color)) { + // get hex values + match = hex.exec(fullHex(color)); // parse numeric values + + this.r = parseInt(match[1], 16); + this.g = parseInt(match[2], 16); + this.b = parseInt(match[3], 16); + } + } else if (Array.isArray(color)) { + this.r = color[0]; + this.g = color[1]; + this.b = color[2]; + } else if (_typeof(color) === 'object') { + this.r = color.r; + this.g = color.g; + this.b = color.b; + } else if (arguments.length === 3) { + this.r = color; + this.g = g; + this.b = b; + } + } // Default to hex conversion + + }, { + key: "toString", + value: function toString() { + return this.toHex(); + } + }, { + key: "toArray", + value: function toArray() { + return [this.r, this.g, this.b]; + } // Build hex value + + }, { + key: "toHex", + value: function toHex() { + return '#' + compToHex(Math.round(this.r)) + compToHex(Math.round(this.g)) + compToHex(Math.round(this.b)); + } // Build rgb value + + }, { + key: "toRgb", + value: function toRgb() { + return 'rgb(' + [this.r, this.g, this.b].join() + ')'; + } // Calculate true brightness + + }, { + key: "brightness", + value: function brightness() { + return this.r / 255 * 0.30 + this.g / 255 * 0.59 + this.b / 255 * 0.11; + } // Testers + // Test if given value is a color string + + }], [{ + key: "test", + value: function test(color) { + color += ''; + return isHex.test(color) || isRgb.test(color); + } // Test if given value is a rgb object + + }, { + key: "isRgb", + value: function isRgb$$1(color) { + return color && typeof color.r === 'number' && typeof color.g === 'number' && typeof color.b === 'number'; + } // Test if given value is a color + + }, { + key: "isColor", + value: function isColor(color) { + return this.isRgb(color) || this.test(color); + } + }]); + + return Color; +}(); + +// Default namespaces +var ns = 'http://www.w3.org/2000/svg'; +var xmlns = 'http://www.w3.org/2000/xmlns/'; +var xlink = 'http://www.w3.org/1999/xlink'; +var svgjs = 'http://svgjs.com/svgjs'; + +var Base = function Base() { + _classCallCheck(this, Base); +}; + +var elements = {}; +var root = Symbol('root'); // Method for element creation + +function makeNode(name) { + // create element + return document.createElementNS(ns, name); +} +function makeInstance(element) { + if (element instanceof Base) return element; + + if (_typeof(element) === 'object') { + return adopt(element); + } + + if (element == null) { + return new elements[root](); + } + + if (typeof element === 'string' && element.charAt(0) !== '<') { + return adopt(document.querySelector(element)); + } + + var node = makeNode('svg'); + node.innerHTML = element; // We can use firstChild here because we know, + // that the first char is < and thus an element + + element = adopt(node.firstChild); + return element; +} +function nodeOrNew(name, node) { + return node || makeNode(name); +} // Adopt existing svg elements + +function adopt(node) { + // check for presence of node + if (!node) return null; // make sure a node isn't already adopted + + if (node.instance instanceof Base) return node.instance; + + if (!(node instanceof window.SVGElement)) { + return new elements.HtmlNode(node); + } // initialize variables + + + var element; // adopt with element-specific settings + + if (node.nodeName === 'svg') { + element = new elements[root](node); + } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') { + element = new elements.Gradient(node); + } else if (elements[capitalize(node.nodeName)]) { + element = new elements[capitalize(node.nodeName)](node); + } else { + element = new elements.Bare(node); + } + + return element; +} +function register(element) { + var name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : element.name; + var asRoot = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + elements[name] = element; + if (asRoot) elements[root] = element; + return element; +} +function getClass(name) { + return elements[name]; +} // Element id sequence + +var did = 1000; // Get next named element id + +function eid(name) { + return 'Svgjs' + capitalize(name) + did++; +} // Deep new id assignment + +function assignNewId(node) { + // do the same for SVG child nodes as well + for (var i = node.children.length - 1; i >= 0; i--) { + assignNewId(node.children[i]); + } + + if (node.id) { + return adopt(node).id(eid(node.nodeName)); + } + + return adopt(node); +} // Method for extending objects + +function extend(modules, methods) { + var key, i; + modules = Array.isArray(modules) ? modules : [modules]; + + for (i = modules.length - 1; i >= 0; i--) { + for (key in methods) { + modules[i].prototype[key] = methods[key]; + } + } +} + +var listenerId = 0; + +function getEvents(node) { + var n = makeInstance(node).getEventHolder(); + if (!n.events) n.events = {}; + return n.events; +} + +function getEventTarget(node) { + return makeInstance(node).getEventTarget(); +} + +function clearEvents(node) { + var n = makeInstance(node).getEventHolder(); + if (n.events) n.events = {}; +} // Add event binder in the SVG namespace + + +function on(node, events, listener, binding, options) { + var l = listener.bind(binding || node); + var bag = getEvents(node); + var n = getEventTarget(node); // events can be an array of events or a string of events + + events = Array.isArray(events) ? events : events.split(delimiter); // add id to listener + + if (!listener._svgjsListenerId) { + listener._svgjsListenerId = ++listenerId; + } + + events.forEach(function (event) { + var ev = event.split('.')[0]; + var ns = event.split('.')[1] || '*'; // ensure valid object + + bag[ev] = bag[ev] || {}; + bag[ev][ns] = bag[ev][ns] || {}; // reference listener + + bag[ev][ns][listener._svgjsListenerId] = l; // add listener + + n.addEventListener(ev, l, options || false); + }); +} // Add event unbinder in the SVG namespace + +function off(node, events, listener, options) { + var bag = getEvents(node); + var n = getEventTarget(node); // listener can be a function or a number + + if (typeof listener === 'function') { + listener = listener._svgjsListenerId; + if (!listener) return; + } // events can be an array of events or a string or undefined + + + events = Array.isArray(events) ? events : (events || '').split(delimiter); + events.forEach(function (event) { + var ev = event && event.split('.')[0]; + var ns = event && event.split('.')[1]; + var namespace, l; + + if (listener) { + // remove listener reference + if (bag[ev] && bag[ev][ns || '*']) { + // removeListener + n.removeEventListener(ev, bag[ev][ns || '*'][listener], options || false); + delete bag[ev][ns || '*'][listener]; + } + } else if (ev && ns) { + // remove all listeners for a namespaced event + if (bag[ev] && bag[ev][ns]) { + for (l in bag[ev][ns]) { + off(n, [ev, ns].join('.'), l); + } + + delete bag[ev][ns]; + } + } else if (ns) { + // remove all listeners for a specific namespace + for (event in bag) { + for (namespace in bag[event]) { + if (ns === namespace) { + off(n, [event, ns].join('.')); + } + } + } + } else if (ev) { + // remove all listeners for the event + if (bag[ev]) { + for (namespace in bag[ev]) { + off(n, [ev, namespace].join('.')); + } + + delete bag[ev]; + } + } else { + // remove all listeners on a given node + for (event in bag) { + off(n, event); + } + + clearEvents(node); + } + }); +} +function dispatch(node, event, data) { + var n = getEventTarget(node); // Dispatch event + + if (event instanceof window.Event) { + n.dispatchEvent(event); + } else { + event = new window.CustomEvent(event, { + detail: data, + cancelable: true + }); + n.dispatchEvent(event); + } + + return event; +} + +var EventTarget = +/*#__PURE__*/ +function (_Base) { + _inherits(EventTarget, _Base); + + function EventTarget() { + var _this; + + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + _ref$events = _ref.events, + events = _ref$events === void 0 ? {} : _ref$events; + + _classCallCheck(this, EventTarget); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(EventTarget).call(this)); + _this.events = events; + return _this; + } + + _createClass(EventTarget, [{ + key: "addEventListener", + value: function addEventListener() {} // Bind given event to listener + + }, { + key: "on", + value: function on$$1(event, listener, binding, options) { + on(this, event, listener, binding, options); + + return this; + } // Unbind event from listener + + }, { + key: "off", + value: function off$$1(event, listener) { + off(this, event, listener); + + return this; + } + }, { + key: "dispatch", + value: function dispatch$$1(event, data) { + return dispatch(this, event, data); + } + }, { + key: "dispatchEvent", + value: function dispatchEvent(event) { + var bag = this.getEventHolder().events; + if (!bag) return true; + var events = bag[event.type]; + + for (var i in events) { + for (var j in events[i]) { + events[i][j](event); + } + } + + return !event.defaultPrevented; + } // Fire given event + + }, { + key: "fire", + value: function fire(event, data) { + this.dispatch(event, data); + return this; + } + }, { + key: "getEventHolder", + value: function getEventHolder() { + return this; + } + }, { + key: "getEventTarget", + value: function getEventTarget() { + return this; + } + }, { + key: "removeEventListener", + value: function removeEventListener() {} + }]); + + return EventTarget; +}(Base); // Add events to elements +var methods$1 = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove', 'mouseenter', 'mouseleave', 'touchstart', 'touchmove', 'touchleave', 'touchend', 'touchcancel'].reduce(function (last, event) { + // add event to Element + var fn = function fn(f) { + if (f === null) { + off(this, event); + } else { + on(this, event, f); + } + + return this; + }; + + last[event] = fn; + return last; +}, {}); +registerMethods('Element', methods$1); + +function noop() {} // Default animation values + +var timeline = { + duration: 400, + ease: '>', + delay: 0 // Default attribute values + +}; +var attrs = { + // fill and stroke + 'fill-opacity': 1, + 'stroke-opacity': 1, + 'stroke-width': 0, + 'stroke-linejoin': 'miter', + 'stroke-linecap': 'butt', + fill: '#000000', + stroke: '#000000', + opacity: 1, + // position + x: 0, + y: 0, + cx: 0, + cy: 0, + // size + width: 0, + height: 0, + // radius + r: 0, + rx: 0, + ry: 0, + // gradient + offset: 0, + 'stop-opacity': 1, + 'stop-color': '#000000', + // text + 'font-size': 16, + 'font-family': 'Helvetica, Arial, sans-serif', + 'text-anchor': 'start' +}; + +var defaults = /*#__PURE__*/Object.freeze({ + noop: noop, + timeline: timeline, + attrs: attrs +}); + +/* eslint no-new-func: "off" */ +var subClassArray = function () { + try { + // try es6 subclassing + return Function('name', 'baseClass', '_constructor', ['baseClass = baseClass || Array', 'return {', '[name]: class extends baseClass {', 'constructor (...args) {', 'super(...args)', '_constructor && _constructor.apply(this, args)', '}', '}', '}[name]'].join('\n')); + } catch (e) { + // Use es5 approach + return function (name) { + var baseClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Array; + + var _constructor = arguments.length > 2 ? arguments[2] : undefined; + + var Arr = function Arr() { + baseClass.apply(this, arguments); + _constructor && _constructor.apply(this, arguments); + }; + + Arr.prototype = Object.create(baseClass.prototype); + Arr.prototype.constructor = Arr; + return Arr; + }; + } +}(); + +var SVGArray = subClassArray('SVGArray', Array, function (arr) { + this.init(arr); +}); +extend(SVGArray, { + init: function init(arr) { + this.length = 0; + this.push.apply(this, _toConsumableArray(this.parse(arr))); + }, + toArray: function toArray() { + return Array.prototype.concat.apply([], this); + }, + toString: function toString() { + return this.join(' '); + }, + // Flattens the array if needed + valueOf: function valueOf() { + var ret = []; + ret.push.apply(ret, _toConsumableArray(this)); + return ret; + }, + // Parse whitespace separated string + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + // If already is an array, no need to parse it + if (array instanceof Array) return array; + return array.trim().split(delimiter).map(parseFloat); + }, + clone: function clone() { + return new this.constructor(this); + }, + toSet: function toSet() { + return new Set(this); + } +}); + +var SVGNumber = +/*#__PURE__*/ +function () { + // Initialize + function SVGNumber() { + _classCallCheck(this, SVGNumber); + + this.init.apply(this, arguments); + } + + _createClass(SVGNumber, [{ + key: "init", + value: function init(value, unit) { + unit = Array.isArray(value) ? value[1] : unit; + value = Array.isArray(value) ? value[0] : value; // initialize defaults + + this.value = 0; + this.unit = unit || ''; // parse value + + if (typeof value === 'number') { + // ensure a valid numeric value + this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; + } else if (typeof value === 'string') { + unit = value.match(numberAndUnit); + + if (unit) { + // make value numeric + this.value = parseFloat(unit[1]); // normalize + + if (unit[5] === '%') { + this.value /= 100; + } else if (unit[5] === 's') { + this.value *= 1000; + } // store unit + + + this.unit = unit[5]; + } + } else { + if (value instanceof SVGNumber) { + this.value = value.valueOf(); + this.unit = value.unit; + } + } + } + }, { + key: "toString", + value: function toString() { + return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; + } + }, { + key: "toJSON", + value: function toJSON() { + return this.toString(); + } + }, { + key: "toArray", + value: function toArray() { + return [this.value, this.unit]; + } + }, { + key: "valueOf", + value: function valueOf() { + return this.value; + } // Add number + + }, { + key: "plus", + value: function plus(number) { + number = new SVGNumber(number); + return new SVGNumber(this + number, this.unit || number.unit); + } // Subtract number + + }, { + key: "minus", + value: function minus(number) { + number = new SVGNumber(number); + return new SVGNumber(this - number, this.unit || number.unit); + } // Multiply number + + }, { + key: "times", + value: function times(number) { + number = new SVGNumber(number); + return new SVGNumber(this * number, this.unit || number.unit); + } // Divide number + + }, { + key: "divide", + value: function divide(number) { + number = new SVGNumber(number); + return new SVGNumber(this / number, this.unit || number.unit); + } + }]); + + return SVGNumber; +}(); + +function attr(attr, val, ns) { + // act as full getter + if (attr == null) { + // get an object of attributes + attr = {}; + val = this.node.attributes; + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = val[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var node = _step.value; + attr[node.nodeName] = isNumber.test(node.nodeValue) ? parseFloat(node.nodeValue) : node.nodeValue; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + return attr; + } else if (Array.isArray(attr)) ; else if (_typeof(attr) === 'object') { + // apply every attribute individually if an object is passed + for (val in attr) { + this.attr(val, attr[val]); + } + } else if (val === null) { + // remove value + this.node.removeAttribute(attr); + } else if (val == null) { + // act as a getter if the first and only argument is not an object + val = this.node.getAttribute(attr); + return val == null ? attrs[attr] // FIXME: do we need to return defaults? + : isNumber.test(val) ? parseFloat(val) : val; + } else { + // convert image fill and stroke to patterns + if (attr === 'fill' || attr === 'stroke') { + if (isImage.test(val)) { + val = this.doc().defs().image(val); + } + } // FIXME: This is fine, but what about the lines above? + // How does attr know about image()? + + + while (typeof val.attrHook === 'function') { + val = val.attrHook(this, attr); + } // ensure correct numeric values (also accepts NaN and Infinity) + + + if (typeof val === 'number') { + val = new SVGNumber(val); + } else if (Color.isColor(val)) { + // ensure full hex color + val = new Color(val); + } else if (val.constructor === Array) { + // Check for plain arrays and parse array values + val = new SVGArray(val); + } // if the passed attribute is leading... + + + if (attr === 'leading') { + // ... call the leading method instead + if (this.leading) { + this.leading(val); + } + } else { + // set given attribute on node + typeof ns === 'string' ? this.node.setAttributeNS(ns, attr, val.toString()) : this.node.setAttribute(attr, val.toString()); + } // rebuild if required + + + if (this.rebuild && (attr === 'font-size' || attr === 'x')) { + this.rebuild(); + } + } + + return this; +} + +var Dom = +/*#__PURE__*/ +function (_EventTarget) { + _inherits(Dom, _EventTarget); + + function Dom(node) { + var _this; + + _classCallCheck(this, Dom); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Dom).call(this, node)); + _this.node = node; + _this.type = node.nodeName; + return _this; + } // Add given element at a position + + + _createClass(Dom, [{ + key: "add", + value: function 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]); + } + + return this; + } // Add element to given container and return self + + }, { + key: "addTo", + value: function addTo(parent) { + return makeInstance(parent).put(this); + } // Returns all child elements + + }, { + key: "children", + value: function children() { + return map(this.node.children, function (node) { + return adopt(node); + }); + } // Remove all elements in this container + + }, { + key: "clear", + value: function clear() { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } // remove defs reference + + + delete this._defs; + return this; + } // Clone element + + }, { + key: "clone", + value: function clone(parent) { + // write dom data to the dom so the clone can pickup the data + this.writeDataToDom(); // 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); // FIXME: after might not be available here + else this.after(clone); + return clone; + } // Iterates over all children and invokes a given block + + }, { + key: "each", + value: function 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]); + + if (deep) { + children[i].each(block, deep); + } + } + + return this; + } // Get first child + + }, { + key: "first", + value: function first() { + return adopt(this.node.firstChild); + } // Get a element at the given index + + }, { + key: "get", + value: function get(i) { + return adopt(this.node.childNodes[i]); + } + }, { + key: "getEventHolder", + value: function getEventHolder() { + return this.node; + } + }, { + key: "getEventTarget", + value: function getEventTarget() { + return this.node; + } // Checks if the given element is a child + + }, { + key: "has", + value: function has(element) { + return this.index(element) >= 0; + } // Get / set id + + }, { + key: "id", + value: function id(_id) { + // generate new id if no id set + 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); + } // Gets index of given element + + }, { + key: "index", + value: function index(element) { + return [].slice.call(this.node.childNodes).indexOf(element.node); + } // Get the last child + + }, { + key: "last", + value: function last() { + return adopt(this.node.lastChild); + } // matches the element vs a css selector + + }, { + key: "matches", + value: function matches(selector) { + var el = this.node; + return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector); + } // Returns the svg node to call native svg methods on it + + }, { + key: "native", + value: function native() { + return this.node; + } // Returns the parent element instance + + }, { + key: "parent", + value: function parent(type) { + var parent = this; // check for parent + + if (!parent.node.parentNode) return null; // get parent element + + parent = adopt(parent.node.parentNode); + if (!type) return parent; // loop trough ancestors if type is given + + while (parent && parent.node instanceof window.SVGElement) { + 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 + + }, { + key: "put", + value: function put(element, i) { + this.add(element, i); + return element; + } // Add element to given container and return container + + }, { + key: "putIn", + value: function putIn(parent) { + return makeInstance(parent).add(this); + } // Remove element + + }, { + key: "remove", + value: function remove() { + if (this.parent()) { + this.parent().removeElement(this); + } + + return this; + } // Remove a given child + + }, { + key: "removeElement", + value: function removeElement(element) { + this.node.removeChild(element.node); + return this; + } // Replace element + + }, { + key: "replace", + value: function replace(element) { + // FIXME: after() might not be available here + this.after(element).remove(); + return element; + } // Return id on string conversion + + }, { + key: "toString", + value: function toString() { + return this.id(); + } // Import raw svg + + }, { + key: "svg", + value: function svg(_svg) { + var well, len; // act as a setter if svg is given + + if (_svg) { + // create temporary holder + well = document.createElementNS(ns, 'svg'); // dump raw svg + + well.innerHTML = _svg; // transplant nodes + + for (len = well.children.length; len--;) { + this.node.appendChild(well.firstElementChild); + } // otherwise act as a getter + + } else { + // write svgjs data to the dom + this.writeDataToDom(); + return this.node.outerHTML; + } + + return this; + } // write svgjs data to the dom + + }, { + key: "writeDataToDom", + value: function writeDataToDom() { + // dump variables recursively + this.each(function () { + this.writeDataToDom(); + }); + return this; + } + }]); + + return Dom; +}(EventTarget); +extend(Dom, { + attr: attr +}); + +var Doc = getClass(root); + +var Element = +/*#__PURE__*/ +function (_Dom) { + _inherits(Element, _Dom); + + function Element(node) { + var _this; + + _classCallCheck(this, Element); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Element).call(this, node)); // initialize data object + + _this.dom = {}; // create circular reference + + _this.node.instance = _assertThisInitialized(_assertThisInitialized(_this)); + + 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')) || {}); + } + + return _this; + } // Move element by its center + + + _createClass(Element, [{ + key: "center", + value: function center(x, y) { + return this.cx(x).cy(y); + } // Move by center over x-axis + + }, { + key: "cx", + value: function cx(x) { + return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2); + } // Move by center over y-axis + + }, { + key: "cy", + value: function cy(y) { + return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2); + } // Get defs + + }, { + key: "defs", + value: function defs() { + return this.doc().defs(); + } // Get parent document + + }, { + key: "doc", + value: function doc() { + var p = this.parent(Doc); + return p && p.doc(); + } + }, { + key: "getEventHolder", + value: function getEventHolder() { + return this; + } // Set height of element + + }, { + key: "height", + value: function height(_height) { + return this.attr('height', _height); + } // Checks whether the given point inside the bounding box of the element + + }, { + key: "inside", + value: function inside(x, y) { + var box = this.bbox(); + 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 + + }, { + key: "move", + value: function move(x, y) { + return this.x(x).y(y); + } // return array of all ancestors of given type up to the root svg + + }, { + key: "parents", + value: function parents(type) { + var parents = []; + var parent = this; + + do { + parent = parent.parent(type); + if (!parent || parent instanceof getClass('HtmlNode')) break; + parents.push(parent); + } while (parent.parent); + + return parents; + } // Get referenced element form attribute value + + }, { + key: "reference", + value: function reference$$1(attr) { + attr = this.attr(attr); + if (!attr) return null; + var m = attr.match(reference); + return m ? makeInstance(m[1]) : null; + } // set given data to the elements data property + + }, { + key: "setData", + value: function setData(o) { + this.dom = o; + return this; + } // Set element size to given width and height + + }, { + key: "size", + value: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height)); + } // Set width of element + + }, { + key: "width", + value: function width(_width) { + return this.attr('width', _width); + } // write svgjs data to the dom + + }, { + key: "writeDataToDom", + value: function 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 _get(_getPrototypeOf(Element.prototype), "writeDataToDom", this).call(this); + } // Move over x-axis + + }, { + key: "x", + value: function x(_x) { + return this.attr('x', _x); + } // Move over y-axis + + }, { + key: "y", + value: function y(_y) { + return this.attr('y', _y); + } + }]); + + return Element; +}(Dom); + +var Container = +/*#__PURE__*/ +function (_Element) { + _inherits(Container, _Element); + + function Container() { + _classCallCheck(this, Container); + + return _possibleConstructorReturn(this, _getPrototypeOf(Container).apply(this, arguments)); + } + + _createClass(Container, [{ + key: "flatten", + value: function flatten(parent) { + this.each(function () { + if (this instanceof Container) return this.flatten(parent).ungroup(parent); + return this.toParent(parent); + }); // we need this so that Doc does not get removed + + this.node.firstElementChild || this.remove(); + return this; + } + }, { + key: "ungroup", + value: function ungroup(parent) { + parent = parent || this.parent(); + this.each(function () { + return this.toParent(parent); + }); + this.remove(); + return this; + } + }]); + + return Container; +}(Element); + +var Defs = +/*#__PURE__*/ +function (_Container) { + _inherits(Defs, _Container); + + function Defs(node) { + _classCallCheck(this, Defs); + + return _possibleConstructorReturn(this, _getPrototypeOf(Defs).call(this, nodeOrNew('defs', node), Defs)); + } + + _createClass(Defs, [{ + key: "flatten", + value: function flatten() { + return this; + } + }, { + key: "ungroup", + value: function ungroup() { + return this; + } + }]); + + return Defs; +}(Container); +register(Defs); + +var Doc$1 = +/*#__PURE__*/ +function (_Container) { + _inherits(Doc, _Container); + + function Doc(node) { + var _this; + + _classCallCheck(this, Doc); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Doc).call(this, nodeOrNew('svg', node), Doc)); + + _this.namespace(); + + return _this; + } + + _createClass(Doc, [{ + key: "isRoot", + value: function isRoot() { + return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document'; + } // Check if this is a root svg + // If not, call docs from this element + + }, { + key: "doc", + value: function doc() { + if (this.isRoot()) return this; + return _get(_getPrototypeOf(Doc.prototype), "doc", this).call(this); + } // Add namespaces + + }, { + key: "namespace", + value: function namespace() { + if (!this.isRoot()) return this.doc().namespace(); + return this.attr({ + xmlns: ns, + version: '1.1' + }).attr('xmlns:xlink', xlink, xmlns).attr('xmlns:svgjs', svgjs, xmlns); + } // Creates and returns defs element + + }, { + key: "defs", + value: function defs() { + if (!this.isRoot()) return this.doc().defs(); + return adopt(this.node.getElementsByTagName('defs')[0]) || this.put(new Defs()); + } // custom parent method + + }, { + key: "parent", + value: function parent(type) { + if (this.isRoot()) { + return this.node.parentNode.nodeName === '#document' ? null : adopt(this.node.parentNode); + } + + return _get(_getPrototypeOf(Doc.prototype), "parent", this).call(this, type); + } + }, { + key: "clear", + value: function clear() { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } + + return this; + } + }]); + + return Doc; +}(Container); +registerMethods({ + Container: { + // Create nested svg document + nested: function nested() { + return this.put(new Doc$1()); + } + } +}); +register(Doc$1, 'Doc', true); + +function parser() { + // Reuse cached element if possible + if (!parser.nodes) { + var svg = new Doc$1().size(2, 0); + svg.node.cssText = ['opacity: 0', 'position: absolute', 'left: -100%', 'top: -100%', 'overflow: hidden'].join(';'); + var path = svg.path().node; + parser.nodes = { + svg: svg, + path: path + }; + } + + if (!parser.nodes.svg.node.parentNode) { + var b = document.body || document.documentElement; + parser.nodes.svg.addTo(b); + } + + return parser.nodes; +} + +var Point = +/*#__PURE__*/ +function () { + // Initialize + function Point(x, y, base) { + _classCallCheck(this, Point); + + var source; + base = base || { + x: 0, + y: 0 // ensure source as object + + }; + source = Array.isArray(x) ? { + x: x[0], + y: x[1] + } : _typeof(x) === 'object' ? { + x: x.x, + y: x.y + } : { + x: x, + y: y // merge source + + }; + this.x = source.x == null ? base.x : source.x; + this.y = source.y == null ? base.y : source.y; + } // Clone point + + + _createClass(Point, [{ + key: "clone", + value: function clone() { + return new Point(this); + } // Convert to native SVGPoint + + }, { + key: "native", + value: function native() { + // create new point + var point = parser().svg.node.createSVGPoint(); // update with current values + + point.x = this.x; + point.y = this.y; + return point; + } // transform point with matrix + + }, { + key: "transform", + value: function transform(m) { + // Perform the matrix multiplication + var x = m.a * this.x + m.c * this.y + m.e; + var y = m.b * this.x + m.d * this.y + m.f; // Return the required point + + return new Point(x, y); + } + }]); + + return Point; +}(); +registerMethods({ + Element: { + // Get point + point: function point(x, y) { + return new Point(x, y).transform(this.screenCTM().inverse()); + } + } +}); + +var abcdef = 'abcdef'.split(''); + +function closeEnough(a, b, threshold) { + return Math.abs(b - a) < (threshold || 1e-6); +} + +var Matrix = +/*#__PURE__*/ +function () { + function Matrix() { + _classCallCheck(this, Matrix); + + this.init.apply(this, arguments); + } // Initialize + + + _createClass(Matrix, [{ + key: "init", + value: function init(source) { + var base = Matrix.fromArray([1, 0, 0, 1, 0, 0]); // ensure source as object + + source = source instanceof Element ? source.matrixify() : typeof source === 'string' ? Matrix.fromArray(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? Matrix.fromArray(source) : _typeof(source) === 'object' && Matrix.isMatrixLike(source) ? source : _typeof(source) === 'object' ? new Matrix().transform(source) : arguments.length === 6 ? Matrix.fromArray([].slice.call(arguments)) : base; // Merge the source matrix with the base matrix + + this.a = source.a != null ? source.a : base.a; + this.b = source.b != null ? source.b : base.b; + this.c = source.c != null ? source.c : base.c; + this.d = source.d != null ? source.d : base.d; + this.e = source.e != null ? source.e : base.e; + this.f = source.f != null ? source.f : base.f; + } // Clones this matrix + + }, { + key: "clone", + value: function clone() { + return new Matrix(this); + } // Transform a matrix into another matrix by manipulating the space + + }, { + key: "transform", + value: function transform(o) { + // Check if o is a matrix and then left multiply it directly + if (Matrix.isMatrixLike(o)) { + var matrix = new Matrix(o); + return matrix.multiplyO(this); + } // Get the proposed transformations and the current transformations + + + var t = Matrix.formatTransforms(o); + var current = this; + + var _transform = new Point(t.ox, t.oy).transform(current), + ox = _transform.x, + oy = _transform.y; // Construct the resulting matrix + + + var transformer = new Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy); // If we want the origin at a particular place, we force it there + + if (isFinite(t.px) || isFinite(t.py)) { + var origin = new Point(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px) + + var dx = t.px ? t.px - origin.x : 0; + var dy = t.py ? t.py - origin.y : 0; + transformer.translateO(dx, dy); + } // Translate now after positioning + + + transformer.translateO(t.tx, t.ty); + return transformer; + } // Applies a matrix defined by its affine parameters + + }, { + key: "compose", + value: function compose(o) { + if (o.origin) { + o.originX = o.origin[0]; + o.originY = o.origin[1]; + } // Get the parameters + + + var ox = o.originX || 0; + var oy = o.originY || 0; + var sx = o.scaleX || 1; + var sy = o.scaleY || 1; + var lam = o.shear || 0; + var theta = o.rotate || 0; + var tx = o.translateX || 0; + var ty = o.translateY || 0; // Apply the standard matrix + + var result = new Matrix().translateO(-ox, -oy).scaleO(sx, sy).shearO(lam).rotateO(theta).translateO(tx, ty).lmultiplyO(this).translateO(ox, oy); + return result; + } // Decomposes this matrix into its affine parameters + + }, { + key: "decompose", + value: function decompose() { + var cx = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var cy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + // Get the parameters from the matrix + var a = this.a; + var b = this.b; + var c = this.c; + var d = this.d; + var e = this.e; + var f = this.f; // Figure out if the winding direction is clockwise or counterclockwise + + var determinant = a * d - b * c; + var ccw = determinant > 0 ? 1 : -1; // Since we only shear in x, we can use the x basis to get the x scale + // and the rotation of the resulting matrix + + var sx = ccw * Math.sqrt(a * a + b * b); + var thetaRad = Math.atan2(ccw * b, ccw * a); + var theta = 180 / Math.PI * thetaRad; + var ct = Math.cos(thetaRad); + var st = Math.sin(thetaRad); // We can then solve the y basis vector simultaneously to get the other + // two affine parameters directly from these parameters + + var lam = (a * c + b * d) / determinant; + var sy = c * sx / (lam * a - b) || d * sx / (lam * b + a); // Use the translations + + var tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy); + var ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy); // Construct the decomposition and return it + + return { + // Return the affine parameters + scaleX: sx, + scaleY: sy, + shear: lam, + rotate: theta, + translateX: tx, + translateY: ty, + originX: cx, + originY: cy, + // Return the matrix parameters + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + }; + } // Left multiplies by the given matrix + + }, { + key: "multiply", + value: function multiply(matrix) { + return this.clone().multiplyO(matrix); + } + }, { + key: "multiplyO", + value: function multiplyO(matrix) { + // Get the matrices + var l = this; + var r = matrix instanceof Matrix ? matrix : new Matrix(matrix); + return Matrix.matrixMultiply(l, r, this); + } + }, { + key: "lmultiply", + value: function lmultiply(matrix) { + return this.clone().lmultiplyO(matrix); + } + }, { + key: "lmultiplyO", + value: function lmultiplyO(matrix) { + var r = this; + var l = matrix instanceof Matrix ? matrix : new Matrix(matrix); + return Matrix.matrixMultiply(l, r, this); + } // Inverses matrix + + }, { + key: "inverseO", + value: function inverseO() { + // Get the current parameters out of the matrix + var a = this.a; + var b = this.b; + var c = this.c; + var d = this.d; + var e = this.e; + var f = this.f; // Invert the 2x2 matrix in the top left + + var det = a * d - b * c; + if (!det) throw new Error('Cannot invert ' + this); // Calculate the top 2x2 matrix + + var na = d / det; + var nb = -b / det; + var nc = -c / det; + var nd = a / det; // Apply the inverted matrix to the top right + + var ne = -(na * e + nc * f); + var nf = -(nb * e + nd * f); // Construct the inverted matrix + + this.a = na; + this.b = nb; + this.c = nc; + this.d = nd; + this.e = ne; + this.f = nf; + return this; + } + }, { + key: "inverse", + value: function inverse() { + return this.clone().inverseO(); + } // Translate matrix + + }, { + key: "translate", + value: function translate(x, y) { + return this.clone().translateO(x, y); + } + }, { + key: "translateO", + value: function translateO(x, y) { + this.e += x || 0; + this.f += y || 0; + return this; + } // Scale matrix + + }, { + key: "scale", + value: function scale(x, y, cx, cy) { + var _this$clone; + + return (_this$clone = this.clone()).scaleO.apply(_this$clone, arguments); + } + }, { + key: "scaleO", + value: function scaleO(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + + // Support uniform scaling + if (arguments.length === 3) { + cy = cx; + cx = y; + y = x; + } + + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a * x; + this.b = b * y; + this.c = c * x; + this.d = d * y; + this.e = e * x - cx * x + cx; + this.f = f * y - cy * y + cy; + return this; + } // Rotate matrix + + }, { + key: "rotate", + value: function rotate(r, cx, cy) { + return this.clone().rotateO(r, cx, cy); + } + }, { + key: "rotateO", + value: function rotateO(r) { + var cx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + // Convert degrees to radians + r = radians(r); + var cos = Math.cos(r); + var sin = Math.sin(r); + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a * cos - b * sin; + this.b = b * cos + a * sin; + this.c = c * cos - d * sin; + this.d = d * cos + c * sin; + this.e = e * cos - f * sin + cy * sin - cx * cos + cx; + this.f = f * cos + e * sin - cx * sin - cy * cos + cy; + return this; + } // Flip matrix on x or y, at a given offset + + }, { + key: "flip", + value: function flip(axis, around) { + return this.clone().flipO(axis, around); + } + }, { + key: "flipO", + value: function flipO(axis, around) { + return axis === 'x' ? this.scaleO(-1, 1, around, 0) : axis === 'y' ? this.scaleO(1, -1, 0, around) : this.scaleO(-1, -1, axis, around || axis); // Define an x, y flip point + } // Shear matrix + + }, { + key: "shear", + value: function shear(a, cx, cy) { + return this.clone().shearO(a, cx, cy); + } + }, { + key: "shearO", + value: function shearO(lx) { + var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a + b * lx; + this.c = c + d * lx; + this.e = e + f * lx - cy * lx; + return this; + } // Skew Matrix + + }, { + key: "skew", + value: function skew(x, y, cx, cy) { + var _this$clone2; + + return (_this$clone2 = this.clone()).skewO.apply(_this$clone2, arguments); + } + }, { + key: "skewO", + value: function skewO(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + + // support uniformal skew + if (arguments.length === 3) { + cy = cx; + cx = y; + y = x; + } // Convert degrees to radians + + + x = radians(x); + y = radians(y); + var lx = Math.tan(x); + var ly = Math.tan(y); + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a + b * lx; + this.b = b + a * ly; + this.c = c + d * lx; + this.d = d + c * ly; + this.e = e + f * lx - cy * lx; + this.f = f + e * ly - cx * ly; + return this; + } // SkewX + + }, { + key: "skewX", + value: function skewX(x, cx, cy) { + return this.skew(x, 0, cx, cy); + } + }, { + key: "skewXO", + value: function skewXO(x, cx, cy) { + return this.skewO(x, 0, cx, cy); + } // SkewY + + }, { + key: "skewY", + value: function skewY(y, cx, cy) { + return this.skew(0, y, cx, cy); + } + }, { + key: "skewYO", + value: function skewYO(y, cx, cy) { + return this.skewO(0, y, cx, cy); + } // Transform around a center point + + }, { + key: "aroundO", + value: function aroundO(cx, cy, matrix) { + var dx = cx || 0; + var dy = cy || 0; + return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy); + } + }, { + key: "around", + value: function around(cx, cy, matrix) { + return this.clone().aroundO(cx, cy, matrix); + } // Convert to native SVGMatrix + + }, { + key: "native", + value: function native() { + // create new matrix + var matrix = parser().svg.node.createSVGMatrix(); // update with current values + + for (var i = abcdef.length - 1; i >= 0; i--) { + matrix[abcdef[i]] = this[abcdef[i]]; + } + + return matrix; + } // Check if two matrices are equal + + }, { + key: "equals", + value: function equals(other) { + var comp = new Matrix(other); + return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f); + } // Convert matrix to string + + }, { + key: "toString", + value: function toString() { + return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'; + } + }, { + key: "toArray", + value: function toArray() { + return [this.a, this.b, this.c, this.d, this.e, this.f]; + } + }, { + key: "valueOf", + value: function valueOf() { + return { + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + }; + } + }], [{ + key: "fromArray", + value: function fromArray(a) { + return { + a: a[0], + b: a[1], + c: a[2], + d: a[3], + e: a[4], + f: a[5] + }; + } + }, { + key: "isMatrixLike", + value: function isMatrixLike(o) { + return o.a != null || o.b != null || o.c != null || o.d != null || o.e != null || o.f != null; + } + }, { + key: "formatTransforms", + value: function formatTransforms(o) { + // Get all of the parameters required to form the matrix + var flipBoth = o.flip === 'both' || o.flip === true; + var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1; + var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1; + var skewX = o.skew && o.skew.length ? o.skew[0] : isFinite(o.skew) ? o.skew : isFinite(o.skewX) ? o.skewX : 0; + var skewY = o.skew && o.skew.length ? o.skew[1] : isFinite(o.skew) ? o.skew : isFinite(o.skewY) ? o.skewY : 0; + var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX : isFinite(o.scale) ? o.scale * flipX : isFinite(o.scaleX) ? o.scaleX * flipX : flipX; + var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY; + var shear = o.shear || 0; + var theta = o.rotate || o.theta || 0; + var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY); + var ox = origin.x; + var oy = origin.y; + var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY); + var px = position.x; + var py = position.y; + var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY); + var tx = translate.x; + var ty = translate.y; + var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY); + var rx = relative.x; + var ry = relative.y; // Populate all of the values + + return { + scaleX: scaleX, + scaleY: scaleY, + skewX: skewX, + skewY: skewY, + shear: shear, + theta: theta, + rx: rx, + ry: ry, + tx: tx, + ty: ty, + ox: ox, + oy: oy, + px: px, + py: py + }; + } // left matrix, right matrix, target matrix which is overwritten + + }, { + key: "matrixMultiply", + value: function matrixMultiply(l, r, o) { + // Work out the product directly + var a = l.a * r.a + l.c * r.b; + var b = l.b * r.a + l.d * r.b; + var c = l.a * r.c + l.c * r.d; + var d = l.b * r.c + l.d * r.d; + var e = l.e + l.a * r.e + l.c * r.f; + var f = l.f + l.b * r.e + l.d * r.f; // make sure to use local variables because l/r and o could be the same + + o.a = a; + o.b = b; + o.c = c; + o.d = d; + o.e = e; + o.f = f; + return o; + } + }]); + + return Matrix; +}(); +registerMethods({ + Element: { + // Get current matrix + ctm: function ctm() { + return new Matrix(this.node.getCTM()); + }, + // Get current screen matrix + screenCTM: function screenCTM() { + /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 + This is needed because FF does not return the transformation matrix + for the inner coordinate system when getScreenCTM() is called on nested svgs. + However all other Browsers do that */ + if (typeof this.isRoot === 'function' && !this.isRoot()) { + var rect = this.rect(1, 1); + var m = rect.node.getScreenCTM(); + rect.remove(); + return new Matrix(m); + } + + return new Matrix(this.node.getScreenCTM()); + } + } +}); + +/*** +Base Class +========== +The base stepper class that will be +***/ + +function makeSetterGetter(k, f) { + return function (v) { + if (v == null) return this[v]; + this[k] = v; + if (f) f.call(this); + return this; + }; +} + +var easing = { + '-': function _(pos) { + return pos; + }, + '<>': function _(pos) { + return -Math.cos(pos * Math.PI) / 2 + 0.5; + }, + '>': function _(pos) { + return Math.sin(pos * Math.PI / 2); + }, + '<': function _(pos) { + return -Math.cos(pos * Math.PI / 2) + 1; + }, + bezier: function bezier(t0, x0, t1, x1) { + return function (t) {// TODO: FINISH + }; + } +}; +var Stepper = +/*#__PURE__*/ +function () { + function Stepper() { + _classCallCheck(this, Stepper); + } + + _createClass(Stepper, [{ + key: "done", + value: function done() { + return false; + } + }]); + + return Stepper; +}(); +/*** +Easing Functions +================ +***/ + +var Ease = +/*#__PURE__*/ +function (_Stepper) { + _inherits(Ease, _Stepper); + + function Ease(fn) { + var _this; + + _classCallCheck(this, Ease); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Ease).call(this)); + _this.ease = easing[fn || timeline.ease] || fn; + return _this; + } + + _createClass(Ease, [{ + key: "step", + value: function step(from, to, pos) { + if (typeof from !== 'number') { + return pos < 1 ? from : to; + } + + return from + (to - from) * this.ease(pos); + } + }]); + + return Ease; +}(Stepper); +/*** +Controller Types +================ +***/ + +var Controller = +/*#__PURE__*/ +function (_Stepper2) { + _inherits(Controller, _Stepper2); + + function Controller(fn) { + var _this2; + + _classCallCheck(this, Controller); + + _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Controller).call(this)); + _this2.stepper = fn; + return _this2; + } + + _createClass(Controller, [{ + key: "step", + value: function step(current, target, dt, c) { + return this.stepper(current, target, dt, c); + } + }, { + key: "done", + value: function done(c) { + return c.done; + } + }]); + + return Controller; +}(Stepper); + +function recalculate() { + // Apply the default parameters + var duration = (this._duration || 500) / 1000; + var overshoot = this._overshoot || 0; // Calculate the PID natural response + + var eps = 1e-10; + var pi = Math.PI; + var os = Math.log(overshoot / 100 + eps); + var zeta = -os / Math.sqrt(pi * pi + os * os); + var wn = 3.9 / (zeta * duration); // Calculate the Spring values + + this.d = 2 * zeta * wn; + this.k = wn * wn; +} + +var Spring = +/*#__PURE__*/ +function (_Controller) { + _inherits(Spring, _Controller); + + function Spring(duration, overshoot) { + var _this3; + + _classCallCheck(this, Spring); + + _this3 = _possibleConstructorReturn(this, _getPrototypeOf(Spring).call(this)); + + _this3.duration(duration || 500).overshoot(overshoot || 0); + + return _this3; + } + + _createClass(Spring, [{ + key: "step", + value: function step(current, target, dt, c) { + if (typeof current === 'string') return current; + c.done = dt === Infinity; + if (dt === Infinity) return target; + if (dt === 0) return current; + if (dt > 100) dt = 16; + dt /= 1000; // Get the previous velocity + + var velocity = c.velocity || 0; // Apply the control to get the new position and store it + + var acceleration = -this.d * velocity - this.k * (current - target); + var newPosition = current + velocity * dt + acceleration * dt * dt / 2; // Store the velocity + + c.velocity = velocity + acceleration * dt; // Figure out if we have converged, and if so, pass the value + + c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002; + return c.done ? target : newPosition; + } + }]); + + return Spring; +}(Controller); +extend(Spring, { + duration: makeSetterGetter('_duration', recalculate), + overshoot: makeSetterGetter('_overshoot', recalculate) +}); +var PID = +/*#__PURE__*/ +function (_Controller2) { + _inherits(PID, _Controller2); + + function PID(p, i, d, windup) { + var _this4; + + _classCallCheck(this, PID); + + _this4 = _possibleConstructorReturn(this, _getPrototypeOf(PID).call(this)); + p = p == null ? 0.1 : p; + i = i == null ? 0.01 : i; + d = d == null ? 0 : d; + windup = windup == null ? 1000 : windup; + + _this4.p(p).i(i).d(d).windup(windup); + + return _this4; + } + + _createClass(PID, [{ + key: "step", + value: function step(current, target, dt, c) { + if (typeof current === 'string') return current; + c.done = dt === Infinity; + if (dt === Infinity) return target; + if (dt === 0) return current; + var p = target - current; + var i = (c.integral || 0) + p * dt; + var d = (p - (c.error || 0)) / dt; + var windup = this.windup; // antiwindup + + if (windup !== false) { + i = Math.max(-windup, Math.min(i, windup)); + } + + c.error = p; + c.integral = i; + c.done = Math.abs(p) < 0.001; + return c.done ? target : current + (this.P * p + this.I * i + this.D * d); + } + }]); + + return PID; +}(Controller); +extend(PID, { + windup: makeSetterGetter('windup'), + p: makeSetterGetter('P'), + i: makeSetterGetter('I'), + d: makeSetterGetter('D') +}); + +var Queue = +/*#__PURE__*/ +function () { + function Queue() { + _classCallCheck(this, Queue); + + this._first = null; + this._last = null; + } + + _createClass(Queue, [{ + key: "push", + value: function push(value) { + // An item stores an id and the provided value + var item = value.next ? value : { + value: value, + next: null, + prev: null // Deal with the queue being empty or populated + + }; + + if (this._last) { + item.prev = this._last; + this._last.next = item; + this._last = item; + } else { + this._last = item; + this._first = item; + } // Update the length and return the current item + + + return item; + } + }, { + key: "shift", + value: function shift() { + // Check if we have a value + var remove = this._first; + if (!remove) return null; // If we do, remove it and relink things + + this._first = remove.next; + if (this._first) this._first.prev = null; + this._last = this._first ? this._last : null; + return remove.value; + } // Shows us the first item in the list + + }, { + key: "first", + value: function first() { + return this._first && this._first.value; + } // Shows us the last item in the list + + }, { + key: "last", + value: function last() { + return this._last && this._last.value; + } // Removes the item that was returned from the push + + }, { + key: "remove", + value: function remove(item) { + // Relink the previous item + if (item.prev) item.prev.next = item.next; + if (item.next) item.next.prev = item.prev; + if (item === this._last) this._last = item.prev; + if (item === this._first) this._first = item.next; // Invalidate item + + item.prev = null; + item.next = null; + } + }]); + + return Queue; +}(); + +var Animator = { + nextDraw: null, + frames: new Queue(), + timeouts: new Queue(), + timer: window.performance || window.Date, + transforms: [], + frame: function frame(fn) { + // Store the node + var node = Animator.frames.push({ + run: fn + }); // Request an animation frame if we don't have one + + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw); + } // Return the node so we can remove it easily + + + return node; + }, + transform_frame: function transform_frame(fn, id) { + Animator.transforms[id] = fn; + }, + timeout: function timeout(fn, delay) { + delay = delay || 0; // Work out when the event should fire + + var time = Animator.timer.now() + delay; // Add the timeout to the end of the queue + + var node = Animator.timeouts.push({ + run: fn, + time: time + }); // Request another animation frame if we need one + + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw); + } + + return node; + }, + cancelFrame: function cancelFrame(node) { + Animator.frames.remove(node); + }, + clearTimeout: function clearTimeout(node) { + Animator.timeouts.remove(node); + }, + _draw: function _draw(now) { + // Run all the timeouts we can run, if they are not ready yet, add them + // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) + var nextTimeout = null; + var lastTimeout = Animator.timeouts.last(); + + while (nextTimeout = Animator.timeouts.shift()) { + // Run the timeout if its time, or push it to the end + if (now >= nextTimeout.time) { + nextTimeout.run(); + } else { + Animator.timeouts.push(nextTimeout); + } // If we hit the last item, we should stop shifting out more items + + + if (nextTimeout === lastTimeout) break; + } // Run all of the animation frames + + + var nextFrame = null; + var lastFrame = Animator.frames.last(); + + while (nextFrame !== lastFrame && (nextFrame = Animator.frames.shift())) { + nextFrame.run(); + } + + Animator.transforms.forEach(function (el) { + el(); + }); // If we have remaining timeouts or frames, draw until we don't anymore + + Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() ? window.requestAnimationFrame(Animator._draw) : null; + } +}; + +function isNulledBox(box) { + return !box.w && !box.h && !box.x && !box.y; +} + +function domContains(node) { + return (document.documentElement.contains || function (node) { + // This is IE - it does not support contains() for top-level SVGs + while (node.parentNode) { + node = node.parentNode; + } + + return node === document; + }).call(document.documentElement, node); +} + +var Box = +/*#__PURE__*/ +function () { + function Box() { + _classCallCheck(this, Box); + + this.init.apply(this, arguments); + } + + _createClass(Box, [{ + key: "init", + value: function init(source) { + var base = [0, 0, 0, 0]; + source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) : Array.isArray(source) ? source : _typeof(source) === 'object' ? [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] : arguments.length === 4 ? [].slice.call(arguments) : base; + this.x = source[0] || 0; + this.y = source[1] || 0; + this.width = this.w = source[2] || 0; + this.height = this.h = source[3] || 0; // Add more bounding box properties + + this.x2 = this.x + this.w; + this.y2 = this.y + this.h; + this.cx = this.x + this.w / 2; + this.cy = this.y + this.h / 2; + } // Merge rect box with another, return a new instance + + }, { + key: "merge", + value: function merge(box) { + var x = Math.min(this.x, box.x); + var y = Math.min(this.y, box.y); + var width = Math.max(this.x + this.width, box.x + box.width) - x; + var height = Math.max(this.y + this.height, box.y + box.height) - y; + return new Box(x, y, width, height); + } + }, { + key: "transform", + value: function transform(m) { + var xMin = Infinity; + var xMax = -Infinity; + var yMin = Infinity; + var yMax = -Infinity; + var pts = [new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2)]; + pts.forEach(function (p) { + p = p.transform(m); + xMin = Math.min(xMin, p.x); + xMax = Math.max(xMax, p.x); + yMin = Math.min(yMin, p.y); + yMax = Math.max(yMax, p.y); + }); + return new Box(xMin, yMin, xMax - xMin, yMax - yMin); + } + }, { + key: "addOffset", + value: function addOffset() { + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset; + this.y += window.pageYOffset; + return this; + } + }, { + key: "toString", + value: function toString() { + return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height; + } + }, { + key: "toArray", + value: function toArray() { + return [this.x, this.y, this.width, this.height]; + } + }, { + key: "isNulled", + value: function isNulled() { + return isNulledBox(this); + } + }]); + + return Box; +}(); + +function getBox(cb) { + var box; + + try { + box = cb(this.node); + + if (isNulledBox(box) && !domContains(this.node)) { + throw new Error('Element not in the dom'); + } + } catch (e) { + try { + var clone = this.clone(parser().svg).show(); + box = cb(clone.node); + clone.remove(); + } catch (e) { + console.warn('Getting a bounding box of this element is not possible'); + } + } + + return box; +} + +registerMethods({ + Element: { + // Get bounding box + bbox: function bbox() { + return new Box(getBox.call(this, function (node) { + return node.getBBox(); + })); + }, + rbox: function rbox(el) { + var box = new Box(getBox.call(this, function (node) { + return node.getBoundingClientRect(); + })); + if (el) return box.transform(el.screenCTM().inverse()); + return box.addOffset(); + } + }, + viewbox: { + viewbox: function viewbox(x, y, width, height) { + // act as getter + if (x == null) return new Box(this.attr('viewBox')); // act as setter + + return this.attr('viewBox', new Box(x, y, width, height)); + } + } +}); + +var PathArray = subClassArray('PathArray', SVGArray); +function pathRegReplace(a, b, c, d) { + return c + d.replace(dots, ' .'); +} + +function arrayToString(a) { + for (var i = 0, il = a.length, s = ''; i < il; i++) { + s += a[i][0]; + + if (a[i][1] != null) { + s += a[i][1]; + + if (a[i][2] != null) { + s += ' '; + s += a[i][2]; + + if (a[i][3] != null) { + s += ' '; + s += a[i][3]; + s += ' '; + s += a[i][4]; + + if (a[i][5] != null) { + s += ' '; + s += a[i][5]; + s += ' '; + s += a[i][6]; + + if (a[i][7] != null) { + s += ' '; + s += a[i][7]; + } + } + } + } + } + } + + return s + ' '; +} + +var pathHandlers = { + M: function M(c, p, p0) { + p.x = p0.x = c[0]; + p.y = p0.y = c[1]; + return ['M', p.x, p.y]; + }, + L: function L(c, p) { + p.x = c[0]; + p.y = c[1]; + return ['L', c[0], c[1]]; + }, + H: function H(c, p) { + p.x = c[0]; + return ['H', c[0]]; + }, + V: function V(c, p) { + p.y = c[0]; + return ['V', c[0]]; + }, + C: function C(c, p) { + p.x = c[4]; + p.y = c[5]; + return ['C', c[0], c[1], c[2], c[3], c[4], c[5]]; + }, + S: function S(c, p) { + p.x = c[2]; + p.y = c[3]; + return ['S', c[0], c[1], c[2], c[3]]; + }, + Q: function Q(c, p) { + p.x = c[2]; + p.y = c[3]; + return ['Q', c[0], c[1], c[2], c[3]]; + }, + T: function T(c, p) { + p.x = c[0]; + p.y = c[1]; + return ['T', c[0], c[1]]; + }, + Z: function Z(c, p, p0) { + p.x = p0.x; + p.y = p0.y; + return ['Z']; + }, + A: function A(c, p) { + p.x = c[5]; + p.y = c[6]; + return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]]; + } +}; +var mlhvqtcsaz = 'mlhvqtcsaz'.split(''); + +for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { + pathHandlers[mlhvqtcsaz[i]] = function (i) { + return function (c, p, p0) { + if (i === 'H') c[0] = c[0] + p.x;else if (i === 'V') c[0] = c[0] + p.y;else if (i === 'A') { + c[5] = c[5] + p.x; + c[6] = c[6] + p.y; + } else { + for (var j = 0, jl = c.length; j < jl; ++j) { + c[j] = c[j] + (j % 2 ? p.y : p.x); + } + } + return pathHandlers[i](c, p, p0); + }; + }(mlhvqtcsaz[i].toUpperCase()); +} + +extend(PathArray, { + // Convert array to string + toString: function toString() { + return arrayToString(this); + }, + // Move path string + move: function move(x, y) { + // get bounding box of current situation + var box = this.bbox(); // get relative offset + + x -= box.x; + y -= box.y; + + if (!isNaN(x) && !isNaN(y)) { + // move every point + for (var l, i = this.length - 1; i >= 0; i--) { + l = this[i][0]; + + if (l === 'M' || l === 'L' || l === 'T') { + this[i][1] += x; + this[i][2] += y; + } else if (l === 'H') { + this[i][1] += x; + } else if (l === 'V') { + this[i][1] += y; + } else if (l === 'C' || l === 'S' || l === 'Q') { + this[i][1] += x; + this[i][2] += y; + this[i][3] += x; + this[i][4] += y; + + if (l === 'C') { + this[i][5] += x; + this[i][6] += y; + } + } else if (l === 'A') { + this[i][6] += x; + this[i][7] += y; + } + } + } + + return this; + }, + // Resize path string + size: function size(width, height) { + // get bounding box of current situation + var box = this.bbox(); + var i, l; // recalculate position of all points according to new size + + for (i = this.length - 1; i >= 0; i--) { + l = this[i][0]; + + if (l === 'M' || l === 'L' || l === 'T') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; + } else if (l === 'H') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + } else if (l === 'V') { + this[i][1] = (this[i][1] - box.y) * height / box.height + box.y; + } else if (l === 'C' || l === 'S' || l === 'Q') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; + this[i][3] = (this[i][3] - box.x) * width / box.width + box.x; + this[i][4] = (this[i][4] - box.y) * height / box.height + box.y; + + if (l === 'C') { + this[i][5] = (this[i][5] - box.x) * width / box.width + box.x; + this[i][6] = (this[i][6] - box.y) * height / box.height + box.y; + } + } else if (l === 'A') { + // resize radii + this[i][1] = this[i][1] * width / box.width; + this[i][2] = this[i][2] * height / box.height; // move position values + + this[i][6] = (this[i][6] - box.x) * width / box.width + box.x; + this[i][7] = (this[i][7] - box.y) * height / box.height + box.y; + } + } + + return this; + }, + // Test if the passed path array use the same path data commands as this path array + equalCommands: function equalCommands(pathArray) { + var i, il, equalCommands; + pathArray = new PathArray(pathArray); + equalCommands = this.length === pathArray.length; + + for (i = 0, il = this.length; equalCommands && i < il; i++) { + equalCommands = this[i][0] === pathArray[i][0]; + } + + return equalCommands; + }, + // Make path array morphable + morph: function morph(pathArray) { + pathArray = new PathArray(pathArray); + + if (this.equalCommands(pathArray)) { + this.destination = pathArray; + } else { + this.destination = null; + } + + return this; + }, + // Get morphed path array at given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; + var sourceArray = this; + var destinationArray = this.destination.value; + var array = []; + var pathArray = new PathArray(); + var i, il, j, jl; // Animate has specified in the SVG spec + // See: https://www.w3.org/TR/SVG11/paths.html#PathElement + + for (i = 0, il = sourceArray.length; i < il; i++) { + array[i] = [sourceArray[i][0]]; + + for (j = 1, jl = sourceArray[i].length; j < jl; j++) { + array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos; + } // For the two flags of the elliptical arc command, the SVG spec say: + // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true + // Elliptical arc command as an array followed by corresponding indexes: + // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // 0 1 2 3 4 5 6 7 + + + if (array[i][0] === 'A') { + array[i][4] = +(array[i][4] !== 0); + array[i][5] = +(array[i][5] !== 0); + } + } // Directly modify the value of a path array, this is done this way for performance + + + pathArray.value = array; + return pathArray; + }, + // Absolutize and parse path to array + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [['M', 0, 0]]; + // if it's already a patharray, no need to parse it + if (array instanceof PathArray) return array; // prepare for parsing + + var s; + var paramCnt = { + 'M': 2, + 'L': 2, + 'H': 1, + 'V': 1, + 'C': 6, + 'S': 4, + 'Q': 4, + 'T': 2, + 'A': 7, + 'Z': 0 + }; + + if (typeof array === 'string') { + array = array.replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 + .replace(pathLetters, ' $& ') // put some room between letters and numbers + .replace(hyphen, '$1 -') // add space before hyphen + .trim() // trim + .split(delimiter); // split into array + } else { + array = array.reduce(function (prev, curr) { + return [].concat.call(prev, curr); + }, []); + } // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] + + + var result = []; + var p = new Point(); + var p0 = new Point(); + var index = 0; + var len = array.length; + + do { + // Test if we have a path letter + if (isPathLetter.test(array[index])) { + s = array[index]; + ++index; // If last letter was a move command and we got no new, it defaults to [L]ine + } else if (s === 'M') { + s = 'L'; + } else if (s === 'm') { + s = 'l'; + } + + result.push(pathHandlers[s].call(null, array.slice(index, index = index + paramCnt[s.toUpperCase()]).map(parseFloat), p, p0)); + } while (len > index); + + return result; + }, + // Get bounding box of path + bbox: function bbox() { + parser().path.setAttribute('d', this.toString()); + return parser.nodes.path.getBBox(); + } +}); + +var Morphable = +/*#__PURE__*/ +function () { + function Morphable(stepper) { + _classCallCheck(this, Morphable); + + // FIXME: the default stepper does not know about easing + this._stepper = stepper || new Ease('-'); + this._from = null; + this._to = null; + this._type = null; + this._context = null; + this._morphObj = null; + } + + _createClass(Morphable, [{ + key: "from", + value: function from(val) { + if (val == null) { + return this._from; + } + + this._from = this._set(val); + return this; + } + }, { + key: "to", + value: function to(val) { + if (val == null) { + return this._to; + } + + this._to = this._set(val); + return this; + } + }, { + key: "type", + value: function type(_type) { + // getter + if (_type == null) { + return this._type; + } // setter + + + this._type = _type; + return this; + } + }, { + key: "_set", + value: function _set$$1(value) { + if (!this._type) { + var type = _typeof(value); + + if (type === 'number') { + this.type(SVGNumber); + } else if (type === 'string') { + if (Color.isColor(value)) { + this.type(Color); + } else if (delimiter.test(value)) { + this.type(pathLetters.test(value) ? PathArray : SVGArray); + } else if (numberAndUnit.test(value)) { + this.type(SVGNumber); + } else { + this.type(NonMorphable); + } + } else if (morphableTypes.indexOf(value.constructor) > -1) { + this.type(value.constructor); + } else if (Array.isArray(value)) { + this.type(SVGArray); + } else if (type === 'object') { + this.type(ObjectBag); + } else { + this.type(NonMorphable); + } + } + + var result = new this._type(value).toArray(); + this._morphObj = this._morphObj || new this._type(); + this._context = this._context || Array.apply(null, Array(result.length)).map(Object); + return result; + } + }, { + key: "stepper", + value: function stepper(_stepper) { + if (_stepper == null) return this._stepper; + this._stepper = _stepper; + return this; + } + }, { + key: "done", + value: function done() { + var complete = this._context.map(this._stepper.done).reduce(function (last, curr) { + return last && curr; + }, true); + + return complete; + } + }, { + key: "at", + value: function at(pos) { + var _this = this; + + return this._morphObj.fromArray(this._from.map(function (i, index) { + return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context); + })); + } + }]); + + return Morphable; +}(); +var NonMorphable = +/*#__PURE__*/ +function () { + function NonMorphable() { + _classCallCheck(this, NonMorphable); + + this.init.apply(this, arguments); + } + + _createClass(NonMorphable, [{ + key: "init", + value: function init(val) { + val = Array.isArray(val) ? val[0] : val; + this.value = val; + } + }, { + key: "valueOf", + value: function valueOf() { + return this.value; + } + }, { + key: "toArray", + value: function toArray() { + return [this.value]; + } + }]); + + return NonMorphable; +}(); +var TransformBag = +/*#__PURE__*/ +function () { + function TransformBag() { + _classCallCheck(this, TransformBag); + + this.init.apply(this, arguments); + } + + _createClass(TransformBag, [{ + key: "init", + value: function init(obj) { + if (Array.isArray(obj)) { + obj = { + scaleX: obj[0], + scaleY: obj[1], + shear: obj[2], + rotate: obj[3], + translateX: obj[4], + translateY: obj[5], + originX: obj[6], + originY: obj[7] + }; + } + + Object.assign(this, TransformBag.defaults, obj); + } + }, { + key: "toArray", + value: function toArray() { + var v = this; + return [v.scaleX, v.scaleY, v.shear, v.rotate, v.translateX, v.translateY, v.originX, v.originY]; + } + }]); + + return TransformBag; +}(); +TransformBag.defaults = { + scaleX: 1, + scaleY: 1, + shear: 0, + rotate: 0, + translateX: 0, + translateY: 0, + originX: 0, + originY: 0 +}; +var ObjectBag = +/*#__PURE__*/ +function () { + function ObjectBag() { + _classCallCheck(this, ObjectBag); + + this.init.apply(this, arguments); + } + + _createClass(ObjectBag, [{ + key: "init", + value: function init(objOrArr) { + this.values = []; + + if (Array.isArray(objOrArr)) { + this.values = objOrArr; + return; + } + + var entries = Object.entries(objOrArr || {}).sort(function (a, b) { + return a[0] - b[0]; + }); + this.values = entries.reduce(function (last, curr) { + return last.concat(curr); + }, []); + } + }, { + key: "valueOf", + value: function valueOf() { + var obj = {}; + var arr = this.values; + + for (var i = 0, len = arr.length; i < len; i += 2) { + obj[arr[i]] = arr[i + 1]; + } + + return obj; + } + }, { + key: "toArray", + value: function toArray() { + return this.values; + } + }]); + + return ObjectBag; +}(); +var morphableTypes = [NonMorphable, TransformBag, ObjectBag]; +function registerMorphableType() { + var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + morphableTypes.push.apply(morphableTypes, _toConsumableArray([].concat(type))); +} +function makeMorphable() { + extend(morphableTypes, { + to: function to(val, args) { + return new Morphable().type(this.constructor).from(this.valueOf()).to(val, args); + }, + fromArray: function fromArray(arr) { + this.init(arr); + return this; + } + }); +} + +var time = window.performance || Date; + +var makeSchedule = function makeSchedule(runnerInfo) { + var start = runnerInfo.start; + var duration = runnerInfo.runner.duration(); + var end = start + duration; + return { + start: start, + duration: duration, + end: end, + runner: runnerInfo.runner + }; +}; + +var Timeline = +/*#__PURE__*/ +function () { + // Construct a new timeline on the given element + function Timeline() { + _classCallCheck(this, Timeline); + + this._timeSource = function () { + return time.now(); + }; + + this._dispatcher = document.createElement('div'); // Store the timing variables + + this._startTime = 0; + this._speed = 1.0; // Play control variables control how the animation proceeds + + this._reverse = false; + this._persist = 0; // Keep track of the running animations and their starting parameters + + this._nextFrame = null; + this._paused = false; + this._runners = []; + this._order = []; + this._time = 0; + this._lastSourceTime = 0; + this._lastStepTime = 0; + } + + _createClass(Timeline, [{ + key: "getEventTarget", + value: function getEventTarget() { + return this._dispatcher; + } + /** + * + */ + // schedules a runner on the timeline + + }, { + key: "schedule", + value: function schedule(runner, delay, when) { + if (runner == null) { + return this._runners.map(makeSchedule).sort(function (a, b) { + return a.start - b.start || a.duration - b.duration; + }); + } + + if (!this.active()) { + this._step(); + + if (when == null) { + when = 'now'; + } + } // The start time for the next animation can either be given explicitly, + // derived from the current timeline time or it can be relative to the + // last start time to chain animations direclty + + + var absoluteStartTime = 0; + delay = delay || 0; // Work out when to start the animation + + if (when == null || when === 'last' || when === 'after') { + // Take the last time and increment + absoluteStartTime = this._startTime; + } else if (when === 'absolute' || when === 'start') { + absoluteStartTime = delay; + delay = 0; + } else if (when === 'now') { + absoluteStartTime = this._time; + } else if (when === 'relative') { + var runnerInfo = this._runners[runner.id]; + + if (runnerInfo) { + absoluteStartTime = runnerInfo.start + delay; + delay = 0; + } + } else { + throw new Error('Invalid value for the "when" parameter'); + } // Manage runner + + + runner.unschedule(); + runner.timeline(this); + runner.time(-delay); // Save startTime for next runner + + this._startTime = absoluteStartTime + runner.duration() + delay; // Save runnerInfo + + this._runners[runner.id] = { + persist: this.persist(), + runner: runner, + start: absoluteStartTime // Save order and continue + + }; + + this._order.push(runner.id); + + this._continue(); + + return this; + } // Remove the runner from this timeline + + }, { + key: "unschedule", + value: function unschedule(runner) { + var index = this._order.indexOf(runner.id); + + if (index < 0) return this; + delete this._runners[runner.id]; + + this._order.splice(index, 1); + + runner.timeline(null); + return this; + } + }, { + key: "play", + value: function play() { + // Now make sure we are not paused and continue the animation + this._paused = false; + return this._continue(); + } + }, { + key: "pause", + value: function pause() { + // Cancel the next animation frame and pause + this._nextFrame = null; + this._paused = true; + return this; + } + }, { + key: "stop", + value: function stop() { + // Cancel the next animation frame and go to start + this.seek(-this._time); + return this.pause(); + } + }, { + key: "finish", + value: function finish() { + this.seek(Infinity); + return this.pause(); + } + }, { + key: "speed", + value: function speed(_speed) { + if (_speed == null) return this._speed; + this._speed = _speed; + return this; + } + }, { + key: "reverse", + value: function reverse(yes) { + var currentSpeed = this.speed(); + if (yes == null) return this.speed(-currentSpeed); + var positive = Math.abs(currentSpeed); + return this.speed(yes ? positive : -positive); + } + }, { + key: "seek", + value: function seek(dt) { + this._time += dt; + return this._continue(); + } + }, { + key: "time", + value: function time(_time) { + if (_time == null) return this._time; + this._time = _time; + return this; + } + }, { + key: "persist", + value: function persist(dtOrForever) { + if (dtOrForever == null) return this._persist; + this._persist = dtOrForever; + return this; + } + }, { + key: "source", + value: function source(fn) { + if (fn == null) return this._timeSource; + this._timeSource = fn; + return this; + } + }, { + key: "_step", + value: function _step() { + // If the timeline is paused, just do nothing + if (this._paused) return; // Get the time delta from the last time and update the time + // TODO: Deal with window.blur window.focus to pause animations + + var time = this._timeSource(); + + var dtSource = time - this._lastSourceTime; + var dtTime = this._speed * dtSource + (this._time - this._lastStepTime); + this._lastSourceTime = time; // Update the time + + this._time += dtTime; + this._lastStepTime = this._time; // this.fire('time', this._time) + // Run all of the runners directly + + var runnersLeft = false; + + for (var i = 0, len = this._order.length; i < len; i++) { + // Get and run the current runner and ignore it if its inactive + var runnerInfo = this._runners[this._order[i]]; + var runner = runnerInfo.runner; + var dt = dtTime; // Make sure that we give the actual difference + // between runner start time and now + + var dtToStart = this._time - runnerInfo.start; // Dont run runner if not started yet + + if (dtToStart < 0) { + runnersLeft = true; + continue; + } else if (dtToStart < dt) { + // Adjust dt to make sure that animation is on point + dt = dtToStart; + } + + if (!runner.active()) continue; // If this runner is still going, signal that we need another animation + // frame, otherwise, remove the completed runner + + var finished = runner.step(dt).done; + + if (!finished) { + runnersLeft = true; // continue + } else if (runnerInfo.persist !== true) { + // runner is finished. And runner might get removed + // TODO: Figure out end time of runner + var endTime = runner.duration() - runner.time() + this._time; + + if (endTime + this._persist < this._time) { + // Delete runner and correct index + delete this._runners[this._order[i]]; + this._order.splice(i--, 1) && --len; + runner.timeline(null); + } + } + } // Get the next animation frame to keep the simulation going + + + if (runnersLeft) { + this._nextFrame = Animator.frame(this._step.bind(this)); + } else { + this._nextFrame = null; + } + + return this; + } // Checks if we are running and continues the animation + + }, { + key: "_continue", + value: function _continue() { + if (this._paused) return this; + + if (!this._nextFrame) { + this._nextFrame = Animator.frame(this._step.bind(this)); + } + + return this; + } + }, { + key: "active", + value: function active() { + return !!this._nextFrame; + } + }]); + + return Timeline; +}(); +registerMethods({ + Element: { + timeline: function timeline() { + this._timeline = this._timeline || new Timeline(); + return this._timeline; + } + } +}); + +var Runner = +/*#__PURE__*/ +function (_EventTarget) { + _inherits(Runner, _EventTarget); + + function Runner(options) { + var _this; + + _classCallCheck(this, Runner); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Runner).call(this)); // Store a unique id on the runner, so that we can identify it later + + _this.id = Runner.id++; // Ensure a default value + + options = options == null ? timeline.duration : options; // Ensure that we get a controller + + options = typeof options === 'function' ? new Controller(options) : options; // Declare all of the variables + + _this._element = null; + _this._timeline = null; + _this.done = false; + _this._queue = []; // Work out the stepper and the duration + + _this._duration = typeof options === 'number' && options; + _this._isDeclarative = options instanceof Controller; + _this._stepper = _this._isDeclarative ? options : new Ease(); // We copy the current values from the timeline because they can change + + _this._history = {}; // Store the state of the runner + + _this.enabled = true; + _this._time = 0; + _this._last = 0; // Save transforms applied to this runner + + _this.transforms = new Matrix(); + _this.transformId = 1; // Looping variables + + _this._haveReversed = false; + _this._reverse = false; + _this._loopsDone = 0; + _this._swing = false; + _this._wait = 0; + _this._times = 1; + return _this; + } + /* + Runner Definitions + ================== + These methods help us define the runtime behaviour of the Runner or they + help us make new runners from the current runner + */ + + + _createClass(Runner, [{ + key: "element", + value: function element(_element) { + if (_element == null) return this._element; + this._element = _element; + + _element._prepareRunner(); + + return this; + } + }, { + key: "timeline", + value: function timeline$$1(_timeline) { + // check explicitly for undefined so we can set the timeline to null + if (typeof _timeline === 'undefined') return this._timeline; + this._timeline = _timeline; + return this; + } + }, { + key: "animate", + value: function animate(duration, delay, when) { + var o = Runner.sanitise(duration, delay, when); + var runner = new Runner(o.duration); + if (this._timeline) runner.timeline(this._timeline); + if (this._element) runner.element(this._element); + return runner.loop(o).schedule(delay, when); + } + }, { + key: "schedule", + value: function schedule(timeline$$1, delay, when) { + // The user doesn't need to pass a timeline if we already have one + if (!(timeline$$1 instanceof Timeline)) { + when = delay; + delay = timeline$$1; + timeline$$1 = this.timeline(); + } // If there is no timeline, yell at the user... + + + if (!timeline$$1) { + throw Error('Runner cannot be scheduled without timeline'); + } // Schedule the runner on the timeline provided + + + timeline$$1.schedule(this, delay, when); + return this; + } + }, { + key: "unschedule", + value: function unschedule() { + var timeline$$1 = this.timeline(); + timeline$$1 && timeline$$1.unschedule(this); + return this; + } + }, { + key: "loop", + value: function loop(times, swing, wait) { + // Deal with the user passing in an object + if (_typeof(times) === 'object') { + swing = times.swing; + wait = times.wait; + times = times.times; + } // Sanitise the values and store them + + + this._times = times || Infinity; + this._swing = swing || false; + this._wait = wait || 0; + return this; + } + }, { + key: "delay", + value: function delay(_delay) { + return this.animate(0, _delay); + } + /* + Basic Functionality + =================== + These methods allow us to attach basic functions to the runner directly + */ + + }, { + key: "queue", + value: function queue(initFn, runFn, isTransform) { + this._queue.push({ + initialiser: initFn || noop, + runner: runFn || noop, + isTransform: isTransform, + initialised: false, + finished: false + }); + + var timeline$$1 = this.timeline(); + timeline$$1 && this.timeline()._continue(); + return this; + } + }, { + key: "during", + value: function during(fn) { + return this.queue(null, fn); + } + }, { + key: "after", + value: function after(fn) { + return this.on('finish', fn); + } + /* + Runner animation methods + ======================== + Control how the animation plays + */ + + }, { + key: "time", + value: function time(_time) { + if (_time == null) { + return this._time; + } + + var dt = _time - this._time; + this.step(dt); + return this; + } + }, { + key: "duration", + value: function duration() { + return this._times * (this._wait + this._duration) - this._wait; + } + }, { + key: "loops", + value: function loops(p) { + var loopDuration = this._duration + this._wait; + + if (p == null) { + var loopsDone = Math.floor(this._time / loopDuration); + var relativeTime = this._time - loopsDone * loopDuration; + var position = relativeTime / this._duration; + return Math.min(loopsDone + position, this._times); + } + + var whole = Math.floor(p); + var partial = p % 1; + var time = loopDuration * whole + this._duration * partial; + return this.time(time); + } + }, { + key: "position", + value: function position(p) { + // Get all of the variables we need + var x = this._time; + var d = this._duration; + var w = this._wait; + var t = this._times; + var s = this._swing; + var r = this._reverse; + var position; + + if (p == null) { + /* + This function converts a time to a position in the range [0, 1] + The full explanation can be found in this desmos demonstration + https://www.desmos.com/calculator/u4fbavgche + The logic is slightly simplified here because we can use booleans + */ + // Figure out the value without thinking about the start or end time + var f = function f(x) { + var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)); + var backwards = swinging && !r || !swinging && r; + var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards; + var clipped = Math.max(Math.min(uncliped, 1), 0); + return clipped; + }; // Figure out the value by incorporating the start time + + + var endTime = t * (w + d) - w; + position = x <= 0 ? Math.round(f(1e-5)) : x < endTime ? f(x) : Math.round(f(endTime - 1e-5)); + return position; + } // Work out the loops done and add the position to the loops done + + + var loopsDone = Math.floor(this.loops()); + var swingForward = s && loopsDone % 2 === 0; + var forwards = swingForward && !r || r && swingForward; + position = loopsDone + (forwards ? p : 1 - p); + return this.loops(position); + } + }, { + key: "progress", + value: function progress(p) { + if (p == null) { + return Math.min(1, this._time / this.duration()); + } + + return this.time(p * this.duration()); + } + }, { + key: "step", + value: function step(dt) { + // If we are inactive, this stepper just gets skipped + if (!this.enabled) return this; // Update the time and get the new position + + dt = dt == null ? 16 : dt; + this._time += dt; + var position = this.position(); // Figure out if we need to run the stepper in this frame + + var running = this._lastPosition !== position && this._time >= 0; + this._lastPosition = position; // Figure out if we just started + + var duration = this.duration(); + var justStarted = this._lastTime < 0 && this._time > 0; + var justFinished = this._lastTime < this._time && this.time > duration; + this._lastTime = this._time; + + if (justStarted) { + this.fire('start', this); + } // Work out if the runner is finished set the done flag here so animations + // know, that they are running in the last step (this is good for + // transformations which can be merged) + + + var declarative = this._isDeclarative; + this.done = !declarative && !justFinished && this._time >= duration; // Call initialise and the run function + + if (running || declarative) { + this._initialise(running); // clear the transforms on this runner so they dont get added again and again + + + this.transforms = new Matrix(); + + var converged = this._run(declarative ? dt : position); + + this.fire('step', this); + } // correct the done flag here + // declaritive animations itself know when they converged + + + this.done = this.done || converged && declarative; + + if (this.done) { + this.fire('finish', this); + } + + return this; + } + }, { + key: "finish", + value: function finish() { + return this.step(Infinity); + } + }, { + key: "reverse", + value: function reverse(_reverse) { + this._reverse = _reverse == null ? !this._reverse : _reverse; + return this; + } + }, { + key: "ease", + value: function ease(fn) { + this._stepper = new Ease(fn); + return this; + } + }, { + key: "active", + value: function active(enabled) { + if (enabled == null) return this.enabled; + this.enabled = enabled; + return this; + } + /* + Private Methods + =============== + Methods that shouldn't be used externally + */ + // Save a morpher to the morpher list so that we can retarget it later + + }, { + key: "_rememberMorpher", + value: function _rememberMorpher(method, morpher) { + this._history[method] = { + morpher: morpher, + caller: this._queue[this._queue.length - 1] + }; + } // Try to set the target for a morpher if the morpher exists, otherwise + // do nothing and return false + + }, { + key: "_tryRetarget", + value: function _tryRetarget(method, target) { + if (this._history[method]) { + // if the last method wasnt even initialised, throw it away + if (!this._history[method].caller.initialised) { + var index = this._queue.indexOf(this._history[method].caller); + + this._queue.splice(index, 1); + + return false; + } // for the case of transformations, we use the special retarget function + // which has access to the outer scope + + + if (this._history[method].caller.isTransform) { + this._history[method].caller.isTransform(target); // for everything else a simple morpher change is sufficient + + } else { + this._history[method].morpher.to(target); + } + + this._history[method].caller.finished = false; + var timeline$$1 = this.timeline(); + timeline$$1 && timeline$$1._continue(); + return true; + } + + return false; + } // Run each initialise function in the runner if required + + }, { + key: "_initialise", + value: function _initialise(running) { + // If we aren't running, we shouldn't initialise when not declarative + if (!running && !this._isDeclarative) return; // Loop through all of the initialisers + + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current initialiser + var current = this._queue[i]; // Determine whether we need to initialise + + var needsIt = this._isDeclarative || !current.initialised && running; + running = !current.finished; // Call the initialiser if we need to + + if (needsIt && running) { + current.initialiser.call(this); + current.initialised = true; + } + } + } // Run each run function for the position or dt given + + }, { + key: "_run", + value: function _run(positionOrDt) { + // Run all of the _queue directly + var allfinished = true; + + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current function to run + var current = this._queue[i]; // Run the function if its not finished, we keep track of the finished + // flag for the sake of declarative _queue + + var converged = current.runner.call(this, positionOrDt); + current.finished = current.finished || converged === true; + allfinished = allfinished && current.finished; + } // We report when all of the constructors are finished + + + return allfinished; + } + }, { + key: "addTransform", + value: function addTransform(transform, index) { + this.transforms.lmultiplyO(transform); + return this; + } + }, { + key: "clearTransform", + value: function clearTransform() { + this.transforms = new Matrix(); + return this; + } + }], [{ + key: "sanitise", + value: function sanitise(duration, delay, when) { + // Initialise the default parameters + var times = 1; + var swing = false; + var wait = 0; + duration = duration || timeline.duration; + delay = delay || timeline.delay; + when = when || 'last'; // If we have an object, unpack the values + + if (_typeof(duration) === 'object' && !(duration instanceof Stepper)) { + delay = duration.delay || delay; + when = duration.when || when; + swing = duration.swing || swing; + times = duration.times || times; + wait = duration.wait || wait; + duration = duration.duration || timeline.duration; + } + + return { + duration: duration, + delay: delay, + swing: swing, + times: times, + wait: wait, + when: when + }; + } + }]); + + return Runner; +}(EventTarget); +Runner.id = 0; + +var FakeRunner = function FakeRunner() { + var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix(); + var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; + var done = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + + _classCallCheck(this, FakeRunner); + + this.transforms = transforms; + this.id = id; + this.done = done; +}; + +extend([Runner, FakeRunner], { + mergeWith: function mergeWith(runner) { + return new FakeRunner(runner.transforms.lmultiply(this.transforms), runner.id); + } +}); // FakeRunner.emptyRunner = new FakeRunner() + +var lmultiply = function lmultiply(last, curr) { + return last.lmultiplyO(curr); +}; + +var getRunnerTransform = function getRunnerTransform(runner) { + return runner.transforms; +}; + +function mergeTransforms() { + // Find the matrix to apply to the element and apply it + var runners = this._transformationRunners.runners; + var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix()); + this.transform(netTransform); + + this._transformationRunners.merge(); + + if (this._transformationRunners.length() === 1) { + this._frameId = null; + } +} + +var RunnerArray = +/*#__PURE__*/ +function () { + function RunnerArray() { + _classCallCheck(this, RunnerArray); + + this.runners = []; + this.ids = []; + } + + _createClass(RunnerArray, [{ + key: "add", + value: function add(runner) { + if (this.runners.includes(runner)) return; + var id = runner.id + 1; + var leftSibling = this.ids.reduce(function (last, curr) { + if (curr > last && curr < id) return curr; + return last; + }, 0); + var index = this.ids.indexOf(leftSibling) + 1; + this.ids.splice(index, 0, id); + this.runners.splice(index, 0, runner); + return this; + } + }, { + key: "getByID", + value: function getByID(id) { + return this.runners[this.ids.indexOf(id + 1)]; + } + }, { + key: "remove", + value: function remove(id) { + var index = this.ids.indexOf(id + 1); + this.ids.splice(index, 1); + this.runners.splice(index, 1); + return this; + } + }, { + key: "merge", + value: function merge() { + var _this2 = this; + + var lastRunner = null; + this.runners.forEach(function (runner, i) { + if (lastRunner && runner.done && lastRunner.done) { + _this2.remove(runner.id); + + _this2.edit(lastRunner.id, runner.mergeWith(lastRunner)); + } + + lastRunner = runner; + }); + return this; + } + }, { + key: "edit", + value: function edit(id, newRunner) { + var index = this.ids.indexOf(id + 1); + this.ids.splice(index, 1, id); + this.runners.splice(index, 1, newRunner); + return this; + } + }, { + key: "length", + value: function length() { + return this.ids.length; + } + }, { + key: "clearBefore", + value: function clearBefore(id) { + var deleteCnt = this.ids.indexOf(id + 1) || 1; + this.ids.splice(0, deleteCnt, 0); + this.runners.splice(0, deleteCnt, new FakeRunner()); + return this; + } + }]); + + return RunnerArray; +}(); + +var frameId = 0; +registerMethods({ + Element: { + animate: function animate(duration, delay, when) { + var o = Runner.sanitise(duration, delay, when); + var timeline$$1 = this.timeline(); + return new Runner(o.duration).loop(o).element(this).timeline(timeline$$1).schedule(delay, when); + }, + delay: function delay(by, when) { + return this.animate(0, by, when); + }, + // this function searches for all runners on the element and deletes the ones + // which run before the current one. This is because absolute transformations + // overwfrite anything anyway so there is no need to waste time computing + // other runners + _clearTransformRunnersBefore: function _clearTransformRunnersBefore(currentRunner) { + this._transformationRunners.clearBefore(currentRunner.id); + }, + _currentTransform: function _currentTransform(current) { + return this._transformationRunners.runners // we need the equal sign here to make sure, that also transformations + // on the same runner which execute before the current transformation are + // taken into account + .filter(function (runner) { + return runner.id <= current.id; + }).map(getRunnerTransform).reduce(lmultiply, new Matrix()); + }, + addRunner: function addRunner(runner) { + this._transformationRunners.add(runner); + + Animator.transform_frame(mergeTransforms.bind(this), this._frameId); + }, + _prepareRunner: function _prepareRunner() { + if (this._frameId == null) { + this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix(this))); + this._frameId = frameId++; + } + } + } +}); +extend(Runner, { + attr: function attr(a, v) { + return this.styleAttr('attr', a, v); + }, + // Add animatable styles + css: function css(s, v) { + return this.styleAttr('css', s, v); + }, + styleAttr: function styleAttr(type, name, val) { + // apply attributes individually + if (_typeof(name) === 'object') { + for (var key in val) { + this.styleAttr(type, key, val[key]); + } + } + + var morpher = new Morphable(this._stepper).to(val); + this.queue(function () { + morpher = morpher.from(this.element()[type](name)); + }, function (pos) { + this.element()[type](name, morpher.at(pos)); + return morpher.done(); + }); + return this; + }, + zoom: function zoom(level, point) { + var morpher = new Morphable(this._stepper).to(new SVGNumber(level)); + this.queue(function () { + morpher = morpher.from(this.zoom()); + }, function (pos) { + this.element().zoom(morpher.at(pos), point); + return morpher.done(); + }); + return this; + }, + + /** + ** absolute transformations + **/ + // + // M v -----|-----(D M v = F v)------|-----> T v + // + // 1. define the final state (T) and decompose it (once) + // t = [tx, ty, the, lam, sy, sx] + // 2. on every frame: pull the current state of all previous transforms + // (M - m can change) + // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] + // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) + // - Note F(0) = M + // - Note F(1) = T + // 4. Now you get the delta matrix as a result: D = F * inv(M) + transform: function transform(transforms, relative, affine) { + // If we have a declarative function, we should retarget it if possible + relative = transforms.relative || relative; + + if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { + return this; + } // Parse the parameters + + + var isMatrix = Matrix.isMatrixLike(transforms); + affine = transforms.affine != null ? transforms.affine : affine != null ? affine : !isMatrix; // Create a morepher and set its type + + var morpher = new Morphable().type(affine ? TransformBag : Matrix).stepper(this._stepper); + var origin; + var element; + var current; + var currentAngle; + var startTransform; + + function setup() { + // make sure element and origin is defined + element = element || this.element(); + origin = origin || getOrigin(transforms, element); + startTransform = new Matrix(relative ? undefined : element); // add the runner to the element so it can merge transformations + + element.addRunner(this); // Deactivate all transforms that have run so far if we are absolute + + if (!relative) { + element._clearTransformRunnersBefore(this); + } + } + + function run(pos) { + // clear all other transforms before this in case something is saved + // on this runner. We are absolute. We dont need these! + if (!relative) this.clearTransform(); + + var _transform = new Point(origin).transform(element._currentTransform(this)), + x = _transform.x, + y = _transform.y; + + var target = new Matrix(_objectSpread({}, transforms, { + origin: [x, y] + })); + var start = this._isDeclarative && current ? current : startTransform; + + if (affine) { + target = target.decompose(x, y); + start = start.decompose(x, y); // Get the current and target angle as it was set + + var rTarget = target.rotate; + var rCurrent = start.rotate; // Figure out the shortest path to rotate directly + + var possibilities = [rTarget - 360, rTarget, rTarget + 360]; + var distances = possibilities.map(function (a) { + return Math.abs(a - rCurrent); + }); + var shortest = Math.min.apply(Math, _toConsumableArray(distances)); + var index = distances.indexOf(shortest); + target.rotate = possibilities[index]; + } + + if (relative) { + // we have to be careful here not to overwrite the rotation + // with the rotate method of Matrix + if (!isMatrix) { + target.rotate = transforms.rotate || 0; + } + + if (this._isDeclarative && currentAngle) { + start.rotate = currentAngle; + } + } + + morpher.from(start); + morpher.to(target); + var affineParameters = morpher.at(pos); + currentAngle = affineParameters.rotate; + current = new Matrix(affineParameters); + this.addTransform(current); + return morpher.done(); + } + + function retarget(newTransforms) { + // only get a new origin if it changed since the last call + if ((newTransforms.origin || 'center').toString() !== (transforms.origin || 'center').toString()) { + origin = getOrigin(transforms, element); + } // overwrite the old transformations with the new ones + + + transforms = _objectSpread({}, newTransforms, { + origin: origin + }); + } + + this.queue(setup, run, retarget); + this._isDeclarative && this._rememberMorpher('transform', morpher); + return this; + }, + // Animatable x-axis + x: function x(_x, relative) { + return this._queueNumber('x', _x); + }, + // Animatable y-axis + y: function y(_y) { + return this._queueNumber('y', _y); + }, + dx: function dx(x) { + return this._queueNumberDelta('dx', x); + }, + dy: function dy(y) { + return this._queueNumberDelta('dy', y); + }, + _queueNumberDelta: function _queueNumberDelta(method, to) { + to = new SVGNumber(to); // Try to change the target if we have this method already registerd + + if (this._tryRetargetDelta(method, to)) return this; // Make a morpher and queue the animation + + var morpher = new Morphable(this._stepper).to(to); + this.queue(function () { + var from = this.element()[method](); + morpher.from(from); + morpher.to(from + to); + }, function (pos) { + this.element()[method](morpher.at(pos)); + return morpher.done(); + }); // Register the morpher so that if it is changed again, we can retarget it + + this._rememberMorpher(method, morpher); + + return this; + }, + _queueObject: function _queueObject(method, to) { + // Try to change the target if we have this method already registerd + if (this._tryRetarget(method, to)) return this; // Make a morpher and queue the animation + + var morpher = new Morphable(this._stepper).to(to); + this.queue(function () { + morpher.from(this.element()[method]()); + }, function (pos) { + this.element()[method](morpher.at(pos)); + return morpher.done(); + }); // Register the morpher so that if it is changed again, we can retarget it + + this._rememberMorpher(method, morpher); + + return this; + }, + _queueNumber: function _queueNumber(method, value) { + return this._queueObject(method, new SVGNumber(value)); + }, + // Animatable center x-axis + cx: function cx(x) { + return this._queueNumber('cx', x); + }, + // Animatable center y-axis + cy: function cy(y) { + return this._queueNumber('cy', y); + }, + // Add animatable move + move: function move(x, y) { + return this.x(x).y(y); + }, + // Add animatable center + center: function center(x, y) { + return this.cx(x).cy(y); + }, + // Add animatable size + size: function size(width, height) { + // animate bbox based size for all other elements + var box; + + if (!width || !height) { + box = this._element.bbox(); + } + + if (!width) { + width = box.width / box.height * height; + } + + if (!height) { + height = box.height / box.width * width; + } + + return this.width(width).height(height); + }, + // Add animatable width + width: function width(_width) { + return this._queueNumber('width', _width); + }, + // Add animatable height + height: function height(_height) { + return this._queueNumber('height', _height); + }, + // Add animatable plot + plot: function plot(a, b, c, d) { + // Lines can be plotted with 4 arguments + if (arguments.length === 4) { + return this.plot([a, b, c, d]); + } // FIXME: this needs to be rewritten such that the element is only accesed + // in the init function + + + return this._queueObject('plot', new this._element.MorphArray(a)); + /* + var morpher = this._element.morphArray().to(a) + this.queue(function () { + morpher.from(this._element.array()) + }, function (pos) { + this._element.plot(morpher.at(pos)) + }) + return this + */ + }, + // Add leading method + leading: function leading(value) { + return this._queueNumber('leading', value); + }, + // Add animatable viewbox + viewbox: function viewbox(x, y, width, height) { + return this._queueObject('viewbox', new Box(x, y, width, height)); + }, + update: function update(o) { + if (_typeof(o) !== 'object') { + return this.update({ + offset: arguments[0], + color: arguments[1], + opacity: arguments[2] + }); + } + + 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', o.offset); + return this; + } +}); + +var sugar = { + stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], + fill: ['color', 'opacity', 'rule'], + prefix: function prefix(t, a) { + return a === 'color' ? t : t + '-' + a; + } // Add sugar for fill and stroke + +}; +['fill', 'stroke'].forEach(function (m) { + var extension = {}; + var i; + + extension[m] = function (o) { + if (typeof o === 'undefined') { + return this; + } + + if (typeof o === 'string' || Color.isRgb(o) || o instanceof Element) { + this.attr(m, o); + } else { + // set all attributes from sugar.fill and sugar.stroke list + for (i = sugar[m].length - 1; i >= 0; i--) { + if (o[sugar[m][i]] != null) { + this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]]); + } + } + } + + return this; + }; + + registerMethods(['Shape', 'Runner'], extension); +}); +registerMethods(['Element', 'Runner'], { + // Let the user set the matrix directly + matrix: function matrix(mat, b, c, d, e, f) { + // Act as a getter + if (mat == null) { + return new Matrix(this); + } // Act as a setter, the user can pass a matrix or a set of numbers + + + return this.attr('transform', new Matrix(mat, b, c, d, e, f)); + }, + // Map rotation to transform + rotate: function rotate(angle, cx, cy) { + return this.transform({ + rotate: angle, + ox: cx, + oy: cy + }, true); + }, + // Map skew to transform + skew: function skew(x, y, cx, cy) { + return arguments.length === 1 || arguments.length === 3 ? this.transform({ + skew: x, + ox: y, + oy: cx + }, true) : this.transform({ + skew: [x, y], + ox: cx, + oy: cy + }, true); + }, + shear: function shear(lam, cx, cy) { + return this.transform({ + shear: lam, + ox: cx, + oy: cy + }, true); + }, + // Map scale to transform + scale: function scale(x, y, cx, cy) { + return arguments.length === 1 || arguments.length === 3 ? this.transform({ + scale: x, + ox: y, + oy: cx + }, true) : this.transform({ + scale: [x, y], + ox: cx, + oy: cy + }, true); + }, + // Map translate to transform + translate: function translate(x, y) { + return this.transform({ + translate: [x, y] + }, true); + }, + // Map relative translations to transform + relative: function relative(x, y) { + return this.transform({ + relative: [x, y] + }, true); + }, + // Map flip to transform + flip: function flip(direction, around) { + var directionString = typeof direction === 'string' ? direction : isFinite(direction) ? 'both' : 'both'; + var origin = direction === 'both' && isFinite(around) ? [around, around] : direction === 'x' ? [around, 0] : direction === 'y' ? [0, around] : isFinite(direction) ? [direction, direction] : [0, 0]; + this.transform({ + flip: directionString, + origin: origin + }, true); + }, + // Opacity + opacity: function opacity(value) { + return this.attr('opacity', value); + }, + // Relative move over x axis + dx: function dx(x) { + return this.x(new SVGNumber(x).plus(this instanceof Runner ? 0 : this.x()), true); + }, + // Relative move over y axis + dy: function dy(y) { + return this.y(new SVGNumber(y).plus(this instanceof Runner ? 0 : this.y()), true); + }, + // Relative move over x and y axes + dmove: function dmove(x, y) { + return this.dx(x).dy(y); + } +}); +registerMethods('radius', { + // Add x and y radius + radius: function radius(x, y) { + var type = (this._element || this).type; + return type === 'radialGradient' || type === 'radialGradient' ? this.attr('r', new SVGNumber(x)) : this.rx(x).ry(y == null ? x : y); + } +}); +registerMethods('Path', { + // Get path length + length: function length() { + return this.node.getTotalLength(); + }, + // Get point at length + pointAt: function pointAt(length) { + return new Point(this.node.getPointAtLength(length)); + } +}); +registerMethods(['Element', 'Runner'], { + // Set font + font: function font(a, v) { + if (_typeof(a) === 'object') { + for (v in a) { + this.font(v, a[v]); + } + } + + return a === 'leading' ? this.leading(v) : a === 'anchor' ? this.attr('text-anchor', v) : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style' ? this.attr('font-' + a, v) : this.attr(a, v); + } +}); + +function untransform() { + return this.attr('transform', null); +} // merge the whole transformation chain into one matrix and returns it + +function matrixify() { + var matrix = (this.attr('transform') || ''). // split transformations + split(transforms).slice(0, -1).map(function (str) { + // generate key => value pairs + var kv = str.trim().split('('); + return [kv[0], kv[1].split(delimiter).map(function (str) { + return parseFloat(str); + })]; + }).reverse() // merge every transformation into one matrix + .reduce(function (matrix, transform) { + if (transform[0] === 'matrix') { + return matrix.lmultiply(Matrix.fromArray(transform[1])); + } + + return matrix[transform[0]].apply(matrix, transform[1]); + }, new Matrix()); + return matrix; +} // add an element to another parent without changing the visual representation on the screen + +function toParent(parent) { + if (this === parent) return this; + var ctm = this.screenCTM(); + var pCtm = parent.screenCTM().inverse(); + this.addTo(parent).untransform().transform(pCtm.multiply(ctm)); + return this; +} // same as above with parent equals root-svg + +function toDoc() { + return this.toParent(this.doc()); +} // Add transformations + +function transform(o, relative) { + // Act as a getter if no object was passed + if (o == null || typeof o === 'string') { + var decomposed = new Matrix(this).decompose(); + return decomposed[o] || decomposed; + } + + if (!Matrix.isMatrixLike(o)) { + // Set the origin according to the defined transform + o = _objectSpread({}, o, { + origin: getOrigin(o, this) + }); + } // The user can pass a boolean, an Element or an Matrix or nothing + + + var cleanRelative = relative === true ? this : relative || false; + var result = new Matrix(cleanRelative).transform(o); + return this.attr('transform', result); +} +registerMethods('Element', { + untransform: untransform, + matrixify: matrixify, + toParent: toParent, + toDoc: toDoc, + transform: transform +}); + +// FIXME: import this to runner + +function rx(rx) { + return this.attr('rx', rx); +} // Radius y value + +function ry(ry) { + return this.attr('ry', ry); +} // Move over x-axis + +function x(x) { + return x == null ? this.cx() - this.rx() : this.cx(x + this.rx()); +} // Move over y-axis + +function y(y) { + return y == null ? this.cy() - this.ry() : this.cy(y + this.ry()); +} // Move by center over x-axis + +function cx(x) { + return x == null ? this.attr('cx') : this.attr('cx', x); +} // Move by center over y-axis + +function cy(y) { + return y == null ? this.attr('cy') : this.attr('cy', y); +} // Set width of element + +function width(width) { + return width == null ? this.rx() * 2 : this.rx(new SVGNumber(width).divide(2)); +} // Set height of element + +function height(height) { + return height == null ? this.ry() * 2 : this.ry(new SVGNumber(height).divide(2)); +} // Custom size function + +function 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)); +} + +var circled = /*#__PURE__*/Object.freeze({ + rx: rx, + ry: ry, + x: x, + y: y, + cx: cx, + cy: cy, + width: width, + height: height, + size: size +}); + +var Shape = +/*#__PURE__*/ +function (_Element) { + _inherits(Shape, _Element); + + function Shape() { + _classCallCheck(this, Shape); + + return _possibleConstructorReturn(this, _getPrototypeOf(Shape).apply(this, arguments)); + } + + return Shape; +}(Element); + +var Circle = +/*#__PURE__*/ +function (_Shape) { + _inherits(Circle, _Shape); + + function Circle(node) { + _classCallCheck(this, Circle); + + return _possibleConstructorReturn(this, _getPrototypeOf(Circle).call(this, nodeOrNew('circle', node), Circle)); + } + + _createClass(Circle, [{ + key: "radius", + value: function radius(r) { + return this.attr('r', r); + } // Radius x value + + }, { + key: "rx", + value: function rx$$1(_rx) { + return this.attr('r', _rx); + } // Alias radius x value + + }, { + key: "ry", + value: function ry$$1(_ry) { + return this.rx(_ry); + } + }]); + + return Circle; +}(Shape); +extend(Circle, { + x: x, + y: y, + cx: cx, + cy: cy, + width: width, + height: height, + size: size +}); +registerMethods({ + Element: { + // Create circle element + circle: function circle(size$$1) { + return this.put(new Circle()).radius(new SVGNumber(size$$1).divide(2)).move(0, 0); + } + } +}); +register(Circle); + +var Ellipse = +/*#__PURE__*/ +function (_Shape) { + _inherits(Ellipse, _Shape); + + function Ellipse(node) { + _classCallCheck(this, Ellipse); + + return _possibleConstructorReturn(this, _getPrototypeOf(Ellipse).call(this, nodeOrNew('ellipse', node), Ellipse)); + } + + return Ellipse; +}(Shape); +extend(Ellipse, circled); +registerMethods('Container', { + // Create an ellipse + ellipse: function ellipse(width$$1, height$$1) { + return this.put(new Ellipse()).size(width$$1, height$$1).move(0, 0); + } +}); +register(Ellipse); + +var Stop = +/*#__PURE__*/ +function (_Element) { + _inherits(Stop, _Element); + + function Stop(node) { + _classCallCheck(this, Stop); + + return _possibleConstructorReturn(this, _getPrototypeOf(Stop).call(this, nodeOrNew('stop', node), Stop)); + } // add color stops + + + _createClass(Stop, [{ + key: "update", + value: function 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)); + return this; + } + }]); + + return Stop; +}(Element); +register(Stop); + +function baseFind(query, parent) { + return map((parent || document).querySelectorAll(query), function (node) { + return adopt(node); + }); +} // Scoped find method + +function find(query) { + return baseFind(query, this.node); +} +registerMethods('Dom', { + find: find +}); + +// FIXME: add to runner +function from(x, y) { + return (this._element || this).type === 'radialGradient' ? this.attr({ + fx: new SVGNumber(x), + fy: new SVGNumber(y) + }) : this.attr({ + x1: new SVGNumber(x), + y1: new SVGNumber(y) + }); +} +function to(x, y) { + return (this._element || this).type === 'radialGradient' ? this.attr({ + cx: new SVGNumber(x), + cy: new SVGNumber(y) + }) : this.attr({ + x2: new SVGNumber(x), + y2: new SVGNumber(y) + }); +} + +var gradiented = /*#__PURE__*/Object.freeze({ + from: from, + to: to +}); + +var Gradient = +/*#__PURE__*/ +function (_Container) { + _inherits(Gradient, _Container); + + function Gradient(type) { + _classCallCheck(this, Gradient); + + return _possibleConstructorReturn(this, _getPrototypeOf(Gradient).call(this, nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type), Gradient)); + } // Add a color stop + + + _createClass(Gradient, [{ + key: "stop", + value: function stop(offset, color, opacity) { + return this.put(new Stop()).update(offset, color, opacity); + } // Update gradient + + }, { + key: "update", + value: function update(block) { + // remove all stops + this.clear(); // invoke passed block + + if (typeof block === 'function') { + block.call(this, this); + } + + return this; + } // Return the fill id + + }, { + key: "url", + value: function url() { + return 'url(#' + this.id() + ')'; + } // Alias string convertion to fill + + }, { + key: "toString", + value: function toString() { + return this.url(); + } // custom attr to handle transform + + }, { + key: "attr", + value: function attr(a, b, c) { + if (a === 'transform') a = 'gradientTransform'; + return _get(_getPrototypeOf(Gradient.prototype), "attr", this).call(this, a, b, c); + } + }, { + key: "targets", + value: function targets() { + return baseFind('svg [fill*="' + this.id() + '"]'); + } + }, { + key: "bbox", + value: function bbox() { + return new Box(); + } + }]); + + return Gradient; +}(Container); +extend(Gradient, gradiented); +registerMethods({ + Container: { + // Create gradient element in defs + gradient: function gradient(type, block) { + return this.defs().gradient(type, block); + } + }, + // define gradient + Defs: { + gradient: function gradient(type, block) { + return this.put(new Gradient(type)).update(block); + } + } +}); +register(Gradient); + +var Pattern = +/*#__PURE__*/ +function (_Container) { + _inherits(Pattern, _Container); + + // Initialize node + function Pattern(node) { + _classCallCheck(this, Pattern); + + return _possibleConstructorReturn(this, _getPrototypeOf(Pattern).call(this, nodeOrNew('pattern', node), Pattern)); + } // Return the fill id + + + _createClass(Pattern, [{ + key: "url", + value: function url() { + return 'url(#' + this.id() + ')'; + } // Update pattern by rebuilding + + }, { + key: "update", + value: function update(block) { + // remove content + this.clear(); // invoke passed block + + if (typeof block === 'function') { + block.call(this, this); + } + + return this; + } // Alias string convertion to fill + + }, { + key: "toString", + value: function toString() { + return this.url(); + } // custom attr to handle transform + + }, { + key: "attr", + value: function attr(a, b, c) { + if (a === 'transform') a = 'patternTransform'; + return _get(_getPrototypeOf(Pattern.prototype), "attr", this).call(this, a, b, c); + } + }, { + key: "targets", + value: function targets() { + return baseFind('svg [fill*="' + this.id() + '"]'); + } + }, { + key: "bbox", + value: function bbox() { + return new Box(); + } + }]); + + return Pattern; +}(Container); +registerMethods({ + Container: { + // Create pattern element in defs + pattern: function pattern(width, height, block) { + return this.defs().pattern(width, height, block); + } + }, + Defs: { + pattern: function pattern(width, height, block) { + return this.put(new Pattern()).update(block).attr({ + x: 0, + y: 0, + width: width, + height: height, + patternUnits: 'userSpaceOnUse' + }); + } + } +}); +register(Pattern); + +var Image = +/*#__PURE__*/ +function (_Shape) { + _inherits(Image, _Shape); + + function Image(node) { + _classCallCheck(this, Image); + + return _possibleConstructorReturn(this, _getPrototypeOf(Image).call(this, nodeOrNew('image', node), Image)); + } // (re)load image + + + _createClass(Image, [{ + key: "load", + value: function load(url, callback) { + if (!url) return this; + var img = new window.Image(); + 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 (p instanceof Pattern) { + // ensure pattern size if not set + if (p.width() === 0 && p.height() === 0) { + p.size(this.width(), this.height()); + } + } + + if (typeof callback === 'function') { + callback.call(this, { + width: img.width, + height: img.height, + ratio: img.width / img.height, + url: url + }); + } + }, this); + on(img, 'load error', function () { + // dont forget to unbind memory leaking events + off(img); + }); + return this.attr('href', img.src = url, xlink); + } + }, { + key: "attrHook", + value: function attrHook(obj) { + var _this = this; + + return obj.doc().defs().pattern(0, 0, function (pattern) { + pattern.add(_this); + }); + } + }]); + + return Image; +}(Shape); +registerMethods({ + Container: { + // create image element, load image and set its size + image: function image(source, callback) { + return this.put(new Image()).size(0, 0).load(source, callback); + } + } +}); +register(Image); + +var PointArray = subClassArray('PointArray', SVGArray); +extend(PointArray, { + // Convert array to string + toString: function toString() { + // convert to a poly point string + for (var i = 0, il = this.length, array = []; i < il; i++) { + array.push(this[i].join(',')); + } + + return array.join(' '); + }, + // Convert array to line object + toLine: function toLine() { + return { + x1: this[0][0], + y1: this[0][1], + x2: this[1][0], + y2: this[1][1] + }; + }, + // Get morphed array at given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; // generate morphed point string + + for (var i = 0, il = this.length, array = []; i < il; i++) { + array.push([this[i][0] + (this.destination[i][0] - this[i][0]) * pos, this[i][1] + (this.destination[i][1] - this[i][1]) * pos]); + } + + return new PointArray(array); + }, + // Parse point string and flat array + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [[0, 0]]; + var points = []; // if it is an array + + if (array instanceof Array) { + // and it is not flat, there is no need to parse it + if (array[0] instanceof Array) { + return array; + } + } else { + // Else, it is considered as a string + // parse points + array = array.trim().split(delimiter).map(parseFloat); + } // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints + // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. + + + if (array.length % 2 !== 0) array.pop(); // wrap points in two-tuples and parse points as floats + + for (var i = 0, len = array.length; i < len; i = i + 2) { + points.push([array[i], array[i + 1]]); + } + + return points; + }, + // Move point string + move: function move(x, y) { + var box = this.bbox(); // get relative offset + + x -= box.x; + y -= box.y; // move every point + + if (!isNaN(x) && !isNaN(y)) { + for (var i = this.length - 1; i >= 0; i--) { + this[i] = [this[i][0] + x, this[i][1] + y]; + } + } + + return this; + }, + // Resize poly string + size: function size(width, height) { + var i; + var box = this.bbox(); // recalculate position of all points according to new size + + for (i = this.length - 1; i >= 0; i--) { + if (box.width) this[i][0] = (this[i][0] - box.x) * width / box.width + box.x; + if (box.height) this[i][1] = (this[i][1] - box.y) * height / box.height + box.y; + } + + return this; + }, + // Get bounding box of points + bbox: function bbox() { + var maxX = -Infinity; + var maxY = -Infinity; + var minX = Infinity; + var minY = Infinity; + this.forEach(function (el) { + maxX = Math.max(el[0], maxX); + maxY = Math.max(el[1], maxY); + minX = Math.min(el[0], minX); + minY = Math.min(el[1], minY); + }); + return { + x: minX, + y: minY, + width: maxX - minX, + height: maxY - minY + }; + } +}); + +var MorphArray = PointArray; // Move by left top corner over x-axis + +function x$1(x) { + return x == null ? this.bbox().x : this.move(x, this.bbox().y); +} // Move by left top corner over y-axis + +function y$1(y) { + return y == null ? this.bbox().y : this.move(this.bbox().x, y); +} // Set width of element + +function width$1(width) { + var b = this.bbox(); + return width == null ? b.width : this.size(width, b.height); +} // Set height of element + +function height$1(height) { + var b = this.bbox(); + return height == null ? b.height : this.size(b.width, height); +} + +var pointed = /*#__PURE__*/Object.freeze({ + MorphArray: MorphArray, + x: x$1, + y: y$1, + width: width$1, + height: height$1 +}); + +var Line = +/*#__PURE__*/ +function (_Shape) { + _inherits(Line, _Shape); + + // Initialize node + function Line(node) { + _classCallCheck(this, Line); + + return _possibleConstructorReturn(this, _getPrototypeOf(Line).call(this, nodeOrNew('line', node), Line)); + } // Get array + + + _createClass(Line, [{ + key: "array", + value: function array() { + return new PointArray([[this.attr('x1'), this.attr('y1')], [this.attr('x2'), this.attr('y2')]]); + } // Overwrite native plot() method + + }, { + key: "plot", + value: function plot(x1, y1, x2, y2) { + if (x1 == null) { + return this.array(); + } else if (typeof y1 !== 'undefined') { + x1 = { + x1: x1, + y1: y1, + x2: x2, + y2: y2 + }; + } else { + x1 = new PointArray(x1).toLine(); + } + + return this.attr(x1); + } // Move by left top corner + + }, { + key: "move", + value: function move(x, y) { + return this.attr(this.array().move(x, y).toLine()); + } // Set element size to given width and height + + }, { + key: "size", + value: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.attr(this.array().size(p.width, p.height).toLine()); + } + }]); + + return Line; +}(Shape); +extend(Line, pointed); +registerMethods({ + Container: { + // Create a line element + line: function line() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + // 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]); + } + } +}); +register(Line); + +var Marker = +/*#__PURE__*/ +function (_Container) { + _inherits(Marker, _Container); + + // Initialize node + function Marker(node) { + _classCallCheck(this, Marker); + + return _possibleConstructorReturn(this, _getPrototypeOf(Marker).call(this, nodeOrNew('marker', node), Marker)); + } // Set width of element + + + _createClass(Marker, [{ + key: "width", + value: function width(_width) { + return this.attr('markerWidth', _width); + } // Set height of element + + }, { + key: "height", + value: function height(_height) { + return this.attr('markerHeight', _height); + } // Set marker refX and refY + + }, { + key: "ref", + value: function ref(x, y) { + return this.attr('refX', x).attr('refY', y); + } // Update marker + + }, { + key: "update", + value: function update(block) { + // remove all content + this.clear(); // invoke passed block + + if (typeof block === 'function') { + block.call(this, this); + } + + return this; + } // Return the fill id + + }, { + key: "toString", + value: function toString() { + return 'url(#' + this.id() + ')'; + } + }]); + + return Marker; +}(Container); +registerMethods({ + Container: { + marker: function marker(width, height, block) { + // Create marker element in defs + return this.defs().marker(width, height, block); + } + }, + Defs: { + // Create marker + marker: function marker(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); + } + }, + marker: { + // Create and attach markers + marker: function marker(_marker, width, height, block) { + var attr = ['marker']; // Build attribute name + + 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); + return this.attr(attr, _marker); + } + } +}); +register(Marker); + +var Path = +/*#__PURE__*/ +function (_Shape) { + _inherits(Path, _Shape); + + // Initialize node + function Path(node) { + _classCallCheck(this, Path); + + return _possibleConstructorReturn(this, _getPrototypeOf(Path).call(this, nodeOrNew('path', node), Path)); + } // Get array + + + _createClass(Path, [{ + key: "array", + value: function array() { + return this._array || (this._array = new PathArray(this.attr('d'))); + } // Plot new path + + }, { + key: "plot", + value: function plot(d) { + return d == null ? this.array() : this.clear().attr('d', typeof d === 'string' ? d : this._array = new PathArray(d)); + } // Clear array cache + + }, { + key: "clear", + value: function clear() { + delete this._array; + return this; + } // Move by left top corner + + }, { + key: "move", + value: function move(x, y) { + return this.attr('d', this.array().move(x, y)); + } // Move by left top corner over x-axis + + }, { + key: "x", + value: function x(_x) { + return _x == null ? this.bbox().x : this.move(_x, this.bbox().y); + } // Move by left top corner over y-axis + + }, { + key: "y", + value: function y(_y) { + return _y == null ? this.bbox().y : this.move(this.bbox().x, _y); + } // Set element size to given width and height + + }, { + key: "size", + value: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.attr('d', this.array().size(p.width, p.height)); + } // Set width of element + + }, { + key: "width", + value: function width(_width) { + return _width == null ? this.bbox().width : this.size(_width, this.bbox().height); + } // Set height of element + + }, { + key: "height", + value: function height(_height) { + return _height == null ? this.bbox().height : this.size(this.bbox().width, _height); + } + }, { + key: "targets", + value: function targets() { + return baseFind('svg textpath [href*="' + this.id() + '"]'); + } + }]); + + return Path; +}(Shape); // Define morphable array +Path.prototype.MorphArray = PathArray; // Add parent method + +registerMethods({ + Container: { + // Create a wrapped path element + path: function path(d) { + // make sure plot is called as a setter + return this.put(new Path()).plot(d || new PathArray()); + } + } +}); +register(Path); + +function array() { + return this._array || (this._array = new PointArray(this.attr('points'))); +} // Plot new path + +function plot(p) { + return p == null ? this.array() : this.clear().attr('points', typeof p === 'string' ? p : this._array = new PointArray(p)); +} // Clear array cache + +function clear() { + delete this._array; + return this; +} // Move by left top corner + +function move(x, y) { + return this.attr('points', this.array().move(x, y)); +} // Set element size to given width and height + +function size$1(width, height) { + var p = proportionalSize(this, width, height); + return this.attr('points', this.array().size(p.width, p.height)); +} + +var poly = /*#__PURE__*/Object.freeze({ + array: array, + plot: plot, + clear: clear, + move: move, + size: size$1 +}); + +var Polygon = +/*#__PURE__*/ +function (_Shape) { + _inherits(Polygon, _Shape); + + // Initialize node + function Polygon(node) { + _classCallCheck(this, Polygon); + + return _possibleConstructorReturn(this, _getPrototypeOf(Polygon).call(this, nodeOrNew('polygon', node), Polygon)); + } + + return Polygon; +}(Shape); +registerMethods({ + Container: { + // Create a wrapped polygon element + polygon: function polygon(p) { + // make sure plot is called as a setter + return this.put(new Polygon()).plot(p || new PointArray()); + } + } +}); +extend(Polygon, pointed); +extend(Polygon, poly); +register(Polygon); + +var Polyline = +/*#__PURE__*/ +function (_Shape) { + _inherits(Polyline, _Shape); + + // Initialize node + function Polyline(node) { + _classCallCheck(this, Polyline); + + return _possibleConstructorReturn(this, _getPrototypeOf(Polyline).call(this, nodeOrNew('polyline', node), Polyline)); + } + + return Polyline; +}(Shape); +registerMethods({ + Container: { + // Create a wrapped polygon element + polyline: function polyline(p) { + // make sure plot is called as a setter + return this.put(new Polyline()).plot(p || new PointArray()); + } + } +}); +extend(Polyline, pointed); +extend(Polyline, poly); +register(Polyline); + +var Rect = +/*#__PURE__*/ +function (_Shape) { + _inherits(Rect, _Shape); + + // Initialize node + function Rect(node) { + _classCallCheck(this, Rect); + + return _possibleConstructorReturn(this, _getPrototypeOf(Rect).call(this, nodeOrNew('rect', node), Rect)); + } // FIXME: unify with circle + // Radius x value + + + _createClass(Rect, [{ + key: "rx", + value: function rx(_rx) { + return this.attr('rx', _rx); + } // Radius y value + + }, { + key: "ry", + value: function ry(_ry) { + return this.attr('ry', _ry); + } + }]); + + return Rect; +}(Shape); +registerMethods({ + Container: { + // Create a rect element + rect: function rect(width, height) { + return this.put(new Rect()).size(width, height); + } + } +}); +register(Rect); + +// Create plain text node +function plain(text) { + // clear if build mode is disabled + if (this._build === false) { + this.clear(); + } // create text node + + + this.node.appendChild(document.createTextNode(text)); + return this; +} // FIXME: Does this also work for textpath? +// Get length of text element + +function length() { + return this.node.getComputedTextLength(); +} + +var textable = /*#__PURE__*/Object.freeze({ + plain: plain, + length: length +}); + +var Text = +/*#__PURE__*/ +function (_Shape) { + _inherits(Text, _Shape); + + // Initialize node + function Text(node) { + var _this; + + _classCallCheck(this, Text); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Text).call(this, nodeOrNew('text', node), Text)); + _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']); + + return _this; + } // Move over x-axis + + + _createClass(Text, [{ + key: "x", + value: function x(_x) { + // act as getter + if (_x == null) { + return this.attr('x'); + } + + return this.attr('x', _x); + } // Move over y-axis + + }, { + key: "y", + value: function y(_y) { + var oy = this.attr('y'); + var o = typeof oy === 'number' ? oy - this.bbox().y : 0; // act as getter + + if (_y == null) { + return typeof oy === 'number' ? oy - o : oy; + } + + return this.attr('y', typeof _y === 'number' ? _y + o : _y); + } // Move center over x-axis + + }, { + key: "cx", + value: function cx(x) { + return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2); + } // Move center over y-axis + + }, { + key: "cy", + value: function cy(y) { + return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2); + } // Set the text content + + }, { + key: "text", + value: function text(_text) { + // act as getter + if (_text === undefined) { + // FIXME use children() or each() + var children = this.node.childNodes; + var firstLine = 0; + _text = ''; + + 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; + 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) { + _text += '\n'; + } // add content of this node + + + _text += children[i].textContent; + } + + return _text; + } // remove existing content + + + this.clear().build(true); + + if (typeof _text === 'function') { + // call block + _text.call(this, this); + } else { + // store text and make sure text is not blank + _text = _text.split('\n'); // build new lines + + 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(); + } // Set / get leading + + }, { + key: "leading", + value: function leading(value) { + // act as getter + if (value == null) { + return this.dom.leading; + } // act as setter + + + this.dom.leading = new SVGNumber(value); + return this.rebuild(); + } // Rebuild appearance type + + }, { + key: "rebuild", + value: function rebuild(_rebuild) { + // store new rebuild flag if given + if (typeof _rebuild === 'boolean') { + this._rebuild = _rebuild; + } // define position of all lines + + + if (this._rebuild) { + var self = this; + var blankLineOffset = 0; + var dy = this.dom.leading * new SVGNumber(this.attr('font-size')); + this.each(function () { + if (this.dom.newLined) { + this.attr('x', self.attr('x')); + + if (this.text() === '\n') { + blankLineOffset += dy; + } else { + this.attr('dy', dy + blankLineOffset); + blankLineOffset = 0; + } + } + }); + this.fire('rebuild'); + } + + return this; + } // Enable / disable build mode + + }, { + key: "build", + value: function build(_build) { + this._build = !!_build; + return this; + } // overwrite method from parent to set data properly + + }, { + key: "setData", + value: function setData(o) { + this.dom = o; + this.dom.leading = new SVGNumber(o.leading || 1.3); + return this; + } + }]); + + return Text; +}(Shape); +extend(Text, textable); +registerMethods({ + Container: { + // Create text element + text: function text(_text2) { + return this.put(new Text()).text(_text2); + }, + // Create plain text element + plain: function plain$$1(text) { + return this.put(new Text()).plain(text); + } + } +}); +register(Text); + +var Tspan = +/*#__PURE__*/ +function (_Text) { + _inherits(Tspan, _Text); + + // Initialize node + function Tspan(node) { + _classCallCheck(this, Tspan); + + return _possibleConstructorReturn(this, _getPrototypeOf(Tspan).call(this, nodeOrNew('tspan', node), Tspan)); + } // Set text content + + + _createClass(Tspan, [{ + key: "text", + value: function text(_text) { + if (_text == null) return this.node.textContent + (this.dom.newLined ? '\n' : ''); + typeof _text === 'function' ? _text.call(this, this) : this.plain(_text); + return this; + } // Shortcut dx + + }, { + key: "dx", + value: function dx(_dx) { + return this.attr('dx', _dx); + } // Shortcut dy + + }, { + key: "dy", + value: function dy(_dy) { + return this.attr('dy', _dy); + } // Create new line + + }, { + key: "newLine", + value: function newLine() { + // fetch text parent + 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 Tspan; +}(Text); +extend(Tspan, textable); +registerMethods({ + Tspan: { + tspan: function tspan(text) { + var tspan = new Tspan(); // clear if build mode is disabled + + if (!this._build) { + this.clear(); + } // add new tspan + + + this.node.appendChild(tspan.node); + return tspan.text(text); + } + } +}); +register(Tspan); + +var Bare = +/*#__PURE__*/ +function (_Container) { + _inherits(Bare, _Container); + + function Bare(node) { + _classCallCheck(this, Bare); + + return _possibleConstructorReturn(this, _getPrototypeOf(Bare).call(this, nodeOrNew(node, typeof node === 'string' ? null : node), Bare)); + } + + _createClass(Bare, [{ + key: "words", + value: function words(text) { + // remove contents + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } // create text node + + + this.node.appendChild(document.createTextNode(text)); + return this; + } + }]); + + return Bare; +}(Container); +register(Bare); +registerMethods('Container', { + // Create an element that is not described by SVG.js + element: function element(node, inherit) { + return this.put(new Bare(node, inherit)); + } +}); + +var ClipPath = +/*#__PURE__*/ +function (_Container) { + _inherits(ClipPath, _Container); + + function ClipPath(node) { + _classCallCheck(this, ClipPath); + + return _possibleConstructorReturn(this, _getPrototypeOf(ClipPath).call(this, nodeOrNew('clipPath', node), ClipPath)); + } // Unclip all clipped elements and remove itself + + + _createClass(ClipPath, [{ + key: "remove", + value: function remove() { + // unclip all targets + this.targets().forEach(function (el) { + el.unclip(); + }); // remove clipPath from parent + + return _get(_getPrototypeOf(ClipPath.prototype), "remove", this).call(this); + } + }, { + key: "targets", + value: function targets() { + return baseFind('svg [clip-path*="' + this.id() + '"]'); + } + }]); + + return ClipPath; +}(Container); +registerMethods({ + Container: { + // Create clipping element + clip: function clip() { + return this.defs().put(new ClipPath()); + } + }, + Element: { + // Distribute clipPath to svg element + clipWith: function clipWith(element) { + // use given clip or create a new one + var clipper = element instanceof ClipPath ? element : this.parent().clip().add(element); // apply mask + + return this.attr('clip-path', 'url("#' + clipper.id() + '")'); + }, + // Unclip element + unclip: function unclip() { + return this.attr('clip-path', null); + }, + clipper: function clipper() { + return this.reference('clip-path'); + } + } +}); +register(ClipPath); + +var G = +/*#__PURE__*/ +function (_Container) { + _inherits(G, _Container); + + function G(node) { + _classCallCheck(this, G); + + return _possibleConstructorReturn(this, _getPrototypeOf(G).call(this, nodeOrNew('g', node), G)); + } + + return G; +}(Container); +registerMethods({ + Element: { + // Create a group element + group: function group() { + return this.put(new G()); + } + } +}); +register(G); + +var HtmlNode = +/*#__PURE__*/ +function (_Dom) { + _inherits(HtmlNode, _Dom); + + function HtmlNode(node) { + _classCallCheck(this, HtmlNode); + + return _possibleConstructorReturn(this, _getPrototypeOf(HtmlNode).call(this, node, HtmlNode)); + } + + return HtmlNode; +}(Dom); +register(HtmlNode); + +var A = +/*#__PURE__*/ +function (_Container) { + _inherits(A, _Container); + + function A(node) { + _classCallCheck(this, A); + + return _possibleConstructorReturn(this, _getPrototypeOf(A).call(this, nodeOrNew('a', node), A)); + } // Link url + + + _createClass(A, [{ + key: "to", + value: function to(url) { + return this.attr('href', url, xlink); + } // Link target attribute + + }, { + key: "target", + value: function target(_target) { + return this.attr('target', _target); + } + }]); + + return A; +}(Container); +registerMethods({ + Container: { + // Create a hyperlink element + link: function link(url) { + return this.put(new A()).to(url); + } + }, + Element: { + // Create a hyperlink element + linkTo: function linkTo(url) { + var link = new A(); + + if (typeof url === 'function') { + url.call(link, link); + } else { + link.to(url); + } + + return this.parent().put(link).put(this); + } + } +}); +register(A); + +var Mask = +/*#__PURE__*/ +function (_Container) { + _inherits(Mask, _Container); + + // Initialize node + function Mask(node) { + _classCallCheck(this, Mask); + + return _possibleConstructorReturn(this, _getPrototypeOf(Mask).call(this, nodeOrNew('mask', node), Mask)); + } // Unmask all masked elements and remove itself + + + _createClass(Mask, [{ + key: "remove", + value: function remove() { + // unmask all targets + this.targets().forEach(function (el) { + el.unmask(); + }); // remove mask from parent + + return _get(_getPrototypeOf(Mask.prototype), "remove", this).call(this); + } + }, { + key: "targets", + value: function targets() { + return baseFind('svg [mask*="' + this.id() + '"]'); + } + }]); + + return Mask; +}(Container); +registerMethods({ + Container: { + mask: function mask() { + return this.defs().put(new Mask()); + } + }, + Element: { + // Distribute mask to svg element + maskWith: function maskWith(element) { + // use given mask or create a new one + var masker = element instanceof Mask ? element : this.parent().mask().add(element); // apply mask + + return this.attr('mask', 'url("#' + masker.id() + '")'); + }, + // Unmask element + unmask: function unmask() { + return this.attr('mask', null); + }, + masker: function masker() { + return this.reference('mask'); + } + } +}); +register(Mask); + +var _Symbol = +/*#__PURE__*/ +function (_Container) { + _inherits(_Symbol, _Container); + + // Initialize node + function _Symbol(node) { + _classCallCheck(this, _Symbol); + + return _possibleConstructorReturn(this, _getPrototypeOf(_Symbol).call(this, nodeOrNew('symbol', node), _Symbol)); + } + + return _Symbol; +}(Container); +registerMethods({ + Container: { + symbol: function symbol() { + return this.put(new _Symbol()); + } + } +}); +register(_Symbol); + +var TextPath = +/*#__PURE__*/ +function (_Text) { + _inherits(TextPath, _Text); + + // Initialize node + function TextPath(node) { + _classCallCheck(this, TextPath); + + return _possibleConstructorReturn(this, _getPrototypeOf(TextPath).call(this, nodeOrNew('textPath', node), TextPath)); + } // return the array of the path track element + + + _createClass(TextPath, [{ + key: "array", + value: function array() { + var track = this.track(); + return track ? track.array() : null; + } // Plot path if any + + }, { + key: "plot", + value: function plot(d) { + var track = this.track(); + var pathArray = null; + + if (track) { + pathArray = track.plot(d); + } + + return d == null ? pathArray : this; + } // Get the path element + + }, { + key: "track", + value: function track() { + return this.reference('href'); + } + }]); + + return TextPath; +}(Text); +registerMethods({ + Container: { + textPath: function textPath(text, path) { + return this.defs().path(path).text(text).addTo(this); + } + }, + Text: { + // Create path for text to run on + path: function path(track) { + var path = new TextPath(); // if d is a path, reuse it + + if (!(track instanceof Path)) { + // create path element + track = this.doc().defs().path(track); + } // link textPath to path and add content + + + path.attr('href', '#' + track, xlink); // add textPath element as child node and return textPath + + return this.put(path); + }, + // FIXME: make this plural? + // Get the textPath children + textPath: function textPath() { + return this.find('textPath'); + } + }, + Path: { + // creates a textPath from this path + text: function text(_text) { + if (_text instanceof Text) { + var txt = _text.text(); + + return _text.clear().path(this).text(txt); + } + + return this.parent().put(new Text()).path(this).text(_text); + } // FIXME: Maybe add `targets` to get all textPaths associated with this path + + } +}); +TextPath.prototype.MorphArray = PathArray; +register(TextPath); + +var Use = +/*#__PURE__*/ +function (_Shape) { + _inherits(Use, _Shape); + + function Use(node) { + _classCallCheck(this, Use); + + return _possibleConstructorReturn(this, _getPrototypeOf(Use).call(this, nodeOrNew('use', node), Use)); + } // Use element as a reference + + + _createClass(Use, [{ + key: "element", + value: function element(_element, file) { + // Set lined element + return this.attr('href', (file || '') + '#' + _element, xlink); + } + }]); + + return Use; +}(Shape); +registerMethods({ + Container: { + // Create a use element + use: function use(element, file) { + return this.put(new Use()).element(element, file); + } + } +}); +register(Use); + +/* Optional Modules */ +extend([Doc$1, Symbol, Image, Pattern, Marker], getMethodsFor('viewbox')); +extend([Line, Polyline, Polygon, Path], getMethodsFor('marker')); +extend(Text, getMethodsFor('Text')); +extend(Path, getMethodsFor('Path')); +extend(Defs, getMethodsFor('Defs')); +extend([Text, Tspan], getMethodsFor('Tspan')); +extend([Rect, Ellipse, Circle, Gradient], getMethodsFor('radius')); +extend(EventTarget, getMethodsFor('EventTarget')); +extend(Dom, getMethodsFor('Dom')); +extend(Element, getMethodsFor('Element')); +extend(Shape, getMethodsFor('Shape')); // extend(Element, getConstructor('Memory')) + +extend(Container, getMethodsFor('Container')); +registerMorphableType([SVGNumber, Color, Box, Matrix, SVGArray, PointArray, PathArray]); +makeMorphable(); + +export { Morphable, registerMorphableType, makeMorphable, TransformBag, ObjectBag, NonMorphable, defaults, parser, baseFind as find, Animator, Controller, Ease, PID, Spring, easing, Queue, Runner, Timeline, SVGArray, Box, Color, EventTarget, Matrix, SVGNumber, PathArray, Point, PointArray, Bare, Circle, ClipPath, Container, Defs, Doc$1 as Doc, Dom, Element, Ellipse, Gradient, G, HtmlNode, A, Image, Line, Marker, Mask, Path, Pattern, Polygon, Polyline, Rect, Shape, Stop, _Symbol as Symbol, Text, TextPath, Tspan, Use, map, filter, radians, degrees, camelCase, capitalize, proportionalSize, getOrigin, ns, xmlns, xlink, svgjs, on, off, dispatch, root, makeNode, makeInstance, nodeOrNew, adopt, register, getClass, eid, assignNewId, extend }; diff --git a/dist/svg.js b/dist/svg.js index 946db81..e218c15 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -6,7 +6,7 @@ * @copyright Wout Fierens * @license MIT * -* BUILT: Mon Nov 05 2018 21:52:42 GMT+0100 (GMT+01:00) +* BUILT: Tue Nov 06 2018 13:43:56 GMT+0100 (GMT+01:00) */; var SVG = (function () { 'use strict'; @@ -216,158 +216,140 @@ var SVG = (function () { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } - var Queue = - /*#__PURE__*/ - function () { - function Queue() { - _classCallCheck(this, Queue); - - this._first = null; - this._last = null; - } + var methods = {}; + function registerMethods(name, m) { + if (Array.isArray(name)) { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; - _createClass(Queue, [{ - key: "push", - value: function push(value) { - // An item stores an id and the provided value - var item = value.next ? value : { - value: value, - next: null, - prev: null // Deal with the queue being empty or populated + try { + for (var _iterator = name[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var _name = _step.value; + registerMethods(_name, m); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } - }; + return; + } - if (this._last) { - item.prev = this._last; - this._last.next = item; - this._last = item; - } else { - this._last = item; - this._first = item; - } // Update the length and return the current item + if (_typeof(name) === 'object') { + var _arr = Object.entries(name); + for (var _i = 0; _i < _arr.length; _i++) { + var _arr$_i = _slicedToArray(_arr[_i], 2), + _name2 = _arr$_i[0], + _m = _arr$_i[1]; - return item; + registerMethods(_name2, _m); } - }, { - key: "shift", - value: function shift() { - // Check if we have a value - var remove = this._first; - if (!remove) return null; // If we do, remove it and relink things - - this._first = remove.next; - if (this._first) this._first.prev = null; - this._last = this._first ? this._last : null; - return remove.value; - } // Shows us the first item in the list - }, { - key: "first", - value: function first() { - return this._first && this._first.value; - } // Shows us the last item in the list + return; + } - }, { - key: "last", - value: function last() { - return this._last && this._last.value; - } // Removes the item that was returned from the push + methods[name] = Object.assign(methods[name] || {}, m); + } + function getMethodsFor(name) { + return methods[name] || {}; + } - }, { - key: "remove", - value: function remove(item) { - // Relink the previous item - if (item.prev) item.prev.next = item.next; - if (item.next) item.next.prev = item.prev; - if (item === this._last) this._last = item.prev; - if (item === this._first) this._first = item.next; // Invalidate item + function siblings() { + return this.parent().children(); + } // Get the curent position siblings - item.prev = null; - item.next = null; - } - }]); + function position() { + return this.parent().index(this); + } // Get the next element (will return null if there is none) - return Queue; - }(); + function next() { + return this.siblings()[this.position() + 1]; + } // Get the next element (will return null if there is none) - var Animator = { - nextDraw: null, - frames: new Queue(), - timeouts: new Queue(), - timer: window.performance || window.Date, - transforms: [], - frame: function frame(fn) { - // Store the node - var node = Animator.frames.push({ - run: fn - }); // Request an animation frame if we don't have one + function prev() { + return this.siblings()[this.position() - 1]; + } // Send given element one step forward - if (Animator.nextDraw === null) { - Animator.nextDraw = window.requestAnimationFrame(Animator._draw); - } // Return the node so we can remove it easily + function forward() { + var i = this.position() + 1; + var p = this.parent(); // move node one step forward + p.removeElement(this).add(this, i); // make sure defs node is always at the top - return node; - }, - transform_frame: function transform_frame(fn, id) { - Animator.transforms[id] = fn; - }, - timeout: function timeout(fn, delay) { - delay = delay || 0; // Work out when the event should fire + if (typeof p.isRoot === 'function' && p.isRoot()) { + p.node.appendChild(p.defs().node); + } - var time = Animator.timer.now() + delay; // Add the timeout to the end of the queue + return this; + } // Send given element one step backward - var node = Animator.timeouts.push({ - run: fn, - time: time - }); // Request another animation frame if we need one + function backward() { + var i = this.position(); - if (Animator.nextDraw === null) { - Animator.nextDraw = window.requestAnimationFrame(Animator._draw); - } + if (i > 0) { + this.parent().removeElement(this).add(this, i - 1); + } - return node; - }, - cancelFrame: function cancelFrame(node) { - Animator.frames.remove(node); - }, - clearTimeout: function clearTimeout(node) { - Animator.timeouts.remove(node); - }, - _draw: function _draw(now) { - // Run all the timeouts we can run, if they are not ready yet, add them - // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) - var nextTimeout = null; - var lastTimeout = Animator.timeouts.last(); + return this; + } // Send given element all the way to the front - while (nextTimeout = Animator.timeouts.shift()) { - // Run the timeout if its time, or push it to the end - if (now >= nextTimeout.time) { - nextTimeout.run(); - } else { - Animator.timeouts.push(nextTimeout); - } // If we hit the last item, we should stop shifting out more items + function front() { + var p = this.parent(); // Move node forward + p.node.appendChild(this.node); // Make sure defs node is always at the top - if (nextTimeout === lastTimeout) break; - } // Run all of the animation frames + if (typeof p.isRoot === 'function' && p.isRoot()) { + p.node.appendChild(p.defs().node); + } + return this; + } // Send given element all the way to the back - var nextFrame = null; - var lastFrame = Animator.frames.last(); + function back() { + if (this.position() > 0) { + this.parent().removeElement(this).add(this, 0); + } - while (nextFrame !== lastFrame && (nextFrame = Animator.frames.shift())) { - nextFrame.run(); - } + return this; + } // Inserts a given element before the targeted element - Animator.transforms.forEach(function (el) { - el(); - }); // If we have remaining timeouts or frames, draw until we don't anymore + function before(element) { + element.remove(); + var i = this.position(); + this.parent().add(element, i); + return this; + } // Inserts a given element after the targeted element - Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() ? window.requestAnimationFrame(Animator._draw) : null; - } - }; + function after(element) { + element.remove(); + var i = this.position(); + this.parent().add(element, i + 1); + return this; + } + registerMethods('Dom', { + siblings: siblings, + position: position, + next: next, + prev: prev, + forward: forward, + backward: backward, + front: front, + back: back, + before: before, + after: after + }); // Parse unit value var numberAndUnit = /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i; // Parse hex value @@ -431,66 +413,84 @@ var SVG = (function () { dots: dots }); - /* eslint no-new-func: "off" */ - var subClassArray = function () { - try { - // try es6 subclassing - return Function('name', 'baseClass', '_constructor', ['baseClass = baseClass || Array', 'return {', '[name]: class extends baseClass {', 'constructor (...args) {', 'super(...args)', '_constructor && _constructor.apply(this, args)', '}', '}', '}[name]'].join('\n')); - } catch (e) { - // Use es5 approach - return function (name) { - var baseClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Array; + function classes() { + var attr = this.attr('class'); + return attr == null ? [] : attr.trim().split(delimiter); + } // Return true if class exists on the node, false otherwise - var _constructor = arguments.length > 2 ? arguments[2] : undefined; - var Arr = function Arr() { - baseClass.apply(this, arguments); - _constructor && _constructor.apply(this, arguments); - }; + function hasClass(name) { + return this.classes().indexOf(name) !== -1; + } // Add class to the node - Arr.prototype = Object.create(baseClass.prototype); - Arr.prototype.constructor = Arr; - return Arr; - }; + + function addClass(name) { + if (!this.hasClass(name)) { + var array = this.classes(); + array.push(name); + this.attr('class', array.join(' ')); } - }(); - // Default namespaces - var ns = 'http://www.w3.org/2000/svg'; - var xmlns = 'http://www.w3.org/2000/xmlns/'; - var xlink = 'http://www.w3.org/1999/xlink'; - var svgjs = 'http://svgjs.com/svgjs'; + return this; + } // Remove class from the node - var ns$1 = /*#__PURE__*/Object.freeze({ - ns: ns, - xmlns: xmlns, - xlink: xlink, - svgjs: svgjs - }); - var Base = function Base() { - _classCallCheck(this, Base); - }; + function removeClass(name) { + if (this.hasClass(name)) { + this.attr('class', this.classes().filter(function (c) { + return c !== name; + }).join(' ')); + } - function isNulledBox(box) { - return !box.w && !box.h && !box.x && !box.y; + return this; + } // Toggle the presence of a class on the node + + + function toggleClass(name) { + return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); } - function domContains(node) { - return (document.documentElement.contains || function (node) { - // This is IE - it does not support contains() for top-level SVGs - while (node.parentNode) { - node = node.parentNode; + + registerMethods('Dom', { + classes: classes, + hasClass: hasClass, + addClass: addClass, + removeClass: removeClass, + toggleClass: toggleClass + }); + + // Map function + function map(array, block) { + var i; + var il = array.length; + var result = []; + + for (i = 0; i < il; i++) { + result.push(block(array[i])); + } + + return result; + } // Filter function + + function filter(array, block) { + var i; + var il = array.length; + var result = []; + + for (i = 0; i < il; i++) { + if (block(array[i])) { + result.push(array[i]); } + } - return node === document; - }).call(document.documentElement, node); - } - function pathRegReplace(a, b, c, d) { - return c + d.replace(dots, ' .'); - } // creates deep clone of array + return result; + } // Degrees to radians + + function radians(d) { + return d % 360 * Math.PI / 180; + } // Radians to degrees - function matcher(el, selector) { - return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector); + function degrees(r) { + return r * 180 / Math.PI % 360; } // Convert dash-separated-string to camelCase function camelCase(s) { @@ -501,15 +501,6 @@ var SVG = (function () { function capitalize(s) { return s.charAt(0).toUpperCase() + s.slice(1); - } // Ensure to six-based hex - - function fullHex(hex$$1) { - return hex$$1.length === 4 ? ['#', hex$$1.substring(1, 2), hex$$1.substring(1, 2), hex$$1.substring(2, 3), hex$$1.substring(2, 3), hex$$1.substring(3, 4), hex$$1.substring(3, 4)].join('') : hex$$1; - } // Component to hex value - - function compToHex(comp) { - var hex$$1 = comp.toString(16); - return hex$$1.length === 1 ? '0' + hex$$1 : hex$$1; } // Calculate proportional width and height values when necessary function proportionalSize(element, width, height) { @@ -527,84 +518,6 @@ var SVG = (function () { width: width, height: height }; - } // Map matrix array to object - - function arrayToMatrix(a) { - return { - a: a[0], - b: a[1], - c: a[2], - d: a[3], - e: a[4], - f: a[5] - }; - } // Add centre point to transform object - - function arrayToString(a) { - for (var i = 0, il = a.length, s = ''; i < il; i++) { - s += a[i][0]; - - if (a[i][1] != null) { - s += a[i][1]; - - if (a[i][2] != null) { - s += ' '; - s += a[i][2]; - - if (a[i][3] != null) { - s += ' '; - s += a[i][3]; - s += ' '; - s += a[i][4]; - - if (a[i][5] != null) { - s += ' '; - s += a[i][5]; - s += ' '; - s += a[i][6]; - - if (a[i][7] != null) { - s += ' '; - s += a[i][7]; - } - } - } - } - } - } - - return s + ' '; - } // Add more bounding box properties - - function fullBox(b) { - if (b.x == null) { - b.x = 0; - b.y = 0; - b.width = 0; - b.height = 0; - } - - b.w = b.width; - b.h = b.height; - b.x2 = b.x + b.width; - b.y2 = b.y + b.height; - b.cx = b.x + b.width / 2; - b.cy = b.y + b.height / 2; - return b; - } // Get id from reference string - - function idFromReference(url) { - var m = (url || '').toString().match(reference); - if (m) return m[1]; - } // Create matrix array for looping - - var abcdef = 'abcdef'.split(''); - function closeEnough(a, b, threshold) { - return Math.abs(b - a) < (threshold || 1e-6); - } // move this to static matrix method - - function isMatrixLike(o) { - return o.a != null || o.b != null || o.c != null || o.d != null || o.e != null || o.f != null; } function getOrigin(o, element) { // Allow origin or around as the names @@ -637,286 +550,374 @@ var SVG = (function () { return [ox, oy]; } - var elements = {}; - var root = Symbol('root'); - function makeInstance(element) { - if (element instanceof Base) return element; - - if (_typeof(element) === 'object') { - return adopt(element); - } + function css(style, val) { + var ret = {}; - if (element == null) { - return new elements[root](); + if (arguments.length === 0) { + // get full style as object + this.node.style.cssText.split(/\s*;\s*/).filter(function (el) { + return !!el.length; + }).forEach(function (el) { + var t = el.split(/\s*:\s*/); + ret[t[0]] = t[1]; + }); + return ret; } - if (typeof element === 'string' && element.charAt(0) !== '<') { - return adopt(document.querySelector(element)); - } + if (arguments.length < 2) { + // get style properties in the array + if (Array.isArray(style)) { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; - var node = makeNode('svg'); - node.innerHTML = element; // We can use firstChild here because we know, - // that the first char is < and thus an element + try { + for (var _iterator = style[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var name = _step.value; + var cased = camelCase(name); + ret[cased] = this.node.style[cased]; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } - element = adopt(node.firstChild); - return element; - } // Adopt existing svg elements + return ret; + } // get style for property - function adopt(node) { - // check for presence of node - if (!node) return null; // make sure a node isn't already adopted - if (node.instance instanceof Base) return node.instance; + if (typeof style === 'string') { + return this.node.style[camelCase(style)]; + } // set styles in object - if (!(node instanceof window.SVGElement)) { - return new elements.HtmlNode(node); - } // initialize variables + if (_typeof(style) === 'object') { + for (var _name in style) { + // set empty string if null/undefined/'' was given + this.node.style[camelCase(_name)] = style[_name] == null || isBlank.test(style[_name]) ? '' : style[_name]; + } + } + } // set style for property - var element; // adopt with element-specific settings - if (node.nodeName === 'svg') { - element = new elements[root](node); - } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') { - element = new elements.Gradient(node); - } else if (elements[capitalize(node.nodeName)]) { - element = new elements[capitalize(node.nodeName)](node); - } else { - element = new elements.Bare(node); + if (arguments.length === 2) { + this.node.style[camelCase(style)] = val == null || isBlank.test(val) ? '' : val; } - return element; - } - function register(element) { - var name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : element.name; - var asRoot = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - elements[name] = element; - if (asRoot) elements[root] = element; - return element; - } - function getClass(name) { - return elements[name]; - } // Element id sequence - - var did = 1000; // Get next named element id + return this; + } // Show element - function eid(name) { - return 'Svgjs' + capitalize(name) + did++; - } // Deep new id assignment + function show() { + return this.css('display', ''); + } // Hide element - function assignNewId(node) { - // do the same for SVG child nodes as well - for (var i = node.children.length - 1; i >= 0; i--) { - assignNewId(node.children[i]); - } + function hide() { + return this.css('display', 'none'); + } // Is element visible? - if (node.id) { - return adopt(node).id(eid(node.nodeName)); - } - - return adopt(node); + function visible() { + return this.css('display') !== 'none'; } - - var adopter = /*#__PURE__*/Object.freeze({ - root: root, - makeInstance: makeInstance, - adopt: adopt, - register: register, - getClass: getClass, - eid: eid, - assignNewId: assignNewId + registerMethods('Dom', { + css: css, + show: show, + hide: hide, + visible: visible }); - function nodeOrNew(name, node) { - return node || makeNode(name); - } // Method for element creation + function data(a, v, r) { + if (_typeof(a) === 'object') { + for (v in a) { + this.data(v, a[v]); + } + } else if (arguments.length < 2) { + try { + return JSON.parse(this.attr('data-' + a)); + } catch (e) { + return this.attr('data-' + a); + } + } else { + this.attr('data-' + a, v === null ? null : r === true || typeof v === 'string' || typeof v === 'number' ? v : JSON.stringify(v)); + } - function makeNode(name) { - // create element - return document.createElementNS(ns, name); - } // Method for extending objects + return this; + } + registerMethods('Dom', { + data: data + }); - function extend(modules, methods) { - var key, i; - modules = Array.isArray(modules) ? modules : [modules]; + // Remember arbitrary data - for (i = modules.length - 1; i >= 0; i--) { - for (key in methods) { - modules[i].prototype[key] = methods[key]; + function remember(k, v) { + // remember every item in an object individually + if (_typeof(arguments[0]) === 'object') { + for (var key in k) { + this.remember(key, k[key]); } + } else if (arguments.length === 1) { + // retrieve memory + return this.memory()[k]; + } else { + // store memory + this.memory()[k] = v; } - } // FIXME: enhanced constructors here - function addFactory(modules, methods) { - extend(modules, methods); - } // Invent new element - - function invent(config) { - // Create element initializer - var initializer = typeof config.create === 'function' ? config.create : function (node) { - config.inherit.call(this, node || makeNode(config.create)); - }; // Inherit prototype + return this; + } // Erase a given memory - if (config.inherit) { - /* eslint new-cap: "off" */ - initializer.prototype = new config.inherit(); - initializer.prototype.constructor = initializer; - } // Extend with methods + function forget() { + if (arguments.length === 0) { + this._memory = {}; + } else { + for (var i = arguments.length - 1; i >= 0; i--) { + delete this.memory()[arguments[i]]; + } + } + return this; + } // return local memory object - if (config.extend) { - extend(initializer, config.extend); - } // Attach construct method to parent + function memory() { + return this._memory = this._memory || {}; + } + registerMethods('Dom', { + remember: remember, + forget: forget, + memory: memory + }); + function fullHex(hex$$1) { + return hex$$1.length === 4 ? ['#', hex$$1.substring(1, 2), hex$$1.substring(1, 2), hex$$1.substring(2, 3), hex$$1.substring(2, 3), hex$$1.substring(3, 4), hex$$1.substring(3, 4)].join('') : hex$$1; + } // Component to hex value - if (config.construct) { - extend(config.parent || getClass('Container'), config.construct); - } - return initializer; + function compToHex(comp) { + var hex$$1 = comp.toString(16); + return hex$$1.length === 1 ? '0' + hex$$1 : hex$$1; } - var tools = /*#__PURE__*/Object.freeze({ - nodeOrNew: nodeOrNew, - makeNode: makeNode, - extend: extend, - addFactory: addFactory, - invent: invent - }); - - var SVGArray = subClassArray('SVGArray', Array, function () { - this.init.apply(this, arguments); - }); - extend(SVGArray, { - init: function init() { - this.length = 0; - this.push.apply(this, _toConsumableArray(this.parse.apply(this, arguments))); - }, - toArray: function toArray() { - return Array.prototype.concat.apply([], this); - }, - toString: function toString() { - return this.join(' '); - }, - // Flattens the array if needed - valueOf: function valueOf() { - var ret = []; - ret.push.apply(ret, _toConsumableArray(this)); - return ret; - }, - // Parse whitespace separated string - parse: function parse() { - var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - // If already is an array, no need to parse it - if (array instanceof Array) return array; - return array.trim().split(delimiter).map(parseFloat); - }, - clone: function clone() { - return new this.constructor(this); - }, - toSet: function toSet() { - return new Set(this); - } - }); - - var SVGNumber = + var Color = /*#__PURE__*/ function () { - // Initialize - function SVGNumber() { - _classCallCheck(this, SVGNumber); + function Color() { + _classCallCheck(this, Color); this.init.apply(this, arguments); } - _createClass(SVGNumber, [{ + _createClass(Color, [{ key: "init", - value: function init(value, unit) { - unit = Array.isArray(value) ? value[1] : unit; - value = Array.isArray(value) ? value[0] : value; // initialize defaults - - this.value = 0; - this.unit = unit || ''; // parse value - - if (typeof value === 'number') { - // ensure a valid numeric value - this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; - } else if (typeof value === 'string') { - unit = value.match(numberAndUnit); + value: function init(color, g, b) { + var match; // initialize defaults - if (unit) { - // make value numeric - this.value = parseFloat(unit[1]); // normalize + this.r = 0; + this.g = 0; + this.b = 0; + if (!color) return; // parse color - if (unit[5] === '%') { - this.value /= 100; - } else if (unit[5] === 's') { - this.value *= 1000; - } // store unit + if (typeof color === 'string') { + if (isRgb.test(color)) { + // get rgb values + match = rgb.exec(color.replace(whitespace, '')); // parse numeric values + this.r = parseInt(match[1]); + this.g = parseInt(match[2]); + this.b = parseInt(match[3]); + } else if (isHex.test(color)) { + // get hex values + match = hex.exec(fullHex(color)); // parse numeric values - this.unit = unit[5]; - } - } else { - if (value instanceof SVGNumber) { - this.value = value.valueOf(); - this.unit = value.unit; + this.r = parseInt(match[1], 16); + this.g = parseInt(match[2], 16); + this.b = parseInt(match[3], 16); } + } else if (Array.isArray(color)) { + this.r = color[0]; + this.g = color[1]; + this.b = color[2]; + } else if (_typeof(color) === 'object') { + this.r = color.r; + this.g = color.g; + this.b = color.b; + } else if (arguments.length === 3) { + this.r = color; + this.g = g; + this.b = b; } - } + } // Default to hex conversion + }, { key: "toString", value: function toString() { - return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; - } - }, { - key: "toJSON", - value: function toJSON() { - return this.toString(); + return this.toHex(); } }, { key: "toArray", value: function toArray() { - return [this.value, this.unit]; - } + return [this.r, this.g, this.b]; + } // Build hex value + }, { - key: "valueOf", - value: function valueOf() { - return this.value; - } // Add number + key: "toHex", + value: function toHex() { + return '#' + compToHex(Math.round(this.r)) + compToHex(Math.round(this.g)) + compToHex(Math.round(this.b)); + } // Build rgb value }, { - key: "plus", - value: function plus(number) { - number = new SVGNumber(number); - return new SVGNumber(this + number, this.unit || number.unit); - } // Subtract number + key: "toRgb", + value: function toRgb() { + return 'rgb(' + [this.r, this.g, this.b].join() + ')'; + } // Calculate true brightness }, { - key: "minus", - value: function minus(number) { - number = new SVGNumber(number); - return new SVGNumber(this - number, this.unit || number.unit); - } // Multiply number + key: "brightness", + value: function brightness() { + return this.r / 255 * 0.30 + this.g / 255 * 0.59 + this.b / 255 * 0.11; + } // Testers + // Test if given value is a color string + + }], [{ + key: "test", + value: function test(color) { + color += ''; + return isHex.test(color) || isRgb.test(color); + } // Test if given value is a rgb object }, { - key: "times", - value: function times(number) { - number = new SVGNumber(number); - return new SVGNumber(this * number, this.unit || number.unit); - } // Divide number + key: "isRgb", + value: function isRgb$$1(color) { + return color && typeof color.r === 'number' && typeof color.g === 'number' && typeof color.b === 'number'; + } // Test if given value is a color }, { - key: "divide", - value: function divide(number) { - number = new SVGNumber(number); - return new SVGNumber(this / number, this.unit || number.unit); + key: "isColor", + value: function isColor(color) { + return this.isRgb(color) || this.test(color); } }]); - return SVGNumber; + return Color; }(); + // Default namespaces + var ns = 'http://www.w3.org/2000/svg'; + var xmlns = 'http://www.w3.org/2000/xmlns/'; + var xlink = 'http://www.w3.org/1999/xlink'; + var svgjs = 'http://svgjs.com/svgjs'; + + var Base = function Base() { + _classCallCheck(this, Base); + }; + + var elements = {}; + var root = Symbol('root'); // Method for element creation + + function makeNode(name) { + // create element + return document.createElementNS(ns, name); + } + function makeInstance(element) { + if (element instanceof Base) return element; + + if (_typeof(element) === 'object') { + return adopt(element); + } + + if (element == null) { + return new elements[root](); + } + + if (typeof element === 'string' && element.charAt(0) !== '<') { + return adopt(document.querySelector(element)); + } + + var node = makeNode('svg'); + node.innerHTML = element; // We can use firstChild here because we know, + // that the first char is < and thus an element + + element = adopt(node.firstChild); + return element; + } + function nodeOrNew(name, node) { + return node || makeNode(name); + } // Adopt existing svg elements + + function adopt(node) { + // check for presence of node + if (!node) return null; // make sure a node isn't already adopted + + if (node.instance instanceof Base) return node.instance; + + if (!(node instanceof window.SVGElement)) { + return new elements.HtmlNode(node); + } // initialize variables + + + var element; // adopt with element-specific settings + + if (node.nodeName === 'svg') { + element = new elements[root](node); + } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') { + element = new elements.Gradient(node); + } else if (elements[capitalize(node.nodeName)]) { + element = new elements[capitalize(node.nodeName)](node); + } else { + element = new elements.Bare(node); + } + + return element; + } + function register(element) { + var name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : element.name; + var asRoot = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + elements[name] = element; + if (asRoot) elements[root] = element; + return element; + } + function getClass(name) { + return elements[name]; + } // Element id sequence + + var did = 1000; // Get next named element id + + function eid(name) { + return 'Svgjs' + capitalize(name) + did++; + } // Deep new id assignment + + function assignNewId(node) { + // do the same for SVG child nodes as well + for (var i = node.children.length - 1; i >= 0; i--) { + assignNewId(node.children[i]); + } + + if (node.id) { + return adopt(node).id(eid(node.nodeName)); + } + + return adopt(node); + } // Method for extending objects + + function extend(modules, methods) { + var key, i; + modules = Array.isArray(modules) ? modules : [modules]; + + for (i = modules.length - 1; i >= 0; i--) { + for (key in methods) { + modules[i].prototype[key] = methods[key]; + } + } + } + var listenerId = 0; function getEvents(node) { @@ -1035,62 +1036,6 @@ var SVG = (function () { return event; } - var events = /*#__PURE__*/Object.freeze({ - on: on, - off: off, - dispatch: dispatch - }); - - var methods = {}; - function registerMethods(name, m) { - if (Array.isArray(name)) { - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = name[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var _name = _step.value; - registerMethods(_name, m); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - return; - } - - if (_typeof(name) === 'object') { - var _arr = Object.entries(name); - - for (var _i = 0; _i < _arr.length; _i++) { - var _arr$_i = _slicedToArray(_arr[_i], 2), - _name2 = _arr$_i[0], - _m = _arr$_i[1]; - - registerMethods(_name2, _m); - } - - return; - } - - methods[name] = Object.assign(methods[name] || {}, m); - } - function getMethodsFor(name) { - return methods[name] || {}; - } - var EventTarget = /*#__PURE__*/ function (_Base) { @@ -1190,54 +1135,6 @@ var SVG = (function () { }, {}); registerMethods('Element', methods$1); - // Map function - function map(array, block) { - var i; - var il = array.length; - var result = []; - - for (i = 0; i < il; i++) { - result.push(block(array[i])); - } - - return result; - } // Filter function - - function filter(array, block) { - var i; - var il = array.length; - var result = []; - - for (i = 0; i < il; i++) { - if (block(array[i])) { - result.push(array[i]); - } - } - - return result; - } // Degrees to radians - - function radians(d) { - return d % 360 * Math.PI / 180; - } // Radians to degrees - - function degrees(r) { - return r * 180 / Math.PI % 360; - } - function filterSVGElements(nodes) { - return this.filter(nodes, function (el) { - return el instanceof window.SVGElement; - }); - } - - var utils = /*#__PURE__*/Object.freeze({ - map: map, - filter: filter, - radians: radians, - degrees: degrees, - filterSVGElements: filterSVGElements - }); - function noop() {} // Default animation values var timeline = { @@ -1284,111 +1181,163 @@ var SVG = (function () { attrs: attrs }); - var Color = - /*#__PURE__*/ - function () { - function Color() { - _classCallCheck(this, Color); - - this.init.apply(this, arguments); - } - - _createClass(Color, [{ - key: "init", - value: function init(color, g, b) { - var match; // initialize defaults + /* eslint no-new-func: "off" */ + var subClassArray = function () { + try { + // try es6 subclassing + return Function('name', 'baseClass', '_constructor', ['baseClass = baseClass || Array', 'return {', '[name]: class extends baseClass {', 'constructor (...args) {', 'super(...args)', '_constructor && _constructor.apply(this, args)', '}', '}', '}[name]'].join('\n')); + } catch (e) { + // Use es5 approach + return function (name) { + var baseClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Array; - this.r = 0; - this.g = 0; - this.b = 0; - if (!color) return; // parse color + var _constructor = arguments.length > 2 ? arguments[2] : undefined; - if (typeof color === 'string') { - if (isRgb.test(color)) { - // get rgb values - match = rgb.exec(color.replace(whitespace, '')); // parse numeric values + var Arr = function Arr() { + baseClass.apply(this, arguments); + _constructor && _constructor.apply(this, arguments); + }; - this.r = parseInt(match[1]); - this.g = parseInt(match[2]); - this.b = parseInt(match[3]); - } else if (isHex.test(color)) { - // get hex values - match = hex.exec(fullHex(color)); // parse numeric values + Arr.prototype = Object.create(baseClass.prototype); + Arr.prototype.constructor = Arr; + return Arr; + }; + } + }(); + + var SVGArray = subClassArray('SVGArray', Array, function (arr) { + this.init(arr); + }); + extend(SVGArray, { + init: function init(arr) { + this.length = 0; + this.push.apply(this, _toConsumableArray(this.parse(arr))); + }, + toArray: function toArray() { + return Array.prototype.concat.apply([], this); + }, + toString: function toString() { + return this.join(' '); + }, + // Flattens the array if needed + valueOf: function valueOf() { + var ret = []; + ret.push.apply(ret, _toConsumableArray(this)); + return ret; + }, + // Parse whitespace separated string + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + // If already is an array, no need to parse it + if (array instanceof Array) return array; + return array.trim().split(delimiter).map(parseFloat); + }, + clone: function clone() { + return new this.constructor(this); + }, + toSet: function toSet() { + return new Set(this); + } + }); + + var SVGNumber = + /*#__PURE__*/ + function () { + // Initialize + function SVGNumber() { + _classCallCheck(this, SVGNumber); + + this.init.apply(this, arguments); + } + + _createClass(SVGNumber, [{ + key: "init", + value: function init(value, unit) { + unit = Array.isArray(value) ? value[1] : unit; + value = Array.isArray(value) ? value[0] : value; // initialize defaults + + this.value = 0; + this.unit = unit || ''; // parse value + + if (typeof value === 'number') { + // ensure a valid numeric value + this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; + } else if (typeof value === 'string') { + unit = value.match(numberAndUnit); + + if (unit) { + // make value numeric + this.value = parseFloat(unit[1]); // normalize + + if (unit[5] === '%') { + this.value /= 100; + } else if (unit[5] === 's') { + this.value *= 1000; + } // store unit - this.r = parseInt(match[1], 16); - this.g = parseInt(match[2], 16); - this.b = parseInt(match[3], 16); - } - } else if (Array.isArray(color)) { - this.r = color[0]; - this.g = color[1]; - this.b = color[2]; - } else if (_typeof(color) === 'object') { - this.r = color.r; - this.g = color.g; - this.b = color.b; - } else if (arguments.length === 3) { - this.r = color; - this.g = g; - this.b = b; - } - } // Default to hex conversion + this.unit = unit[5]; + } + } else { + if (value instanceof SVGNumber) { + this.value = value.valueOf(); + this.unit = value.unit; + } + } + } }, { key: "toString", value: function toString() { - return this.toHex(); + return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value) + this.unit; + } + }, { + key: "toJSON", + value: function toJSON() { + return this.toString(); } }, { key: "toArray", value: function toArray() { - return [this.r, this.g, this.b]; - } // Build hex value - + return [this.value, this.unit]; + } }, { - key: "toHex", - value: function toHex() { - return '#' + compToHex(Math.round(this.r)) + compToHex(Math.round(this.g)) + compToHex(Math.round(this.b)); - } // Build rgb value + key: "valueOf", + value: function valueOf() { + return this.value; + } // Add number }, { - key: "toRgb", - value: function toRgb() { - return 'rgb(' + [this.r, this.g, this.b].join() + ')'; - } // Calculate true brightness + key: "plus", + value: function plus(number) { + number = new SVGNumber(number); + return new SVGNumber(this + number, this.unit || number.unit); + } // Subtract number }, { - key: "brightness", - value: function brightness() { - return this.r / 255 * 0.30 + this.g / 255 * 0.59 + this.b / 255 * 0.11; - } // Testers - // Test if given value is a color string - - }], [{ - key: "test", - value: function test(color) { - color += ''; - return isHex.test(color) || isRgb.test(color); - } // Test if given value is a rgb object + key: "minus", + value: function minus(number) { + number = new SVGNumber(number); + return new SVGNumber(this - number, this.unit || number.unit); + } // Multiply number }, { - key: "isRgb", - value: function isRgb$$1(color) { - return color && typeof color.r === 'number' && typeof color.g === 'number' && typeof color.b === 'number'; - } // Test if given value is a color + key: "times", + value: function times(number) { + number = new SVGNumber(number); + return new SVGNumber(this * number, this.unit || number.unit); + } // Divide number }, { - key: "isColor", - value: function isColor(color) { - return this.isRgb(color) || this.test(color); + key: "divide", + value: function divide(number) { + number = new SVGNumber(number); + return new SVGNumber(this / number, this.unit || number.unit); } }]); - return Color; + return SVGNumber; }(); - // Set svg element attribute - function attr(attr, val, ns) { // act as full getter if (attr == null) { @@ -1621,7 +1570,8 @@ var SVG = (function () { }, { key: "matches", value: function matches(selector) { - return matcher(this.node, selector); + var el = this.node; + return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector); } // Returns the svg node to call native svg methods on it }, { @@ -1830,9 +1780,11 @@ var SVG = (function () { }, { key: "reference", - value: function reference(attr) { - var id = idFromReference(this.attr(attr)); - return id ? makeInstance(id) : null; + value: function reference$$1(attr) { + attr = this.attr(attr); + if (!attr) return null; + var m = attr.match(reference); + return m ? makeInstance(m[1]) : null; } // set given data to the elements data property }, { @@ -1921,41 +1873,6 @@ var SVG = (function () { return Container; }(Element); - var Bare = - /*#__PURE__*/ - function (_Container) { - _inherits(Bare, _Container); - - function Bare(node) { - _classCallCheck(this, Bare); - - return _possibleConstructorReturn(this, _getPrototypeOf(Bare).call(this, nodeOrNew(node, typeof node === 'string' ? null : node), Bare)); - } - - _createClass(Bare, [{ - key: "words", - value: function words(text) { - // remove contents - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild); - } // create text node - - - this.node.appendChild(document.createTextNode(text)); - return this; - } - }]); - - return Bare; - }(Container); - register(Bare); - registerMethods('Container', { - // Create an element that is not described by SVG.js - element: function element(node, inherit) { - return this.put(new Bare(node, inherit)); - } - }); - var Defs = /*#__PURE__*/ function (_Container) { @@ -2067,13 +1984,8 @@ var SVG = (function () { function parser() { // Reuse cached element if possible if (!parser.nodes) { - var svg = new Doc$1().size(2, 0).css({ - opacity: 0, - position: 'absolute', - left: '-100%', - top: '-100%', - overflow: 'hidden' - }); + var svg = new Doc$1().size(2, 0); + svg.node.cssText = ['opacity: 0', 'position: absolute', 'left: -100%', 'top: -100%', 'overflow: hidden'].join(';'); var path = svg.path().node; parser.nodes = { svg: svg, @@ -2157,320 +2069,555 @@ var SVG = (function () { } }); - var Box = + var abcdef = 'abcdef'.split(''); + + function closeEnough(a, b, threshold) { + return Math.abs(b - a) < (threshold || 1e-6); + } + + var Matrix = /*#__PURE__*/ function () { - function Box() { - _classCallCheck(this, Box); + function Matrix() { + _classCallCheck(this, Matrix); this.init.apply(this, arguments); - } + } // Initialize - _createClass(Box, [{ + + _createClass(Matrix, [{ key: "init", value: function init(source) { - var base = [0, 0, 0, 0]; - source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) : Array.isArray(source) ? source : _typeof(source) === 'object' ? [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] : arguments.length === 4 ? [].slice.call(arguments) : base; - this.x = source[0]; - this.y = source[1]; - this.width = source[2]; - this.height = source[3]; // add center, right, bottom... + var base = Matrix.fromArray([1, 0, 0, 1, 0, 0]); // ensure source as object - fullBox(this); - } // Merge rect box with another, return a new instance + source = source instanceof Element ? source.matrixify() : typeof source === 'string' ? Matrix.fromArray(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? Matrix.fromArray(source) : _typeof(source) === 'object' && Matrix.isMatrixLike(source) ? source : _typeof(source) === 'object' ? new Matrix().transform(source) : arguments.length === 6 ? Matrix.fromArray([].slice.call(arguments)) : base; // Merge the source matrix with the base matrix + + this.a = source.a != null ? source.a : base.a; + this.b = source.b != null ? source.b : base.b; + this.c = source.c != null ? source.c : base.c; + this.d = source.d != null ? source.d : base.d; + this.e = source.e != null ? source.e : base.e; + this.f = source.f != null ? source.f : base.f; + } // Clones this matrix }, { - key: "merge", - value: function merge(box) { - var x = Math.min(this.x, box.x); - var y = Math.min(this.y, box.y); - var width = Math.max(this.x + this.width, box.x + box.width) - x; - var height = Math.max(this.y + this.height, box.y + box.height) - y; - return new Box(x, y, width, height); - } + key: "clone", + value: function clone() { + return new Matrix(this); + } // Transform a matrix into another matrix by manipulating the space + }, { key: "transform", - value: function transform(m) { - var xMin = Infinity; - var xMax = -Infinity; - var yMin = Infinity; - var yMax = -Infinity; - var pts = [new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2)]; - pts.forEach(function (p) { - p = p.transform(m); - xMin = Math.min(xMin, p.x); - xMax = Math.max(xMax, p.x); - yMin = Math.min(yMin, p.y); - yMax = Math.max(yMax, p.y); - }); - return new Box(xMin, yMin, xMax - xMin, yMax - yMin); - } - }, { - key: "addOffset", - value: function addOffset() { - // offset by window scroll position, because getBoundingClientRect changes when window is scrolled - this.x += window.pageXOffset; - this.y += window.pageYOffset; - return this; - } - }, { - key: "toString", - value: function toString() { - return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height; - } - }, { - key: "toArray", - value: function toArray() { - return [this.x, this.y, this.width, this.height]; - } - }]); - - return Box; - }(); + value: function transform(o) { + // Check if o is a matrix and then left multiply it directly + if (Matrix.isMatrixLike(o)) { + var matrix = new Matrix(o); + return matrix.multiplyO(this); + } // Get the proposed transformations and the current transformations - function getBox(cb) { - var box; - try { - box = cb(this.node); + var t = Matrix.formatTransforms(o); + var current = this; - if (isNulledBox(box) && !domContains(this.node)) { - throw new Error('Element not in the dom'); - } - } catch (e) { - try { - var clone = this.clone(parser().svg).show(); - box = cb(clone.node); - clone.remove(); - } catch (e) { - console.warn('Getting a bounding box of this element is not possible'); - } - } + var _transform = new Point(t.ox, t.oy).transform(current), + ox = _transform.x, + oy = _transform.y; // Construct the resulting matrix - return box; - } - registerMethods({ - Element: { - // Get bounding box - bbox: function bbox() { - return new Box(getBox.call(this, function (node) { - return node.getBBox(); - })); - }, - rbox: function rbox(el) { - var box = new Box(getBox.call(this, function (node) { - return node.getBoundingClientRect(); - })); - if (el) return box.transform(el.screenCTM().inverse()); - return box.addOffset(); - } - }, - viewbox: { - viewbox: function viewbox(x, y, width, height) { - // act as getter - if (x == null) return new Box(this.attr('viewBox')); // act as setter + var transformer = new Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy); // If we want the origin at a particular place, we force it there - return this.attr('viewBox', new Box(x, y, width, height)); - } - } - }); + if (isFinite(t.px) || isFinite(t.py)) { + var origin = new Point(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px) - var Shape = - /*#__PURE__*/ - function (_Element) { - _inherits(Shape, _Element); + var dx = t.px ? t.px - origin.x : 0; + var dy = t.py ? t.py - origin.y : 0; + transformer.translateO(dx, dy); + } // Translate now after positioning - function Shape() { - _classCallCheck(this, Shape); - return _possibleConstructorReturn(this, _getPrototypeOf(Shape).apply(this, arguments)); - } + transformer.translateO(t.tx, t.ty); + return transformer; + } // Applies a matrix defined by its affine parameters - return Shape; - }(Element); + }, { + key: "compose", + value: function compose(o) { + if (o.origin) { + o.originX = o.origin[0]; + o.originY = o.origin[1]; + } // Get the parameters - // FIXME: import this to runner - function rx(rx) { - return this.attr('rx', rx); - } // Radius y value + var ox = o.originX || 0; + var oy = o.originY || 0; + var sx = o.scaleX || 1; + var sy = o.scaleY || 1; + var lam = o.shear || 0; + var theta = o.rotate || 0; + var tx = o.translateX || 0; + var ty = o.translateY || 0; // Apply the standard matrix - function ry(ry) { - return this.attr('ry', ry); - } // Move over x-axis + var result = new Matrix().translateO(-ox, -oy).scaleO(sx, sy).shearO(lam).rotateO(theta).translateO(tx, ty).lmultiplyO(this).translateO(ox, oy); + return result; + } // Decomposes this matrix into its affine parameters - function x(x) { - return x == null ? this.cx() - this.rx() : this.cx(x + this.rx()); - } // Move over y-axis + }, { + key: "decompose", + value: function decompose() { + var cx = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var cy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + // Get the parameters from the matrix + var a = this.a; + var b = this.b; + var c = this.c; + var d = this.d; + var e = this.e; + var f = this.f; // Figure out if the winding direction is clockwise or counterclockwise - function y(y) { - return y == null ? this.cy() - this.ry() : this.cy(y + this.ry()); - } // Move by center over x-axis + var determinant = a * d - b * c; + var ccw = determinant > 0 ? 1 : -1; // Since we only shear in x, we can use the x basis to get the x scale + // and the rotation of the resulting matrix - function cx(x) { - return x == null ? this.attr('cx') : this.attr('cx', x); - } // Move by center over y-axis + var sx = ccw * Math.sqrt(a * a + b * b); + var thetaRad = Math.atan2(ccw * b, ccw * a); + var theta = 180 / Math.PI * thetaRad; + var ct = Math.cos(thetaRad); + var st = Math.sin(thetaRad); // We can then solve the y basis vector simultaneously to get the other + // two affine parameters directly from these parameters - function cy(y) { - return y == null ? this.attr('cy') : this.attr('cy', y); - } // Set width of element + var lam = (a * c + b * d) / determinant; + var sy = c * sx / (lam * a - b) || d * sx / (lam * b + a); // Use the translations - function width(width) { - return width == null ? this.rx() * 2 : this.rx(new SVGNumber(width).divide(2)); - } // Set height of element + var tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy); + var ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy); // Construct the decomposition and return it - function height(height) { - return height == null ? this.ry() * 2 : this.ry(new SVGNumber(height).divide(2)); - } // Custom size function + return { + // Return the affine parameters + scaleX: sx, + scaleY: sy, + shear: lam, + rotate: theta, + translateX: tx, + translateY: ty, + originX: cx, + originY: cy, + // Return the matrix parameters + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + }; + } // Left multiplies by the given matrix - function 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)); - } + }, { + key: "multiply", + value: function multiply(matrix) { + return this.clone().multiplyO(matrix); + } + }, { + key: "multiplyO", + value: function multiplyO(matrix) { + // Get the matrices + var l = this; + var r = matrix instanceof Matrix ? matrix : new Matrix(matrix); + return Matrix.matrixMultiply(l, r, this); + } + }, { + key: "lmultiply", + value: function lmultiply(matrix) { + return this.clone().lmultiplyO(matrix); + } + }, { + key: "lmultiplyO", + value: function lmultiplyO(matrix) { + var r = this; + var l = matrix instanceof Matrix ? matrix : new Matrix(matrix); + return Matrix.matrixMultiply(l, r, this); + } // Inverses matrix - var circled = /*#__PURE__*/Object.freeze({ - rx: rx, - ry: ry, - x: x, - y: y, - cx: cx, - cy: cy, - width: width, - height: height, - size: size - }); + }, { + key: "inverseO", + value: function inverseO() { + // Get the current parameters out of the matrix + var a = this.a; + var b = this.b; + var c = this.c; + var d = this.d; + var e = this.e; + var f = this.f; // Invert the 2x2 matrix in the top left - var Circle = - /*#__PURE__*/ - function (_Shape) { - _inherits(Circle, _Shape); + var det = a * d - b * c; + if (!det) throw new Error('Cannot invert ' + this); // Calculate the top 2x2 matrix - function Circle(node) { - _classCallCheck(this, Circle); + var na = d / det; + var nb = -b / det; + var nc = -c / det; + var nd = a / det; // Apply the inverted matrix to the top right - return _possibleConstructorReturn(this, _getPrototypeOf(Circle).call(this, nodeOrNew('circle', node), Circle)); - } + var ne = -(na * e + nc * f); + var nf = -(nb * e + nd * f); // Construct the inverted matrix - _createClass(Circle, [{ - key: "radius", - value: function radius(r) { - return this.attr('r', r); - } // Radius x value + this.a = na; + this.b = nb; + this.c = nc; + this.d = nd; + this.e = ne; + this.f = nf; + return this; + } + }, { + key: "inverse", + value: function inverse() { + return this.clone().inverseO(); + } // Translate matrix }, { - key: "rx", - value: function rx$$1(_rx) { - return this.attr('r', _rx); - } // Alias radius x value + key: "translate", + value: function translate(x, y) { + return this.clone().translateO(x, y); + } + }, { + key: "translateO", + value: function translateO(x, y) { + this.e += x || 0; + this.f += y || 0; + return this; + } // Scale matrix }, { - key: "ry", - value: function ry$$1(_ry) { - return this.rx(_ry); + key: "scale", + value: function scale(x, y, cx, cy) { + var _this$clone; + + return (_this$clone = this.clone()).scaleO.apply(_this$clone, arguments); } - }]); + }, { + key: "scaleO", + value: function scaleO(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; - return Circle; - }(Shape); - extend(Circle, { - x: x, - y: y, - cx: cx, - cy: cy, - width: width, - height: height, - size: size - }); - registerMethods({ - Element: { - // Create circle element - circle: function circle(size$$1) { - return this.put(new Circle()).radius(new SVGNumber(size$$1).divide(2)).move(0, 0); + // Support uniform scaling + if (arguments.length === 3) { + cy = cx; + cx = y; + y = x; + } + + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a * x; + this.b = b * y; + this.c = c * x; + this.d = d * y; + this.e = e * x - cx * x + cx; + this.f = f * y - cy * y + cy; + return this; + } // Rotate matrix + + }, { + key: "rotate", + value: function rotate(r, cx, cy) { + return this.clone().rotateO(r, cx, cy); } - } - }); - register(Circle); + }, { + key: "rotateO", + value: function rotateO(r) { + var cx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + // Convert degrees to radians + r = radians(r); + var cos = Math.cos(r); + var sin = Math.sin(r); + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a * cos - b * sin; + this.b = b * cos + a * sin; + this.c = c * cos - d * sin; + this.d = d * cos + c * sin; + this.e = e * cos - f * sin + cy * sin - cx * cos + cx; + this.f = f * cos + e * sin - cx * sin - cy * cos + cy; + return this; + } // Flip matrix on x or y, at a given offset - function baseFind(query, parent) { - return map((parent || document).querySelectorAll(query), function (node) { - return adopt(node); - }); - } // Scoped find method + }, { + key: "flip", + value: function flip(axis, around) { + return this.clone().flipO(axis, around); + } + }, { + key: "flipO", + value: function flipO(axis, around) { + return axis === 'x' ? this.scaleO(-1, 1, around, 0) : axis === 'y' ? this.scaleO(1, -1, 0, around) : this.scaleO(-1, -1, axis, around || axis); // Define an x, y flip point + } // Shear matrix - function find(query) { - return baseFind(query, this.node); - } - registerMethods('Dom', { - find: find - }); + }, { + key: "shear", + value: function shear(a, cx, cy) { + return this.clone().shearO(a, cx, cy); + } + }, { + key: "shearO", + value: function shearO(lx) { + var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a + b * lx; + this.c = c + d * lx; + this.e = e + f * lx - cy * lx; + return this; + } // Skew Matrix - var ClipPath = - /*#__PURE__*/ - function (_Container) { - _inherits(ClipPath, _Container); + }, { + key: "skew", + value: function skew(x, y, cx, cy) { + var _this$clone2; - function ClipPath(node) { - _classCallCheck(this, ClipPath); + return (_this$clone2 = this.clone()).skewO.apply(_this$clone2, arguments); + } + }, { + key: "skewO", + value: function skewO(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; - return _possibleConstructorReturn(this, _getPrototypeOf(ClipPath).call(this, nodeOrNew('clipPath', node), ClipPath)); - } // Unclip all clipped elements and remove itself + // support uniformal skew + if (arguments.length === 3) { + cy = cx; + cx = y; + y = x; + } // Convert degrees to radians - _createClass(ClipPath, [{ - key: "remove", - value: function remove() { - // unclip all targets - this.targets().forEach(function (el) { - el.unclip(); - }); // remove clipPath from parent + x = radians(x); + y = radians(y); + var lx = Math.tan(x); + var ly = Math.tan(y); + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + this.a = a + b * lx; + this.b = b + a * ly; + this.c = c + d * lx; + this.d = d + c * ly; + this.e = e + f * lx - cy * lx; + this.f = f + e * ly - cx * ly; + return this; + } // SkewX - return _get(_getPrototypeOf(ClipPath.prototype), "remove", this).call(this); - } }, { - key: "targets", - value: function targets() { - return baseFind('svg [clip-path*="' + this.id() + '"]'); + key: "skewX", + value: function skewX(x, cx, cy) { + return this.skew(x, 0, cx, cy); } - }]); + }, { + key: "skewXO", + value: function skewXO(x, cx, cy) { + return this.skewO(x, 0, cx, cy); + } // SkewY - return ClipPath; - }(Container); - registerMethods({ - Container: { - // Create clipping element - clip: function clip() { - return this.defs().put(new ClipPath()); + }, { + key: "skewY", + value: function skewY(y, cx, cy) { + return this.skew(0, y, cx, cy); } - }, - Element: { - // Distribute clipPath to svg element - clipWith: function clipWith(element) { - // use given clip or create a new one - var clipper = element instanceof ClipPath ? element : this.parent().clip().add(element); // apply mask + }, { + key: "skewYO", + value: function skewYO(y, cx, cy) { + return this.skewO(0, y, cx, cy); + } // Transform around a center point - return this.attr('clip-path', 'url("#' + clipper.id() + '")'); - }, - // Unclip element - unclip: function unclip() { - return this.attr('clip-path', null); - }, - clipper: function clipper() { - return this.reference('clip-path'); + }, { + key: "aroundO", + value: function aroundO(cx, cy, matrix) { + var dx = cx || 0; + var dy = cy || 0; + return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy); } - } - }); - register(ClipPath); - - /*** - Base Class - ========== - The base stepper class that will be - ***/ + }, { + key: "around", + value: function around(cx, cy, matrix) { + return this.clone().aroundO(cx, cy, matrix); + } // Convert to native SVGMatrix - function makeSetterGetter(k, f) { - return function (v) { - if (v == null) return this[v]; + }, { + key: "native", + value: function native() { + // create new matrix + var matrix = parser().svg.node.createSVGMatrix(); // update with current values + + for (var i = abcdef.length - 1; i >= 0; i--) { + matrix[abcdef[i]] = this[abcdef[i]]; + } + + return matrix; + } // Check if two matrices are equal + + }, { + key: "equals", + value: function equals(other) { + var comp = new Matrix(other); + return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f); + } // Convert matrix to string + + }, { + key: "toString", + value: function toString() { + return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'; + } + }, { + key: "toArray", + value: function toArray() { + return [this.a, this.b, this.c, this.d, this.e, this.f]; + } + }, { + key: "valueOf", + value: function valueOf() { + return { + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + }; + } + }], [{ + key: "fromArray", + value: function fromArray(a) { + return { + a: a[0], + b: a[1], + c: a[2], + d: a[3], + e: a[4], + f: a[5] + }; + } + }, { + key: "isMatrixLike", + value: function isMatrixLike(o) { + return o.a != null || o.b != null || o.c != null || o.d != null || o.e != null || o.f != null; + } + }, { + key: "formatTransforms", + value: function formatTransforms(o) { + // Get all of the parameters required to form the matrix + var flipBoth = o.flip === 'both' || o.flip === true; + var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1; + var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1; + var skewX = o.skew && o.skew.length ? o.skew[0] : isFinite(o.skew) ? o.skew : isFinite(o.skewX) ? o.skewX : 0; + var skewY = o.skew && o.skew.length ? o.skew[1] : isFinite(o.skew) ? o.skew : isFinite(o.skewY) ? o.skewY : 0; + var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX : isFinite(o.scale) ? o.scale * flipX : isFinite(o.scaleX) ? o.scaleX * flipX : flipX; + var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY; + var shear = o.shear || 0; + var theta = o.rotate || o.theta || 0; + var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY); + var ox = origin.x; + var oy = origin.y; + var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY); + var px = position.x; + var py = position.y; + var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY); + var tx = translate.x; + var ty = translate.y; + var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY); + var rx = relative.x; + var ry = relative.y; // Populate all of the values + + return { + scaleX: scaleX, + scaleY: scaleY, + skewX: skewX, + skewY: skewY, + shear: shear, + theta: theta, + rx: rx, + ry: ry, + tx: tx, + ty: ty, + ox: ox, + oy: oy, + px: px, + py: py + }; + } // left matrix, right matrix, target matrix which is overwritten + + }, { + key: "matrixMultiply", + value: function matrixMultiply(l, r, o) { + // Work out the product directly + var a = l.a * r.a + l.c * r.b; + var b = l.b * r.a + l.d * r.b; + var c = l.a * r.c + l.c * r.d; + var d = l.b * r.c + l.d * r.d; + var e = l.e + l.a * r.e + l.c * r.f; + var f = l.f + l.b * r.e + l.d * r.f; // make sure to use local variables because l/r and o could be the same + + o.a = a; + o.b = b; + o.c = c; + o.d = d; + o.e = e; + o.f = f; + return o; + } + }]); + + return Matrix; + }(); + registerMethods({ + Element: { + // Get current matrix + ctm: function ctm() { + return new Matrix(this.node.getCTM()); + }, + // Get current screen matrix + screenCTM: function screenCTM() { + /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 + This is needed because FF does not return the transformation matrix + for the inner coordinate system when getScreenCTM() is called on nested svgs. + However all other Browsers do that */ + if (typeof this.isRoot === 'function' && !this.isRoot()) { + var rect = this.rect(1, 1); + var m = rect.node.getScreenCTM(); + rect.remove(); + return new Matrix(m); + } + + return new Matrix(this.node.getScreenCTM()); + } + } + }); + + /*** + Base Class + ========== + The base stepper class that will be + ***/ + + function makeSetterGetter(k, f) { + return function (v) { + if (v == null) return this[v]; this[k] = v; if (f) f.call(this); return this; @@ -2692,3224 +2839,3205 @@ var SVG = (function () { d: makeSetterGetter('D') }); - var Ellipse = + var Queue = /*#__PURE__*/ - function (_Shape) { - _inherits(Ellipse, _Shape); - - function Ellipse(node) { - _classCallCheck(this, Ellipse); + function () { + function Queue() { + _classCallCheck(this, Queue); - return _possibleConstructorReturn(this, _getPrototypeOf(Ellipse).call(this, nodeOrNew('ellipse', node), Ellipse)); + this._first = null; + this._last = null; } - return Ellipse; - }(Shape); - extend(Ellipse, circled); - registerMethods('Container', { - // Create an ellipse - ellipse: function ellipse(width$$1, height$$1) { - return this.put(new Ellipse()).size(width$$1, height$$1).move(0, 0); - } - }); - register(Ellipse); + _createClass(Queue, [{ + key: "push", + value: function push(value) { + // An item stores an id and the provided value + var item = value.next ? value : { + value: value, + next: null, + prev: null // Deal with the queue being empty or populated - var Stop = - /*#__PURE__*/ - function (_Element) { - _inherits(Stop, _Element); + }; - function Stop(node) { - _classCallCheck(this, Stop); + if (this._last) { + item.prev = this._last; + this._last.next = item; + this._last = item; + } else { + this._last = item; + this._first = item; + } // Update the length and return the current item - return _possibleConstructorReturn(this, _getPrototypeOf(Stop).call(this, nodeOrNew('stop', node), Stop)); - } // add color stops + return item; + } + }, { + key: "shift", + value: function shift() { + // Check if we have a value + var remove = this._first; + if (!remove) return null; // If we do, remove it and relink things - _createClass(Stop, [{ - key: "update", - value: function update(o) { - if (typeof o === 'number' || o instanceof SVGNumber) { - o = { - offset: arguments[0], - color: arguments[1], - opacity: arguments[2] - }; - } // set attributes + this._first = remove.next; + if (this._first) this._first.prev = null; + this._last = this._first ? this._last : null; + return remove.value; + } // Shows us the first item in the list + + }, { + key: "first", + value: function first() { + return this._first && this._first.value; + } // Shows us the last item in the list + }, { + key: "last", + value: function last() { + return this._last && this._last.value; + } // Removes the item that was returned from the push - 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; + }, { + key: "remove", + value: function remove(item) { + // Relink the previous item + if (item.prev) item.prev.next = item.next; + if (item.next) item.next.prev = item.prev; + if (item === this._last) this._last = item.prev; + if (item === this._first) this._first = item.next; // Invalidate item + + item.prev = null; + item.next = null; } }]); - return Stop; - }(Element); - register(Stop); + return Queue; + }(); - // FIXME: add to runner - function from(x, y) { - return (this._element || this).type === 'radialGradient' ? this.attr({ - fx: new SVGNumber(x), - fy: new SVGNumber(y) - }) : this.attr({ - x1: new SVGNumber(x), - y1: new SVGNumber(y) - }); - } - function to(x, y) { - return (this._element || this).type === 'radialGradient' ? this.attr({ - cx: new SVGNumber(x), - cy: new SVGNumber(y) - }) : this.attr({ - x2: new SVGNumber(x), - y2: new SVGNumber(y) - }); - } + var Animator = { + nextDraw: null, + frames: new Queue(), + timeouts: new Queue(), + timer: window.performance || window.Date, + transforms: [], + frame: function frame(fn) { + // Store the node + var node = Animator.frames.push({ + run: fn + }); // Request an animation frame if we don't have one - var gradiented = /*#__PURE__*/Object.freeze({ - from: from, - to: to - }); + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw); + } // Return the node so we can remove it easily - var Gradient = - /*#__PURE__*/ - function (_Container) { - _inherits(Gradient, _Container); - function Gradient(type) { - _classCallCheck(this, Gradient); + return node; + }, + transform_frame: function transform_frame(fn, id) { + Animator.transforms[id] = fn; + }, + timeout: function timeout(fn, delay) { + delay = delay || 0; // Work out when the event should fire - return _possibleConstructorReturn(this, _getPrototypeOf(Gradient).call(this, nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type), Gradient)); - } // Add a color stop + var time = Animator.timer.now() + delay; // Add the timeout to the end of the queue + var node = Animator.timeouts.push({ + run: fn, + time: time + }); // Request another animation frame if we need one - _createClass(Gradient, [{ - key: "stop", - value: function stop(offset, color, opacity) { - return this.put(new Stop()).update(offset, color, opacity); - } // Update gradient + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw); + } - }, { - key: "update", - value: function update(block) { - // remove all stops - this.clear(); // invoke passed block + return node; + }, + cancelFrame: function cancelFrame(node) { + Animator.frames.remove(node); + }, + clearTimeout: function clearTimeout(node) { + Animator.timeouts.remove(node); + }, + _draw: function _draw(now) { + // Run all the timeouts we can run, if they are not ready yet, add them + // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) + var nextTimeout = null; + var lastTimeout = Animator.timeouts.last(); - if (typeof block === 'function') { - block.call(this, this); - } + while (nextTimeout = Animator.timeouts.shift()) { + // Run the timeout if its time, or push it to the end + if (now >= nextTimeout.time) { + nextTimeout.run(); + } else { + Animator.timeouts.push(nextTimeout); + } // If we hit the last item, we should stop shifting out more items - return this; - } // Return the fill id - }, { - key: "url", - value: function url() { - return 'url(#' + this.id() + ')'; - } // Alias string convertion to fill + if (nextTimeout === lastTimeout) break; + } // Run all of the animation frames - }, { - key: "toString", - value: function toString() { - return this.url(); - } // custom attr to handle transform - }, { - key: "attr", - value: function attr(a, b, c) { - if (a === 'transform') a = 'gradientTransform'; - return _get(_getPrototypeOf(Gradient.prototype), "attr", this).call(this, a, b, c); - } - }, { - key: "targets", - value: function targets() { - return find('svg [fill*="' + this.id() + '"]'); - } - }, { - key: "bbox", - value: function bbox() { - return new Box(); - } - }]); + var nextFrame = null; + var lastFrame = Animator.frames.last(); - return Gradient; - }(Container); - extend(Gradient, gradiented); - registerMethods({ - Container: { - // Create gradient element in defs - gradient: function gradient(type, block) { - return this.defs().gradient(type, block); - } - }, - // define gradient - Defs: { - gradient: function gradient(type, block) { - return this.put(new Gradient(type)).update(block); + while (nextFrame !== lastFrame && (nextFrame = Animator.frames.shift())) { + nextFrame.run(); } - } - }); - register(Gradient); - - var G = - /*#__PURE__*/ - function (_Container) { - _inherits(G, _Container); - function G(node) { - _classCallCheck(this, G); + Animator.transforms.forEach(function (el) { + el(); + }); // If we have remaining timeouts or frames, draw until we don't anymore - return _possibleConstructorReturn(this, _getPrototypeOf(G).call(this, nodeOrNew('g', node), G)); + Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() ? window.requestAnimationFrame(Animator._draw) : null; } + }; - return G; - }(Container); - registerMethods({ - Element: { - // Create a group element - group: function group() { - return this.put(new G()); + function isNulledBox(box) { + return !box.w && !box.h && !box.x && !box.y; + } + + function domContains(node) { + return (document.documentElement.contains || function (node) { + // This is IE - it does not support contains() for top-level SVGs + while (node.parentNode) { + node = node.parentNode; } - } - }); - register(G); - var HtmlNode = - /*#__PURE__*/ - function (_Dom) { - _inherits(HtmlNode, _Dom); + return node === document; + }).call(document.documentElement, node); + } - function HtmlNode(node) { - _classCallCheck(this, HtmlNode); + var Box = + /*#__PURE__*/ + function () { + function Box() { + _classCallCheck(this, Box); - return _possibleConstructorReturn(this, _getPrototypeOf(HtmlNode).call(this, node, HtmlNode)); + this.init.apply(this, arguments); } - return HtmlNode; - }(Dom); - register(HtmlNode); + _createClass(Box, [{ + key: "init", + value: function init(source) { + var base = [0, 0, 0, 0]; + source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) : Array.isArray(source) ? source : _typeof(source) === 'object' ? [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] : arguments.length === 4 ? [].slice.call(arguments) : base; + this.x = source[0] || 0; + this.y = source[1] || 0; + this.width = this.w = source[2] || 0; + this.height = this.h = source[3] || 0; // Add more bounding box properties + + this.x2 = this.x + this.w; + this.y2 = this.y + this.h; + this.cx = this.x + this.w / 2; + this.cy = this.y + this.h / 2; + } // Merge rect box with another, return a new instance - var A = - /*#__PURE__*/ - function (_Container) { - _inherits(A, _Container); + }, { + key: "merge", + value: function merge(box) { + var x = Math.min(this.x, box.x); + var y = Math.min(this.y, box.y); + var width = Math.max(this.x + this.width, box.x + box.width) - x; + var height = Math.max(this.y + this.height, box.y + box.height) - y; + return new Box(x, y, width, height); + } + }, { + key: "transform", + value: function transform(m) { + var xMin = Infinity; + var xMax = -Infinity; + var yMin = Infinity; + var yMax = -Infinity; + var pts = [new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2)]; + pts.forEach(function (p) { + p = p.transform(m); + xMin = Math.min(xMin, p.x); + xMax = Math.max(xMax, p.x); + yMin = Math.min(yMin, p.y); + yMax = Math.max(yMax, p.y); + }); + return new Box(xMin, yMin, xMax - xMin, yMax - yMin); + } + }, { + key: "addOffset", + value: function addOffset() { + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset; + this.y += window.pageYOffset; + return this; + } + }, { + key: "toString", + value: function toString() { + return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height; + } + }, { + key: "toArray", + value: function toArray() { + return [this.x, this.y, this.width, this.height]; + } + }, { + key: "isNulled", + value: function isNulled() { + return isNulledBox(this); + } + }]); - function A(node) { - _classCallCheck(this, A); + return Box; + }(); - return _possibleConstructorReturn(this, _getPrototypeOf(A).call(this, nodeOrNew('a', node), A)); - } // Link url + function getBox(cb) { + var box; + try { + box = cb(this.node); - _createClass(A, [{ - key: "to", - value: function to(url) { - return this.attr('href', url, xlink); - } // Link target attribute - - }, { - key: "target", - value: function target(_target) { - return this.attr('target', _target); - } - }]); - - return A; - }(Container); - registerMethods({ - Container: { - // Create a hyperlink element - link: function link(url) { - return this.put(new A()).to(url); + if (isNulledBox(box) && !domContains(this.node)) { + throw new Error('Element not in the dom'); } - }, - Element: { - // Create a hyperlink element - linkTo: function linkTo(url) { - var link = new A(); - - if (typeof url === 'function') { - url.call(link, link); - } else { - link.to(url); - } - - return this.parent().put(link).put(this); + } catch (e) { + try { + var clone = this.clone(parser().svg).show(); + box = cb(clone.node); + clone.remove(); + } catch (e) { + console.warn('Getting a bounding box of this element is not possible'); } } - }); - register(A); - - var Pattern = - /*#__PURE__*/ - function (_Container) { - _inherits(Pattern, _Container); - - // Initialize node - function Pattern(node) { - _classCallCheck(this, Pattern); - - return _possibleConstructorReturn(this, _getPrototypeOf(Pattern).call(this, nodeOrNew('pattern', node), Pattern)); - } // Return the fill id - - - _createClass(Pattern, [{ - key: "url", - value: function url() { - return 'url(#' + this.id() + ')'; - } // Update pattern by rebuilding - - }, { - key: "update", - value: function update(block) { - // remove content - this.clear(); // invoke passed block - - if (typeof block === 'function') { - block.call(this, this); - } - - return this; - } // Alias string convertion to fill - - }, { - key: "toString", - value: function toString() { - return this.url(); - } // custom attr to handle transform - }, { - key: "attr", - value: function attr(a, b, c) { - if (a === 'transform') a = 'patternTransform'; - return _get(_getPrototypeOf(Pattern.prototype), "attr", this).call(this, a, b, c); - } - }, { - key: "targets", - value: function targets() { - return find('svg [fill*="' + this.id() + '"]'); - } - }, { - key: "bbox", - value: function bbox() { - return new Box(); - } - }]); + return box; + } - return Pattern; - }(Container); registerMethods({ - Container: { - // Create pattern element in defs - pattern: function pattern(width, height, block) { - return this.defs().pattern(width, height, block); + Element: { + // Get bounding box + bbox: function bbox() { + return new Box(getBox.call(this, function (node) { + return node.getBBox(); + })); + }, + rbox: function rbox(el) { + var box = new Box(getBox.call(this, function (node) { + return node.getBoundingClientRect(); + })); + if (el) return box.transform(el.screenCTM().inverse()); + return box.addOffset(); } }, - Defs: { - pattern: function pattern(width, height, block) { - return this.put(new Pattern()).update(block).attr({ - x: 0, - y: 0, - width: width, - height: height, - patternUnits: 'userSpaceOnUse' - }); + viewbox: { + viewbox: function viewbox(x, y, width, height) { + // act as getter + if (x == null) return new Box(this.attr('viewBox')); // act as setter + + return this.attr('viewBox', new Box(x, y, width, height)); } } }); - register(Pattern); - var Image = - /*#__PURE__*/ - function (_Shape) { - _inherits(Image, _Shape); + var PathArray = subClassArray('PathArray', SVGArray); + function pathRegReplace(a, b, c, d) { + return c + d.replace(dots, ' .'); + } - function Image(node) { - _classCallCheck(this, Image); + function arrayToString(a) { + for (var i = 0, il = a.length, s = ''; i < il; i++) { + s += a[i][0]; - return _possibleConstructorReturn(this, _getPrototypeOf(Image).call(this, nodeOrNew('image', node), Image)); - } // (re)load image + if (a[i][1] != null) { + s += a[i][1]; + if (a[i][2] != null) { + s += ' '; + s += a[i][2]; - _createClass(Image, [{ - key: "load", - value: function load(url, callback) { - if (!url) return this; - var img = new window.Image(); - on(img, 'load', function (e) { - var p = this.parent(Pattern); // ensure image size + if (a[i][3] != null) { + s += ' '; + s += a[i][3]; + s += ' '; + s += a[i][4]; - if (this.width() === 0 && this.height() === 0) { - this.size(img.width, img.height); - } + if (a[i][5] != null) { + s += ' '; + s += a[i][5]; + s += ' '; + s += a[i][6]; - if (p instanceof Pattern) { - // ensure pattern size if not set - if (p.width() === 0 && p.height() === 0) { - p.size(this.width(), this.height()); + if (a[i][7] != null) { + s += ' '; + s += a[i][7]; + } } } - - if (typeof callback === 'function') { - callback.call(this, { - width: img.width, - height: img.height, - ratio: img.width / img.height, - url: url - }); - } - }, this); - on(img, 'load error', function () { - // dont forget to unbind memory leaking events - off(img); - }); - return this.attr('href', img.src = url, xlink); - } - }, { - key: "attrHook", - value: function attrHook(obj) { - var _this = this; - - return obj.doc().defs().pattern(0, 0, function (pattern) { - pattern.add(_this); - }); - } - }]); - - return Image; - }(Shape); - registerMethods({ - Container: { - // create image element, load image and set its size - image: function image(source, callback) { - return this.put(new Image()).size(0, 0).load(source, callback); + } } } - }); - register(Image); - var PointArray = subClassArray('PointArray', SVGArray); - extend(PointArray, { - // Convert array to string - toString: function toString() { - // convert to a poly point string - for (var i = 0, il = this.length, array = []; i < il; i++) { - array.push(this[i].join(',')); - } + return s + ' '; + } - return array.join(' '); + var pathHandlers = { + M: function M(c, p, p0) { + p.x = p0.x = c[0]; + p.y = p0.y = c[1]; + return ['M', p.x, p.y]; }, - // Convert array to line object - toLine: function toLine() { - return { - x1: this[0][0], - y1: this[0][1], - x2: this[1][0], - y2: this[1][1] - }; + L: function L(c, p) { + p.x = c[0]; + p.y = c[1]; + return ['L', c[0], c[1]]; }, - // Get morphed array at given position - at: function at(pos) { - // make sure a destination is defined - if (!this.destination) return this; // generate morphed point string - - for (var i = 0, il = this.length, array = []; i < il; i++) { - array.push([this[i][0] + (this.destination[i][0] - this[i][0]) * pos, this[i][1] + (this.destination[i][1] - this[i][1]) * pos]); - } - - return new PointArray(array); + H: function H(c, p) { + p.x = c[0]; + return ['H', c[0]]; }, - // Parse point string and flat array - parse: function parse() { - var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [[0, 0]]; - var points = []; // if it is an array + V: function V(c, p) { + p.y = c[0]; + return ['V', c[0]]; + }, + C: function C(c, p) { + p.x = c[4]; + p.y = c[5]; + return ['C', c[0], c[1], c[2], c[3], c[4], c[5]]; + }, + S: function S(c, p) { + p.x = c[2]; + p.y = c[3]; + return ['S', c[0], c[1], c[2], c[3]]; + }, + Q: function Q(c, p) { + p.x = c[2]; + p.y = c[3]; + return ['Q', c[0], c[1], c[2], c[3]]; + }, + T: function T(c, p) { + p.x = c[0]; + p.y = c[1]; + return ['T', c[0], c[1]]; + }, + Z: function Z(c, p, p0) { + p.x = p0.x; + p.y = p0.y; + return ['Z']; + }, + A: function A(c, p) { + p.x = c[5]; + p.y = c[6]; + return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]]; + } + }; + var mlhvqtcsaz = 'mlhvqtcsaz'.split(''); - if (array instanceof Array) { - // and it is not flat, there is no need to parse it - if (array[0] instanceof Array) { - return array; + for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { + pathHandlers[mlhvqtcsaz[i]] = function (i) { + return function (c, p, p0) { + if (i === 'H') c[0] = c[0] + p.x;else if (i === 'V') c[0] = c[0] + p.y;else if (i === 'A') { + c[5] = c[5] + p.x; + c[6] = c[6] + p.y; + } else { + for (var j = 0, jl = c.length; j < jl; ++j) { + c[j] = c[j] + (j % 2 ? p.y : p.x); + } } - } else { - // Else, it is considered as a string - // parse points - array = array.trim().split(delimiter).map(parseFloat); - } // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints - // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. - - - if (array.length % 2 !== 0) array.pop(); // wrap points in two-tuples and parse points as floats - - for (var i = 0, len = array.length; i < len; i = i + 2) { - points.push([array[i], array[i + 1]]); - } + return pathHandlers[i](c, p, p0); + }; + }(mlhvqtcsaz[i].toUpperCase()); + } - return points; + extend(PathArray, { + // Convert array to string + toString: function toString() { + return arrayToString(this); }, - // Move point string + // Move path string move: function move(x, y) { + // get bounding box of current situation var box = this.bbox(); // get relative offset x -= box.x; - y -= box.y; // move every point + y -= box.y; if (!isNaN(x) && !isNaN(y)) { - for (var i = this.length - 1; i >= 0; i--) { - this[i] = [this[i][0] + x, this[i][1] + y]; + // move every point + for (var l, i = this.length - 1; i >= 0; i--) { + l = this[i][0]; + + if (l === 'M' || l === 'L' || l === 'T') { + this[i][1] += x; + this[i][2] += y; + } else if (l === 'H') { + this[i][1] += x; + } else if (l === 'V') { + this[i][1] += y; + } else if (l === 'C' || l === 'S' || l === 'Q') { + this[i][1] += x; + this[i][2] += y; + this[i][3] += x; + this[i][4] += y; + + if (l === 'C') { + this[i][5] += x; + this[i][6] += y; + } + } else if (l === 'A') { + this[i][6] += x; + this[i][7] += y; + } } } return this; }, - // Resize poly string + // Resize path string size: function size(width, height) { - var i; - var box = this.bbox(); // recalculate position of all points according to new size + // get bounding box of current situation + var box = this.bbox(); + var i, l; // recalculate position of all points according to new size for (i = this.length - 1; i >= 0; i--) { - if (box.width) this[i][0] = (this[i][0] - box.x) * width / box.width + box.x; - if (box.height) this[i][1] = (this[i][1] - box.y) * height / box.height + box.y; + l = this[i][0]; + + if (l === 'M' || l === 'L' || l === 'T') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; + } else if (l === 'H') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + } else if (l === 'V') { + this[i][1] = (this[i][1] - box.y) * height / box.height + box.y; + } else if (l === 'C' || l === 'S' || l === 'Q') { + this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; + this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; + this[i][3] = (this[i][3] - box.x) * width / box.width + box.x; + this[i][4] = (this[i][4] - box.y) * height / box.height + box.y; + + if (l === 'C') { + this[i][5] = (this[i][5] - box.x) * width / box.width + box.x; + this[i][6] = (this[i][6] - box.y) * height / box.height + box.y; + } + } else if (l === 'A') { + // resize radii + this[i][1] = this[i][1] * width / box.width; + this[i][2] = this[i][2] * height / box.height; // move position values + + this[i][6] = (this[i][6] - box.x) * width / box.width + box.x; + this[i][7] = (this[i][7] - box.y) * height / box.height + box.y; + } } return this; }, - // Get bounding box of points - bbox: function bbox() { - var maxX = -Infinity; - var maxY = -Infinity; - var minX = Infinity; - var minY = Infinity; - this.forEach(function (el) { - maxX = Math.max(el[0], maxX); - maxY = Math.max(el[1], maxY); - minX = Math.min(el[0], minX); - minY = Math.min(el[1], minY); - }); - return { - x: minX, - y: minY, - width: maxX - minX, - height: maxY - minY - }; - } - }); + // Test if the passed path array use the same path data commands as this path array + equalCommands: function equalCommands(pathArray) { + var i, il, equalCommands; + pathArray = new PathArray(pathArray); + equalCommands = this.length === pathArray.length; - var MorphArray = PointArray; // Move by left top corner over x-axis + for (i = 0, il = this.length; equalCommands && i < il; i++) { + equalCommands = this[i][0] === pathArray[i][0]; + } - function x$1(x) { - return x == null ? this.bbox().x : this.move(x, this.bbox().y); - } // Move by left top corner over y-axis + return equalCommands; + }, + // Make path array morphable + morph: function morph(pathArray) { + pathArray = new PathArray(pathArray); - function y$1(y) { - return y == null ? this.bbox().y : this.move(this.bbox().x, y); - } // Set width of element + if (this.equalCommands(pathArray)) { + this.destination = pathArray; + } else { + this.destination = null; + } - function width$1(width) { - var b = this.bbox(); - return width == null ? b.width : this.size(width, b.height); - } // Set height of element + return this; + }, + // Get morphed path array at given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; + var sourceArray = this; + var destinationArray = this.destination.value; + var array = []; + var pathArray = new PathArray(); + var i, il, j, jl; // Animate has specified in the SVG spec + // See: https://www.w3.org/TR/SVG11/paths.html#PathElement - function height$1(height) { - var b = this.bbox(); - return height == null ? b.height : this.size(b.width, height); - } + for (i = 0, il = sourceArray.length; i < il; i++) { + array[i] = [sourceArray[i][0]]; - var pointed = /*#__PURE__*/Object.freeze({ - MorphArray: MorphArray, - x: x$1, - y: y$1, - width: width$1, - height: height$1 - }); + for (j = 1, jl = sourceArray[i].length; j < jl; j++) { + array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos; + } // For the two flags of the elliptical arc command, the SVG spec say: + // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true + // Elliptical arc command as an array followed by corresponding indexes: + // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // 0 1 2 3 4 5 6 7 - var Line = - /*#__PURE__*/ - function (_Shape) { - _inherits(Line, _Shape); - // Initialize node - function Line(node) { - _classCallCheck(this, Line); + if (array[i][0] === 'A') { + array[i][4] = +(array[i][4] !== 0); + array[i][5] = +(array[i][5] !== 0); + } + } // Directly modify the value of a path array, this is done this way for performance - return _possibleConstructorReturn(this, _getPrototypeOf(Line).call(this, nodeOrNew('line', node), Line)); - } // Get array + pathArray.value = array; + return pathArray; + }, + // Absolutize and parse path to array + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [['M', 0, 0]]; + // if it's already a patharray, no need to parse it + if (array instanceof PathArray) return array; // prepare for parsing - _createClass(Line, [{ - key: "array", - value: function array() { - return new PointArray([[this.attr('x1'), this.attr('y1')], [this.attr('x2'), this.attr('y2')]]); - } // Overwrite native plot() method - - }, { - key: "plot", - value: function plot(x1, y1, x2, y2) { - if (x1 == null) { - return this.array(); - } else if (typeof y1 !== 'undefined') { - x1 = { - x1: x1, - y1: y1, - x2: x2, - y2: y2 - }; - } else { - x1 = new PointArray(x1).toLine(); - } + var s; + var paramCnt = { + 'M': 2, + 'L': 2, + 'H': 1, + 'V': 1, + 'C': 6, + 'S': 4, + 'Q': 4, + 'T': 2, + 'A': 7, + 'Z': 0 + }; - return this.attr(x1); - } // Move by left top corner + if (typeof array === 'string') { + array = array.replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 + .replace(pathLetters, ' $& ') // put some room between letters and numbers + .replace(hyphen, '$1 -') // add space before hyphen + .trim() // trim + .split(delimiter); // split into array + } else { + array = array.reduce(function (prev, curr) { + return [].concat.call(prev, curr); + }, []); + } // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] - }, { - key: "move", - value: function move(x, y) { - return this.attr(this.array().move(x, y).toLine()); - } // Set element size to given width and height - }, { - key: "size", - value: function size(width, height) { - var p = proportionalSize(this, width, height); - return this.attr(this.array().size(p.width, p.height).toLine()); - } - }]); + var result = []; + var p = new Point(); + var p0 = new Point(); + var index = 0; + var len = array.length; - return Line; - }(Shape); - extend(Line, pointed); - registerMethods({ - Container: { - // Create a line element - line: function line() { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; + do { + // Test if we have a path letter + if (isPathLetter.test(array[index])) { + s = array[index]; + ++index; // If last letter was a move command and we got no new, it defaults to [L]ine + } else if (s === 'M') { + s = 'L'; + } else if (s === 'm') { + s = 'l'; } - // 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]); - } + result.push(pathHandlers[s].call(null, array.slice(index, index = index + paramCnt[s.toUpperCase()]).map(parseFloat), p, p0)); + } while (len > index); + + return result; + }, + // Get bounding box of path + bbox: function bbox() { + parser().path.setAttribute('d', this.toString()); + return parser.nodes.path.getBBox(); } }); - register(Line); - var Marker = + var Morphable = /*#__PURE__*/ - function (_Container) { - _inherits(Marker, _Container); - - // Initialize node - function Marker(node) { - _classCallCheck(this, Marker); - - return _possibleConstructorReturn(this, _getPrototypeOf(Marker).call(this, nodeOrNew('marker', node), Marker)); - } // Set width of element + function () { + function Morphable(stepper) { + _classCallCheck(this, Morphable); + // FIXME: the default stepper does not know about easing + this._stepper = stepper || new Ease('-'); + this._from = null; + this._to = null; + this._type = null; + this._context = null; + this._morphObj = null; + } - _createClass(Marker, [{ - key: "width", - value: function width(_width) { - return this.attr('markerWidth', _width); - } // Set height of element + _createClass(Morphable, [{ + key: "from", + value: function from(val) { + if (val == null) { + return this._from; + } + this._from = this._set(val); + return this; + } }, { - key: "height", - value: function height(_height) { - return this.attr('markerHeight', _height); - } // Set marker refX and refY + key: "to", + value: function to(val) { + if (val == null) { + return this._to; + } + this._to = this._set(val); + return this; + } }, { - key: "ref", - value: function ref(x, y) { - return this.attr('refX', x).attr('refY', y); - } // Update marker + key: "type", + value: function type(_type) { + // getter + if (_type == null) { + return this._type; + } // setter + + this._type = _type; + return this; + } }, { - key: "update", - value: function update(block) { - // remove all content - this.clear(); // invoke passed block + key: "_set", + value: function _set$$1(value) { + if (!this._type) { + var type = _typeof(value); - if (typeof block === 'function') { - block.call(this, this); + if (type === 'number') { + this.type(SVGNumber); + } else if (type === 'string') { + if (Color.isColor(value)) { + this.type(Color); + } else if (delimiter.test(value)) { + this.type(pathLetters.test(value) ? PathArray : SVGArray); + } else if (numberAndUnit.test(value)) { + this.type(SVGNumber); + } else { + this.type(NonMorphable); + } + } else if (morphableTypes.indexOf(value.constructor) > -1) { + this.type(value.constructor); + } else if (Array.isArray(value)) { + this.type(SVGArray); + } else if (type === 'object') { + this.type(ObjectBag); + } else { + this.type(NonMorphable); + } } - return this; - } // Return the fill id - + var result = new this._type(value).toArray(); + this._morphObj = this._morphObj || new this._type(); + this._context = this._context || Array.apply(null, Array(result.length)).map(Object); + return result; + } }, { - key: "toString", - value: function toString() { - return 'url(#' + this.id() + ')'; + key: "stepper", + value: function stepper(_stepper) { + if (_stepper == null) return this._stepper; + this._stepper = _stepper; + return this; } - }]); + }, { + key: "done", + value: function done() { + var complete = this._context.map(this._stepper.done).reduce(function (last, curr) { + return last && curr; + }, true); - return Marker; - }(Container); - registerMethods({ - Container: { - marker: function marker(width, height, block) { - // Create marker element in defs - return this.defs().marker(width, height, block); - } - }, - Defs: { - // Create marker - marker: function marker(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 complete; } - }, - marker: { - // Create and attach markers - marker: function marker(_marker, width, height, block) { - var attr = ['marker']; // Build attribute name - - if (_marker !== 'all') attr.push(_marker); - attr = attr.join('-'); // Set marker attribute + }, { + key: "at", + value: function at(pos) { + var _this = this; - _marker = arguments[1] instanceof Marker ? arguments[1] : this.defs().marker(width, height, block); - return this.attr(attr, _marker); + return this._morphObj.fromArray(this._from.map(function (i, index) { + return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context); + })); } - } - }); - register(Marker); + }]); - var Mask = + return Morphable; + }(); + var NonMorphable = /*#__PURE__*/ - function (_Container) { - _inherits(Mask, _Container); + function () { + function NonMorphable() { + _classCallCheck(this, NonMorphable); - // Initialize node - function Mask(node) { - _classCallCheck(this, Mask); - - return _possibleConstructorReturn(this, _getPrototypeOf(Mask).call(this, nodeOrNew('mask', node), Mask)); - } // Unmask all masked elements and remove itself - - - _createClass(Mask, [{ - key: "remove", - value: function remove() { - // unmask all targets - this.targets().forEach(function (el) { - el.unmask(); - }); // remove mask from parent + this.init.apply(this, arguments); + } - return _get(_getPrototypeOf(Mask.prototype), "remove", this).call(this); + _createClass(NonMorphable, [{ + key: "init", + value: function init(val) { + val = Array.isArray(val) ? val[0] : val; + this.value = val; } }, { - key: "targets", - value: function targets() { - return baseFind('svg [mask*="' + this.id() + '"]'); + key: "valueOf", + value: function valueOf() { + return this.value; + } + }, { + key: "toArray", + value: function toArray() { + return [this.value]; } }]); - return Mask; - }(Container); - registerMethods({ - Container: { - mask: function mask() { - return this.defs().put(new Mask()); - } - }, - Element: { - // Distribute mask to svg element - maskWith: function maskWith(element) { - // use given mask or create a new one - var masker = element instanceof Mask ? element : this.parent().mask().add(element); // apply mask + return NonMorphable; + }(); + var TransformBag = + /*#__PURE__*/ + function () { + function TransformBag() { + _classCallCheck(this, TransformBag); - return this.attr('mask', 'url("#' + masker.id() + '")'); - }, - // Unmask element - unmask: function unmask() { - return this.attr('mask', null); - }, - masker: function masker() { - return this.reference('mask'); - } + this.init.apply(this, arguments); } - }); - register(Mask); - var Matrix = + _createClass(TransformBag, [{ + key: "init", + value: function init(obj) { + if (Array.isArray(obj)) { + obj = { + scaleX: obj[0], + scaleY: obj[1], + shear: obj[2], + rotate: obj[3], + translateX: obj[4], + translateY: obj[5], + originX: obj[6], + originY: obj[7] + }; + } + + Object.assign(this, TransformBag.defaults, obj); + } + }, { + key: "toArray", + value: function toArray() { + var v = this; + return [v.scaleX, v.scaleY, v.shear, v.rotate, v.translateX, v.translateY, v.originX, v.originY]; + } + }]); + + return TransformBag; + }(); + TransformBag.defaults = { + scaleX: 1, + scaleY: 1, + shear: 0, + rotate: 0, + translateX: 0, + translateY: 0, + originX: 0, + originY: 0 + }; + var ObjectBag = /*#__PURE__*/ function () { - function Matrix() { - _classCallCheck(this, Matrix); + function ObjectBag() { + _classCallCheck(this, ObjectBag); this.init.apply(this, arguments); - } // Initialize - + } - _createClass(Matrix, [{ + _createClass(ObjectBag, [{ key: "init", - value: function init(source) { - var base = arrayToMatrix([1, 0, 0, 1, 0, 0]); // ensure source as object - - source = source instanceof Element ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? arrayToMatrix(source) : _typeof(source) === 'object' && isMatrixLike(source) ? source : _typeof(source) === 'object' ? new Matrix().transform(source) : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) : base; // Merge the source matrix with the base matrix + value: function init(objOrArr) { + this.values = []; - this.a = source.a != null ? source.a : base.a; - this.b = source.b != null ? source.b : base.b; - this.c = source.c != null ? source.c : base.c; - this.d = source.d != null ? source.d : base.d; - this.e = source.e != null ? source.e : base.e; - this.f = source.f != null ? source.f : base.f; - } // Clones this matrix + if (Array.isArray(objOrArr)) { + this.values = objOrArr; + return; + } + var entries = Object.entries(objOrArr || {}).sort(function (a, b) { + return a[0] - b[0]; + }); + this.values = entries.reduce(function (last, curr) { + return last.concat(curr); + }, []); + } }, { - key: "clone", - value: function clone() { - return new Matrix(this); - } // Transform a matrix into another matrix by manipulating the space + key: "valueOf", + value: function valueOf() { + var obj = {}; + var arr = this.values; + + for (var i = 0, len = arr.length; i < len; i += 2) { + obj[arr[i]] = arr[i + 1]; + } + return obj; + } }, { - key: "transform", - value: function transform(o) { - // Check if o is a matrix and then left multiply it directly - if (isMatrixLike(o)) { - var matrix = new Matrix(o); - return matrix.multiplyO(this); - } // Get the proposed transformations and the current transformations + key: "toArray", + value: function toArray() { + return this.values; + } + }]); + return ObjectBag; + }(); + var morphableTypes = [NonMorphable, TransformBag, ObjectBag]; + function registerMorphableType() { + var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + morphableTypes.push.apply(morphableTypes, _toConsumableArray([].concat(type))); + } + function makeMorphable() { + extend(morphableTypes, { + to: function to(val, args) { + return new Morphable().type(this.constructor).from(this.valueOf()).to(val, args); + }, + fromArray: function fromArray(arr) { + this.init(arr); + return this; + } + }); + } - var t = Matrix.formatTransforms(o); - var current = this; + var time = window.performance || Date; - var _transform = new Point(t.ox, t.oy).transform(current), - ox = _transform.x, - oy = _transform.y; // Construct the resulting matrix + var makeSchedule = function makeSchedule(runnerInfo) { + var start = runnerInfo.start; + var duration = runnerInfo.runner.duration(); + var end = start + duration; + return { + start: start, + duration: duration, + end: end, + runner: runnerInfo.runner + }; + }; + var Timeline = + /*#__PURE__*/ + function () { + // Construct a new timeline on the given element + function Timeline() { + _classCallCheck(this, Timeline); - var transformer = new Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy); // If we want the origin at a particular place, we force it there + this._timeSource = function () { + return time.now(); + }; - if (isFinite(t.px) || isFinite(t.py)) { - var origin = new Point(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px) + this._dispatcher = document.createElement('div'); // Store the timing variables - var dx = t.px ? t.px - origin.x : 0; - var dy = t.py ? t.py - origin.y : 0; - transformer.translateO(dx, dy); - } // Translate now after positioning + this._startTime = 0; + this._speed = 1.0; // Play control variables control how the animation proceeds + this._reverse = false; + this._persist = 0; // Keep track of the running animations and their starting parameters - transformer.translateO(t.tx, t.ty); - return transformer; - } // Applies a matrix defined by its affine parameters + this._nextFrame = null; + this._paused = false; + this._runners = []; + this._order = []; + this._time = 0; + this._lastSourceTime = 0; + this._lastStepTime = 0; + } + + _createClass(Timeline, [{ + key: "getEventTarget", + value: function getEventTarget() { + return this._dispatcher; + } + /** + * + */ + // schedules a runner on the timeline }, { - key: "compose", - value: function compose(o) { - if (o.origin) { - o.originX = o.origin[0]; - o.originY = o.origin[1]; - } // Get the parameters + key: "schedule", + value: function schedule(runner, delay, when) { + if (runner == null) { + return this._runners.map(makeSchedule).sort(function (a, b) { + return a.start - b.start || a.duration - b.duration; + }); + } + if (!this.active()) { + this._step(); - var ox = o.originX || 0; - var oy = o.originY || 0; - var sx = o.scaleX || 1; - var sy = o.scaleY || 1; - var lam = o.shear || 0; - var theta = o.rotate || 0; - var tx = o.translateX || 0; - var ty = o.translateY || 0; // Apply the standard matrix + if (when == null) { + when = 'now'; + } + } // The start time for the next animation can either be given explicitly, + // derived from the current timeline time or it can be relative to the + // last start time to chain animations direclty - var result = new Matrix().translateO(-ox, -oy).scaleO(sx, sy).shearO(lam).rotateO(theta).translateO(tx, ty).lmultiplyO(this).translateO(ox, oy); - return result; - } // Decomposes this matrix into its affine parameters - }, { - key: "decompose", - value: function decompose() { - var cx = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; - var cy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - // Get the parameters from the matrix - var a = this.a; - var b = this.b; - var c = this.c; - var d = this.d; - var e = this.e; - var f = this.f; // Figure out if the winding direction is clockwise or counterclockwise + var absoluteStartTime = 0; + delay = delay || 0; // Work out when to start the animation - var determinant = a * d - b * c; - var ccw = determinant > 0 ? 1 : -1; // Since we only shear in x, we can use the x basis to get the x scale - // and the rotation of the resulting matrix + if (when == null || when === 'last' || when === 'after') { + // Take the last time and increment + absoluteStartTime = this._startTime; + } else if (when === 'absolute' || when === 'start') { + absoluteStartTime = delay; + delay = 0; + } else if (when === 'now') { + absoluteStartTime = this._time; + } else if (when === 'relative') { + var runnerInfo = this._runners[runner.id]; - var sx = ccw * Math.sqrt(a * a + b * b); - var thetaRad = Math.atan2(ccw * b, ccw * a); - var theta = 180 / Math.PI * thetaRad; - var ct = Math.cos(thetaRad); - var st = Math.sin(thetaRad); // We can then solve the y basis vector simultaneously to get the other - // two affine parameters directly from these parameters + if (runnerInfo) { + absoluteStartTime = runnerInfo.start + delay; + delay = 0; + } + } else { + throw new Error('Invalid value for the "when" parameter'); + } // Manage runner - var lam = (a * c + b * d) / determinant; - var sy = c * sx / (lam * a - b) || d * sx / (lam * b + a); // Use the translations - var tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy); - var ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy); // Construct the decomposition and return it + runner.unschedule(); + runner.timeline(this); + runner.time(-delay); // Save startTime for next runner + + this._startTime = absoluteStartTime + runner.duration() + delay; // Save runnerInfo + + this._runners[runner.id] = { + persist: this.persist(), + runner: runner, + start: absoluteStartTime // Save order and continue - return { - // Return the affine parameters - scaleX: sx, - scaleY: sy, - shear: lam, - rotate: theta, - translateX: tx, - translateY: ty, - originX: cx, - originY: cy, - // Return the matrix parameters - a: this.a, - b: this.b, - c: this.c, - d: this.d, - e: this.e, - f: this.f }; - } // Left multiplies by the given matrix + + this._order.push(runner.id); + + this._continue(); + + return this; + } // Remove the runner from this timeline }, { - key: "multiply", - value: function multiply(matrix) { - return this.clone().multiplyO(matrix); + key: "unschedule", + value: function unschedule(runner) { + var index = this._order.indexOf(runner.id); + + if (index < 0) return this; + delete this._runners[runner.id]; + + this._order.splice(index, 1); + + runner.timeline(null); + return this; } }, { - key: "multiplyO", - value: function multiplyO(matrix) { - // Get the matrices - var l = this; - var r = matrix instanceof Matrix ? matrix : new Matrix(matrix); - return Matrix.matrixMultiply(l, r, this); + key: "play", + value: function play() { + // Now make sure we are not paused and continue the animation + this._paused = false; + return this._continue(); } }, { - key: "lmultiply", - value: function lmultiply(matrix) { - return this.clone().lmultiplyO(matrix); + key: "pause", + value: function pause() { + // Cancel the next animation frame and pause + this._nextFrame = null; + this._paused = true; + return this; } }, { - key: "lmultiplyO", - value: function lmultiplyO(matrix) { - var r = this; - var l = matrix instanceof Matrix ? matrix : new Matrix(matrix); - return Matrix.matrixMultiply(l, r, this); - } // Inverses matrix - + key: "stop", + value: function stop() { + // Cancel the next animation frame and go to start + this.seek(-this._time); + return this.pause(); + } }, { - key: "inverseO", - value: function inverseO() { - // Get the current parameters out of the matrix - var a = this.a; - var b = this.b; - var c = this.c; - var d = this.d; - var e = this.e; - var f = this.f; // Invert the 2x2 matrix in the top left - - var det = a * d - b * c; - if (!det) throw new Error('Cannot invert ' + this); // Calculate the top 2x2 matrix - - var na = d / det; - var nb = -b / det; - var nc = -c / det; - var nd = a / det; // Apply the inverted matrix to the top right - - var ne = -(na * e + nc * f); - var nf = -(nb * e + nd * f); // Construct the inverted matrix - - this.a = na; - this.b = nb; - this.c = nc; - this.d = nd; - this.e = ne; - this.f = nf; + key: "finish", + value: function finish() { + this.seek(Infinity); + return this.pause(); + } + }, { + key: "speed", + value: function speed(_speed) { + if (_speed == null) return this._speed; + this._speed = _speed; return this; } }, { - key: "inverse", - value: function inverse() { - return this.clone().inverseO(); - } // Translate matrix - + key: "reverse", + value: function reverse(yes) { + var currentSpeed = this.speed(); + if (yes == null) return this.speed(-currentSpeed); + var positive = Math.abs(currentSpeed); + return this.speed(yes ? positive : -positive); + } }, { - key: "translate", - value: function translate(x, y) { - return this.clone().translateO(x, y); + key: "seek", + value: function seek(dt) { + this._time += dt; + return this._continue(); } }, { - key: "translateO", - value: function translateO(x, y) { - this.e += x || 0; - this.f += y || 0; + key: "time", + value: function time(_time) { + if (_time == null) return this._time; + this._time = _time; return this; - } // Scale matrix - - }, { - key: "scale", - value: function scale(x, y, cx, cy) { - var _this$clone; - - return (_this$clone = this.clone()).scaleO.apply(_this$clone, arguments); } }, { - key: "scaleO", - value: function scaleO(x) { - var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; - var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; - - // Support uniform scaling - if (arguments.length === 3) { - cy = cx; - cx = y; - y = x; - } - - var a = this.a, - b = this.b, - c = this.c, - d = this.d, - e = this.e, - f = this.f; - this.a = a * x; - this.b = b * y; - this.c = c * x; - this.d = d * y; - this.e = e * x - cx * x + cx; - this.f = f * y - cy * y + cy; + key: "persist", + value: function persist(dtOrForever) { + if (dtOrForever == null) return this._persist; + this._persist = dtOrForever; return this; - } // Rotate matrix - + } }, { - key: "rotate", - value: function rotate(r, cx, cy) { - return this.clone().rotateO(r, cx, cy); + key: "source", + value: function source(fn) { + if (fn == null) return this._timeSource; + this._timeSource = fn; + return this; } }, { - key: "rotateO", - value: function rotateO(r) { - var cx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - // Convert degrees to radians - r = radians(r); - var cos = Math.cos(r); - var sin = Math.sin(r); - var a = this.a, - b = this.b, - c = this.c, - d = this.d, - e = this.e, - f = this.f; - this.a = a * cos - b * sin; - this.b = b * cos + a * sin; - this.c = c * cos - d * sin; - this.d = d * cos + c * sin; - this.e = e * cos - f * sin + cy * sin - cx * cos + cx; - this.f = f * cos + e * sin - cx * sin - cy * cos + cy; - return this; - } // Flip matrix on x or y, at a given offset + key: "_step", + value: function _step() { + // If the timeline is paused, just do nothing + if (this._paused) return; // Get the time delta from the last time and update the time + // TODO: Deal with window.blur window.focus to pause animations - }, { - key: "flip", - value: function flip(axis, around) { - return this.clone().flipO(axis, around); - } - }, { - key: "flipO", - value: function flipO(axis, around) { - return axis === 'x' ? this.scaleO(-1, 1, around, 0) : axis === 'y' ? this.scaleO(1, -1, 0, around) : this.scaleO(-1, -1, axis, around || axis); // Define an x, y flip point - } // Shear matrix + var time = this._timeSource(); - }, { - key: "shear", - value: function shear(a, cx, cy) { - return this.clone().shearO(a, cx, cy); - } - }, { - key: "shearO", - value: function shearO(lx) { - var cy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var a = this.a, - b = this.b, - c = this.c, - d = this.d, - e = this.e, - f = this.f; - this.a = a + b * lx; - this.c = c + d * lx; - this.e = e + f * lx - cy * lx; - return this; - } // Skew Matrix + var dtSource = time - this._lastSourceTime; + var dtTime = this._speed * dtSource + (this._time - this._lastStepTime); + this._lastSourceTime = time; // Update the time - }, { - key: "skew", - value: function skew(x, y, cx, cy) { - var _this$clone2; + this._time += dtTime; + this._lastStepTime = this._time; // this.fire('time', this._time) + // Run all of the runners directly - return (_this$clone2 = this.clone()).skewO.apply(_this$clone2, arguments); - } - }, { - key: "skewO", - value: function skewO(x) { - var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; - var cx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var cy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + var runnersLeft = false; - // support uniformal skew - if (arguments.length === 3) { - cy = cx; - cx = y; - y = x; - } // Convert degrees to radians + for (var i = 0, len = this._order.length; i < len; i++) { + // Get and run the current runner and ignore it if its inactive + var runnerInfo = this._runners[this._order[i]]; + var runner = runnerInfo.runner; + var dt = dtTime; // Make sure that we give the actual difference + // between runner start time and now + var dtToStart = this._time - runnerInfo.start; // Dont run runner if not started yet - x = radians(x); - y = radians(y); - var lx = Math.tan(x); - var ly = Math.tan(y); - var a = this.a, - b = this.b, - c = this.c, - d = this.d, - e = this.e, - f = this.f; - this.a = a + b * lx; - this.b = b + a * ly; - this.c = c + d * lx; - this.d = d + c * ly; - this.e = e + f * lx - cy * lx; - this.f = f + e * ly - cx * ly; - return this; - } // SkewX + if (dtToStart < 0) { + runnersLeft = true; + continue; + } else if (dtToStart < dt) { + // Adjust dt to make sure that animation is on point + dt = dtToStart; + } - }, { - key: "skewX", - value: function skewX(x, cx, cy) { - return this.skew(x, 0, cx, cy); - } - }, { - key: "skewXO", - value: function skewXO(x, cx, cy) { - return this.skewO(x, 0, cx, cy); - } // SkewY + if (!runner.active()) continue; // If this runner is still going, signal that we need another animation + // frame, otherwise, remove the completed runner - }, { - key: "skewY", - value: function skewY(y, cx, cy) { - return this.skew(0, y, cx, cy); - } - }, { - key: "skewYO", - value: function skewYO(y, cx, cy) { - return this.skewO(0, y, cx, cy); - } // Transform around a center point + var finished = runner.step(dt).done; - }, { - key: "aroundO", - value: function aroundO(cx, cy, matrix) { - var dx = cx || 0; - var dy = cy || 0; - return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy); - } - }, { - key: "around", - value: function around(cx, cy, matrix) { - return this.clone().aroundO(cx, cy, matrix); - } // Convert to native SVGMatrix + if (!finished) { + runnersLeft = true; // continue + } else if (runnerInfo.persist !== true) { + // runner is finished. And runner might get removed + // TODO: Figure out end time of runner + var endTime = runner.duration() - runner.time() + this._time; - }, { - key: "native", - value: function native() { - // create new matrix - var matrix = parser().svg.node.createSVGMatrix(); // update with current values + if (endTime + this._persist < this._time) { + // Delete runner and correct index + delete this._runners[this._order[i]]; + this._order.splice(i--, 1) && --len; + runner.timeline(null); + } + } + } // Get the next animation frame to keep the simulation going - for (var i = abcdef.length - 1; i >= 0; i--) { - matrix[abcdef[i]] = this[abcdef[i]]; + + if (runnersLeft) { + this._nextFrame = Animator.frame(this._step.bind(this)); + } else { + this._nextFrame = null; } - return matrix; - } // Check if two matrices are equal + return this; + } // Checks if we are running and continues the animation }, { - key: "equals", - value: function equals(other) { - var comp = new Matrix(other); - return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f); - } // Convert matrix to string + key: "_continue", + value: function _continue() { + if (this._paused) return this; - }, { - key: "toString", - value: function toString() { - return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'; + if (!this._nextFrame) { + this._nextFrame = Animator.frame(this._step.bind(this)); + } + + return this; } }, { - key: "toArray", - value: function toArray() { - return [this.a, this.b, this.c, this.d, this.e, this.f]; + key: "active", + value: function active() { + return !!this._nextFrame; } - }, { - key: "valueOf", - value: function valueOf() { - return { - a: this.a, - b: this.b, - c: this.c, - d: this.d, - e: this.e, - f: this.f - }; - } // TODO: Refactor this to a static function of matrix.js + }]); - }], [{ - key: "formatTransforms", - value: function formatTransforms(o) { - // Get all of the parameters required to form the matrix - var flipBoth = o.flip === 'both' || o.flip === true; - var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1; - var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1; - var skewX = o.skew && o.skew.length ? o.skew[0] : isFinite(o.skew) ? o.skew : isFinite(o.skewX) ? o.skewX : 0; - var skewY = o.skew && o.skew.length ? o.skew[1] : isFinite(o.skew) ? o.skew : isFinite(o.skewY) ? o.skewY : 0; - var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX : isFinite(o.scale) ? o.scale * flipX : isFinite(o.scaleX) ? o.scaleX * flipX : flipX; - var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY; - var shear = o.shear || 0; - var theta = o.rotate || o.theta || 0; - var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY); - var ox = origin.x; - var oy = origin.y; - var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY); - var px = position.x; - var py = position.y; - var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY); - var tx = translate.x; - var ty = translate.y; - var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY); - var rx = relative.x; - var ry = relative.y; // Populate all of the values + return Timeline; + }(); + registerMethods({ + Element: { + timeline: function timeline() { + this._timeline = this._timeline || new Timeline(); + return this._timeline; + } + } + }); - return { - scaleX: scaleX, - scaleY: scaleY, - skewX: skewX, - skewY: skewY, - shear: shear, - theta: theta, - rx: rx, - ry: ry, - tx: tx, - ty: ty, - ox: ox, - oy: oy, - px: px, - py: py - }; - } // left matrix, right matrix, target matrix which is overwritten + var Runner = + /*#__PURE__*/ + function (_EventTarget) { + _inherits(Runner, _EventTarget); - }, { - key: "matrixMultiply", - value: function matrixMultiply(l, r, o) { - // Work out the product directly - var a = l.a * r.a + l.c * r.b; - var b = l.b * r.a + l.d * r.b; - var c = l.a * r.c + l.c * r.d; - var d = l.b * r.c + l.d * r.d; - var e = l.e + l.a * r.e + l.c * r.f; - var f = l.f + l.b * r.e + l.d * r.f; // make sure to use local variables because l/r and o could be the same + function Runner(options) { + var _this; - o.a = a; - o.b = b; - o.c = c; - o.d = d; - o.e = e; - o.f = f; - return o; - } - }]); + _classCallCheck(this, Runner); - return Matrix; - }(); - registerMethods({ - Element: { - // Get current matrix - ctm: function ctm() { - return new Matrix(this.node.getCTM()); - }, - // Get current screen matrix - screenCTM: function screenCTM() { - /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 - This is needed because FF does not return the transformation matrix - for the inner coordinate system when getScreenCTM() is called on nested svgs. - However all other Browsers do that */ - if (typeof this.isRoot === 'function' && !this.isRoot()) { - var rect = this.rect(1, 1); - var m = rect.node.getScreenCTM(); - rect.remove(); - return new Matrix(m); - } + _this = _possibleConstructorReturn(this, _getPrototypeOf(Runner).call(this)); // Store a unique id on the runner, so that we can identify it later - return new Matrix(this.node.getScreenCTM()); - } - } - }); + _this.id = Runner.id++; // Ensure a default value - var PathArray = subClassArray('PathArray', SVGArray); - var pathHandlers = { - M: function M(c, p, p0) { - p.x = p0.x = c[0]; - p.y = p0.y = c[1]; - return ['M', p.x, p.y]; - }, - L: function L(c, p) { - p.x = c[0]; - p.y = c[1]; - return ['L', c[0], c[1]]; - }, - H: function H(c, p) { - p.x = c[0]; - return ['H', c[0]]; - }, - V: function V(c, p) { - p.y = c[0]; - return ['V', c[0]]; - }, - C: function C(c, p) { - p.x = c[4]; - p.y = c[5]; - return ['C', c[0], c[1], c[2], c[3], c[4], c[5]]; - }, - S: function S(c, p) { - p.x = c[2]; - p.y = c[3]; - return ['S', c[0], c[1], c[2], c[3]]; - }, - Q: function Q(c, p) { - p.x = c[2]; - p.y = c[3]; - return ['Q', c[0], c[1], c[2], c[3]]; - }, - T: function T(c, p) { - p.x = c[0]; - p.y = c[1]; - return ['T', c[0], c[1]]; - }, - Z: function Z(c, p, p0) { - p.x = p0.x; - p.y = p0.y; - return ['Z']; - }, - A: function A(c, p) { - p.x = c[5]; - p.y = c[6]; - return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]]; - } - }; - var mlhvqtcsaz = 'mlhvqtcsaz'.split(''); + options = options == null ? timeline.duration : options; // Ensure that we get a controller - for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { - pathHandlers[mlhvqtcsaz[i]] = function (i) { - return function (c, p, p0) { - if (i === 'H') c[0] = c[0] + p.x;else if (i === 'V') c[0] = c[0] + p.y;else if (i === 'A') { - c[5] = c[5] + p.x; - c[6] = c[6] + p.y; - } else { - for (var j = 0, jl = c.length; j < jl; ++j) { - c[j] = c[j] + (j % 2 ? p.y : p.x); - } - } - return pathHandlers[i](c, p, p0); - }; - }(mlhvqtcsaz[i].toUpperCase()); - } + options = typeof options === 'function' ? new Controller(options) : options; // Declare all of the variables - extend(PathArray, { - // Convert array to string - toString: function toString() { - return arrayToString(this); - }, - // Move path string - move: function move(x, y) { - // get bounding box of current situation - var box = this.bbox(); // get relative offset + _this._element = null; + _this._timeline = null; + _this.done = false; + _this._queue = []; // Work out the stepper and the duration - x -= box.x; - y -= box.y; + _this._duration = typeof options === 'number' && options; + _this._isDeclarative = options instanceof Controller; + _this._stepper = _this._isDeclarative ? options : new Ease(); // We copy the current values from the timeline because they can change - if (!isNaN(x) && !isNaN(y)) { - // move every point - for (var l, i = this.length - 1; i >= 0; i--) { - l = this[i][0]; + _this._history = {}; // Store the state of the runner - if (l === 'M' || l === 'L' || l === 'T') { - this[i][1] += x; - this[i][2] += y; - } else if (l === 'H') { - this[i][1] += x; - } else if (l === 'V') { - this[i][1] += y; - } else if (l === 'C' || l === 'S' || l === 'Q') { - this[i][1] += x; - this[i][2] += y; - this[i][3] += x; - this[i][4] += y; + _this.enabled = true; + _this._time = 0; + _this._last = 0; // Save transforms applied to this runner - if (l === 'C') { - this[i][5] += x; - this[i][6] += y; - } - } else if (l === 'A') { - this[i][6] += x; - this[i][7] += y; - } - } - } + _this.transforms = new Matrix(); + _this.transformId = 1; // Looping variables - return this; - }, - // Resize path string - size: function size(width, height) { - // get bounding box of current situation - var box = this.bbox(); - var i, l; // recalculate position of all points according to new size + _this._haveReversed = false; + _this._reverse = false; + _this._loopsDone = 0; + _this._swing = false; + _this._wait = 0; + _this._times = 1; + return _this; + } + /* + Runner Definitions + ================== + These methods help us define the runtime behaviour of the Runner or they + help us make new runners from the current runner + */ - for (i = this.length - 1; i >= 0; i--) { - l = this[i][0]; - if (l === 'M' || l === 'L' || l === 'T') { - this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; - this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; - } else if (l === 'H') { - this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; - } else if (l === 'V') { - this[i][1] = (this[i][1] - box.y) * height / box.height + box.y; - } else if (l === 'C' || l === 'S' || l === 'Q') { - this[i][1] = (this[i][1] - box.x) * width / box.width + box.x; - this[i][2] = (this[i][2] - box.y) * height / box.height + box.y; - this[i][3] = (this[i][3] - box.x) * width / box.width + box.x; - this[i][4] = (this[i][4] - box.y) * height / box.height + box.y; + _createClass(Runner, [{ + key: "element", + value: function element(_element) { + if (_element == null) return this._element; + this._element = _element; - if (l === 'C') { - this[i][5] = (this[i][5] - box.x) * width / box.width + box.x; - this[i][6] = (this[i][6] - box.y) * height / box.height + box.y; - } - } else if (l === 'A') { - // resize radii - this[i][1] = this[i][1] * width / box.width; - this[i][2] = this[i][2] * height / box.height; // move position values + _element._prepareRunner(); - this[i][6] = (this[i][6] - box.x) * width / box.width + box.x; - this[i][7] = (this[i][7] - box.y) * height / box.height + box.y; - } + return this; } - - return this; - }, - // Test if the passed path array use the same path data commands as this path array - equalCommands: function equalCommands(pathArray) { - var i, il, equalCommands; - pathArray = new PathArray(pathArray); - equalCommands = this.length === pathArray.length; - - for (i = 0, il = this.length; equalCommands && i < il; i++) { - equalCommands = this[i][0] === pathArray[i][0]; + }, { + key: "timeline", + value: function timeline$$1(_timeline) { + // check explicitly for undefined so we can set the timeline to null + if (typeof _timeline === 'undefined') return this._timeline; + this._timeline = _timeline; + return this; } - - return equalCommands; - }, - // Make path array morphable - morph: function morph(pathArray) { - pathArray = new PathArray(pathArray); - - if (this.equalCommands(pathArray)) { - this.destination = pathArray; - } else { - this.destination = null; + }, { + key: "animate", + value: function animate(duration, delay, when) { + var o = Runner.sanitise(duration, delay, when); + var runner = new Runner(o.duration); + if (this._timeline) runner.timeline(this._timeline); + if (this._element) runner.element(this._element); + return runner.loop(o).schedule(delay, when); } + }, { + key: "schedule", + value: function schedule(timeline$$1, delay, when) { + // The user doesn't need to pass a timeline if we already have one + if (!(timeline$$1 instanceof Timeline)) { + when = delay; + delay = timeline$$1; + timeline$$1 = this.timeline(); + } // If there is no timeline, yell at the user... - return this; - }, - // Get morphed path array at given position - at: function at(pos) { - // make sure a destination is defined - if (!this.destination) return this; - var sourceArray = this; - var destinationArray = this.destination.value; - var array = []; - var pathArray = new PathArray(); - var i, il, j, jl; // Animate has specified in the SVG spec - // See: https://www.w3.org/TR/SVG11/paths.html#PathElement - - for (i = 0, il = sourceArray.length; i < il; i++) { - array[i] = [sourceArray[i][0]]; - - for (j = 1, jl = sourceArray[i].length; j < jl; j++) { - array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos; - } // For the two flags of the elliptical arc command, the SVG spec say: - // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true - // Elliptical arc command as an array followed by corresponding indexes: - // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] - // 0 1 2 3 4 5 6 7 - - - if (array[i][0] === 'A') { - array[i][4] = +(array[i][4] !== 0); - array[i][5] = +(array[i][5] !== 0); - } - } // Directly modify the value of a path array, this is done this way for performance - - - pathArray.value = array; - return pathArray; - }, - // Absolutize and parse path to array - parse: function parse() { - var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [['M', 0, 0]]; - // if it's already a patharray, no need to parse it - if (array instanceof PathArray) return array; // prepare for parsing - - var s; - var paramCnt = { - 'M': 2, - 'L': 2, - 'H': 1, - 'V': 1, - 'C': 6, - 'S': 4, - 'Q': 4, - 'T': 2, - 'A': 7, - 'Z': 0 - }; - - if (typeof array === 'string') { - array = array.replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 - .replace(pathLetters, ' $& ') // put some room between letters and numbers - .replace(hyphen, '$1 -') // add space before hyphen - .trim() // trim - .split(delimiter); // split into array - } else { - array = array.reduce(function (prev, curr) { - return [].concat.call(prev, curr); - }, []); - } // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] - - - var result = []; - var p = new Point(); - var p0 = new Point(); - var index = 0; - var len = array.length; - - do { - // Test if we have a path letter - if (isPathLetter.test(array[index])) { - s = array[index]; - ++index; // If last letter was a move command and we got no new, it defaults to [L]ine - } else if (s === 'M') { - s = 'L'; - } else if (s === 'm') { - s = 'l'; - } - - result.push(pathHandlers[s].call(null, array.slice(index, index = index + paramCnt[s.toUpperCase()]).map(parseFloat), p, p0)); - } while (len > index); - - return result; - }, - // Get bounding box of path - bbox: function bbox() { - parser().path.setAttribute('d', this.toString()); - return parser.nodes.path.getBBox(); - } - }); - - var Morphable = - /*#__PURE__*/ - function () { - function Morphable(stepper) { - _classCallCheck(this, Morphable); - // FIXME: the default stepper does not know about easing - this._stepper = stepper || new Ease('-'); - this._from = null; - this._to = null; - this._type = null; - this._context = null; - this._morphObj = null; - } + if (!timeline$$1) { + throw Error('Runner cannot be scheduled without timeline'); + } // Schedule the runner on the timeline provided - _createClass(Morphable, [{ - key: "from", - value: function from(val) { - if (val == null) { - return this._from; - } - this._from = this._set(val); + timeline$$1.schedule(this, delay, when); return this; } }, { - key: "to", - value: function to(val) { - if (val == null) { - return this._to; - } - - this._to = this._set(val); + key: "unschedule", + value: function unschedule() { + var timeline$$1 = this.timeline(); + timeline$$1 && timeline$$1.unschedule(this); return this; } }, { - key: "type", - value: function type(_type) { - // getter - if (_type == null) { - return this._type; - } // setter + key: "loop", + value: function loop(times, swing, wait) { + // Deal with the user passing in an object + if (_typeof(times) === 'object') { + swing = times.swing; + wait = times.wait; + times = times.times; + } // Sanitise the values and store them - this._type = _type; + this._times = times || Infinity; + this._swing = swing || false; + this._wait = wait || 0; return this; } }, { - key: "_set", - value: function _set$$1(value) { - if (!this._type) { - var type = _typeof(value); - - if (type === 'number') { - this.type(SVGNumber); - } else if (type === 'string') { - if (Color.isColor(value)) { - this.type(Color); - } else if (delimiter.test(value)) { - this.type(pathLetters.test(value) ? PathArray : SVGArray); - } else if (numberAndUnit.test(value)) { - this.type(SVGNumber); - } else { - this.type(NonMorphable); - } - } else if (morphableTypes.indexOf(value.constructor) > -1) { - this.type(value.constructor); - } else if (Array.isArray(value)) { - this.type(SVGArray); - } else if (type === 'object') { - this.type(ObjectBag); - } else { - this.type(NonMorphable); - } - } - - var result = new this._type(value).toArray(); - this._morphObj = this._morphObj || new this._type(); - this._context = this._context || Array.apply(null, Array(result.length)).map(Object); - return result; + key: "delay", + value: function delay(_delay) { + return this.animate(0, _delay); } + /* + Basic Functionality + =================== + These methods allow us to attach basic functions to the runner directly + */ + }, { - key: "stepper", - value: function stepper(_stepper) { - if (_stepper == null) return this._stepper; - this._stepper = _stepper; + key: "queue", + value: function queue(initFn, runFn, isTransform) { + this._queue.push({ + initialiser: initFn || noop, + runner: runFn || noop, + isTransform: isTransform, + initialised: false, + finished: false + }); + + var timeline$$1 = this.timeline(); + timeline$$1 && this.timeline()._continue(); return this; } }, { - key: "done", - value: function done() { - var complete = this._context.map(this._stepper.done).reduce(function (last, curr) { - return last && curr; - }, true); - - return complete; + key: "during", + value: function during(fn) { + return this.queue(null, fn); } }, { - key: "at", - value: function at(pos) { - var _this = this; - - return this._morphObj.fromArray(this._from.map(function (i, index) { - return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context); - })); + key: "after", + value: function after(fn) { + return this.on('finish', fn); } - }]); + /* + Runner animation methods + ======================== + Control how the animation plays + */ - return Morphable; - }(); - var NonMorphable = - /*#__PURE__*/ - function () { - function NonMorphable() { - _classCallCheck(this, NonMorphable); - - this.init.apply(this, arguments); - } + }, { + key: "time", + value: function time(_time) { + if (_time == null) { + return this._time; + } - _createClass(NonMorphable, [{ - key: "init", - value: function init(val) { - val = Array.isArray(val) ? val[0] : val; - this.value = val; + var dt = _time - this._time; + this.step(dt); + return this; } }, { - key: "valueOf", - value: function valueOf() { - return this.value; + key: "duration", + value: function duration() { + return this._times * (this._wait + this._duration) - this._wait; } }, { - key: "toArray", - value: function toArray() { - return [this.value]; - } - }]); - - return NonMorphable; - }(); - var TransformBag = - /*#__PURE__*/ - function () { - function TransformBag() { - _classCallCheck(this, TransformBag); - - this.init.apply(this, arguments); - } + key: "loops", + value: function loops(p) { + var loopDuration = this._duration + this._wait; - _createClass(TransformBag, [{ - key: "init", - value: function init(obj) { - if (Array.isArray(obj)) { - obj = { - scaleX: obj[0], - scaleY: obj[1], - shear: obj[2], - rotate: obj[3], - translateX: obj[4], - translateY: obj[5], - originX: obj[6], - originY: obj[7] - }; + if (p == null) { + var loopsDone = Math.floor(this._time / loopDuration); + var relativeTime = this._time - loopsDone * loopDuration; + var position = relativeTime / this._duration; + return Math.min(loopsDone + position, this._times); } - Object.assign(this, TransformBag.defaults, obj); + var whole = Math.floor(p); + var partial = p % 1; + var time = loopDuration * whole + this._duration * partial; + return this.time(time); } }, { - key: "toArray", - value: function toArray() { - var v = this; - return [v.scaleX, v.scaleY, v.shear, v.rotate, v.translateX, v.translateY, v.originX, v.originY]; - } - }]); + key: "position", + value: function position(p) { + // Get all of the variables we need + var x = this._time; + var d = this._duration; + var w = this._wait; + var t = this._times; + var s = this._swing; + var r = this._reverse; + var position; - return TransformBag; - }(); - TransformBag.defaults = { - scaleX: 1, - scaleY: 1, - shear: 0, - rotate: 0, - translateX: 0, - translateY: 0, - originX: 0, - originY: 0 - }; - var ObjectBag = - /*#__PURE__*/ - function () { - function ObjectBag() { - _classCallCheck(this, ObjectBag); + if (p == null) { + /* + This function converts a time to a position in the range [0, 1] + The full explanation can be found in this desmos demonstration + https://www.desmos.com/calculator/u4fbavgche + The logic is slightly simplified here because we can use booleans + */ + // Figure out the value without thinking about the start or end time + var f = function f(x) { + var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)); + var backwards = swinging && !r || !swinging && r; + var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards; + var clipped = Math.max(Math.min(uncliped, 1), 0); + return clipped; + }; // Figure out the value by incorporating the start time - this.init.apply(this, arguments); - } - _createClass(ObjectBag, [{ - key: "init", - value: function init(objOrArr) { - this.values = []; + var endTime = t * (w + d) - w; + position = x <= 0 ? Math.round(f(1e-5)) : x < endTime ? f(x) : Math.round(f(endTime - 1e-5)); + return position; + } // Work out the loops done and add the position to the loops done - if (Array.isArray(objOrArr)) { - this.values = objOrArr; - return; - } - var entries = Object.entries(objOrArr || {}).sort(function (a, b) { - return a[0] - b[0]; - }); - this.values = entries.reduce(function (last, curr) { - return last.concat(curr); - }, []); + var loopsDone = Math.floor(this.loops()); + var swingForward = s && loopsDone % 2 === 0; + var forwards = swingForward && !r || r && swingForward; + position = loopsDone + (forwards ? p : 1 - p); + return this.loops(position); } }, { - key: "valueOf", - value: function valueOf() { - var obj = {}; - var arr = this.values; - - for (var i = 0, len = arr.length; i < len; i += 2) { - obj[arr[i]] = arr[i + 1]; + key: "progress", + value: function progress(p) { + if (p == null) { + return Math.min(1, this._time / this.duration()); } - return obj; + return this.time(p * this.duration()); } }, { - key: "toArray", - value: function toArray() { - return this.values; - } - }]); + key: "step", + value: function step(dt) { + // If we are inactive, this stepper just gets skipped + if (!this.enabled) return this; // Update the time and get the new position - return ObjectBag; - }(); - var morphableTypes = [NonMorphable, TransformBag, ObjectBag]; - function registerMorphableType() { - var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - morphableTypes.push.apply(morphableTypes, _toConsumableArray([].concat(type))); - } - function makeMorphable() { - extend(morphableTypes, { - to: function to(val, args) { - return new Morphable().type(this.constructor).from(this.valueOf()).to(val, args); - }, - fromArray: function fromArray(arr) { - this.init(arr); - return this; - } - }); - } + dt = dt == null ? 16 : dt; + this._time += dt; + var position = this.position(); // Figure out if we need to run the stepper in this frame - var Path = - /*#__PURE__*/ - function (_Shape) { - _inherits(Path, _Shape); + var running = this._lastPosition !== position && this._time >= 0; + this._lastPosition = position; // Figure out if we just started - // Initialize node - function Path(node) { - _classCallCheck(this, Path); + var duration = this.duration(); + var justStarted = this._lastTime < 0 && this._time > 0; + var justFinished = this._lastTime < this._time && this.time > duration; + this._lastTime = this._time; - return _possibleConstructorReturn(this, _getPrototypeOf(Path).call(this, nodeOrNew('path', node), Path)); - } // Get array + if (justStarted) { + this.fire('start', this); + } // Work out if the runner is finished set the done flag here so animations + // know, that they are running in the last step (this is good for + // transformations which can be merged) - _createClass(Path, [{ - key: "array", - value: function array() { - return this._array || (this._array = new PathArray(this.attr('d'))); - } // Plot new path + var declarative = this._isDeclarative; + this.done = !declarative && !justFinished && this._time >= duration; // Call initialise and the run function - }, { - key: "plot", - value: function plot(d) { - return d == null ? this.array() : this.clear().attr('d', typeof d === 'string' ? d : this._array = new PathArray(d)); - } // Clear array cache + if (running || declarative) { + this._initialise(running); // clear the transforms on this runner so they dont get added again and again - }, { - key: "clear", - value: function clear() { - delete this._array; - return this; - } // Move by left top corner - }, { - key: "move", - value: function move(x, y) { - return this.attr('d', this.array().move(x, y)); - } // Move by left top corner over x-axis + this.transforms = new Matrix(); - }, { - key: "x", - value: function x(_x) { - return _x == null ? this.bbox().x : this.move(_x, this.bbox().y); - } // Move by left top corner over y-axis + var converged = this._run(declarative ? dt : position); - }, { - key: "y", - value: function y(_y) { - return _y == null ? this.bbox().y : this.move(this.bbox().x, _y); - } // Set element size to given width and height + this.fire('step', this); + } // correct the done flag here + // declaritive animations itself know when they converged - }, { - key: "size", - value: function size(width, height) { - var p = proportionalSize(this, width, height); - return this.attr('d', this.array().size(p.width, p.height)); - } // Set width of element - }, { - key: "width", - value: function width(_width) { - return _width == null ? this.bbox().width : this.size(_width, this.bbox().height); - } // Set height of element + this.done = this.done || converged && declarative; + + if (this.done) { + this.fire('finish', this); + } + return this; + } }, { - key: "height", - value: function height(_height) { - return _height == null ? this.bbox().height : this.size(this.bbox().width, _height); + key: "finish", + value: function finish() { + return this.step(Infinity); } }, { - key: "targets", - value: function targets() { - return baseFind('svg textpath [href*="' + this.id() + '"]'); + key: "reverse", + value: function reverse(_reverse) { + this._reverse = _reverse == null ? !this._reverse : _reverse; + return this; } - }]); - - return Path; - }(Shape); // Define morphable array - Path.prototype.MorphArray = PathArray; // Add parent method - - registerMethods({ - Container: { - // Create a wrapped path element - path: function path(d) { - // make sure plot is called as a setter - return this.put(new Path()).plot(d || new PathArray()); + }, { + key: "ease", + value: function ease(fn) { + this._stepper = new Ease(fn); + return this; } - } - }); - register(Path); - - // Add polygon-specific functions - - function array() { - return this._array || (this._array = new PointArray(this.attr('points'))); - } // Plot new path - - function plot(p) { - return p == null ? this.array() : this.clear().attr('points', typeof p === 'string' ? p : this._array = new PointArray(p)); - } // Clear array cache + }, { + key: "active", + value: function active(enabled) { + if (enabled == null) return this.enabled; + this.enabled = enabled; + return this; + } + /* + Private Methods + =============== + Methods that shouldn't be used externally + */ + // Save a morpher to the morpher list so that we can retarget it later - function clear() { - delete this._array; - return this; - } // Move by left top corner + }, { + key: "_rememberMorpher", + value: function _rememberMorpher(method, morpher) { + this._history[method] = { + morpher: morpher, + caller: this._queue[this._queue.length - 1] + }; + } // Try to set the target for a morpher if the morpher exists, otherwise + // do nothing and return false - function move(x, y) { - return this.attr('points', this.array().move(x, y)); - } // Set element size to given width and height + }, { + key: "_tryRetarget", + value: function _tryRetarget(method, target) { + if (this._history[method]) { + // if the last method wasnt even initialised, throw it away + if (!this._history[method].caller.initialised) { + var index = this._queue.indexOf(this._history[method].caller); - function size$1(width, height) { - var p = proportionalSize(this, width, height); - return this.attr('points', this.array().size(p.width, p.height)); - } + this._queue.splice(index, 1); - var poly = /*#__PURE__*/Object.freeze({ - array: array, - plot: plot, - clear: clear, - move: move, - size: size$1 - }); + return false; + } // for the case of transformations, we use the special retarget function + // which has access to the outer scope - var Polygon = - /*#__PURE__*/ - function (_Shape) { - _inherits(Polygon, _Shape); - // Initialize node - function Polygon(node) { - _classCallCheck(this, Polygon); + if (this._history[method].caller.isTransform) { + this._history[method].caller.isTransform(target); // for everything else a simple morpher change is sufficient - return _possibleConstructorReturn(this, _getPrototypeOf(Polygon).call(this, nodeOrNew('polygon', node), Polygon)); - } + } else { + this._history[method].morpher.to(target); + } - return Polygon; - }(Shape); - registerMethods({ - Container: { - // Create a wrapped polygon element - polygon: function polygon(p) { - // make sure plot is called as a setter - return this.put(new Polygon()).plot(p || new PointArray()); - } - } - }); - extend(Polygon, pointed); - extend(Polygon, poly); - register(Polygon); + this._history[method].caller.finished = false; + var timeline$$1 = this.timeline(); + timeline$$1 && timeline$$1._continue(); + return true; + } - var Polyline = - /*#__PURE__*/ - function (_Shape) { - _inherits(Polyline, _Shape); + return false; + } // Run each initialise function in the runner if required - // Initialize node - function Polyline(node) { - _classCallCheck(this, Polyline); + }, { + key: "_initialise", + value: function _initialise(running) { + // If we aren't running, we shouldn't initialise when not declarative + if (!running && !this._isDeclarative) return; // Loop through all of the initialisers - return _possibleConstructorReturn(this, _getPrototypeOf(Polyline).call(this, nodeOrNew('polyline', node), Polyline)); - } + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current initialiser + var current = this._queue[i]; // Determine whether we need to initialise - return Polyline; - }(Shape); - registerMethods({ - Container: { - // Create a wrapped polygon element - polyline: function polyline(p) { - // make sure plot is called as a setter - return this.put(new Polyline()).plot(p || new PointArray()); - } - } - }); - extend(Polyline, pointed); - extend(Polyline, poly); - register(Polyline); + var needsIt = this._isDeclarative || !current.initialised && running; + running = !current.finished; // Call the initialiser if we need to - var Rect = - /*#__PURE__*/ - function (_Shape) { - _inherits(Rect, _Shape); + if (needsIt && running) { + current.initialiser.call(this); + current.initialised = true; + } + } + } // Run each run function for the position or dt given - // Initialize node - function Rect(node) { - _classCallCheck(this, Rect); + }, { + key: "_run", + value: function _run(positionOrDt) { + // Run all of the _queue directly + var allfinished = true; - return _possibleConstructorReturn(this, _getPrototypeOf(Rect).call(this, nodeOrNew('rect', node), Rect)); - } // FIXME: unify with circle - // Radius x value + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current function to run + var current = this._queue[i]; // Run the function if its not finished, we keep track of the finished + // flag for the sake of declarative _queue + var converged = current.runner.call(this, positionOrDt); + current.finished = current.finished || converged === true; + allfinished = allfinished && current.finished; + } // We report when all of the constructors are finished - _createClass(Rect, [{ - key: "rx", - value: function rx(_rx) { - return this.attr('rx', _rx); - } // Radius y value + return allfinished; + } }, { - key: "ry", - value: function ry(_ry) { - return this.attr('ry', _ry); + key: "addTransform", + value: function addTransform(transform, index) { + this.transforms.lmultiplyO(transform); + return this; } - }]); - - return Rect; - }(Shape); - registerMethods({ - Container: { - // Create a rect element - rect: function rect(width, height) { - return this.put(new Rect()).size(width, height); + }, { + key: "clearTransform", + value: function clearTransform() { + this.transforms = new Matrix(); + return this; } - } - }); - register(Rect); + }], [{ + key: "sanitise", + value: function sanitise(duration, delay, when) { + // Initialise the default parameters + var times = 1; + var swing = false; + var wait = 0; + duration = duration || timeline.duration; + delay = delay || timeline.delay; + when = when || 'last'; // If we have an object, unpack the values - var time = window.performance || Date; + if (_typeof(duration) === 'object' && !(duration instanceof Stepper)) { + delay = duration.delay || delay; + when = duration.when || when; + swing = duration.swing || swing; + times = duration.times || times; + wait = duration.wait || wait; + duration = duration.duration || timeline.duration; + } - var makeSchedule = function makeSchedule(runnerInfo) { - var start = runnerInfo.start; - var duration = runnerInfo.runner.duration(); - var end = start + duration; - return { - start: start, - duration: duration, - end: end, - runner: runnerInfo.runner - }; - }; - - var Timeline = - /*#__PURE__*/ - function () { - // Construct a new timeline on the given element - function Timeline() { - _classCallCheck(this, Timeline); - - this._timeSource = function () { - return time.now(); - }; - - this._dispatcher = document.createElement('div'); // Store the timing variables - - this._startTime = 0; - this._speed = 1.0; // Play control variables control how the animation proceeds - - this._reverse = false; - this._persist = 0; // Keep track of the running animations and their starting parameters - - this._nextFrame = null; - this._paused = false; - this._runners = []; - this._order = []; - this._time = 0; - this._lastSourceTime = 0; - this._lastStepTime = 0; - } - - _createClass(Timeline, [{ - key: "getEventTarget", - value: function getEventTarget() { - return this._dispatcher; + return { + duration: duration, + delay: delay, + swing: swing, + times: times, + wait: wait, + when: when + }; } - /** - * - */ - // schedules a runner on the timeline - - }, { - key: "schedule", - value: function schedule(runner, delay, when) { - if (runner == null) { - return this._runners.map(makeSchedule).sort(function (a, b) { - return a.start - b.start || a.duration - b.duration; - }); - } - - if (!this.active()) { - this._step(); - - if (when == null) { - when = 'now'; - } - } // The start time for the next animation can either be given explicitly, - // derived from the current timeline time or it can be relative to the - // last start time to chain animations direclty - - - var absoluteStartTime = 0; - delay = delay || 0; // Work out when to start the animation - - if (when == null || when === 'last' || when === 'after') { - // Take the last time and increment - absoluteStartTime = this._startTime; - } else if (when === 'absolute' || when === 'start') { - absoluteStartTime = delay; - delay = 0; - } else if (when === 'now') { - absoluteStartTime = this._time; - } else if (when === 'relative') { - var runnerInfo = this._runners[runner.id]; + }]); - if (runnerInfo) { - absoluteStartTime = runnerInfo.start + delay; - delay = 0; - } - } else { - throw new Error('Invalid value for the "when" parameter'); - } // Manage runner + return Runner; + }(EventTarget); + Runner.id = 0; + var FakeRunner = function FakeRunner() { + var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix(); + var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; + var done = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; - runner.unschedule(); - runner.timeline(this); - runner.time(-delay); // Save startTime for next runner + _classCallCheck(this, FakeRunner); - this._startTime = absoluteStartTime + runner.duration() + delay; // Save runnerInfo + this.transforms = transforms; + this.id = id; + this.done = done; + }; - this._runners[runner.id] = { - persist: this.persist(), - runner: runner, - start: absoluteStartTime // Save order and continue + extend([Runner, FakeRunner], { + mergeWith: function mergeWith(runner) { + return new FakeRunner(runner.transforms.lmultiply(this.transforms), runner.id); + } + }); // FakeRunner.emptyRunner = new FakeRunner() - }; + var lmultiply = function lmultiply(last, curr) { + return last.lmultiplyO(curr); + }; - this._order.push(runner.id); + var getRunnerTransform = function getRunnerTransform(runner) { + return runner.transforms; + }; - this._continue(); + function mergeTransforms() { + // Find the matrix to apply to the element and apply it + var runners = this._transformationRunners.runners; + var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix()); + this.transform(netTransform); - return this; - } // Remove the runner from this timeline + this._transformationRunners.merge(); - }, { - key: "unschedule", - value: function unschedule(runner) { - var index = this._order.indexOf(runner.id); + if (this._transformationRunners.length() === 1) { + this._frameId = null; + } + } - if (index < 0) return this; - delete this._runners[runner.id]; + var RunnerArray = + /*#__PURE__*/ + function () { + function RunnerArray() { + _classCallCheck(this, RunnerArray); - this._order.splice(index, 1); + this.runners = []; + this.ids = []; + } - runner.timeline(null); + _createClass(RunnerArray, [{ + key: "add", + value: function add(runner) { + if (this.runners.includes(runner)) return; + var id = runner.id + 1; + var leftSibling = this.ids.reduce(function (last, curr) { + if (curr > last && curr < id) return curr; + return last; + }, 0); + var index = this.ids.indexOf(leftSibling) + 1; + this.ids.splice(index, 0, id); + this.runners.splice(index, 0, runner); return this; } }, { - key: "play", - value: function play() { - // Now make sure we are not paused and continue the animation - this._paused = false; - return this._continue(); + key: "getByID", + value: function getByID(id) { + return this.runners[this.ids.indexOf(id + 1)]; } }, { - key: "pause", - value: function pause() { - // Cancel the next animation frame and pause - this._nextFrame = null; - this._paused = true; + key: "remove", + value: function remove(id) { + var index = this.ids.indexOf(id + 1); + this.ids.splice(index, 1); + this.runners.splice(index, 1); return this; } }, { - key: "stop", - value: function stop() { - // Cancel the next animation frame and go to start - this.seek(-this._time); - return this.pause(); - } - }, { - key: "finish", - value: function finish() { - this.seek(Infinity); - return this.pause(); - } - }, { - key: "speed", - value: function speed(_speed) { - if (_speed == null) return this._speed; - this._speed = _speed; + key: "merge", + value: function merge() { + var _this2 = this; + + var lastRunner = null; + this.runners.forEach(function (runner, i) { + if (lastRunner && runner.done && lastRunner.done) { + _this2.remove(runner.id); + + _this2.edit(lastRunner.id, runner.mergeWith(lastRunner)); + } + + lastRunner = runner; + }); return this; } }, { - key: "reverse", - value: function reverse(yes) { - var currentSpeed = this.speed(); - if (yes == null) return this.speed(-currentSpeed); - var positive = Math.abs(currentSpeed); - return this.speed(yes ? positive : -positive); - } - }, { - key: "seek", - value: function seek(dt) { - this._time += dt; - return this._continue(); - } - }, { - key: "time", - value: function time(_time) { - if (_time == null) return this._time; - this._time = _time; + key: "edit", + value: function edit(id, newRunner) { + var index = this.ids.indexOf(id + 1); + this.ids.splice(index, 1, id); + this.runners.splice(index, 1, newRunner); return this; } }, { - key: "persist", - value: function persist(dtOrForever) { - if (dtOrForever == null) return this._persist; - this._persist = dtOrForever; - return this; + key: "length", + value: function length() { + return this.ids.length; } }, { - key: "source", - value: function source(fn) { - if (fn == null) return this._timeSource; - this._timeSource = fn; + key: "clearBefore", + value: function clearBefore(id) { + var deleteCnt = this.ids.indexOf(id + 1) || 1; + this.ids.splice(0, deleteCnt, 0); + this.runners.splice(0, deleteCnt, new FakeRunner()); return this; } - }, { - key: "_step", - value: function _step() { - // If the timeline is paused, just do nothing - if (this._paused) return; // Get the time delta from the last time and update the time - // TODO: Deal with window.blur window.focus to pause animations - - var time = this._timeSource(); - - var dtSource = time - this._lastSourceTime; - var dtTime = this._speed * dtSource + (this._time - this._lastStepTime); - this._lastSourceTime = time; // Update the time - - this._time += dtTime; - this._lastStepTime = this._time; // this.fire('time', this._time) - // Run all of the runners directly - - var runnersLeft = false; + }]); - for (var i = 0, len = this._order.length; i < len; i++) { - // Get and run the current runner and ignore it if its inactive - var runnerInfo = this._runners[this._order[i]]; - var runner = runnerInfo.runner; - var dt = dtTime; // Make sure that we give the actual difference - // between runner start time and now + return RunnerArray; + }(); - var dtToStart = this._time - runnerInfo.start; // Dont run runner if not started yet + var frameId = 0; + registerMethods({ + Element: { + animate: function animate(duration, delay, when) { + var o = Runner.sanitise(duration, delay, when); + var timeline$$1 = this.timeline(); + return new Runner(o.duration).loop(o).element(this).timeline(timeline$$1).schedule(delay, when); + }, + delay: function delay(by, when) { + return this.animate(0, by, when); + }, + // this function searches for all runners on the element and deletes the ones + // which run before the current one. This is because absolute transformations + // overwfrite anything anyway so there is no need to waste time computing + // other runners + _clearTransformRunnersBefore: function _clearTransformRunnersBefore(currentRunner) { + this._transformationRunners.clearBefore(currentRunner.id); + }, + _currentTransform: function _currentTransform(current) { + return this._transformationRunners.runners // we need the equal sign here to make sure, that also transformations + // on the same runner which execute before the current transformation are + // taken into account + .filter(function (runner) { + return runner.id <= current.id; + }).map(getRunnerTransform).reduce(lmultiply, new Matrix()); + }, + addRunner: function addRunner(runner) { + this._transformationRunners.add(runner); - if (dtToStart < 0) { - runnersLeft = true; - continue; - } else if (dtToStart < dt) { - // Adjust dt to make sure that animation is on point - dt = dtToStart; - } + Animator.transform_frame(mergeTransforms.bind(this), this._frameId); + }, + _prepareRunner: function _prepareRunner() { + if (this._frameId == null) { + this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix(this))); + this._frameId = frameId++; + } + } + } + }); + extend(Runner, { + attr: function attr(a, v) { + return this.styleAttr('attr', a, v); + }, + // Add animatable styles + css: function css(s, v) { + return this.styleAttr('css', s, v); + }, + styleAttr: function styleAttr(type, name, val) { + // apply attributes individually + if (_typeof(name) === 'object') { + for (var key in val) { + this.styleAttr(type, key, val[key]); + } + } - if (!runner.active()) continue; // If this runner is still going, signal that we need another animation - // frame, otherwise, remove the completed runner + var morpher = new Morphable(this._stepper).to(val); + this.queue(function () { + morpher = morpher.from(this.element()[type](name)); + }, function (pos) { + this.element()[type](name, morpher.at(pos)); + return morpher.done(); + }); + return this; + }, + zoom: function zoom(level, point) { + var morpher = new Morphable(this._stepper).to(new SVGNumber(level)); + this.queue(function () { + morpher = morpher.from(this.zoom()); + }, function (pos) { + this.element().zoom(morpher.at(pos), point); + return morpher.done(); + }); + return this; + }, - var finished = runner.step(dt).done; + /** + ** absolute transformations + **/ + // + // M v -----|-----(D M v = F v)------|-----> T v + // + // 1. define the final state (T) and decompose it (once) + // t = [tx, ty, the, lam, sy, sx] + // 2. on every frame: pull the current state of all previous transforms + // (M - m can change) + // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] + // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) + // - Note F(0) = M + // - Note F(1) = T + // 4. Now you get the delta matrix as a result: D = F * inv(M) + transform: function transform(transforms, relative, affine) { + // If we have a declarative function, we should retarget it if possible + relative = transforms.relative || relative; - if (!finished) { - runnersLeft = true; // continue - } else if (runnerInfo.persist !== true) { - // runner is finished. And runner might get removed - // TODO: Figure out end time of runner - var endTime = runner.duration() - runner.time() + this._time; + if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { + return this; + } // Parse the parameters - if (endTime + this._persist < this._time) { - // Delete runner and correct index - delete this._runners[this._order[i]]; - this._order.splice(i--, 1) && --len; - runner.timeline(null); - } - } - } // Get the next animation frame to keep the simulation going + var isMatrix = Matrix.isMatrixLike(transforms); + affine = transforms.affine != null ? transforms.affine : affine != null ? affine : !isMatrix; // Create a morepher and set its type - if (runnersLeft) { - this._nextFrame = Animator.frame(this._step.bind(this)); - } else { - this._nextFrame = null; - } + var morpher = new Morphable().type(affine ? TransformBag : Matrix).stepper(this._stepper); + var origin; + var element; + var current; + var currentAngle; + var startTransform; - return this; - } // Checks if we are running and continues the animation + function setup() { + // make sure element and origin is defined + element = element || this.element(); + origin = origin || getOrigin(transforms, element); + startTransform = new Matrix(relative ? undefined : element); // add the runner to the element so it can merge transformations - }, { - key: "_continue", - value: function _continue() { - if (this._paused) return this; + element.addRunner(this); // Deactivate all transforms that have run so far if we are absolute - if (!this._nextFrame) { - this._nextFrame = Animator.frame(this._step.bind(this)); + if (!relative) { + element._clearTransformRunnersBefore(this); } - - return this; - } - }, { - key: "active", - value: function active() { - return !!this._nextFrame; } - }]); - - return Timeline; - }(); - registerMethods({ - Element: { - timeline: function timeline() { - this._timeline = this._timeline || new Timeline(); - return this._timeline; - } - } - }); - // easing = { - // '-': function (pos) { return pos }, - // '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, - // '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, - // '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } - // } + function run(pos) { + // clear all other transforms before this in case something is saved + // on this runner. We are absolute. We dont need these! + if (!relative) this.clearTransform(); - var Runner = - /*#__PURE__*/ - function (_EventTarget) { - _inherits(Runner, _EventTarget); + var _transform = new Point(origin).transform(element._currentTransform(this)), + x = _transform.x, + y = _transform.y; - function Runner(options) { - var _this; + var target = new Matrix(_objectSpread({}, transforms, { + origin: [x, y] + })); + var start = this._isDeclarative && current ? current : startTransform; - _classCallCheck(this, Runner); + if (affine) { + target = target.decompose(x, y); + start = start.decompose(x, y); // Get the current and target angle as it was set - _this = _possibleConstructorReturn(this, _getPrototypeOf(Runner).call(this)); // Store a unique id on the runner, so that we can identify it later + var rTarget = target.rotate; + var rCurrent = start.rotate; // Figure out the shortest path to rotate directly - _this.id = Runner.id++; // Ensure a default value + var possibilities = [rTarget - 360, rTarget, rTarget + 360]; + var distances = possibilities.map(function (a) { + return Math.abs(a - rCurrent); + }); + var shortest = Math.min.apply(Math, _toConsumableArray(distances)); + var index = distances.indexOf(shortest); + target.rotate = possibilities[index]; + } - options = options == null ? timeline.duration : options; // Ensure that we get a controller + if (relative) { + // we have to be careful here not to overwrite the rotation + // with the rotate method of Matrix + if (!isMatrix) { + target.rotate = transforms.rotate || 0; + } - options = typeof options === 'function' ? new Controller(options) : options; // Declare all of the variables + if (this._isDeclarative && currentAngle) { + start.rotate = currentAngle; + } + } - _this._element = null; - _this._timeline = null; - _this.done = false; - _this._queue = []; // Work out the stepper and the duration + morpher.from(start); + morpher.to(target); + var affineParameters = morpher.at(pos); + currentAngle = affineParameters.rotate; + current = new Matrix(affineParameters); + this.addTransform(current); + return morpher.done(); + } - _this._duration = typeof options === 'number' && options; - _this._isDeclarative = options instanceof Controller; - _this._stepper = _this._isDeclarative ? options : new Ease(); // We copy the current values from the timeline because they can change + function retarget(newTransforms) { + // only get a new origin if it changed since the last call + if ((newTransforms.origin || 'center').toString() !== (transforms.origin || 'center').toString()) { + origin = getOrigin(transforms, element); + } // overwrite the old transformations with the new ones - _this._history = {}; // Store the state of the runner - _this.enabled = true; - _this._time = 0; - _this._last = 0; // Save transforms applied to this runner + transforms = _objectSpread({}, newTransforms, { + origin: origin + }); + } - _this.transforms = new Matrix(); - _this.transformId = 1; // Looping variables + this.queue(setup, run, retarget); + this._isDeclarative && this._rememberMorpher('transform', morpher); + return this; + }, + // Animatable x-axis + x: function x(_x, relative) { + return this._queueNumber('x', _x); + }, + // Animatable y-axis + y: function y(_y) { + return this._queueNumber('y', _y); + }, + dx: function dx(x) { + return this._queueNumberDelta('dx', x); + }, + dy: function dy(y) { + return this._queueNumberDelta('dy', y); + }, + _queueNumberDelta: function _queueNumberDelta(method, to) { + to = new SVGNumber(to); // Try to change the target if we have this method already registerd - _this._haveReversed = false; - _this._reverse = false; - _this._loopsDone = 0; - _this._swing = false; - _this._wait = 0; - _this._times = 1; - return _this; - } - /* - Runner Definitions - ================== - These methods help us define the runtime behaviour of the Runner or they - help us make new runners from the current runner - */ + if (this._tryRetargetDelta(method, to)) return this; // Make a morpher and queue the animation + var morpher = new Morphable(this._stepper).to(to); + this.queue(function () { + var from = this.element()[method](); + morpher.from(from); + morpher.to(from + to); + }, function (pos) { + this.element()[method](morpher.at(pos)); + return morpher.done(); + }); // Register the morpher so that if it is changed again, we can retarget it - _createClass(Runner, [{ - key: "element", - value: function element(_element) { - if (_element == null) return this._element; - this._element = _element; + this._rememberMorpher(method, morpher); - _element._prepareRunner(); + return this; + }, + _queueObject: function _queueObject(method, to) { + // Try to change the target if we have this method already registerd + if (this._tryRetarget(method, to)) return this; // Make a morpher and queue the animation - return this; - } - }, { - key: "timeline", - value: function timeline$$1(_timeline) { - // check explicitly for undefined so we can set the timeline to null - if (typeof _timeline === 'undefined') return this._timeline; - this._timeline = _timeline; - return this; - } - }, { - key: "animate", - value: function animate(duration, delay, when) { - var o = Runner.sanitise(duration, delay, when); - var runner = new Runner(o.duration); - if (this._timeline) runner.timeline(this._timeline); - if (this._element) runner.element(this._element); - return runner.loop(o).schedule(delay, when); - } - }, { - key: "schedule", - value: function schedule(timeline$$1, delay, when) { - // The user doesn't need to pass a timeline if we already have one - if (!(timeline$$1 instanceof Timeline)) { - when = delay; - delay = timeline$$1; - timeline$$1 = this.timeline(); - } // If there is no timeline, yell at the user... + var morpher = new Morphable(this._stepper).to(to); + this.queue(function () { + morpher.from(this.element()[method]()); + }, function (pos) { + this.element()[method](morpher.at(pos)); + return morpher.done(); + }); // Register the morpher so that if it is changed again, we can retarget it + this._rememberMorpher(method, morpher); - if (!timeline$$1) { - throw Error('Runner cannot be scheduled without timeline'); - } // Schedule the runner on the timeline provided + return this; + }, + _queueNumber: function _queueNumber(method, value) { + return this._queueObject(method, new SVGNumber(value)); + }, + // Animatable center x-axis + cx: function cx(x) { + return this._queueNumber('cx', x); + }, + // Animatable center y-axis + cy: function cy(y) { + return this._queueNumber('cy', y); + }, + // Add animatable move + move: function move(x, y) { + return this.x(x).y(y); + }, + // Add animatable center + center: function center(x, y) { + return this.cx(x).cy(y); + }, + // Add animatable size + size: function size(width, height) { + // animate bbox based size for all other elements + var box; + if (!width || !height) { + box = this._element.bbox(); + } - timeline$$1.schedule(this, delay, when); - return this; + if (!width) { + width = box.width / box.height * height; } - }, { - key: "unschedule", - value: function unschedule() { - var timeline$$1 = this.timeline(); - timeline$$1 && timeline$$1.unschedule(this); - return this; + + if (!height) { + height = box.height / box.width * width; } - }, { - key: "loop", - value: function loop(times, swing, wait) { - // Deal with the user passing in an object - if (_typeof(times) === 'object') { - swing = times.swing; - wait = times.wait; - times = times.times; - } // Sanitise the values and store them + + return this.width(width).height(height); + }, + // Add animatable width + width: function width(_width) { + return this._queueNumber('width', _width); + }, + // Add animatable height + height: function height(_height) { + return this._queueNumber('height', _height); + }, + // Add animatable plot + plot: function plot(a, b, c, d) { + // Lines can be plotted with 4 arguments + if (arguments.length === 4) { + return this.plot([a, b, c, d]); + } // FIXME: this needs to be rewritten such that the element is only accesed + // in the init function - this._times = times || Infinity; - this._swing = swing || false; - this._wait = wait || 0; - return this; - } - }, { - key: "delay", - value: function delay(_delay) { - return this.animate(0, _delay); - } + return this._queueObject('plot', new this._element.MorphArray(a)); /* - Basic Functionality - =================== - These methods allow us to attach basic functions to the runner directly + var morpher = this._element.morphArray().to(a) + this.queue(function () { + morpher.from(this._element.array()) + }, function (pos) { + this._element.plot(morpher.at(pos)) + }) + return this */ - - }, { - key: "queue", - value: function queue(initFn, runFn, isTransform) { - this._queue.push({ - initialiser: initFn || noop, - runner: runFn || noop, - isTransform: isTransform, - initialised: false, - finished: false + }, + // Add leading method + leading: function leading(value) { + return this._queueNumber('leading', value); + }, + // Add animatable viewbox + viewbox: function viewbox(x, y, width, height) { + return this._queueObject('viewbox', new Box(x, y, width, height)); + }, + update: function update(o) { + if (_typeof(o) !== 'object') { + return this.update({ + offset: arguments[0], + color: arguments[1], + opacity: arguments[2] }); + } - var timeline$$1 = this.timeline(); - timeline$$1 && this.timeline()._continue(); + 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', o.offset); + return this; + } + }); + + var sugar = { + stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], + fill: ['color', 'opacity', 'rule'], + prefix: function prefix(t, a) { + return a === 'color' ? t : t + '-' + a; + } // Add sugar for fill and stroke + + }; + ['fill', 'stroke'].forEach(function (m) { + var extension = {}; + var i; + + extension[m] = function (o) { + if (typeof o === 'undefined') { return this; } - }, { - key: "during", - value: function during(fn) { - return this.queue(null, fn); - } - }, { - key: "after", - value: function after(fn) { - return this.on('finish', fn); - } - /* - Runner animation methods - ======================== - Control how the animation plays - */ - }, { - key: "time", - value: function time(_time) { - if (_time == null) { - return this._time; + if (typeof o === 'string' || Color.isRgb(o) || o instanceof Element) { + this.attr(m, o); + } else { + // set all attributes from sugar.fill and sugar.stroke list + for (i = sugar[m].length - 1; i >= 0; i--) { + if (o[sugar[m][i]] != null) { + this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]]); + } + } + } + + return this; + }; + + registerMethods(['Shape', 'Runner'], extension); + }); + registerMethods(['Element', 'Runner'], { + // Let the user set the matrix directly + matrix: function matrix(mat, b, c, d, e, f) { + // Act as a getter + if (mat == null) { + return new Matrix(this); + } // Act as a setter, the user can pass a matrix or a set of numbers + + + return this.attr('transform', new Matrix(mat, b, c, d, e, f)); + }, + // Map rotation to transform + rotate: function rotate(angle, cx, cy) { + return this.transform({ + rotate: angle, + ox: cx, + oy: cy + }, true); + }, + // Map skew to transform + skew: function skew(x, y, cx, cy) { + return arguments.length === 1 || arguments.length === 3 ? this.transform({ + skew: x, + ox: y, + oy: cx + }, true) : this.transform({ + skew: [x, y], + ox: cx, + oy: cy + }, true); + }, + shear: function shear(lam, cx, cy) { + return this.transform({ + shear: lam, + ox: cx, + oy: cy + }, true); + }, + // Map scale to transform + scale: function scale(x, y, cx, cy) { + return arguments.length === 1 || arguments.length === 3 ? this.transform({ + scale: x, + ox: y, + oy: cx + }, true) : this.transform({ + scale: [x, y], + ox: cx, + oy: cy + }, true); + }, + // Map translate to transform + translate: function translate(x, y) { + return this.transform({ + translate: [x, y] + }, true); + }, + // Map relative translations to transform + relative: function relative(x, y) { + return this.transform({ + relative: [x, y] + }, true); + }, + // Map flip to transform + flip: function flip(direction, around) { + var directionString = typeof direction === 'string' ? direction : isFinite(direction) ? 'both' : 'both'; + var origin = direction === 'both' && isFinite(around) ? [around, around] : direction === 'x' ? [around, 0] : direction === 'y' ? [0, around] : isFinite(direction) ? [direction, direction] : [0, 0]; + this.transform({ + flip: directionString, + origin: origin + }, true); + }, + // Opacity + opacity: function opacity(value) { + return this.attr('opacity', value); + }, + // Relative move over x axis + dx: function dx(x) { + return this.x(new SVGNumber(x).plus(this instanceof Runner ? 0 : this.x()), true); + }, + // Relative move over y axis + dy: function dy(y) { + return this.y(new SVGNumber(y).plus(this instanceof Runner ? 0 : this.y()), true); + }, + // Relative move over x and y axes + dmove: function dmove(x, y) { + return this.dx(x).dy(y); + } + }); + registerMethods('radius', { + // Add x and y radius + radius: function radius(x, y) { + var type = (this._element || this).type; + return type === 'radialGradient' || type === 'radialGradient' ? this.attr('r', new SVGNumber(x)) : this.rx(x).ry(y == null ? x : y); + } + }); + registerMethods('Path', { + // Get path length + length: function length() { + return this.node.getTotalLength(); + }, + // Get point at length + pointAt: function pointAt(length) { + return new Point(this.node.getPointAtLength(length)); + } + }); + registerMethods(['Element', 'Runner'], { + // Set font + font: function font(a, v) { + if (_typeof(a) === 'object') { + for (v in a) { + this.font(v, a[v]); + } + } + + return a === 'leading' ? this.leading(v) : a === 'anchor' ? this.attr('text-anchor', v) : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style' ? this.attr('font-' + a, v) : this.attr(a, v); + } + }); + + function untransform() { + return this.attr('transform', null); + } // merge the whole transformation chain into one matrix and returns it + + function matrixify() { + var matrix = (this.attr('transform') || ''). // split transformations + split(transforms).slice(0, -1).map(function (str) { + // generate key => value pairs + var kv = str.trim().split('('); + return [kv[0], kv[1].split(delimiter).map(function (str) { + return parseFloat(str); + })]; + }).reverse() // merge every transformation into one matrix + .reduce(function (matrix, transform) { + if (transform[0] === 'matrix') { + return matrix.lmultiply(Matrix.fromArray(transform[1])); + } + + return matrix[transform[0]].apply(matrix, transform[1]); + }, new Matrix()); + return matrix; + } // add an element to another parent without changing the visual representation on the screen + + function toParent(parent) { + if (this === parent) return this; + var ctm = this.screenCTM(); + var pCtm = parent.screenCTM().inverse(); + this.addTo(parent).untransform().transform(pCtm.multiply(ctm)); + return this; + } // same as above with parent equals root-svg + + function toDoc() { + return this.toParent(this.doc()); + } // Add transformations + + function transform(o, relative) { + // Act as a getter if no object was passed + if (o == null || typeof o === 'string') { + var decomposed = new Matrix(this).decompose(); + return decomposed[o] || decomposed; + } + + if (!Matrix.isMatrixLike(o)) { + // Set the origin according to the defined transform + o = _objectSpread({}, o, { + origin: getOrigin(o, this) + }); + } // The user can pass a boolean, an Element or an Matrix or nothing + + + var cleanRelative = relative === true ? this : relative || false; + var result = new Matrix(cleanRelative).transform(o); + return this.attr('transform', result); + } + registerMethods('Element', { + untransform: untransform, + matrixify: matrixify, + toParent: toParent, + toDoc: toDoc, + transform: transform + }); + + // FIXME: import this to runner + + function rx(rx) { + return this.attr('rx', rx); + } // Radius y value + + function ry(ry) { + return this.attr('ry', ry); + } // Move over x-axis + + function x(x) { + return x == null ? this.cx() - this.rx() : this.cx(x + this.rx()); + } // Move over y-axis + + function y(y) { + return y == null ? this.cy() - this.ry() : this.cy(y + this.ry()); + } // Move by center over x-axis + + function cx(x) { + return x == null ? this.attr('cx') : this.attr('cx', x); + } // Move by center over y-axis + + function cy(y) { + return y == null ? this.attr('cy') : this.attr('cy', y); + } // Set width of element + + function width(width) { + return width == null ? this.rx() * 2 : this.rx(new SVGNumber(width).divide(2)); + } // Set height of element + + function height(height) { + return height == null ? this.ry() * 2 : this.ry(new SVGNumber(height).divide(2)); + } // Custom size function + + function 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)); + } + + var circled = /*#__PURE__*/Object.freeze({ + rx: rx, + ry: ry, + x: x, + y: y, + cx: cx, + cy: cy, + width: width, + height: height, + size: size + }); + + var Shape = + /*#__PURE__*/ + function (_Element) { + _inherits(Shape, _Element); + + function Shape() { + _classCallCheck(this, Shape); + + return _possibleConstructorReturn(this, _getPrototypeOf(Shape).apply(this, arguments)); + } + + return Shape; + }(Element); + + var Circle = + /*#__PURE__*/ + function (_Shape) { + _inherits(Circle, _Shape); + + function Circle(node) { + _classCallCheck(this, Circle); + + return _possibleConstructorReturn(this, _getPrototypeOf(Circle).call(this, nodeOrNew('circle', node), Circle)); + } + + _createClass(Circle, [{ + key: "radius", + value: function radius(r) { + return this.attr('r', r); + } // Radius x value + + }, { + key: "rx", + value: function rx$$1(_rx) { + return this.attr('r', _rx); + } // Alias radius x value + + }, { + key: "ry", + value: function ry$$1(_ry) { + return this.rx(_ry); + } + }]); + + return Circle; + }(Shape); + extend(Circle, { + x: x, + y: y, + cx: cx, + cy: cy, + width: width, + height: height, + size: size + }); + registerMethods({ + Element: { + // Create circle element + circle: function circle(size$$1) { + return this.put(new Circle()).radius(new SVGNumber(size$$1).divide(2)).move(0, 0); + } + } + }); + register(Circle); + + var Ellipse = + /*#__PURE__*/ + function (_Shape) { + _inherits(Ellipse, _Shape); + + function Ellipse(node) { + _classCallCheck(this, Ellipse); + + return _possibleConstructorReturn(this, _getPrototypeOf(Ellipse).call(this, nodeOrNew('ellipse', node), Ellipse)); + } + + return Ellipse; + }(Shape); + extend(Ellipse, circled); + registerMethods('Container', { + // Create an ellipse + ellipse: function ellipse(width$$1, height$$1) { + return this.put(new Ellipse()).size(width$$1, height$$1).move(0, 0); + } + }); + register(Ellipse); + + var Stop = + /*#__PURE__*/ + function (_Element) { + _inherits(Stop, _Element); + + function Stop(node) { + _classCallCheck(this, Stop); + + return _possibleConstructorReturn(this, _getPrototypeOf(Stop).call(this, nodeOrNew('stop', node), Stop)); + } // add color stops + + + _createClass(Stop, [{ + key: "update", + value: function 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)); + return this; + } + }]); + + return Stop; + }(Element); + register(Stop); + + function baseFind(query, parent) { + return map((parent || document).querySelectorAll(query), function (node) { + return adopt(node); + }); + } // Scoped find method + + function find(query) { + return baseFind(query, this.node); + } + registerMethods('Dom', { + find: find + }); + + // FIXME: add to runner + function from(x, y) { + return (this._element || this).type === 'radialGradient' ? this.attr({ + fx: new SVGNumber(x), + fy: new SVGNumber(y) + }) : this.attr({ + x1: new SVGNumber(x), + y1: new SVGNumber(y) + }); + } + function to(x, y) { + return (this._element || this).type === 'radialGradient' ? this.attr({ + cx: new SVGNumber(x), + cy: new SVGNumber(y) + }) : this.attr({ + x2: new SVGNumber(x), + y2: new SVGNumber(y) + }); + } + + var gradiented = /*#__PURE__*/Object.freeze({ + from: from, + to: to + }); + + var Gradient = + /*#__PURE__*/ + function (_Container) { + _inherits(Gradient, _Container); + + function Gradient(type) { + _classCallCheck(this, Gradient); + + return _possibleConstructorReturn(this, _getPrototypeOf(Gradient).call(this, nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type), Gradient)); + } // Add a color stop + + + _createClass(Gradient, [{ + key: "stop", + value: function stop(offset, color, opacity) { + return this.put(new Stop()).update(offset, color, opacity); + } // Update gradient + + }, { + key: "update", + value: function update(block) { + // remove all stops + this.clear(); // invoke passed block + + if (typeof block === 'function') { + block.call(this, this); } - var dt = _time - this._time; - this.step(dt); return this; + } // Return the fill id + + }, { + key: "url", + value: function url() { + return 'url(#' + this.id() + ')'; + } // Alias string convertion to fill + + }, { + key: "toString", + value: function toString() { + return this.url(); + } // custom attr to handle transform + + }, { + key: "attr", + value: function attr(a, b, c) { + if (a === 'transform') a = 'gradientTransform'; + return _get(_getPrototypeOf(Gradient.prototype), "attr", this).call(this, a, b, c); } }, { - key: "duration", - value: function duration() { - return this._times * (this._wait + this._duration) - this._wait; + key: "targets", + value: function targets() { + return baseFind('svg [fill*="' + this.id() + '"]'); } }, { - key: "loops", - value: function loops(p) { - var loopDuration = this._duration + this._wait; + key: "bbox", + value: function bbox() { + return new Box(); + } + }]); - if (p == null) { - var loopsDone = Math.floor(this._time / loopDuration); - var relativeTime = this._time - loopsDone * loopDuration; - var position = relativeTime / this._duration; - return Math.min(loopsDone + position, this._times); + return Gradient; + }(Container); + extend(Gradient, gradiented); + registerMethods({ + Container: { + // Create gradient element in defs + gradient: function gradient(type, block) { + return this.defs().gradient(type, block); + } + }, + // define gradient + Defs: { + gradient: function gradient(type, block) { + return this.put(new Gradient(type)).update(block); + } + } + }); + register(Gradient); + + var Pattern = + /*#__PURE__*/ + function (_Container) { + _inherits(Pattern, _Container); + + // Initialize node + function Pattern(node) { + _classCallCheck(this, Pattern); + + return _possibleConstructorReturn(this, _getPrototypeOf(Pattern).call(this, nodeOrNew('pattern', node), Pattern)); + } // Return the fill id + + + _createClass(Pattern, [{ + key: "url", + value: function url() { + return 'url(#' + this.id() + ')'; + } // Update pattern by rebuilding + + }, { + key: "update", + value: function update(block) { + // remove content + this.clear(); // invoke passed block + + if (typeof block === 'function') { + block.call(this, this); } - var whole = Math.floor(p); - var partial = p % 1; - var time = loopDuration * whole + this._duration * partial; - return this.time(time); + return this; + } // Alias string convertion to fill + + }, { + key: "toString", + value: function toString() { + return this.url(); + } // custom attr to handle transform + + }, { + key: "attr", + value: function attr(a, b, c) { + if (a === 'transform') a = 'patternTransform'; + return _get(_getPrototypeOf(Pattern.prototype), "attr", this).call(this, a, b, c); } }, { - key: "position", - value: function position(p) { - // Get all of the variables we need - var x = this._time; - var d = this._duration; - var w = this._wait; - var t = this._times; - var s = this._swing; - var r = this._reverse; - var position; + key: "targets", + value: function targets() { + return baseFind('svg [fill*="' + this.id() + '"]'); + } + }, { + key: "bbox", + value: function bbox() { + return new Box(); + } + }]); + + return Pattern; + }(Container); + registerMethods({ + Container: { + // Create pattern element in defs + pattern: function pattern(width, height, block) { + return this.defs().pattern(width, height, block); + } + }, + Defs: { + pattern: function pattern(width, height, block) { + return this.put(new Pattern()).update(block).attr({ + x: 0, + y: 0, + width: width, + height: height, + patternUnits: 'userSpaceOnUse' + }); + } + } + }); + register(Pattern); - if (p == null) { - /* - This function converts a time to a position in the range [0, 1] - The full explanation can be found in this desmos demonstration - https://www.desmos.com/calculator/u4fbavgche - The logic is slightly simplified here because we can use booleans - */ - // Figure out the value without thinking about the start or end time - var f = function f(x) { - var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)); - var backwards = swinging && !r || !swinging && r; - var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards; - var clipped = Math.max(Math.min(uncliped, 1), 0); - return clipped; - }; // Figure out the value by incorporating the start time + var Image = + /*#__PURE__*/ + function (_Shape) { + _inherits(Image, _Shape); + function Image(node) { + _classCallCheck(this, Image); - var endTime = t * (w + d) - w; - position = x <= 0 ? Math.round(f(1e-5)) : x < endTime ? f(x) : Math.round(f(endTime - 1e-5)); - return position; - } // Work out the loops done and add the position to the loops done + return _possibleConstructorReturn(this, _getPrototypeOf(Image).call(this, nodeOrNew('image', node), Image)); + } // (re)load image - var loopsDone = Math.floor(this.loops()); - var swingForward = s && loopsDone % 2 === 0; - var forwards = swingForward && !r || r && swingForward; - position = loopsDone + (forwards ? p : 1 - p); - return this.loops(position); - } - }, { - key: "progress", - value: function progress(p) { - if (p == null) { - return Math.min(1, this._time / this.duration()); - } + _createClass(Image, [{ + key: "load", + value: function load(url, callback) { + if (!url) return this; + var img = new window.Image(); + on(img, 'load', function (e) { + var p = this.parent(Pattern); // ensure image size - return this.time(p * this.duration()); + if (this.width() === 0 && this.height() === 0) { + this.size(img.width, img.height); + } + + if (p instanceof Pattern) { + // ensure pattern size if not set + if (p.width() === 0 && p.height() === 0) { + p.size(this.width(), this.height()); + } + } + + if (typeof callback === 'function') { + callback.call(this, { + width: img.width, + height: img.height, + ratio: img.width / img.height, + url: url + }); + } + }, this); + on(img, 'load error', function () { + // dont forget to unbind memory leaking events + off(img); + }); + return this.attr('href', img.src = url, xlink); } }, { - key: "step", - value: function step(dt) { - // If we are inactive, this stepper just gets skipped - if (!this.enabled) return this; // Update the time and get the new position - - dt = dt == null ? 16 : dt; - this._time += dt; - var position = this.position(); // Figure out if we need to run the stepper in this frame + key: "attrHook", + value: function attrHook(obj) { + var _this = this; - var running = this._lastPosition !== position && this._time >= 0; - this._lastPosition = position; // Figure out if we just started + return obj.doc().defs().pattern(0, 0, function (pattern) { + pattern.add(_this); + }); + } + }]); - var duration = this.duration(); - var justStarted = this._lastTime < 0 && this._time > 0; - var justFinished = this._lastTime < this._time && this.time > duration; - this._lastTime = this._time; + return Image; + }(Shape); + registerMethods({ + Container: { + // create image element, load image and set its size + image: function image(source, callback) { + return this.put(new Image()).size(0, 0).load(source, callback); + } + } + }); + register(Image); - if (justStarted) { - this.fire('start', this); - } // Work out if the runner is finished set the done flag here so animations - // know, that they are running in the last step (this is good for - // transformations which can be merged) + var PointArray = subClassArray('PointArray', SVGArray); + extend(PointArray, { + // Convert array to string + toString: function toString() { + // convert to a poly point string + for (var i = 0, il = this.length, array = []; i < il; i++) { + array.push(this[i].join(',')); + } + return array.join(' '); + }, + // Convert array to line object + toLine: function toLine() { + return { + x1: this[0][0], + y1: this[0][1], + x2: this[1][0], + y2: this[1][1] + }; + }, + // Get morphed array at given position + at: function at(pos) { + // make sure a destination is defined + if (!this.destination) return this; // generate morphed point string - var declarative = this._isDeclarative; - this.done = !declarative && !justFinished && this._time >= duration; // Call initialise and the run function + for (var i = 0, il = this.length, array = []; i < il; i++) { + array.push([this[i][0] + (this.destination[i][0] - this[i][0]) * pos, this[i][1] + (this.destination[i][1] - this[i][1]) * pos]); + } - if (running || declarative) { - this._initialise(running); // clear the transforms on this runner so they dont get added again and again + return new PointArray(array); + }, + // Parse point string and flat array + parse: function parse() { + var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [[0, 0]]; + var points = []; // if it is an array + if (array instanceof Array) { + // and it is not flat, there is no need to parse it + if (array[0] instanceof Array) { + return array; + } + } else { + // Else, it is considered as a string + // parse points + array = array.trim().split(delimiter).map(parseFloat); + } // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints + // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. - this.transforms = new Matrix(); - var converged = this._run(declarative ? dt : position); + if (array.length % 2 !== 0) array.pop(); // wrap points in two-tuples and parse points as floats - this.fire('step', this); - } // correct the done flag here - // declaritive animations itself know when they converged + for (var i = 0, len = array.length; i < len; i = i + 2) { + points.push([array[i], array[i + 1]]); + } + return points; + }, + // Move point string + move: function move(x, y) { + var box = this.bbox(); // get relative offset - this.done = this.done || converged && declarative; + x -= box.x; + y -= box.y; // move every point - if (this.done) { - this.fire('finish', this); + if (!isNaN(x) && !isNaN(y)) { + for (var i = this.length - 1; i >= 0; i--) { + this[i] = [this[i][0] + x, this[i][1] + y]; } - - return this; - } - }, { - key: "finish", - value: function finish() { - return this.step(Infinity); - } - }, { - key: "reverse", - value: function reverse(_reverse) { - this._reverse = _reverse == null ? !this._reverse : _reverse; - return this; - } - }, { - key: "ease", - value: function ease(fn) { - this._stepper = new Ease(fn); - return this; - } - }, { - key: "active", - value: function active(enabled) { - if (enabled == null) return this.enabled; - this.enabled = enabled; - return this; } - /* - Private Methods - =============== - Methods that shouldn't be used externally - */ - // Save a morpher to the morpher list so that we can retarget it later - }, { - key: "_rememberMorpher", - value: function _rememberMorpher(method, morpher) { - this._history[method] = { - morpher: morpher, - caller: this._queue[this._queue.length - 1] - }; - } // Try to set the target for a morpher if the morpher exists, otherwise - // do nothing and return false + return this; + }, + // Resize poly string + size: function size(width, height) { + var i; + var box = this.bbox(); // recalculate position of all points according to new size - }, { - key: "_tryRetarget", - value: function _tryRetarget(method, target) { - if (this._history[method]) { - // if the last method wasnt even initialised, throw it away - if (!this._history[method].caller.initialised) { - var index = this._queue.indexOf(this._history[method].caller); + for (i = this.length - 1; i >= 0; i--) { + if (box.width) this[i][0] = (this[i][0] - box.x) * width / box.width + box.x; + if (box.height) this[i][1] = (this[i][1] - box.y) * height / box.height + box.y; + } + + return this; + }, + // Get bounding box of points + bbox: function bbox() { + var maxX = -Infinity; + var maxY = -Infinity; + var minX = Infinity; + var minY = Infinity; + this.forEach(function (el) { + maxX = Math.max(el[0], maxX); + maxY = Math.max(el[1], maxY); + minX = Math.min(el[0], minX); + minY = Math.min(el[1], minY); + }); + return { + x: minX, + y: minY, + width: maxX - minX, + height: maxY - minY + }; + } + }); - this._queue.splice(index, 1); + var MorphArray = PointArray; // Move by left top corner over x-axis - return false; - } // for the case of transformations, we use the special retarget function - // which has access to the outer scope + function x$1(x) { + return x == null ? this.bbox().x : this.move(x, this.bbox().y); + } // Move by left top corner over y-axis + function y$1(y) { + return y == null ? this.bbox().y : this.move(this.bbox().x, y); + } // Set width of element - if (this._history[method].caller.isTransform) { - this._history[method].caller.isTransform(target); // for everything else a simple morpher change is sufficient + function width$1(width) { + var b = this.bbox(); + return width == null ? b.width : this.size(width, b.height); + } // Set height of element - } else { - this._history[method].morpher.to(target); - } + function height$1(height) { + var b = this.bbox(); + return height == null ? b.height : this.size(b.width, height); + } - this._history[method].caller.finished = false; - var timeline$$1 = this.timeline(); - timeline$$1 && timeline$$1._continue(); - return true; - } + var pointed = /*#__PURE__*/Object.freeze({ + MorphArray: MorphArray, + x: x$1, + y: y$1, + width: width$1, + height: height$1 + }); - return false; - } // Run each initialise function in the runner if required + var Line = + /*#__PURE__*/ + function (_Shape) { + _inherits(Line, _Shape); - }, { - key: "_initialise", - value: function _initialise(running) { - // If we aren't running, we shouldn't initialise when not declarative - if (!running && !this._isDeclarative) return; // Loop through all of the initialisers + // Initialize node + function Line(node) { + _classCallCheck(this, Line); - for (var i = 0, len = this._queue.length; i < len; ++i) { - // Get the current initialiser - var current = this._queue[i]; // Determine whether we need to initialise + return _possibleConstructorReturn(this, _getPrototypeOf(Line).call(this, nodeOrNew('line', node), Line)); + } // Get array - var needsIt = this._isDeclarative || !current.initialised && running; - running = !current.finished; // Call the initialiser if we need to - if (needsIt && running) { - current.initialiser.call(this); - current.initialised = true; - } - } - } // Run each run function for the position or dt given + _createClass(Line, [{ + key: "array", + value: function array() { + return new PointArray([[this.attr('x1'), this.attr('y1')], [this.attr('x2'), this.attr('y2')]]); + } // Overwrite native plot() method }, { - key: "_run", - value: function _run(positionOrDt) { - // Run all of the _queue directly - var allfinished = true; - - for (var i = 0, len = this._queue.length; i < len; ++i) { - // Get the current function to run - var current = this._queue[i]; // Run the function if its not finished, we keep track of the finished - // flag for the sake of declarative _queue - - var converged = current.runner.call(this, positionOrDt); - current.finished = current.finished || converged === true; - allfinished = allfinished && current.finished; - } // We report when all of the constructors are finished + key: "plot", + value: function plot(x1, y1, x2, y2) { + if (x1 == null) { + return this.array(); + } else if (typeof y1 !== 'undefined') { + x1 = { + x1: x1, + y1: y1, + x2: x2, + y2: y2 + }; + } else { + x1 = new PointArray(x1).toLine(); + } + return this.attr(x1); + } // Move by left top corner - return allfinished; - } }, { - key: "addTransform", - value: function addTransform(transform, index) { - this.transforms.lmultiplyO(transform); - return this; - } + key: "move", + value: function move(x, y) { + return this.attr(this.array().move(x, y).toLine()); + } // Set element size to given width and height + }, { - key: "clearTransform", - value: function clearTransform() { - this.transforms = new Matrix(); - return this; + key: "size", + value: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.attr(this.array().size(p.width, p.height).toLine()); } - }], [{ - key: "sanitise", - value: function sanitise(duration, delay, when) { - // Initialise the default parameters - var times = 1; - var swing = false; - var wait = 0; - duration = duration || timeline.duration; - delay = delay || timeline.delay; - when = when || 'last'; // If we have an object, unpack the values + }]); - if (_typeof(duration) === 'object' && !(duration instanceof Stepper)) { - delay = duration.delay || delay; - when = duration.when || when; - swing = duration.swing || swing; - times = duration.times || times; - wait = duration.wait || wait; - duration = duration.duration || timeline.duration; + return Line; + }(Shape); + extend(Line, pointed); + registerMethods({ + Container: { + // Create a line element + line: function line() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; } - return { - duration: duration, - delay: delay, - swing: swing, - times: times, - wait: wait, - when: when - }; + // 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]); } - }]); - - return Runner; - }(EventTarget); - Runner.id = 0; - - var FakeRunner = function FakeRunner() { - var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix(); - var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; - var done = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; - - _classCallCheck(this, FakeRunner); - - this.transforms = transforms; - this.id = id; - this.done = done; - }; - - extend([Runner, FakeRunner], { - mergeWith: function mergeWith(runner) { - return new FakeRunner(runner.transforms.lmultiply(this.transforms), runner.id); } - }); // FakeRunner.emptyRunner = new FakeRunner() - - var lmultiply = function lmultiply(last, curr) { - return last.lmultiplyO(curr); - }; - - var getRunnerTransform = function getRunnerTransform(runner) { - return runner.transforms; - }; + }); + register(Line); - function mergeTransforms() { - // Find the matrix to apply to the element and apply it - var runners = this._transformationRunners.runners; - var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix()); - this.transform(netTransform); + var Marker = + /*#__PURE__*/ + function (_Container) { + _inherits(Marker, _Container); - this._transformationRunners.merge(); + // Initialize node + function Marker(node) { + _classCallCheck(this, Marker); - if (this._transformationRunners.length() === 1) { - this._frameId = null; - } - } + return _possibleConstructorReturn(this, _getPrototypeOf(Marker).call(this, nodeOrNew('marker', node), Marker)); + } // Set width of element - var RunnerArray = - /*#__PURE__*/ - function () { - function RunnerArray() { - _classCallCheck(this, RunnerArray); - this.runners = []; - this.ids = []; - } + _createClass(Marker, [{ + key: "width", + value: function width(_width) { + return this.attr('markerWidth', _width); + } // Set height of element - _createClass(RunnerArray, [{ - key: "add", - value: function add(runner) { - if (this.runners.includes(runner)) return; - var id = runner.id + 1; - var leftSibling = this.ids.reduce(function (last, curr) { - if (curr > last && curr < id) return curr; - return last; - }, 0); - var index = this.ids.indexOf(leftSibling) + 1; - this.ids.splice(index, 0, id); - this.runners.splice(index, 0, runner); - return this; - } - }, { - key: "getByID", - value: function getByID(id) { - return this.runners[this.ids.indexOf(id + 1)]; - } }, { - key: "remove", - value: function remove(id) { - var index = this.ids.indexOf(id + 1); - this.ids.splice(index, 1); - this.runners.splice(index, 1); - return this; - } + key: "height", + value: function height(_height) { + return this.attr('markerHeight', _height); + } // Set marker refX and refY + }, { - key: "merge", - value: function merge() { - var _this2 = this; + key: "ref", + value: function ref(x, y) { + return this.attr('refX', x).attr('refY', y); + } // Update marker - var lastRunner = null; - this.runners.forEach(function (runner, i) { - if (lastRunner && runner.done && lastRunner.done) { - _this2.remove(runner.id); + }, { + key: "update", + value: function update(block) { + // remove all content + this.clear(); // invoke passed block - _this2.edit(lastRunner.id, runner.mergeWith(lastRunner)); - } + if (typeof block === 'function') { + block.call(this, this); + } - lastRunner = runner; - }); - return this; - } - }, { - key: "edit", - value: function edit(id, newRunner) { - var index = this.ids.indexOf(id + 1); - this.ids.splice(index, 1, id); - this.runners.splice(index, 1, newRunner); return this; - } - }, { - key: "length", - value: function length() { - return this.ids.length; - } + } // Return the fill id + }, { - key: "clearBefore", - value: function clearBefore(id) { - var deleteCnt = this.ids.indexOf(id + 1) || 1; - this.ids.splice(0, deleteCnt, 0); - this.runners.splice(0, deleteCnt, new FakeRunner()); - return this; + key: "toString", + value: function toString() { + return 'url(#' + this.id() + ')'; } }]); - return RunnerArray; - }(); - - var frameId = 0; + return Marker; + }(Container); registerMethods({ - Element: { - animate: function animate(duration, delay, when) { - var o = Runner.sanitise(duration, delay, when); - var timeline$$1 = this.timeline(); - return new Runner(o.duration).loop(o).element(this).timeline(timeline$$1).schedule(delay, when); - }, - delay: function delay(by, when) { - return this.animate(0, by, when); - }, - // this function searches for all runners on the element and deletes the ones - // which run before the current one. This is because absolute transformations - // overwfrite anything anyway so there is no need to waste time computing - // other runners - _clearTransformRunnersBefore: function _clearTransformRunnersBefore(currentRunner) { - this._transformationRunners.clearBefore(currentRunner.id); - }, - _currentTransform: function _currentTransform(current) { - return this._transformationRunners.runners // we need the equal sign here to make sure, that also transformations - // on the same runner which execute before the current transformation are - // taken into account - .filter(function (runner) { - return runner.id <= current.id; - }).map(getRunnerTransform).reduce(lmultiply, new Matrix()); - }, - addRunner: function addRunner(runner) { - this._transformationRunners.add(runner); - - Animator.transform_frame(mergeTransforms.bind(this), this._frameId); - }, - _prepareRunner: function _prepareRunner() { - if (this._frameId == null) { - this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix(this))); - this._frameId = frameId++; - } + Container: { + marker: function marker(width, height, block) { + // Create marker element in defs + return this.defs().marker(width, height, block); } - } - }); - extend(Runner, { - attr: function attr(a, v) { - return this.styleAttr('attr', a, v); - }, - // Add animatable styles - css: function css(s, v) { - return this.styleAttr('css', s, v); }, - styleAttr: function styleAttr(type, name, val) { - // apply attributes individually - if (_typeof(name) === 'object') { - for (var key in val) { - this.styleAttr(type, key, val[key]); - } + Defs: { + // Create marker + marker: function marker(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); } - - var morpher = new Morphable(this._stepper).to(val); - this.queue(function () { - morpher = morpher.from(this.element()[type](name)); - }, function (pos) { - this.element()[type](name, morpher.at(pos)); - return morpher.done(); - }); - return this; - }, - zoom: function zoom(level, point) { - var morpher = new Morphable(this._stepper).to(new SVGNumber(level)); - this.queue(function () { - morpher = morpher.from(this.zoom()); - }, function (pos) { - this.element().zoom(morpher.at(pos), point); - return morpher.done(); - }); - return this; }, + marker: { + // Create and attach markers + marker: function marker(_marker, width, height, block) { + var attr = ['marker']; // Build attribute name - /** - ** absolute transformations - **/ - // - // M v -----|-----(D M v = F v)------|-----> T v - // - // 1. define the final state (T) and decompose it (once) - // t = [tx, ty, the, lam, sy, sx] - // 2. on every frame: pull the current state of all previous transforms - // (M - m can change) - // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] - // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) - // - Note F(0) = M - // - Note F(1) = T - // 4. Now you get the delta matrix as a result: D = F * inv(M) - transform: function transform(transforms, relative, affine) { - // If we have a declarative function, we should retarget it if possible - relative = transforms.relative || relative; - - if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { - return this; - } // Parse the parameters - + if (_marker !== 'all') attr.push(_marker); + attr = attr.join('-'); // Set marker attribute - var isMatrix = isMatrixLike(transforms); - affine = transforms.affine != null ? transforms.affine : affine != null ? affine : !isMatrix; // Create a morepher and set its type + _marker = arguments[1] instanceof Marker ? arguments[1] : this.defs().marker(width, height, block); + return this.attr(attr, _marker); + } + } + }); + register(Marker); - var morpher = new Morphable().type(affine ? TransformBag : Matrix).stepper(this._stepper); - var origin; - var element; - var current; - var currentAngle; - var startTransform; + var Path = + /*#__PURE__*/ + function (_Shape) { + _inherits(Path, _Shape); - function setup() { - // make sure element and origin is defined - element = element || this.element(); - origin = origin || getOrigin(transforms, element); - startTransform = new Matrix(relative ? undefined : element); // add the runner to the element so it can merge transformations + // Initialize node + function Path(node) { + _classCallCheck(this, Path); - element.addRunner(this); // Deactivate all transforms that have run so far if we are absolute + return _possibleConstructorReturn(this, _getPrototypeOf(Path).call(this, nodeOrNew('path', node), Path)); + } // Get array - if (!relative) { - element._clearTransformRunnersBefore(this); - } - } - function run(pos) { - // clear all other transforms before this in case something is saved - // on this runner. We are absolute. We dont need these! - if (!relative) this.clearTransform(); + _createClass(Path, [{ + key: "array", + value: function array() { + return this._array || (this._array = new PathArray(this.attr('d'))); + } // Plot new path - var _transform = new Point(origin).transform(element._currentTransform(this)), - x = _transform.x, - y = _transform.y; + }, { + key: "plot", + value: function plot(d) { + return d == null ? this.array() : this.clear().attr('d', typeof d === 'string' ? d : this._array = new PathArray(d)); + } // Clear array cache - var target = new Matrix(_objectSpread({}, transforms, { - origin: [x, y] - })); - var start = this._isDeclarative && current ? current : startTransform; + }, { + key: "clear", + value: function clear() { + delete this._array; + return this; + } // Move by left top corner - if (affine) { - target = target.decompose(x, y); - start = start.decompose(x, y); // Get the current and target angle as it was set + }, { + key: "move", + value: function move(x, y) { + return this.attr('d', this.array().move(x, y)); + } // Move by left top corner over x-axis - var rTarget = target.rotate; - var rCurrent = start.rotate; // Figure out the shortest path to rotate directly + }, { + key: "x", + value: function x(_x) { + return _x == null ? this.bbox().x : this.move(_x, this.bbox().y); + } // Move by left top corner over y-axis - var possibilities = [rTarget - 360, rTarget, rTarget + 360]; - var distances = possibilities.map(function (a) { - return Math.abs(a - rCurrent); - }); - var shortest = Math.min.apply(Math, _toConsumableArray(distances)); - var index = distances.indexOf(shortest); - target.rotate = possibilities[index]; - } + }, { + key: "y", + value: function y(_y) { + return _y == null ? this.bbox().y : this.move(this.bbox().x, _y); + } // Set element size to given width and height - if (relative) { - // we have to be careful here not to overwrite the rotation - // with the rotate method of Matrix - if (!isMatrix) { - target.rotate = transforms.rotate || 0; - } + }, { + key: "size", + value: function size(width, height) { + var p = proportionalSize(this, width, height); + return this.attr('d', this.array().size(p.width, p.height)); + } // Set width of element - if (this._isDeclarative && currentAngle) { - start.rotate = currentAngle; - } - } + }, { + key: "width", + value: function width(_width) { + return _width == null ? this.bbox().width : this.size(_width, this.bbox().height); + } // Set height of element - morpher.from(start); - morpher.to(target); - var affineParameters = morpher.at(pos); - currentAngle = affineParameters.rotate; - current = new Matrix(affineParameters); - this.addTransform(current); - return morpher.done(); + }, { + key: "height", + value: function height(_height) { + return _height == null ? this.bbox().height : this.size(this.bbox().width, _height); } + }, { + key: "targets", + value: function targets() { + return baseFind('svg textpath [href*="' + this.id() + '"]'); + } + }]); - function retarget(newTransforms) { - // only get a new origin if it changed since the last call - if ((newTransforms.origin || 'center').toString() !== (transforms.origin || 'center').toString()) { - origin = getOrigin(transforms, element); - } // overwrite the old transformations with the new ones - + return Path; + }(Shape); // Define morphable array + Path.prototype.MorphArray = PathArray; // Add parent method - transforms = _objectSpread({}, newTransforms, { - origin: origin - }); + registerMethods({ + Container: { + // Create a wrapped path element + path: function path(d) { + // make sure plot is called as a setter + return this.put(new Path()).plot(d || new PathArray()); } + } + }); + register(Path); - this.queue(setup, run, retarget); - this._isDeclarative && this._rememberMorpher('transform', morpher); - return this; - }, - // Animatable x-axis - x: function x(_x, relative) { - return this._queueNumber('x', _x); - }, - // Animatable y-axis - y: function y(_y) { - return this._queueNumber('y', _y); - }, - dx: function dx(x) { - return this._queueNumberDelta('dx', x); - }, - dy: function dy(y) { - return this._queueNumberDelta('dy', y); - }, - _queueNumberDelta: function _queueNumberDelta(method, to) { - to = new SVGNumber(to); // Try to change the target if we have this method already registerd + function array() { + return this._array || (this._array = new PointArray(this.attr('points'))); + } // Plot new path - if (this._tryRetargetDelta(method, to)) return this; // Make a morpher and queue the animation + function plot(p) { + return p == null ? this.array() : this.clear().attr('points', typeof p === 'string' ? p : this._array = new PointArray(p)); + } // Clear array cache - var morpher = new Morphable(this._stepper).to(to); - this.queue(function () { - var from = this.element()[method](); - morpher.from(from); - morpher.to(from + to); - }, function (pos) { - this.element()[method](morpher.at(pos)); - return morpher.done(); - }); // Register the morpher so that if it is changed again, we can retarget it + function clear() { + delete this._array; + return this; + } // Move by left top corner - this._rememberMorpher(method, morpher); + function move(x, y) { + return this.attr('points', this.array().move(x, y)); + } // Set element size to given width and height - return this; - }, - _queueObject: function _queueObject(method, to) { - // Try to change the target if we have this method already registerd - if (this._tryRetarget(method, to)) return this; // Make a morpher and queue the animation + function size$1(width, height) { + var p = proportionalSize(this, width, height); + return this.attr('points', this.array().size(p.width, p.height)); + } - var morpher = new Morphable(this._stepper).to(to); - this.queue(function () { - morpher.from(this.element()[method]()); - }, function (pos) { - this.element()[method](morpher.at(pos)); - return morpher.done(); - }); // Register the morpher so that if it is changed again, we can retarget it + var poly = /*#__PURE__*/Object.freeze({ + array: array, + plot: plot, + clear: clear, + move: move, + size: size$1 + }); - this._rememberMorpher(method, morpher); + var Polygon = + /*#__PURE__*/ + function (_Shape) { + _inherits(Polygon, _Shape); - return this; - }, - _queueNumber: function _queueNumber(method, value) { - return this._queueObject(method, new SVGNumber(value)); - }, - // Animatable center x-axis - cx: function cx(x) { - return this._queueNumber('cx', x); - }, - // Animatable center y-axis - cy: function cy(y) { - return this._queueNumber('cy', y); - }, - // Add animatable move - move: function move(x, y) { - return this.x(x).y(y); - }, - // Add animatable center - center: function center(x, y) { - return this.cx(x).cy(y); - }, - // Add animatable size - size: function size(width, height) { - // animate bbox based size for all other elements - var box; + // Initialize node + function Polygon(node) { + _classCallCheck(this, Polygon); - if (!width || !height) { - box = this._element.bbox(); - } + return _possibleConstructorReturn(this, _getPrototypeOf(Polygon).call(this, nodeOrNew('polygon', node), Polygon)); + } - if (!width) { - width = box.width / box.height * height; + return Polygon; + }(Shape); + registerMethods({ + Container: { + // Create a wrapped polygon element + polygon: function polygon(p) { + // make sure plot is called as a setter + return this.put(new Polygon()).plot(p || new PointArray()); } + } + }); + extend(Polygon, pointed); + extend(Polygon, poly); + register(Polygon); - if (!height) { - height = box.height / box.width * width; - } + var Polyline = + /*#__PURE__*/ + function (_Shape) { + _inherits(Polyline, _Shape); - return this.width(width).height(height); - }, - // Add animatable width - width: function width(_width) { - return this._queueNumber('width', _width); - }, - // Add animatable height - height: function height(_height) { - return this._queueNumber('height', _height); - }, - // Add animatable plot - plot: function plot(a, b, c, d) { - // Lines can be plotted with 4 arguments - if (arguments.length === 4) { - return this.plot([a, b, c, d]); - } // FIXME: this needs to be rewritten such that the element is only accesed - // in the init function + // Initialize node + function Polyline(node) { + _classCallCheck(this, Polyline); + return _possibleConstructorReturn(this, _getPrototypeOf(Polyline).call(this, nodeOrNew('polyline', node), Polyline)); + } - return this._queueObject('plot', new this._element.MorphArray(a)); - /* - var morpher = this._element.morphArray().to(a) - this.queue(function () { - morpher.from(this._element.array()) - }, function (pos) { - this._element.plot(morpher.at(pos)) - }) - return this - */ - }, - // Add leading method - leading: function leading(value) { - return this._queueNumber('leading', value); - }, - // Add animatable viewbox - viewbox: function viewbox(x, y, width, height) { - return this._queueObject('viewbox', new Box(x, y, width, height)); - }, - update: function update(o) { - if (_typeof(o) !== 'object') { - return this.update({ - offset: arguments[0], - color: arguments[1], - opacity: arguments[2] - }); + return Polyline; + }(Shape); + registerMethods({ + Container: { + // Create a wrapped polygon element + polyline: function polyline(p) { + // make sure plot is called as a setter + return this.put(new Polyline()).plot(p || new PointArray()); } - - 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', o.offset); - return this; } }); + extend(Polyline, pointed); + extend(Polyline, poly); + register(Polyline); + + var Rect = + /*#__PURE__*/ + function (_Shape) { + _inherits(Rect, _Shape); + + // Initialize node + function Rect(node) { + _classCallCheck(this, Rect); + + return _possibleConstructorReturn(this, _getPrototypeOf(Rect).call(this, nodeOrNew('rect', node), Rect)); + } // FIXME: unify with circle + // Radius x value - var _Symbol = - /*#__PURE__*/ - function (_Container) { - _inherits(_Symbol, _Container); - // Initialize node - function _Symbol(node) { - _classCallCheck(this, _Symbol); + _createClass(Rect, [{ + key: "rx", + value: function rx(_rx) { + return this.attr('rx', _rx); + } // Radius y value - return _possibleConstructorReturn(this, _getPrototypeOf(_Symbol).call(this, nodeOrNew('symbol', node), _Symbol)); - } + }, { + key: "ry", + value: function ry(_ry) { + return this.attr('ry', _ry); + } + }]); - return _Symbol; - }(Container); + return Rect; + }(Shape); registerMethods({ Container: { - symbol: function symbol() { - return this.put(new _Symbol()); + // Create a rect element + rect: function rect(width, height) { + return this.put(new Rect()).size(width, height); } } }); - register(_Symbol); + register(Rect); // Create plain text node function plain(text) { @@ -6119,92 +6247,6 @@ var SVG = (function () { }); register(Text); - var TextPath = - /*#__PURE__*/ - function (_Text) { - _inherits(TextPath, _Text); - - // Initialize node - function TextPath(node) { - _classCallCheck(this, TextPath); - - return _possibleConstructorReturn(this, _getPrototypeOf(TextPath).call(this, nodeOrNew('textPath', node), TextPath)); - } // return the array of the path track element - - - _createClass(TextPath, [{ - key: "array", - value: function array() { - var track = this.track(); - return track ? track.array() : null; - } // Plot path if any - - }, { - key: "plot", - value: function plot(d) { - var track = this.track(); - var pathArray = null; - - if (track) { - pathArray = track.plot(d); - } - - return d == null ? pathArray : this; - } // Get the path element - - }, { - key: "track", - value: function track() { - return this.reference('href'); - } - }]); - - return TextPath; - }(Text); - registerMethods({ - Container: { - textPath: function textPath(text, path) { - return this.defs().path(path).text(text).addTo(this); - } - }, - Text: { - // Create path for text to run on - path: function path(track) { - var path = new TextPath(); // if d is a path, reuse it - - if (!(track instanceof Path)) { - // create path element - track = this.doc().defs().path(track); - } // link textPath to path and add content - - - path.attr('href', '#' + track, xlink); // add textPath element as child node and return textPath - - return this.put(path); - }, - // FIXME: make this plural? - // Get the textPath children - textPath: function textPath() { - return this.find('textPath'); - } - }, - Path: { - // creates a textPath from this path - text: function text(_text) { - if (_text instanceof Text) { - var txt = _text.text(); - - return _text.clear().path(this).text(txt); - } - - return this.parent().put(new Text()).path(this).text(_text); - } // FIXME: Maybe add `targets` to get all textPaths associated with this path - - } - }); - TextPath.prototype.MorphArray = PathArray; - register(TextPath); - var Tspan = /*#__PURE__*/ function (_Text) { @@ -6242,646 +6284,521 @@ var SVG = (function () { key: "newLine", value: function newLine() { // fetch text parent - 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 Tspan; - }(Text); - extend(Tspan, textable); - registerMethods({ - Tspan: { - tspan: function tspan(text) { - var tspan = new Tspan(); // clear if build mode is disabled - - if (!this._build) { - this.clear(); - } // add new tspan - - - this.node.appendChild(tspan.node); - return tspan.text(text); - } - } - }); - register(Tspan); - - var Use = - /*#__PURE__*/ - function (_Shape) { - _inherits(Use, _Shape); - - function Use(node) { - _classCallCheck(this, Use); - - return _possibleConstructorReturn(this, _getPrototypeOf(Use).call(this, nodeOrNew('use', node), Use)); - } // Use element as a reference - - - _createClass(Use, [{ - key: "element", - value: function element(_element, file) { - // Set lined element - return this.attr('href', (file || '') + '#' + _element, xlink); - } - }]); - - return Use; - }(Shape); - registerMethods({ - Container: { - // Create a use element - use: function use(element, file) { - return this.put(new Use()).element(element, file); - } - } - }); - register(Use); - - - - var Classes = /*#__PURE__*/Object.freeze({ - Animator: Animator, - SVGArray: SVGArray, - Bare: Bare, - Box: Box, - Circle: Circle, - ClipPath: ClipPath, - Color: Color, - Container: Container, - Controller: Controller, - Ease: Ease, - PID: PID, - Spring: Spring, - Defs: Defs, - Doc: Doc$1, - Dom: Dom, - Element: Element, - Ellipse: Ellipse, - EventTarget: EventTarget, - Gradient: Gradient, - G: G, - HtmlNode: HtmlNode, - A: A, - Image: Image, - Line: Line, - Marker: Marker, - Mask: Mask, - Matrix: Matrix, - Morphable: Morphable, - SVGNumber: SVGNumber, - Path: Path, - PathArray: PathArray, - Pattern: Pattern, - Point: Point, - PointArray: PointArray, - Polygon: Polygon, - Polyline: Polyline, - Queue: Queue, - Rect: Rect, - Runner: Runner, - Shape: Shape, - Stop: Stop, - Symbol: _Symbol, - Text: Text, - TextPath: TextPath, - Timeline: Timeline, - Tspan: Tspan, - Use: Use - }); - - // ### This module adds backward / forward functionality to elements. - - function siblings() { - return this.parent().children(); - } // Get the curent position siblings - - function position() { - return this.parent().index(this); - } // Get the next element (will return null if there is none) - - function next() { - return this.siblings()[this.position() + 1]; - } // Get the next element (will return null if there is none) - - function prev() { - return this.siblings()[this.position() - 1]; - } // Send given element one step forward - - function forward() { - var i = this.position() + 1; - 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); - } - - return this; - } // Send given element one step backward + var t = this.parent(Text); // mark new line - function backward() { - var i = this.position(); + this.dom.newLined = true; // apply new position - if (i > 0) { - this.parent().removeElement(this).add(this, i - 1); - } + return this.dy(t.dom.leading * t.attr('font-size')).attr('x', t.x()); + } + }]); - return this; - } // Send given element all the way to the front + return Tspan; + }(Text); + extend(Tspan, textable); + registerMethods({ + Tspan: { + tspan: function tspan(text) { + var tspan = new Tspan(); // clear if build mode is disabled - function front() { - var p = this.parent(); // Move node forward + if (!this._build) { + this.clear(); + } // add new tspan - p.node.appendChild(this.node); // Make sure defs node is always at the top - if (typeof p.isRoot === 'function' && p.isRoot()) { - p.node.appendChild(p.defs().node); + this.node.appendChild(tspan.node); + return tspan.text(text); + } } + }); + register(Tspan); - return this; - } // Send given element all the way to the back + var Bare = + /*#__PURE__*/ + function (_Container) { + _inherits(Bare, _Container); - function back() { - if (this.position() > 0) { - this.parent().removeElement(this).add(this, 0); - } + function Bare(node) { + _classCallCheck(this, Bare); - return this; - } // Inserts a given element before the targeted element + return _possibleConstructorReturn(this, _getPrototypeOf(Bare).call(this, nodeOrNew(node, typeof node === 'string' ? null : node), Bare)); + } - function before(element) { - element.remove(); - var i = this.position(); - this.parent().add(element, i); - return this; - } // Inserts a given element after the targeted element + _createClass(Bare, [{ + key: "words", + value: function words(text) { + // remove contents + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild); + } // create text node - function after(element) { - element.remove(); - var i = this.position(); - this.parent().add(element, i + 1); - return this; - } - registerMethods('Dom', { - siblings: siblings, - position: position, - next: next, - prev: prev, - forward: forward, - backward: backward, - front: front, - back: back, - before: before, - after: after - }); - function data(a, v, r) { - if (_typeof(a) === 'object') { - for (v in a) { - this.data(v, a[v]); - } - } else if (arguments.length < 2) { - try { - return JSON.parse(this.attr('data-' + a)); - } catch (e) { - return this.attr('data-' + a); + this.node.appendChild(document.createTextNode(text)); + return this; } - } else { - this.attr('data-' + a, v === null ? null : r === true || typeof v === 'string' || typeof v === 'number' ? v : JSON.stringify(v)); - } + }]); - return this; - } - registerMethods('Dom', { - data: data + return Bare; + }(Container); + register(Bare); + registerMethods('Container', { + // Create an element that is not described by SVG.js + element: function element(node, inherit) { + return this.put(new Bare(node, inherit)); + } }); - function classes() { - var attr = this.attr('class'); - return attr == null ? [] : attr.trim().split(delimiter); - } // Return true if class exists on the node, false otherwise + var ClipPath = + /*#__PURE__*/ + function (_Container) { + _inherits(ClipPath, _Container); + function ClipPath(node) { + _classCallCheck(this, ClipPath); - function hasClass(name) { - return this.classes().indexOf(name) !== -1; - } // Add class to the node + return _possibleConstructorReturn(this, _getPrototypeOf(ClipPath).call(this, nodeOrNew('clipPath', node), ClipPath)); + } // Unclip all clipped elements and remove itself - function addClass(name) { - if (!this.hasClass(name)) { - var array = this.classes(); - array.push(name); - this.attr('class', array.join(' ')); - } + _createClass(ClipPath, [{ + key: "remove", + value: function remove() { + // unclip all targets + this.targets().forEach(function (el) { + el.unclip(); + }); // remove clipPath from parent - return this; - } // Remove class from the node + return _get(_getPrototypeOf(ClipPath.prototype), "remove", this).call(this); + } + }, { + key: "targets", + value: function targets() { + return baseFind('svg [clip-path*="' + this.id() + '"]'); + } + }]); + return ClipPath; + }(Container); + registerMethods({ + Container: { + // Create clipping element + clip: function clip() { + return this.defs().put(new ClipPath()); + } + }, + Element: { + // Distribute clipPath to svg element + clipWith: function clipWith(element) { + // use given clip or create a new one + var clipper = element instanceof ClipPath ? element : this.parent().clip().add(element); // apply mask - function removeClass(name) { - if (this.hasClass(name)) { - this.attr('class', this.classes().filter(function (c) { - return c !== name; - }).join(' ')); + return this.attr('clip-path', 'url("#' + clipper.id() + '")'); + }, + // Unclip element + unclip: function unclip() { + return this.attr('clip-path', null); + }, + clipper: function clipper() { + return this.reference('clip-path'); + } } + }); + register(ClipPath); - return this; - } // Toggle the presence of a class on the node + var G = + /*#__PURE__*/ + function (_Container) { + _inherits(G, _Container); + function G(node) { + _classCallCheck(this, G); - function toggleClass(name) { - return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); - } + return _possibleConstructorReturn(this, _getPrototypeOf(G).call(this, nodeOrNew('g', node), G)); + } - registerMethods('Dom', { - classes: classes, - hasClass: hasClass, - addClass: addClass, - removeClass: removeClass, - toggleClass: toggleClass + return G; + }(Container); + registerMethods({ + Element: { + // Create a group element + group: function group() { + return this.put(new G()); + } + } }); + register(G); - // Dynamic style generator + var HtmlNode = + /*#__PURE__*/ + function (_Dom) { + _inherits(HtmlNode, _Dom); - function css(style, val) { - var ret = {}; + function HtmlNode(node) { + _classCallCheck(this, HtmlNode); - if (arguments.length === 0) { - // get full style as object - this.node.style.cssText.split(/\s*;\s*/).filter(function (el) { - return !!el.length; - }).forEach(function (el) { - var t = el.split(/\s*:\s*/); - ret[t[0]] = t[1]; - }); - return ret; + return _possibleConstructorReturn(this, _getPrototypeOf(HtmlNode).call(this, node, HtmlNode)); } - if (arguments.length < 2) { - // get style properties in the array - if (Array.isArray(style)) { - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; + return HtmlNode; + }(Dom); + register(HtmlNode); - try { - for (var _iterator = style[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var name = _step.value; - var cased = camelCase(name); - ret[cased] = this.node.style[cased]; - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } + var A = + /*#__PURE__*/ + function (_Container) { + _inherits(A, _Container); + + function A(node) { + _classCallCheck(this, A); - return ret; - } // get style for property + return _possibleConstructorReturn(this, _getPrototypeOf(A).call(this, nodeOrNew('a', node), A)); + } // Link url - if (typeof style === 'string') { - return this.node.style[camelCase(style)]; - } // set styles in object + _createClass(A, [{ + key: "to", + value: function to(url) { + return this.attr('href', url, xlink); + } // Link target attribute + }, { + key: "target", + value: function target(_target) { + return this.attr('target', _target); + } + }]); - if (_typeof(style) === 'object') { - for (var _name in style) { - // set empty string if null/undefined/'' was given - this.node.style[camelCase(_name)] = style[_name] == null || isBlank.test(style[_name]) ? '' : style[_name]; - } + return A; + }(Container); + registerMethods({ + Container: { + // Create a hyperlink element + link: function link(url) { + return this.put(new A()).to(url); } - } // set style for property + }, + Element: { + // Create a hyperlink element + linkTo: function linkTo(url) { + var link = new A(); + if (typeof url === 'function') { + url.call(link, link); + } else { + link.to(url); + } - if (arguments.length === 2) { - this.node.style[camelCase(style)] = val == null || isBlank.test(val) ? '' : val; + return this.parent().put(link).put(this); + } } + }); + register(A); - return this; - } // Show element + var Mask = + /*#__PURE__*/ + function (_Container) { + _inherits(Mask, _Container); - function show() { - return this.css('display', ''); - } // Hide element + // Initialize node + function Mask(node) { + _classCallCheck(this, Mask); - function hide() { - return this.css('display', 'none'); - } // Is element visible? + return _possibleConstructorReturn(this, _getPrototypeOf(Mask).call(this, nodeOrNew('mask', node), Mask)); + } // Unmask all masked elements and remove itself - function visible() { - return this.css('display') !== 'none'; - } - registerMethods('Dom', { - css: css, - show: show, - hide: hide, - visible: visible - }); - function untransform() { - return this.attr('transform', null); - } // merge the whole transformation chain into one matrix and returns it + _createClass(Mask, [{ + key: "remove", + value: function remove() { + // unmask all targets + this.targets().forEach(function (el) { + el.unmask(); + }); // remove mask from parent - function matrixify() { - var matrix = (this.attr('transform') || ''). // split transformations - split(transforms).slice(0, -1).map(function (str) { - // generate key => value pairs - var kv = str.trim().split('('); - return [kv[0], kv[1].split(delimiter).map(function (str) { - return parseFloat(str); - })]; - }).reverse() // merge every transformation into one matrix - .reduce(function (matrix, transform) { - if (transform[0] === 'matrix') { - return matrix.lmultiply(arrayToMatrix(transform[1])); + return _get(_getPrototypeOf(Mask.prototype), "remove", this).call(this); + } + }, { + key: "targets", + value: function targets() { + return baseFind('svg [mask*="' + this.id() + '"]'); } + }]); - return matrix[transform[0]].apply(matrix, transform[1]); - }, new Matrix()); - return matrix; - } // add an element to another parent without changing the visual representation on the screen + return Mask; + }(Container); + registerMethods({ + Container: { + mask: function mask() { + return this.defs().put(new Mask()); + } + }, + Element: { + // Distribute mask to svg element + maskWith: function maskWith(element) { + // use given mask or create a new one + var masker = element instanceof Mask ? element : this.parent().mask().add(element); // apply mask - function toParent(parent) { - if (this === parent) return this; - var ctm = this.screenCTM(); - var pCtm = parent.screenCTM().inverse(); - this.addTo(parent).untransform().transform(pCtm.multiply(ctm)); - return this; - } // same as above with parent equals root-svg + return this.attr('mask', 'url("#' + masker.id() + '")'); + }, + // Unmask element + unmask: function unmask() { + return this.attr('mask', null); + }, + masker: function masker() { + return this.reference('mask'); + } + } + }); + register(Mask); - function toDoc() { - return this.toParent(this.doc()); - } // Add transformations + var _Symbol = + /*#__PURE__*/ + function (_Container) { + _inherits(_Symbol, _Container); - function transform(o, relative) { - // Act as a getter if no object was passed - if (o == null || typeof o === 'string') { - var decomposed = new Matrix(this).decompose(); - return decomposed[o] || decomposed; + // Initialize node + function _Symbol(node) { + _classCallCheck(this, _Symbol); + + return _possibleConstructorReturn(this, _getPrototypeOf(_Symbol).call(this, nodeOrNew('symbol', node), _Symbol)); } - if (!isMatrixLike(o)) { - // Set the origin according to the defined transform - o = _objectSpread({}, o, { - origin: getOrigin(o, this) - }); - } // The user can pass a boolean, an Element or an Matrix or nothing + return _Symbol; + }(Container); + registerMethods({ + Container: { + symbol: function symbol() { + return this.put(new _Symbol()); + } + } + }); + register(_Symbol); + var TextPath = + /*#__PURE__*/ + function (_Text) { + _inherits(TextPath, _Text); - var cleanRelative = relative === true ? this : relative || false; - var result = new Matrix(cleanRelative).transform(o); - return this.attr('transform', result); - } - registerMethods('Element', { - untransform: untransform, - matrixify: matrixify, - toParent: toParent, - toDoc: toDoc, - transform: transform - }); + // Initialize node + function TextPath(node) { + _classCallCheck(this, TextPath); - // Remember arbitrary data + return _possibleConstructorReturn(this, _getPrototypeOf(TextPath).call(this, nodeOrNew('textPath', node), TextPath)); + } // return the array of the path track element - function remember(k, v) { - // remember every item in an object individually - if (_typeof(arguments[0]) === 'object') { - for (var key in k) { - this.remember(key, k[key]); - } - } else if (arguments.length === 1) { - // retrieve memory - return this.memory()[k]; - } else { - // store memory - this.memory()[k] = v; - } - return this; - } // Erase a given memory + _createClass(TextPath, [{ + key: "array", + value: function array() { + var track = this.track(); + return track ? track.array() : null; + } // Plot path if any - function forget() { - if (arguments.length === 0) { - this._memory = {}; - } else { - for (var i = arguments.length - 1; i >= 0; i--) { - delete this.memory()[arguments[i]]; - } - } + }, { + key: "plot", + value: function plot(d) { + var track = this.track(); + var pathArray = null; - return this; - } // return local memory object + if (track) { + pathArray = track.plot(d); + } - function memory() { - return this._memory = this._memory || {}; - } - registerMethods('Dom', { - remember: remember, - forget: forget, - memory: memory - }); + return d == null ? pathArray : this; + } // Get the path element + + }, { + key: "track", + value: function track() { + return this.reference('href'); + } + }]); + + return TextPath; + }(Text); + registerMethods({ + Container: { + textPath: function textPath(text, path) { + return this.defs().path(path).text(text).addTo(this); + } + }, + Text: { + // Create path for text to run on + path: function path(track) { + var path = new TextPath(); // if d is a path, reuse it - var sugar = { - stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], - fill: ['color', 'opacity', 'rule'], - prefix: function prefix(t, a) { - return a === 'color' ? t : t + '-' + a; - } // Add sugar for fill and stroke + if (!(track instanceof Path)) { + // create path element + track = this.doc().defs().path(track); + } // link textPath to path and add content - }; - ['fill', 'stroke'].forEach(function (m) { - var extension = {}; - var i; - extension[m] = function (o) { - if (typeof o === 'undefined') { - return this; + path.attr('href', '#' + track, xlink); // add textPath element as child node and return textPath + + return this.put(path); + }, + // FIXME: make this plural? + // Get the textPath children + textPath: function textPath() { + return this.find('textPath'); } + }, + Path: { + // creates a textPath from this path + text: function text(_text) { + if (_text instanceof Text) { + var txt = _text.text(); - if (typeof o === 'string' || Color.isRgb(o) || o instanceof Element) { - this.attr(m, o); - } else { - // set all attributes from sugar.fill and sugar.stroke list - for (i = sugar[m].length - 1; i >= 0; i--) { - if (o[sugar[m][i]] != null) { - this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]]); - } + return _text.clear().path(this).text(txt); } - } - return this; - }; + return this.parent().put(new Text()).path(this).text(_text); + } // FIXME: Maybe add `targets` to get all textPaths associated with this path - registerMethods(['Shape', 'Runner'], extension); + } }); - registerMethods(['Element', 'Runner'], { - // Let the user set the matrix directly - matrix: function matrix(mat, b, c, d, e, f) { - // Act as a getter - if (mat == null) { - return new Matrix(this); - } // Act as a setter, the user can pass a matrix or a set of numbers + TextPath.prototype.MorphArray = PathArray; + register(TextPath); + var Use = + /*#__PURE__*/ + function (_Shape) { + _inherits(Use, _Shape); - return this.attr('transform', new Matrix(mat, b, c, d, e, f)); - }, - // Map rotation to transform - rotate: function rotate(angle, cx, cy) { - return this.transform({ - rotate: angle, - ox: cx, - oy: cy - }, true); - }, - // Map skew to transform - skew: function skew(x, y, cx, cy) { - return arguments.length === 1 || arguments.length === 3 ? this.transform({ - skew: x, - ox: y, - oy: cx - }, true) : this.transform({ - skew: [x, y], - ox: cx, - oy: cy - }, true); - }, - shear: function shear(lam, cx, cy) { - return this.transform({ - shear: lam, - ox: cx, - oy: cy - }, true); - }, - // Map scale to transform - scale: function scale(x, y, cx, cy) { - return arguments.length === 1 || arguments.length === 3 ? this.transform({ - scale: x, - ox: y, - oy: cx - }, true) : this.transform({ - scale: [x, y], - ox: cx, - oy: cy - }, true); - }, - // Map translate to transform - translate: function translate(x, y) { - return this.transform({ - translate: [x, y] - }, true); - }, - // Map relative translations to transform - relative: function relative(x, y) { - return this.transform({ - relative: [x, y] - }, true); - }, - // Map flip to transform - flip: function flip(direction, around) { - var directionString = typeof direction === 'string' ? direction : isFinite(direction) ? 'both' : 'both'; - var origin = direction === 'both' && isFinite(around) ? [around, around] : direction === 'x' ? [around, 0] : direction === 'y' ? [0, around] : isFinite(direction) ? [direction, direction] : [0, 0]; - this.transform({ - flip: directionString, - origin: origin - }, true); - }, - // Opacity - opacity: function opacity(value) { - return this.attr('opacity', value); - }, - // Relative move over x axis - dx: function dx(x) { - return this.x(new SVGNumber(x).plus(this instanceof Runner ? 0 : this.x()), true); - }, - // Relative move over y axis - dy: function dy(y) { - return this.y(new SVGNumber(y).plus(this instanceof Runner ? 0 : this.y()), true); - }, - // Relative move over x and y axes - dmove: function dmove(x, y) { - return this.dx(x).dy(y); - } - }); - registerMethods('radius', { - // Add x and y radius - radius: function radius(x, y) { - var type = (this._element || this).type; - return type === 'radialGradient' || type === 'radialGradient' ? this.attr('r', new SVGNumber(x)) : this.rx(x).ry(y == null ? x : y); - } - }); - registerMethods('Path', { - // Get path length - length: function length() { - return this.node.getTotalLength(); - }, - // Get point at length - pointAt: function pointAt(length) { - return new Point(this.node.getPointAtLength(length)); - } - }); - registerMethods(['Element', 'Runner'], { - // Set font - font: function font(a, v) { - if (_typeof(a) === 'object') { - for (v in a) { - this.font(v, a[v]); - } + function Use(node) { + _classCallCheck(this, Use); + + return _possibleConstructorReturn(this, _getPrototypeOf(Use).call(this, nodeOrNew('use', node), Use)); + } // Use element as a reference + + + _createClass(Use, [{ + key: "element", + value: function element(_element, file) { + // Set lined element + return this.attr('href', (file || '') + '#' + _element, xlink); } + }]); - return a === 'leading' ? this.leading(v) : a === 'anchor' ? this.attr('text-anchor', v) : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style' ? this.attr('font-' + a, v) : this.attr(a, v); + return Use; + }(Shape); + registerMethods({ + Container: { + // Create a use element + use: function use(element, file) { + return this.put(new Use()).element(element, file); + } } }); + register(Use); - var extend$1 = extend; - extend$1([Doc$1, _Symbol, Image, Pattern, Marker], getMethodsFor('viewbox')); - extend$1([Line, Polyline, Polygon, Path], getMethodsFor('marker')); - extend$1(Text, getMethodsFor('Text')); - extend$1(Path, getMethodsFor('Path')); - extend$1(Defs, getMethodsFor('Defs')); - extend$1([Text, Tspan], getMethodsFor('Tspan')); - extend$1([Rect, Ellipse, Circle, Gradient], getMethodsFor('radius')); - extend$1(EventTarget, getMethodsFor('EventTarget')); - extend$1(Dom, getMethodsFor('Dom')); - extend$1(Element, getMethodsFor('Element')); - extend$1(Shape, getMethodsFor('Shape')); // extend(Classes.Element, getConstructor('Memory')) - - extend$1(Container, getMethodsFor('Container')); + /* Optional Modules */ + extend([Doc$1, Symbol, Image, Pattern, Marker], getMethodsFor('viewbox')); + extend([Line, Polyline, Polygon, Path], getMethodsFor('marker')); + extend(Text, getMethodsFor('Text')); + extend(Path, getMethodsFor('Path')); + extend(Defs, getMethodsFor('Defs')); + extend([Text, Tspan], getMethodsFor('Tspan')); + extend([Rect, Ellipse, Circle, Gradient], getMethodsFor('radius')); + extend(EventTarget, getMethodsFor('EventTarget')); + extend(Dom, getMethodsFor('Dom')); + extend(Element, getMethodsFor('Element')); + extend(Shape, getMethodsFor('Shape')); // extend(Element, getConstructor('Memory')) + + extend(Container, getMethodsFor('Container')); registerMorphableType([SVGNumber, Color, Box, Matrix, SVGArray, PointArray, PathArray]); - makeMorphable(); // The main wrapping element + makeMorphable(); + + var svgMembers = /*#__PURE__*/Object.freeze({ + Morphable: Morphable, + registerMorphableType: registerMorphableType, + makeMorphable: makeMorphable, + TransformBag: TransformBag, + ObjectBag: ObjectBag, + NonMorphable: NonMorphable, + defaults: defaults, + parser: parser, + find: baseFind, + Animator: Animator, + Controller: Controller, + Ease: Ease, + PID: PID, + Spring: Spring, + easing: easing, + Queue: Queue, + Runner: Runner, + Timeline: Timeline, + SVGArray: SVGArray, + Box: Box, + Color: Color, + EventTarget: EventTarget, + Matrix: Matrix, + SVGNumber: SVGNumber, + PathArray: PathArray, + Point: Point, + PointArray: PointArray, + Bare: Bare, + Circle: Circle, + ClipPath: ClipPath, + Container: Container, + Defs: Defs, + Doc: Doc$1, + Dom: Dom, + Element: Element, + Ellipse: Ellipse, + Gradient: Gradient, + G: G, + HtmlNode: HtmlNode, + A: A, + Image: Image, + Line: Line, + Marker: Marker, + Mask: Mask, + Path: Path, + Pattern: Pattern, + Polygon: Polygon, + Polyline: Polyline, + Rect: Rect, + Shape: Shape, + Stop: Stop, + Symbol: _Symbol, + Text: Text, + TextPath: TextPath, + Tspan: Tspan, + Use: Use, + map: map, + filter: filter, + radians: radians, + degrees: degrees, + camelCase: camelCase, + capitalize: capitalize, + proportionalSize: proportionalSize, + getOrigin: getOrigin, + ns: ns, + xmlns: xmlns, + xlink: xlink, + svgjs: svgjs, + on: on, + off: off, + dispatch: dispatch, + root: root, + makeNode: makeNode, + makeInstance: makeInstance, + nodeOrNew: nodeOrNew, + adopt: adopt, + register: register, + getClass: getClass, + eid: eid, + assignNewId: assignNewId, + extend: extend + }); function SVG(element) { return makeInstance(element); } - Object.assign(SVG, Classes); - Object.assign(SVG, tools); - Object.assign(SVG, adopter); - SVG.utils = utils; + Object.assign(SVG, svgMembers); + SVG.utils = SVG; SVG.regex = regex; SVG.get = SVG; - SVG.find = baseFind; - Object.assign(SVG, ns$1); - SVG.easing = easing; - Object.assign(SVG, events); - SVG.TransformBag = TransformBag; - SVG.ObjectBag = ObjectBag; - SVG.NonMorphable = NonMorphable; - SVG.parser = parser; - SVG.defaults = defaults; return SVG; diff --git a/dist/svg.min.js b/dist/svg.min.js index 001199b..d7c90c1 100644 --- a/dist/svg.min.js +++ b/dist/svg.min.js @@ -1 +1 @@ -var SVG=function(){"use strict";function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;n=e.time?e.run():d.timeouts.push(e),e!==n););for(var i=null,r=d.frames.last();i!==r&&(i=d.frames.shift());)i.run();d.transforms.forEach(function(t){t()}),d.nextDraw=d.timeouts.first()||d.frames.first()?window.requestAnimationFrame(d._draw):null}},v=/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,y=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,p=/rgb\((\d+),(\d+),(\d+)\)/,m=/(#[a-z0-9\-_]+)/i,e=/\)\s*,?\s*/,g=/\s/g,w=/^#[a-f0-9]{3,6}$/i,k=/^rgb\(/,b=/^(\s+)?$/,x=/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,A=/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,C=/[\s,]+/,j=/([^e])-/gi,M=/[MLHVCSQTAZ]/gi,S=/[MLHVCSQTAZ]/i,T=/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,E=/\./g,N=Object.freeze({numberAndUnit:v,hex:y,rgb:p,reference:m,transforms:e,whitespace:g,isHex:w,isRgb:k,isCss:/[^:]+:[^;]+;?/,isBlank:b,isNumber:x,isPercent:/^-?[\d.]+%$/,isImage:A,delimiter:C,hyphen:j,pathLetters:M,isPathLetter:S,numbersWithDots:T,dots:E}),D=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1",delay:0},Mt={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},St=Object.freeze({noop:Ct,timeline:jt,attrs:Mt}),Tt=function(){function t(){o(this,t),this.init.apply(this,arguments)}return a(t,[{key:"init",value:function(t,e,n){var i,r;(this.r=0,this.g=0,this.b=0,t)&&("string"==typeof t?k.test(t)?(i=p.exec(t.replace(g,"")),this.r=parseInt(i[1]),this.g=parseInt(i[2]),this.b=parseInt(i[3])):w.test(t)&&(i=y.exec(4===(r=t).length?["#",r.substring(1,2),r.substring(1,2),r.substring(2,3),r.substring(2,3),r.substring(3,4),r.substring(3,4)].join(""):r),this.r=parseInt(i[1],16),this.g=parseInt(i[2],16),this.b=parseInt(i[3],16)):Array.isArray(t)?(this.r=t[0],this.g=t[1],this.b=t[2]):"object"===l(t)?(this.r=t.r,this.g=t.g,this.b=t.b):3===arguments.length&&(this.r=t,this.g=e,this.b=n))}},{key:"toString",value:function(){return this.toHex()}},{key:"toArray",value:function(){return[this.r,this.g,this.b]}},{key:"toHex",value:function(){return"#"+H(Math.round(this.r))+H(Math.round(this.g))+H(Math.round(this.b))}},{key:"toRgb",value:function(){return"rgb("+[this.r,this.g,this.b].join()+")"}},{key:"brightness",value:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11}}],[{key:"test",value:function(t){return t+="",w.test(t)||k.test(t)}},{key:"isRgb",value:function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}},{key:"isColor",value:function(t){return this.isRgb(t)||this.test(t)}}]),t}();var Et=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this,t))).node=t,e.type=t.nodeName,e}return r(n,xt),a(n,[{key:"add",value:function(t,e){return t=Z(t),null==e?this.node.appendChild(t.node):t.node!==this.node.childNodes[e]&&this.node.insertBefore(t.node,this.node.childNodes[e]),this}},{key:"addTo",value:function(t){return Z(t).put(this)}},{key:"children",value:function(){return _t(this.node.children,function(t){return K(t)})}},{key:"clear",value:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return delete this._defs,this}},{key:"clone",value:function(t){this.writeDataToDom();var e=rt(this.node.cloneNode(!0));return t?t.add(e):this.after(e),e}},{key:"each",value:function(t,e){var n,i,r=this.children();for(n=0,i=r.length;nn.x&&e>n.y&&t":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},ie=function(){function t(){o(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),re=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).ease=ne[t||jt.ease]||t,e}return r(n,ie),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),se=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).stepper=t,e}return r(n,ie),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function ue(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var oe=function(t){function i(t,e){var n;return o(this,i),(n=h(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,se),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100i;this._lastTime=this._time,r&&this.fire("start",this);var u=this._isDeclarative;if(this.done=!u&&!s&&this._time>=i,n||u){this._initialise(n),this.transforms=new Oe;var o=this._run(u?t:e);this.fire("step",this)}return this.done=this.done||o&&u,this.done&&this.fire("finish",this),this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new re(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e",delay:0},vt={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"},yt=Object.freeze({noop:ft,timeline:dt,attrs:vt}),pt=function(){try{return Function("name","baseClass","_constructor",["baseClass = baseClass || Array","return {","[name]: class extends baseClass {","constructor (...args) {","super(...args)","_constructor && _constructor.apply(this, args)","}","}","}[name]"].join("\n"))}catch(t){return function(t){var e=1n.x&&e>n.y&&t":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,n,i){return function(t){}}},Nt=function(){function t(){o(this,t)}return a(t,[{key:"done",value:function(){return!1}}]),t}(),Dt=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).ease=Et[t||dt.ease]||t,e}return r(n,Nt),a(n,[{key:"step",value:function(t,e,n){return"number"!=typeof t?n<1?t:e:t+(e-t)*this.ease(n)}}]),n}(),Pt=function(t){function n(t){var e;return o(this,n),(e=h(this,u(n).call(this))).stepper=t,e}return r(n,Nt),a(n,[{key:"step",value:function(t,e,n,i){return this.stepper(t,e,n,i)}},{key:"done",value:function(t){return t.done}}]),n}();function zt(){var t=(this._duration||500)/1e3,e=this._overshoot||0,n=Math.PI,i=Math.log(e/100+1e-10),r=-i/Math.sqrt(n*n+i*i),s=3.9/(r*t);this.d=2*r*s,this.k=s*s}var Rt=function(t){function i(t,e){var n;return o(this,i),(n=h(this,u(i).call(this))).duration(t||500).overshoot(e||0),n}return r(i,Pt),a(i,[{key:"step",value:function(t,e,n,i){if("string"==typeof t)return t;if(i.done=n===1/0,n===1/0)return e;if(0===n)return t;100=e.time?e.run():It.timeouts.push(e),e!==n););for(var i=null,r=It.frames.last();i!==r&&(i=It.frames.shift());)i.run();It.transforms.forEach(function(t){t()}),It.nextDraw=It.timeouts.first()||It.frames.first()?window.requestAnimationFrame(It._draw):null}};function Ft(t){return!(t.w||t.h||t.x||t.y)}var Xt=function(){function u(){o(this,u),this.init.apply(this,arguments)}return a(u,[{key:"init",value:function(t){t="string"==typeof t?t.split(C).map(parseFloat):Array.isArray(t)?t:"object"===l(t)?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):[0,0,0,0],this.x=t[0]||0,this.y=t[1]||0,this.width=this.w=t[2]||0,this.height=this.h=t[3]||0,this.x2=this.x+this.w,this.y2=this.y+this.h,this.cx=this.x+this.w/2,this.cy=this.y+this.h/2}},{key:"merge",value:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new u(e,n,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-n)}},{key:"transform",value:function(e){var n=1/0,i=-1/0,r=1/0,s=-1/0;return[new Mt(this.x,this.y),new Mt(this.x2,this.y),new Mt(this.x,this.y2),new Mt(this.x2,this.y2)].forEach(function(t){t=t.transform(e),n=Math.min(n,t.x),i=Math.max(i,t.x),r=Math.min(r,t.y),s=Math.max(s,t.y)}),new u(n,r,i-n,s-r)}},{key:"addOffset",value:function(){return this.x+=window.pageXOffset,this.y+=window.pageYOffset,this}},{key:"toString",value:function(){return this.x+" "+this.y+" "+this.width+" "+this.height}},{key:"toArray",value:function(){return[this.x,this.y,this.width,this.height]}},{key:"isNulled",value:function(){return Ft(this)}}]),u}();function Yt(e){var n,t;try{if(Ft(n=e(this.node))&&(t=this.node,!(document.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===document}).call(document.documentElement,t)))throw new Error("Element not in the dom")}catch(t){try{var i=this.clone(At().svg).show();n=e(i.node),i.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return n}v({Element:{bbox:function(){return new Xt(Yt.call(this,function(t){return t.getBBox()}))},rbox:function(t){var e=new Xt(Yt.call(this,function(t){return t.getBoundingClientRect()}));return t?e.transform(t.screenCTM().inverse()):e.addOffset()}},viewbox:{viewbox:function(t,e,n,i){return null==t?new Xt(this.attr("viewBox")):this.attr("viewBox",new Xt(t,e,n,i))}}});var Ht=pt("PathArray",mt);function Bt(t,e,n,i){return n+i.replace(N," .")}for(var Gt={M:function(t,e,n){return e.x=n.x=t[0],e.y=n.y=t[1],["M",e.x,e.y]},L:function(t,e){return e.x=t[0],e.y=t[1],["L",t[0],t[1]]},H:function(t,e){return e.x=t[0],["H",t[0]]},V:function(t,e){return e.y=t[0],["V",t[0]]},C:function(t,e){return e.x=t[4],e.y=t[5],["C",t[0],t[1],t[2],t[3],t[4],t[5]]},S:function(t,e){return e.x=t[2],e.y=t[3],["S",t[0],t[1],t[2],t[3]]},Q:function(t,e){return e.x=t[2],e.y=t[3],["Q",t[0],t[1],t[2],t[3]]},T:function(t,e){return e.x=t[0],e.y=t[1],["T",t[0],t[1]]},Z:function(t,e,n){return e.x=n.x,e.y=n.y,["Z"]},A:function(t,e){return e.x=t[5],e.y=t[6],["A",t[0],t[1],t[2],t[3],t[4],t[5],t[6]]}},Vt="mlhvqtcsaz".split(""),Qt=0,Ut=Vt.length;Qti;this._lastTime=this._time,r&&this.fire("start",this);var u=this._isDeclarative;if(this.done=!u&&!s&&this._time>=i,n||u){this._initialise(n),this.transforms=new St;var o=this._run(u?t:e);this.fire("step",this)}return this.done=this.done||o&&u,this.done&&this.fire("finish",this),this}},{key:"finish",value:function(){return this.step(1/0)}},{key:"reverse",value:function(t){return this._reverse=null==t?!this._reverse:t,this}},{key:"ease",value:function(t){return this._stepper=new Dt(t),this}},{key:"active",value:function(t){return null==t?this.enabled:(this.enabled=t,this)}},{key:"_rememberMorpher",value:function(t,e){this._history[t]={morpher:e,caller:this._queue[this._queue.length-1]}}},{key:"_tryRetarget",value:function(t,e){if(this._history[t]){if(!this._history[t].caller.initialised){var n=this._queue.indexOf(this._history[t].caller);return this._queue.splice(n,1),!1}this._history[t].caller.isTransform?this._history[t].caller.isTransform(e):this._history[t].morpher.to(e),this._history[t].caller.finished=!1;var i=this.timeline();return i&&i._continue(),!0}return!1}},{key:"_initialise",value:function(t){if(t||this._isDeclarative)for(var e=0,n=this._queue.length;e= nextTimeout.time) { - nextTimeout.run() - } else { - Animator.timeouts.push(nextTimeout) - } - - // If we hit the last item, we should stop shifting out more items - if (nextTimeout === lastTimeout) break - } - - // Run all of the animation frames - var nextFrame = null - var lastFrame = Animator.frames.last() - while ((nextFrame !== lastFrame) && (nextFrame = Animator.frames.shift())) { - nextFrame.run() - } - - Animator.transforms.forEach(function (el) { el() }) - - // If we have remaining timeouts or frames, draw until we don't anymore - Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() - ? window.requestAnimationFrame(Animator._draw) - : null - } -} - -export default Animator diff --git a/src/ArrayPolyfill.js b/src/ArrayPolyfill.js deleted file mode 100644 index cf95d54..0000000 --- a/src/ArrayPolyfill.js +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint no-new-func: "off" */ -export const subClassArray = (function () { - try { - // try es6 subclassing - return Function('name', 'baseClass', '_constructor', [ - 'baseClass = baseClass || Array', - 'return {', - '[name]: class extends baseClass {', - 'constructor (...args) {', - 'super(...args)', - '_constructor && _constructor.apply(this, args)', - '}', - '}', - '}[name]' - ].join('\n')) - } catch (e) { - // Use es5 approach - return (name, baseClass = Array, _constructor) => { - const Arr = function () { - baseClass.apply(this, arguments) - _constructor && _constructor.apply(this, arguments) - } - - Arr.prototype = Object.create(baseClass.prototype) - Arr.prototype.constructor = Arr - - return Arr - } - } -})() diff --git a/src/Bare.js b/src/Bare.js deleted file mode 100644 index 7b3be98..0000000 --- a/src/Bare.js +++ /dev/null @@ -1,31 +0,0 @@ -import { nodeOrNew } from './tools.js' -import { register } from './adopter.js' -import Container from './Container.js' -import { registerMethods } from './methods.js' - -export default class Bare extends Container { - constructor (node) { - super(nodeOrNew(node, typeof node === 'string' ? null : node), Bare) - } - - words (text) { - // remove contents - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) - } - - // create text node - this.node.appendChild(document.createTextNode(text)) - - return this - } -} - -register(Bare) - -registerMethods('Container', { - // Create an element that is not described by SVG.js - element (node, inherit) { - return this.put(new Bare(node, inherit)) - } -}) diff --git a/src/Base.js b/src/Base.js deleted file mode 100644 index d2897a1..0000000 --- a/src/Base.js +++ /dev/null @@ -1,10 +0,0 @@ -export default class Base { - // constructor (node/*, {extensions = []} */) { - // // this.tags = [] - // // - // // for (let extension of extensions) { - // // extension.setup.call(this, node) - // // this.tags.push(extension.name) - // // } - // } -} diff --git a/src/Box.js b/src/Box.js deleted file mode 100644 index 148beb3..0000000 --- a/src/Box.js +++ /dev/null @@ -1,127 +0,0 @@ -import Point from './Point.js' -import parser from './parser.js' -import { fullBox, domContains, isNulledBox } from './helpers.js' -import { delimiter } from './regex.js' -import { registerMethods } from './methods.js' - -export default class Box { - constructor (...args) { - this.init(...args) - } - - init (source) { - var base = [0, 0, 0, 0] - source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) - : Array.isArray(source) ? source - : typeof source === 'object' ? [source.left != null ? source.left - : source.x, source.top != null ? source.top : source.y, source.width, source.height] - : arguments.length === 4 ? [].slice.call(arguments) - : base - - this.x = source[0] - this.y = source[1] - this.width = source[2] - this.height = source[3] - - // add center, right, bottom... - fullBox(this) - } - - // Merge rect box with another, return a new instance - merge (box) { - let x = Math.min(this.x, box.x) - let y = Math.min(this.y, box.y) - let width = Math.max(this.x + this.width, box.x + box.width) - x - let height = Math.max(this.y + this.height, box.y + box.height) - y - - return new Box(x, y, width, height) - } - - transform (m) { - let xMin = Infinity - let xMax = -Infinity - let yMin = Infinity - let yMax = -Infinity - - let pts = [ - new Point(this.x, this.y), - new Point(this.x2, this.y), - new Point(this.x, this.y2), - new Point(this.x2, this.y2) - ] - - pts.forEach(function (p) { - p = p.transform(m) - xMin = Math.min(xMin, p.x) - xMax = Math.max(xMax, p.x) - yMin = Math.min(yMin, p.y) - yMax = Math.max(yMax, p.y) - }) - - return new Box( - xMin, yMin, - xMax - xMin, - yMax - yMin - ) - } - - addOffset () { - // offset by window scroll position, because getBoundingClientRect changes when window is scrolled - this.x += window.pageXOffset - this.y += window.pageYOffset - return this - } - - toString () { - return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height - } - - toArray () { - return [this.x, this.y, this.width, this.height] - } -} - -function getBox (cb) { - let box - - try { - box = cb(this.node) - - if (isNulledBox(box) && !domContains(this.node)) { - throw new Error('Element not in the dom') - } - } catch (e) { - try { - let clone = this.clone(parser().svg).show() - box = cb(clone.node) - clone.remove() - } catch (e) { - console.warn('Getting a bounding box of this element is not possible') - } - } - return box -} - -registerMethods({ - Element: { - // Get bounding box - bbox () { - return new Box(getBox.call(this, (node) => node.getBBox())) - }, - - rbox (el) { - let box = new Box(getBox.call(this, (node) => node.getBoundingClientRect())) - if (el) return box.transform(el.screenCTM().inverse()) - return box.addOffset() - } - }, - viewbox: { - viewbox (x, y, width, height) { - // act as getter - if (x == null) return new Box(this.attr('viewBox')) - - // act as setter - return this.attr('viewBox', new Box(x, y, width, height)) - } - } -}) diff --git a/src/Circle.js b/src/Circle.js deleted file mode 100644 index 8879eec..0000000 --- a/src/Circle.js +++ /dev/null @@ -1,41 +0,0 @@ -import Shape from './Shape.js' -import { nodeOrNew, extend } from './tools.js' -import { x, y, cx, cy, width, height, size } from './circled.js' -import SVGNumber from './SVGNumber.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Circle extends Shape { - constructor (node) { - super(nodeOrNew('circle', node), Circle) - } - - radius (r) { - return this.attr('r', r) - } - - // Radius x value - rx (rx) { - return this.attr('r', rx) - } - - // Alias radius x value - ry (ry) { - return this.rx(ry) - } -} - -extend(Circle, { x, y, cx, cy, width, height, size }) - -registerMethods({ - Element: { - // Create circle element - circle (size) { - return this.put(new Circle()) - .radius(new SVGNumber(size).divide(2)) - .move(0, 0) - } - } -}) - -register(Circle) diff --git a/src/ClipPath.js b/src/ClipPath.js deleted file mode 100644 index 953d5cf..0000000 --- a/src/ClipPath.js +++ /dev/null @@ -1,59 +0,0 @@ -import Container from './Container.js' -import { nodeOrNew } from './tools.js' -import find from './selector.js' -// import {remove} from './Element.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class ClipPath extends Container { - constructor (node) { - super(nodeOrNew('clipPath', node), ClipPath) - } - - // Unclip all clipped elements and remove itself - remove () { - // unclip all targets - this.targets().forEach(function (el) { - el.unclip() - }) - - // remove clipPath from parent - return super.remove() - } - - targets () { - return find('svg [clip-path*="' + this.id() + '"]') - } -} - -registerMethods({ - Container: { - // Create clipping element - clip: function () { - return this.defs().put(new ClipPath()) - } - }, - Element: { - // Distribute clipPath to svg element - clipWith (element) { - // use given clip or create a new one - let clipper = element instanceof ClipPath - ? element - : this.parent().clip().add(element) - - // apply mask - return this.attr('clip-path', 'url("#' + clipper.id() + '")') - }, - - // Unclip element - unclip () { - return this.attr('clip-path', null) - }, - - clipper () { - return this.reference('clip-path') - } - } -}) - -register(ClipPath) diff --git a/src/Color.js b/src/Color.js deleted file mode 100644 index ed3531c..0000000 --- a/src/Color.js +++ /dev/null @@ -1,130 +0,0 @@ -/* - -Color { - constructor (a, b, c, space) { - space: 'hsl' - a: 30 - b: 20 - c: 10 - }, - - toRgb () { return new Color in rgb space } - toHsl () { return new Color in hsl space } - toLab () { return new Color in lab space } - - toArray () { [space, a, b, c] } - fromArray () { convert it back } -} - -// Conversions aren't always exact because of monitor profiles etc... -new Color(h, s, l, 'hsl') !== new Color(r, g, b).hsl() -new Color(100, 100, 100, [space]) -new Color('hsl(30, 20, 10)') - -// Sugar -SVG.rgb(30, 20, 50).lab() -SVG.hsl() -SVG.lab('rgb(100, 100, 100)') -*/ - -import { isHex, isRgb, whitespace, rgb, hex } from './regex.js' -import { fullHex, compToHex } from './helpers.js' - -export default class Color { - constructor (...args) { - this.init(...args) - } - - init (color, g, b) { - let match - - // initialize defaults - this.r = 0 - this.g = 0 - this.b = 0 - - if (!color) return - - // parse color - if (typeof color === 'string') { - if (isRgb.test(color)) { - // get rgb values - match = rgb.exec(color.replace(whitespace, '')) - - // parse numeric values - this.r = parseInt(match[1]) - this.g = parseInt(match[2]) - this.b = parseInt(match[3]) - } else if (isHex.test(color)) { - // get hex values - match = hex.exec(fullHex(color)) - - // parse numeric values - this.r = parseInt(match[1], 16) - this.g = parseInt(match[2], 16) - this.b = parseInt(match[3], 16) - } - } else if (Array.isArray(color)) { - this.r = color[0] - this.g = color[1] - this.b = color[2] - } else if (typeof color === 'object') { - this.r = color.r - this.g = color.g - this.b = color.b - } else if (arguments.length === 3) { - this.r = color - this.g = g - this.b = b - } - } - - // Default to hex conversion - toString () { - return this.toHex() - } - - toArray () { - return [this.r, this.g, this.b] - } - - // Build hex value - toHex () { - return '#' + - compToHex(Math.round(this.r)) + - compToHex(Math.round(this.g)) + - compToHex(Math.round(this.b)) - } - - // Build rgb value - toRgb () { - return 'rgb(' + [this.r, this.g, this.b].join() + ')' - } - - // Calculate true brightness - brightness () { - return (this.r / 255 * 0.30) + - (this.g / 255 * 0.59) + - (this.b / 255 * 0.11) - } - - // Testers - - // Test if given value is a color string - static test (color) { - color += '' - return isHex.test(color) || isRgb.test(color) - } - - // Test if given value is a rgb object - static isRgb (color) { - return color && typeof color.r === 'number' && - typeof color.g === 'number' && - typeof color.b === 'number' - } - - // Test if given value is a color - static isColor (color) { - return this.isRgb(color) || this.test(color) - } -} diff --git a/src/Container.js b/src/Container.js deleted file mode 100644 index c45d805..0000000 --- a/src/Container.js +++ /dev/null @@ -1,26 +0,0 @@ -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) - }) - - // we need this so that Doc does not get removed - this.node.firstElementChild || this.remove() - - return this - } - - ungroup (parent) { - parent = parent || this.parent() - - this.each(function () { - return this.toParent(parent) - }) - - this.remove() - - return this - } -} diff --git a/src/Controller.js b/src/Controller.js deleted file mode 100644 index 0bf5ac0..0000000 --- a/src/Controller.js +++ /dev/null @@ -1,174 +0,0 @@ - -import { timeline } from './defaults.js' -import { extend } from './tools.js' - -/*** -Base Class -========== -The base stepper class that will be -***/ - -function makeSetterGetter (k, f) { - return function (v) { - if (v == null) return this[v] - this[k] = v - if (f) f.call(this) - return this - } -} - -export let easing = { - '-': function (pos) { return pos }, - '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, - '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, - '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }, - bezier: function (t0, x0, t1, x1) { - return function (t) { - // TODO: FINISH - } - } -} - -export class Stepper { - done () { return false } -} - -/*** -Easing Functions -================ -***/ - -export class Ease extends Stepper { - constructor (fn) { - super() - this.ease = easing[fn || timeline.ease] || fn - } - - step (from, to, pos) { - if (typeof from !== 'number') { - return pos < 1 ? from : to - } - return from + (to - from) * this.ease(pos) - } -} - -/*** -Controller Types -================ -***/ - -export class Controller extends Stepper { - constructor (fn) { - super() - this.stepper = fn - } - - step (current, target, dt, c) { - return this.stepper(current, target, dt, c) - } - - done (c) { - return c.done - } -} - -function recalculate () { - // Apply the default parameters - var duration = (this._duration || 500) / 1000 - var overshoot = this._overshoot || 0 - - // Calculate the PID natural response - var eps = 1e-10 - var pi = Math.PI - var os = Math.log(overshoot / 100 + eps) - var zeta = -os / Math.sqrt(pi * pi + os * os) - var wn = 3.9 / (zeta * duration) - - // Calculate the Spring values - this.d = 2 * zeta * wn - this.k = wn * wn -} - -export class Spring extends Controller { - constructor (duration, overshoot) { - super() - this.duration(duration || 500) - .overshoot(overshoot || 0) - } - - step (current, target, dt, c) { - if (typeof current === 'string') return current - c.done = dt === Infinity - if (dt === Infinity) return target - if (dt === 0) return current - - if (dt > 100) dt = 16 - - dt /= 1000 - - // Get the previous velocity - var velocity = c.velocity || 0 - - // Apply the control to get the new position and store it - var acceleration = -this.d * velocity - this.k * (current - target) - var newPosition = current + - velocity * dt + - acceleration * dt * dt / 2 - - // Store the velocity - c.velocity = velocity + acceleration * dt - - // Figure out if we have converged, and if so, pass the value - c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002 - return c.done ? target : newPosition - } -} - -extend(Spring, { - duration: makeSetterGetter('_duration', recalculate), - overshoot: makeSetterGetter('_overshoot', recalculate) -}) - -export class PID extends Controller { - constructor (p, i, d, windup) { - super() - - p = p == null ? 0.1 : p - i = i == null ? 0.01 : i - d = d == null ? 0 : d - windup = windup == null ? 1000 : windup - this.p(p).i(i).d(d).windup(windup) - } - - step (current, target, dt, c) { - if (typeof current === 'string') return current - c.done = dt === Infinity - - if (dt === Infinity) return target - if (dt === 0) return current - - var p = target - current - var i = (c.integral || 0) + p * dt - var d = (p - (c.error || 0)) / dt - var windup = this.windup - - // antiwindup - if (windup !== false) { - i = Math.max(-windup, Math.min(i, windup)) - } - - c.error = p - c.integral = i - - c.done = Math.abs(p) < 0.001 - - return c.done ? target : current + (this.P * p + this.I * i + this.D * d) - } -} - -extend(PID, { - windup: makeSetterGetter('windup'), - p: makeSetterGetter('P'), - i: makeSetterGetter('I'), - d: makeSetterGetter('D') -}) diff --git a/src/Defs.js b/src/Defs.js deleted file mode 100644 index ddcf733..0000000 --- a/src/Defs.js +++ /dev/null @@ -1,14 +0,0 @@ -import Container from './Container.js' -import { nodeOrNew } from './tools.js' -import { register } from './adopter.js' - -export default class Defs extends Container { - constructor (node) { - super(nodeOrNew('defs', node), Defs) - } - - flatten () { return this } - ungroup () { return this } -} - -register(Defs) diff --git a/src/Doc.js b/src/Doc.js deleted file mode 100644 index b44a122..0000000 --- a/src/Doc.js +++ /dev/null @@ -1,73 +0,0 @@ -import Container from './Container.js' -import Defs from './Defs.js' -import { nodeOrNew } from './tools.js' -import { ns, xlink, xmlns, svgjs } from './namespaces.js' -import { adopt, register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Doc extends Container { - constructor (node) { - super(nodeOrNew('svg', node), Doc) - this.namespace() - } - - isRoot () { - return !this.node.parentNode || - !(this.node.parentNode instanceof window.SVGElement) || - this.node.parentNode.nodeName === '#document' - } - - // Check if this is a root svg - // If not, call docs from this element - doc () { - if (this.isRoot()) return this - return super.doc() - } - - // Add namespaces - namespace () { - if (!this.isRoot()) return this.doc().namespace() - return this - .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.doc().defs() - - return adopt(this.node.getElementsByTagName('defs')[0]) || - this.put(new Defs()) - } - - // custom parent method - parent (type) { - if (this.isRoot()) { - return this.node.parentNode.nodeName === '#document' - ? null - : adopt(this.node.parentNode) - } - - return super.parent(type) - } - - clear () { - // remove children - while (this.node.hasChildNodes()) { - this.node.removeChild(this.node.lastChild) - } - return this - } -} - -registerMethods({ - Container: { - // Create nested svg document - nested () { - return this.put(new Doc()) - } - } -}) - -register(Doc, 'Doc', true) diff --git a/src/Dom.js b/src/Dom.js deleted file mode 100644 index 5c84308..0000000 --- a/src/Dom.js +++ /dev/null @@ -1,238 +0,0 @@ -import EventTarget from './EventTarget.js' -import { assignNewId, adopt, makeInstance, eid } from './adopter.js' -import { map } from './utils.js' -import { matcher } from './helpers.js' -import { ns } from './namespaces.js' - -import { extend } from './tools.js' -import attr from './attr.js' - -export default class Dom extends EventTarget { - constructor (node) { - super(node) - this.node = node - this.type = node.nodeName - } - - // Add given element at a position - 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]) - } - - return this - } - - // Add element to given container and return self - addTo (parent) { - return makeInstance(parent).put(this) - } - - // Returns all child elements - children () { - return 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) - } - - // remove defs reference - delete this._defs - - return this - } - - // Clone element - clone (parent) { - // write dom data to the dom so the clone can pickup the data - this.writeDataToDom() - - // clone element and assign new id - let clone = assignNewId(this.node.cloneNode(true)) - - // insert the clone in the given parent or after myself - if (parent) parent.add(clone) - // FIXME: after might not be available here - else this.after(clone) - - return clone - } - - // Iterates over all children and invokes a given block - 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]) - - if (deep) { - children[i].each(block, deep) - } - } - - return this - } - - // Get first child - first () { - return adopt(this.node.firstChild) - } - - // Get a element at the given index - 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 - } - - // Get / set id - id (id) { - // generate new id if no id set - 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) - } - - // Gets index of given element - index (element) { - return [].slice.call(this.node.childNodes).indexOf(element.node) - } - - // Get the last child - last () { - return adopt(this.node.lastChild) - } - - // matches the element vs a css selector - matches (selector) { - return matcher(this.node, selector) - } - - // Returns the svg node to call native svg methods on it - native () { - return this.node - } - - // Returns the parent element instance - parent (type) { - var parent = this - - // check for parent - if (!parent.node.parentNode) return null - - // get parent element - parent = adopt(parent.node.parentNode) - - if (!type) return parent - - // loop trough ancestors if type is given - while (parent && parent.node instanceof window.SVGElement) { - 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) - return element - } - - // Add element to given container and return container - putIn (parent) { - return makeInstance(parent).add(this) - } - - // Remove element - remove () { - if (this.parent()) { - this.parent().removeElement(this) - } - - return this - } - - // Remove a given child - removeElement (element) { - this.node.removeChild(element.node) - - return this - } - - // Replace element - replace (element) { - // FIXME: after() might not be available here - this.after(element).remove() - - return element - } - - // Return id on string conversion - toString () { - return this.id() - } - - // Import raw svg - svg (svg) { - var well, len - - // act as a setter if svg is given - if (svg) { - // create temporary holder - well = document.createElementNS(ns, 'svg') - // dump raw svg - well.innerHTML = svg - - // transplant nodes - for (len = well.children.length; len--;) { - this.node.appendChild(well.firstElementChild) - } - - // otherwise act as a getter - } else { - // write svgjs data to the dom - this.writeDataToDom() - - return this.node.outerHTML - } - - return this - } - - // write svgjs data to the dom - writeDataToDom () { - // dump variables recursively - this.each(function () { - this.writeDataToDom() - }) - - return this - } -} - -extend(Dom, { attr }) diff --git a/src/Element.js b/src/Element.js deleted file mode 100644 index 4c3dcf6..0000000 --- a/src/Element.js +++ /dev/null @@ -1,138 +0,0 @@ -import { proportionalSize, idFromReference } from './helpers.js' -import { makeInstance, root, getClass } from './adopter.js' -import SVGNumber from './SVGNumber.js' -import Dom from './Dom.js' - -const Doc = getClass(root) - -export default class Element extends Dom { - constructor (node) { - super(node) - - // initialize data object - this.dom = {} - - // create circular reference - this.node.instance = this - - 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')) || {}) - } - } - - // Move element by its center - 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) - } - - // Move by center over y-axis - cy (y) { - return y == null - ? this.y() + this.height() / 2 - : this.y(y - this.height() / 2) - } - - // Get defs - defs () { - return this.doc().defs() - } - - // Get parent document - doc () { - let p = this.parent(Doc) - return p && p.doc() - } - - getEventHolder () { - return this - } - - // Set height of element - height (height) { - return this.attr('height', height) - } - - // Checks whether the given point inside the bounding box of the element - inside (x, y) { - let box = this.bbox() - - 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) - } - - // return array of all ancestors of given type up to the root svg - parents (type) { - let parents = [] - let parent = this - - do { - parent = parent.parent(type) - if (!parent || parent instanceof getClass('HtmlNode')) break - - parents.push(parent) - } while (parent.parent) - - return parents - } - - // Get referenced element form attribute value - reference (attr) { - let id = idFromReference(this.attr(attr)) - return id ? makeInstance(id) : null - } - - // set given data to the elements data property - setData (o) { - this.dom = o - return this - } - - // Set element size to given width and height - size (width, height) { - let p = proportionalSize(this, width, height) - - return this - .width(new SVGNumber(p.width)) - .height(new SVGNumber(p.height)) - } - - // Set width of element - width (width) { - return this.attr('width', width) - } - - // write svgjs data to the dom - 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 super.writeDataToDom() - } - - // Move over x-axis - x (x) { - return this.attr('x', x) - } - - // Move over y-axis - y (y) { - return this.attr('y', y) - } -} diff --git a/src/Ellipse.js b/src/Ellipse.js deleted file mode 100644 index 2cc1d09..0000000 --- a/src/Ellipse.js +++ /dev/null @@ -1,22 +0,0 @@ -import Shape from './Shape.js' -import * as circled from './circled.js' -import { extend, nodeOrNew } from './tools.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Ellipse extends Shape { - constructor (node) { - super(nodeOrNew('ellipse', node), Ellipse) - } -} - -extend(Ellipse, circled) - -registerMethods('Container', { - // Create an ellipse - ellipse: function (width, height) { - return this.put(new Ellipse()).size(width, height).move(0, 0) - } -}) - -register(Ellipse) diff --git a/src/EventTarget.js b/src/EventTarget.js deleted file mode 100644 index bc7a09c..0000000 --- a/src/EventTarget.js +++ /dev/null @@ -1,90 +0,0 @@ -import Base from './Base.js' -import { on, off, dispatch } from './event.js' -import { registerMethods } from './methods.js' - -export default class EventTarget extends Base { - constructor ({ events = {} } = {}) { - super() - this.events = events - } - - addEventListener () {} - - // Bind given event to listener - on (event, listener, binding, options) { - on(this, event, listener, binding, options) - return this - } - - // Unbind event from listener - off (event, listener) { - off(this, event, listener) - return this - } - - dispatch (event, data) { - return dispatch(this, event, data) - } - - dispatchEvent (event) { - const bag = this.getEventHolder().events - if (!bag) return true - - const events = bag[event.type] - - for (let i in events) { - for (let j in events[i]) { - events[i][j](event) - } - } - - return !event.defaultPrevented - } - - // Fire given event - fire (event, data) { - this.dispatch(event, data) - return this - } - - getEventHolder () { - return this - } - - getEventTarget () { - return this - } - - removeEventListener () {} -} - -// Add events to elements -const methods = [ 'click', - 'dblclick', - 'mousedown', - 'mouseup', - 'mouseover', - 'mouseout', - 'mousemove', - 'mouseenter', - 'mouseleave', - 'touchstart', - 'touchmove', - 'touchleave', - 'touchend', - 'touchcancel' ].reduce(function (last, event) { - // add event to Element - const fn = function (f) { - if (f === null) { - off(this, event) - } else { - on(this, event, f) - } - return this - } - - last[event] = fn - return last -}, {}) - -registerMethods('Element', methods) diff --git a/src/G.js b/src/G.js deleted file mode 100644 index 2532f30..0000000 --- a/src/G.js +++ /dev/null @@ -1,21 +0,0 @@ -import Container from './Container.js' -import { nodeOrNew } from './tools.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class G extends Container { - constructor (node) { - super(nodeOrNew('g', node), G) - } -} - -registerMethods({ - Element: { - // Create a group element - group: function () { - return this.put(new G()) - } - } -}) - -register(G) diff --git a/src/Gradient.js b/src/Gradient.js deleted file mode 100644 index 5d7dd2a..0000000 --- a/src/Gradient.js +++ /dev/null @@ -1,79 +0,0 @@ -import Stop from './Stop.js' -import Container from './Container.js' -import * as gradiented from './gradiented.js' -import { nodeOrNew, extend } from './tools.js' -// import attr from './attr.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' -import Box from './Box.js' -import { find } from './selector.js' - -export default class Gradient extends Container { - constructor (type) { - super( - nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type), - Gradient - ) - } - - // Add a color stop - stop (offset, color, opacity) { - return this.put(new Stop()).update(offset, color, opacity) - } - - // Update gradient - update (block) { - // remove all stops - this.clear() - - // invoke passed block - 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) - } - - targets () { - return find('svg [fill*="' + this.id() + '"]') - } - - bbox () { - return new Box() - } -} - -extend(Gradient, gradiented) - -registerMethods({ - Container: { - // Create gradient element in defs - gradient (type, block) { - return this.defs().gradient(type, block) - } - }, - // define gradient - Defs: { - gradient (type, block) { - return this.put(new Gradient(type)).update(block) - } - } -}) - -register(Gradient) diff --git a/src/HtmlNode.js b/src/HtmlNode.js deleted file mode 100644 index ced223f..0000000 --- a/src/HtmlNode.js +++ /dev/null @@ -1,10 +0,0 @@ -import Dom from './Dom.js' -import { register } from './adopter.js' - -export default class HtmlNode extends Dom { - constructor (node) { - super(node, HtmlNode) - } -} - -register(HtmlNode) diff --git a/src/Image.js b/src/Image.js deleted file mode 100644 index f257492..0000000 --- a/src/Image.js +++ /dev/null @@ -1,69 +0,0 @@ -import Shape from './Shape.js' -import Pattern from './Pattern.js' -import { on, off } from './event.js' -import { nodeOrNew } from './tools.js' -import { xlink } from './namespaces.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Image extends Shape { - constructor (node) { - super(nodeOrNew('image', node), Image) - } - - // (re)load image - load (url, callback) { - if (!url) return this - - var img = new window.Image() - - 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 (p instanceof Pattern) { - // ensure pattern size if not set - if (p.width() === 0 && p.height() === 0) { - p.size(this.width(), this.height()) - } - } - - if (typeof callback === 'function') { - callback.call(this, { - width: img.width, - height: img.height, - ratio: img.width / img.height, - url: url - }) - } - }, this) - - on(img, 'load error', function () { - // dont forget to unbind memory leaking events - off(img) - }) - - return this.attr('href', (img.src = url), xlink) - } - - attrHook (obj) { - return obj.doc().defs().pattern(0, 0, (pattern) => { - pattern.add(this) - }) - } -} - -registerMethods({ - Container: { - // create image element, load image and set its size - image (source, callback) { - return this.put(new Image()).size(0, 0).load(source, callback) - } - } -}) - -register(Image) diff --git a/src/Line.js b/src/Line.js deleted file mode 100644 index 4028e48..0000000 --- a/src/Line.js +++ /dev/null @@ -1,64 +0,0 @@ -import { proportionalSize } from './helpers.js' -import { nodeOrNew, extend } from './tools.js' -import PointArray from './PointArray.js' -import Shape from './Shape.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' -import * as pointed from './pointed.js' - -export default class Line extends Shape { - // Initialize node - constructor (node) { - super(nodeOrNew('line', node), Line) - } - - // Get array - array () { - 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) { - return this.array() - } else if (typeof y1 !== 'undefined') { - x1 = { x1: x1, y1: y1, x2: x2, y2: y2 } - } else { - x1 = new PointArray(x1).toLine() - } - - return this.attr(x1) - } - - // Move by left top corner - 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()) - } -} - -extend(Line, pointed) - -registerMethods({ - Container: { - // Create a line element - line (...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] - ) - } - } -}) - -register(Line) diff --git a/src/Marker.js b/src/Marker.js deleted file mode 100644 index 16b2480..0000000 --- a/src/Marker.js +++ /dev/null @@ -1,82 +0,0 @@ -import Container from './Container.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' -import { nodeOrNew } from './tools.js' - -export default class Marker extends Container { - // Initialize node - constructor (node) { - super(nodeOrNew('marker', node), Marker) - } - - // Set width of element - width (width) { - return this.attr('markerWidth', width) - } - - // Set height of element - height (height) { - return this.attr('markerHeight', height) - } - - // Set marker refX and refY - ref (x, y) { - return this.attr('refX', x).attr('refY', y) - } - - // Update marker - update (block) { - // remove all content - this.clear() - - // invoke passed block - if (typeof block === 'function') { block.call(this, this) } - - return this - } - - // Return the fill id - toString () { - return 'url(#' + this.id() + ')' - } -} - -registerMethods({ - Container: { - marker (width, height, block) { - // Create marker element in defs - return this.defs().marker(width, height, block) - } - }, - Defs: { - // Create marker - marker (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) - } - }, - marker: { - // Create and attach markers - marker (marker, width, height, block) { - var attr = ['marker'] - - // Build attribute name - 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) - - return this.attr(attr, marker) - } - } -}) - -register(Marker) diff --git a/src/Mask.js b/src/Mask.js deleted file mode 100644 index c5a2faa..0000000 --- a/src/Mask.js +++ /dev/null @@ -1,59 +0,0 @@ -import Container from './Container.js' -import { nodeOrNew } from './tools.js' -import find from './selector.js' -// import {remove} from './Element.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Mask extends Container { - // Initialize node - constructor (node) { - super(nodeOrNew('mask', node), Mask) - } - - // Unmask all masked elements and remove itself - remove () { - // unmask all targets - this.targets().forEach(function (el) { - el.unmask() - }) - - // remove mask from parent - return super.remove() - } - - targets () { - return find('svg [mask*="' + this.id() + '"]') - } -} - -registerMethods({ - Container: { - mask () { - return this.defs().put(new Mask()) - } - }, - Element: { - // Distribute mask to svg element - maskWith (element) { - // use given mask or create a new one - var masker = element instanceof Mask - ? element - : this.parent().mask().add(element) - - // apply mask - return this.attr('mask', 'url("#' + masker.id() + '")') - }, - - // Unmask element - unmask () { - return this.attr('mask', null) - }, - - masker () { - return this.reference('mask') - } - } -}) - -register(Mask) diff --git a/src/Matrix.js b/src/Matrix.js deleted file mode 100644 index 00e4448..0000000 --- a/src/Matrix.js +++ /dev/null @@ -1,502 +0,0 @@ -import { abcdef, arrayToMatrix, closeEnough, isMatrixLike } from './helpers.js' -import Point from './Point.js' -import { delimiter } from './regex.js' -import { radians } from './utils.js' -import parser from './parser.js' -import Element from './Element.js' -import { registerMethods } from './methods.js' - -export default class Matrix { - constructor (...args) { - this.init(...args) - } - - // Initialize - init (source) { - var base = arrayToMatrix([1, 0, 0, 1, 0, 0]) - - // ensure source as object - source = source instanceof Element ? source.matrixify() - : typeof source === 'string' ? arrayToMatrix(source.split(delimiter).map(parseFloat)) - : Array.isArray(source) ? arrayToMatrix(source) - : (typeof source === 'object' && isMatrixLike(source)) ? source - : (typeof source === 'object') ? new Matrix().transform(source) - : arguments.length === 6 ? arrayToMatrix([].slice.call(arguments)) - : base - - // Merge the source matrix with the base matrix - this.a = source.a != null ? source.a : base.a - this.b = source.b != null ? source.b : base.b - this.c = source.c != null ? source.c : base.c - this.d = source.d != null ? source.d : base.d - this.e = source.e != null ? source.e : base.e - this.f = source.f != null ? source.f : base.f - } - - // Clones this matrix - clone () { - return new Matrix(this) - } - - // Transform a matrix into another matrix by manipulating the space - transform (o) { - // Check if o is a matrix and then left multiply it directly - if (isMatrixLike(o)) { - var matrix = new Matrix(o) - return matrix.multiplyO(this) - } - - // Get the proposed transformations and the current transformations - var t = Matrix.formatTransforms(o) - var current = this - let { x: ox, y: oy } = new Point(t.ox, t.oy).transform(current) - - // Construct the resulting matrix - var transformer = new Matrix() - .translateO(t.rx, t.ry) - .lmultiplyO(current) - .translateO(-ox, -oy) - .scaleO(t.scaleX, t.scaleY) - .skewO(t.skewX, t.skewY) - .shearO(t.shear) - .rotateO(t.theta) - .translateO(ox, oy) - - // If we want the origin at a particular place, we force it there - if (isFinite(t.px) || isFinite(t.py)) { - const origin = new Point(ox, oy).transform(transformer) - // TODO: Replace t.px with isFinite(t.px) - const dx = t.px ? t.px - origin.x : 0 - const dy = t.py ? t.py - origin.y : 0 - transformer.translateO(dx, dy) - } - - // Translate now after positioning - transformer.translateO(t.tx, t.ty) - return transformer - } - - // Applies a matrix defined by its affine parameters - compose (o) { - if (o.origin) { - o.originX = o.origin[0] - o.originY = o.origin[1] - } - // Get the parameters - var ox = o.originX || 0 - var oy = o.originY || 0 - var sx = o.scaleX || 1 - var sy = o.scaleY || 1 - var lam = o.shear || 0 - var theta = o.rotate || 0 - var tx = o.translateX || 0 - var ty = o.translateY || 0 - - // Apply the standard matrix - var result = new Matrix() - .translateO(-ox, -oy) - .scaleO(sx, sy) - .shearO(lam) - .rotateO(theta) - .translateO(tx, ty) - .lmultiplyO(this) - .translateO(ox, oy) - return result - } - - // Decomposes this matrix into its affine parameters - decompose (cx = 0, cy = 0) { - // Get the parameters from the matrix - var a = this.a - var b = this.b - var c = this.c - var d = this.d - var e = this.e - var f = this.f - - // Figure out if the winding direction is clockwise or counterclockwise - var determinant = a * d - b * c - var ccw = determinant > 0 ? 1 : -1 - - // Since we only shear in x, we can use the x basis to get the x scale - // and the rotation of the resulting matrix - var sx = ccw * Math.sqrt(a * a + b * b) - var thetaRad = Math.atan2(ccw * b, ccw * a) - var theta = 180 / Math.PI * thetaRad - var ct = Math.cos(thetaRad) - var st = Math.sin(thetaRad) - - // We can then solve the y basis vector simultaneously to get the other - // two affine parameters directly from these parameters - var lam = (a * c + b * d) / determinant - var sy = ((c * sx) / (lam * a - b)) || ((d * sx) / (lam * b + a)) - - // Use the translations - let tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy) - let ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy) - - // Construct the decomposition and return it - return { - // Return the affine parameters - scaleX: sx, - scaleY: sy, - shear: lam, - rotate: theta, - translateX: tx, - translateY: ty, - originX: cx, - originY: cy, - - // Return the matrix parameters - a: this.a, - b: this.b, - c: this.c, - d: this.d, - e: this.e, - f: this.f - } - } - - // Left multiplies by the given matrix - multiply (matrix) { - return this.clone().multiplyO(matrix) - } - - multiplyO (matrix) { - // Get the matrices - var l = this - var r = matrix instanceof Matrix - ? matrix - : new Matrix(matrix) - - return Matrix.matrixMultiply(l, r, this) - } - - lmultiply (matrix) { - return this.clone().lmultiplyO(matrix) - } - - lmultiplyO (matrix) { - var r = this - var l = matrix instanceof Matrix - ? matrix - : new Matrix(matrix) - - return Matrix.matrixMultiply(l, r, this) - } - - // Inverses matrix - inverseO () { - // Get the current parameters out of the matrix - var a = this.a - var b = this.b - var c = this.c - var d = this.d - var e = this.e - var f = this.f - - // Invert the 2x2 matrix in the top left - var det = a * d - b * c - if (!det) throw new Error('Cannot invert ' + this) - - // Calculate the top 2x2 matrix - var na = d / det - var nb = -b / det - var nc = -c / det - var nd = a / det - - // Apply the inverted matrix to the top right - var ne = -(na * e + nc * f) - var nf = -(nb * e + nd * f) - - // Construct the inverted matrix - this.a = na - this.b = nb - this.c = nc - this.d = nd - this.e = ne - this.f = nf - - return this - } - - inverse () { - return this.clone().inverseO() - } - - // Translate matrix - translate (x, y) { - return this.clone().translateO(x, y) - } - - translateO (x, y) { - this.e += x || 0 - this.f += y || 0 - return this - } - - // Scale matrix - scale (x, y, cx, cy) { - return this.clone().scaleO(...arguments) - } - - scaleO (x, y = x, cx = 0, cy = 0) { - // Support uniform scaling - if (arguments.length === 3) { - cy = cx - cx = y - y = x - } - - let { a, b, c, d, e, f } = this - - this.a = a * x - this.b = b * y - this.c = c * x - this.d = d * y - this.e = e * x - cx * x + cx - this.f = f * y - cy * y + cy - - return this - } - - // Rotate matrix - rotate (r, cx, cy) { - return this.clone().rotateO(r, cx, cy) - } - - rotateO (r, cx = 0, cy = 0) { - // Convert degrees to radians - r = radians(r) - - let cos = Math.cos(r) - let sin = Math.sin(r) - - let { a, b, c, d, e, f } = this - - this.a = a * cos - b * sin - this.b = b * cos + a * sin - this.c = c * cos - d * sin - this.d = d * cos + c * sin - this.e = e * cos - f * sin + cy * sin - cx * cos + cx - this.f = f * cos + e * sin - cx * sin - cy * cos + cy - - return this - } - - // Flip matrix on x or y, at a given offset - flip (axis, around) { - return this.clone().flipO(axis, around) - } - - flipO (axis, around) { - return axis === 'x' ? this.scaleO(-1, 1, around, 0) - : axis === 'y' ? this.scaleO(1, -1, 0, around) - : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point - } - - // Shear matrix - shear (a, cx, cy) { - return this.clone().shearO(a, cx, cy) - } - - shearO (lx, cx = 0, cy = 0) { - let { a, b, c, d, e, f } = this - - this.a = a + b * lx - this.c = c + d * lx - this.e = e + f * lx - cy * lx - - return this - } - - // Skew Matrix - skew (x, y, cx, cy) { - return this.clone().skewO(...arguments) - } - - skewO (x, y = x, cx = 0, cy = 0) { - // support uniformal skew - if (arguments.length === 3) { - cy = cx - cx = y - y = x - } - - // Convert degrees to radians - x = radians(x) - y = radians(y) - - let lx = Math.tan(x) - let ly = Math.tan(y) - - let { a, b, c, d, e, f } = this - - this.a = a + b * lx - this.b = b + a * ly - this.c = c + d * lx - this.d = d + c * ly - this.e = e + f * lx - cy * lx - this.f = f + e * ly - cx * ly - - return this - } - - // SkewX - skewX (x, cx, cy) { - return this.skew(x, 0, cx, cy) - } - - skewXO (x, cx, cy) { - return this.skewO(x, 0, cx, cy) - } - - // SkewY - skewY (y, cx, cy) { - return this.skew(0, y, cx, cy) - } - - skewYO (y, cx, cy) { - return this.skewO(0, y, cx, cy) - } - - // Transform around a center point - aroundO (cx, cy, matrix) { - var dx = cx || 0 - var dy = cy || 0 - return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy) - } - - around (cx, cy, matrix) { - return this.clone().aroundO(cx, cy, matrix) - } - - // Convert to native SVGMatrix - native () { - // create new matrix - var matrix = parser().svg.node.createSVGMatrix() - - // update with current values - for (var i = abcdef.length - 1; i >= 0; i--) { - matrix[abcdef[i]] = this[abcdef[i]] - } - - return matrix - } - - // Check if two matrices are equal - equals (other) { - var comp = new Matrix(other) - return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && - closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && - closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f) - } - - // Convert matrix to string - toString () { - return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')' - } - - toArray () { - return [this.a, this.b, this.c, this.d, this.e, this.f] - } - - valueOf () { - return { - a: this.a, - b: this.b, - c: this.c, - d: this.d, - e: this.e, - f: this.f - } - } - - // TODO: Refactor this to a static function of matrix.js - static formatTransforms (o) { - // Get all of the parameters required to form the matrix - var flipBoth = o.flip === 'both' || o.flip === true - var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1 - var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1 - var skewX = o.skew && o.skew.length ? o.skew[0] - : isFinite(o.skew) ? o.skew - : isFinite(o.skewX) ? o.skewX - : 0 - var skewY = o.skew && o.skew.length ? o.skew[1] - : isFinite(o.skew) ? o.skew - : isFinite(o.skewY) ? o.skewY - : 0 - var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX - : isFinite(o.scale) ? o.scale * flipX - : isFinite(o.scaleX) ? o.scaleX * flipX - : flipX - var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY - : isFinite(o.scale) ? o.scale * flipY - : isFinite(o.scaleY) ? o.scaleY * flipY - : flipY - var shear = o.shear || 0 - var theta = o.rotate || o.theta || 0 - var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY) - var ox = origin.x - var oy = origin.y - var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY) - var px = position.x - var py = position.y - var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY) - var tx = translate.x - var ty = translate.y - var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY) - var rx = relative.x - var ry = relative.y - - // Populate all of the values - return { - scaleX, scaleY, skewX, skewY, shear, theta, rx, ry, tx, ty, ox, oy, px, py - } - } - - // left matrix, right matrix, target matrix which is overwritten - static matrixMultiply (l, r, o) { - // Work out the product directly - var a = l.a * r.a + l.c * r.b - var b = l.b * r.a + l.d * r.b - var c = l.a * r.c + l.c * r.d - var d = l.b * r.c + l.d * r.d - var e = l.e + l.a * r.e + l.c * r.f - var f = l.f + l.b * r.e + l.d * r.f - - // make sure to use local variables because l/r and o could be the same - o.a = a - o.b = b - o.c = c - o.d = d - o.e = e - o.f = f - - return o - } -} - -registerMethods({ - Element: { - // Get current matrix - ctm () { - return new Matrix(this.node.getCTM()) - }, - - // Get current screen matrix - screenCTM () { - /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 - This is needed because FF does not return the transformation matrix - for the inner coordinate system when getScreenCTM() is called on nested svgs. - However all other Browsers do that */ - if (typeof this.isRoot === 'function' && !this.isRoot()) { - var rect = this.rect(1, 1) - var m = rect.node.getScreenCTM() - rect.remove() - return new Matrix(m) - } - return new Matrix(this.node.getScreenCTM()) - } - } -}) diff --git a/src/Morphable.js b/src/Morphable.js deleted file mode 100644 index f9dd7f0..0000000 --- a/src/Morphable.js +++ /dev/null @@ -1,240 +0,0 @@ -import { extend } from './tools.js' -import { Ease } from './Controller.js' -import Color from './Color.js' -import SVGNumber from './SVGNumber.js' -import SVGArray from './SVGArray.js' -import PathArray from './PathArray.js' -import { delimiter, pathLetters, numberAndUnit } from './regex.js' - -export default class Morphable { - constructor (stepper) { - // FIXME: the default stepper does not know about easing - this._stepper = stepper || new Ease('-') - - this._from = null - this._to = null - this._type = null - this._context = null - this._morphObj = null - } - - from (val) { - if (val == null) { - return this._from - } - - this._from = this._set(val) - return this - } - - to (val) { - if (val == null) { - return this._to - } - - this._to = this._set(val) - return this - } - - type (type) { - // getter - if (type == null) { - return this._type - } - - // setter - this._type = type - return this - } - - _set (value) { - if (!this._type) { - var type = typeof value - - if (type === 'number') { - this.type(SVGNumber) - } else if (type === 'string') { - if (Color.isColor(value)) { - this.type(Color) - } else if (delimiter.test(value)) { - this.type(pathLetters.test(value) - ? PathArray - : SVGArray - ) - } else if (numberAndUnit.test(value)) { - this.type(SVGNumber) - } else { - this.type(NonMorphable) - } - } else if (morphableTypes.indexOf(value.constructor) > -1) { - this.type(value.constructor) - } else if (Array.isArray(value)) { - this.type(SVGArray) - } else if (type === 'object') { - this.type(ObjectBag) - } else { - this.type(NonMorphable) - } - } - - var result = (new this._type(value)).toArray() - this._morphObj = this._morphObj || new this._type() - this._context = this._context || - Array.apply(null, Array(result.length)).map(Object) - return result - } - - stepper (stepper) { - if (stepper == null) return this._stepper - this._stepper = stepper - return this - } - - done () { - var complete = this._context - .map(this._stepper.done) - .reduce(function (last, curr) { - return last && curr - }, true) - return complete - } - - at (pos) { - var _this = this - - return this._morphObj.fromArray( - this._from.map(function (i, index) { - return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context) - }) - ) - } -} - -export class NonMorphable { - constructor (...args) { - this.init(...args) - } - - init (val) { - val = Array.isArray(val) ? val[0] : val - this.value = val - } - - valueOf () { - return this.value - } - - toArray () { - return [this.value] - } -} - -export class TransformBag { - constructor (...args) { - this.init(...args) - } - - init (obj) { - if (Array.isArray(obj)) { - obj = { - scaleX: obj[0], - scaleY: obj[1], - shear: obj[2], - rotate: obj[3], - translateX: obj[4], - translateY: obj[5], - originX: obj[6], - originY: obj[7] - } - } - - Object.assign(this, TransformBag.defaults, obj) - } - - toArray () { - var v = this - - return [ - v.scaleX, - v.scaleY, - v.shear, - v.rotate, - v.translateX, - v.translateY, - v.originX, - v.originY - ] - } -} - -TransformBag.defaults = { - scaleX: 1, - scaleY: 1, - shear: 0, - rotate: 0, - translateX: 0, - translateY: 0, - originX: 0, - originY: 0 -} - -export class ObjectBag { - constructor (...args) { - this.init(...args) - } - - init (objOrArr) { - this.values = [] - - if (Array.isArray(objOrArr)) { - this.values = objOrArr - return - } - - var entries = Object.entries(objOrArr || {}).sort((a, b) => { - return a[0] - b[0] - }) - - this.values = entries.reduce((last, curr) => last.concat(curr), []) - } - - valueOf () { - var obj = {} - var arr = this.values - - for (var i = 0, len = arr.length; i < len; i += 2) { - obj[arr[i]] = arr[i + 1] - } - - return obj - } - - toArray () { - return this.values - } -} - -const morphableTypes = [ - NonMorphable, - TransformBag, - ObjectBag -] - -export function registerMorphableType (type = []) { - morphableTypes.push(...[].concat(type)) -} - -export function makeMorphable () { - extend(morphableTypes, { - to (val, args) { - return new Morphable() - .type(this.constructor) - .from(this.valueOf()) - .to(val, args) - }, - fromArray (arr) { - this.init(arr) - return this - } - }) -} diff --git a/src/Path.js b/src/Path.js deleted file mode 100644 index 3557e22..0000000 --- a/src/Path.js +++ /dev/null @@ -1,82 +0,0 @@ -import { proportionalSize } from './helpers.js' -import { nodeOrNew } from './tools.js' -import Shape from './Shape.js' -import PathArray from './PathArray.js' -import find from './selector.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Path extends Shape { - // Initialize node - constructor (node) { - super(nodeOrNew('path', node), Path) - } - - // Get array - array () { - 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))) - } - - // 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 by left top corner over x-axis - 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) - } - - // 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)) - } - - // Set width of element - 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) - } - - targets () { - return find('svg textpath [href*="' + this.id() + '"]') - } -} - -// Define morphable array -Path.prototype.MorphArray = PathArray - -// Add parent method -registerMethods({ - Container: { - // Create a wrapped path element - path (d) { - // make sure plot is called as a setter - return this.put(new Path()).plot(d || new PathArray()) - } - } -}) - -register(Path) diff --git a/src/PathArray.js b/src/PathArray.js deleted file mode 100644 index 9fa5b99..0000000 --- a/src/PathArray.js +++ /dev/null @@ -1,291 +0,0 @@ -import { arrayToString, pathRegReplace } from './helpers.js' -import parser from './parser.js' -import { numbersWithDots, pathLetters, hyphen, delimiter, isPathLetter } from './regex.js' -import Point from './Point.js' -import SVGArray from './SVGArray.js' -import { subClassArray } from './ArrayPolyfill.js' -import { extend } from './tools.js' - -const PathArray = subClassArray('PathArray', SVGArray) - -export default PathArray - -const pathHandlers = { - M: function (c, p, p0) { - p.x = p0.x = c[0] - p.y = p0.y = c[1] - - return ['M', p.x, p.y] - }, - L: function (c, p) { - p.x = c[0] - p.y = c[1] - return ['L', c[0], c[1]] - }, - H: function (c, p) { - p.x = c[0] - return ['H', c[0]] - }, - V: function (c, p) { - p.y = c[0] - return ['V', c[0]] - }, - C: function (c, p) { - p.x = c[4] - p.y = c[5] - return ['C', c[0], c[1], c[2], c[3], c[4], c[5]] - }, - S: function (c, p) { - p.x = c[2] - p.y = c[3] - return ['S', c[0], c[1], c[2], c[3]] - }, - Q: function (c, p) { - p.x = c[2] - p.y = c[3] - return ['Q', c[0], c[1], c[2], c[3]] - }, - T: function (c, p) { - p.x = c[0] - p.y = c[1] - return ['T', c[0], c[1]] - }, - Z: function (c, p, p0) { - p.x = p0.x - p.y = p0.y - return ['Z'] - }, - A: function (c, p) { - p.x = c[5] - p.y = c[6] - return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]] - } -} - -let mlhvqtcsaz = 'mlhvqtcsaz'.split('') - -for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { - pathHandlers[mlhvqtcsaz[i]] = (function (i) { - return function (c, p, p0) { - if (i === 'H') c[0] = c[0] + p.x - else if (i === 'V') c[0] = c[0] + p.y - else if (i === 'A') { - c[5] = c[5] + p.x - c[6] = c[6] + p.y - } else { - for (var j = 0, jl = c.length; j < jl; ++j) { - c[j] = c[j] + (j % 2 ? p.y : p.x) - } - } - - return pathHandlers[i](c, p, p0) - } - })(mlhvqtcsaz[i].toUpperCase()) -} - -extend(PathArray, { - // Convert array to string - toString () { - return arrayToString(this) - }, - - // Move path string - move (x, y) { - // get bounding box of current situation - var box = this.bbox() - - // get relative offset - x -= box.x - y -= box.y - - if (!isNaN(x) && !isNaN(y)) { - // move every point - for (var l, i = this.length - 1; i >= 0; i--) { - l = this[i][0] - - if (l === 'M' || l === 'L' || l === 'T') { - this[i][1] += x - this[i][2] += y - } else if (l === 'H') { - this[i][1] += x - } else if (l === 'V') { - this[i][1] += y - } else if (l === 'C' || l === 'S' || l === 'Q') { - this[i][1] += x - this[i][2] += y - this[i][3] += x - this[i][4] += y - - if (l === 'C') { - this[i][5] += x - this[i][6] += y - } - } else if (l === 'A') { - this[i][6] += x - this[i][7] += y - } - } - } - - return this - }, - - // Resize path string - size (width, height) { - // get bounding box of current situation - var box = this.bbox() - var i, l - - // recalculate position of all points according to new size - for (i = this.length - 1; i >= 0; i--) { - l = this[i][0] - - if (l === 'M' || l === 'L' || l === 'T') { - this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x - this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y - } else if (l === 'H') { - this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x - } else if (l === 'V') { - this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y - } else if (l === 'C' || l === 'S' || l === 'Q') { - this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x - this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y - this[i][3] = ((this[i][3] - box.x) * width) / box.width + box.x - this[i][4] = ((this[i][4] - box.y) * height) / box.height + box.y - - if (l === 'C') { - this[i][5] = ((this[i][5] - box.x) * width) / box.width + box.x - this[i][6] = ((this[i][6] - box.y) * height) / box.height + box.y - } - } else if (l === 'A') { - // resize radii - this[i][1] = (this[i][1] * width) / box.width - this[i][2] = (this[i][2] * height) / box.height - - // move position values - this[i][6] = ((this[i][6] - box.x) * width) / box.width + box.x - this[i][7] = ((this[i][7] - box.y) * height) / box.height + box.y - } - } - - return this - }, - - // Test if the passed path array use the same path data commands as this path array - equalCommands (pathArray) { - var i, il, equalCommands - - pathArray = new PathArray(pathArray) - - equalCommands = this.length === pathArray.length - for (i = 0, il = this.length; equalCommands && i < il; i++) { - equalCommands = this[i][0] === pathArray[i][0] - } - - return equalCommands - }, - - // Make path array morphable - morph (pathArray) { - pathArray = new PathArray(pathArray) - - if (this.equalCommands(pathArray)) { - this.destination = pathArray - } else { - this.destination = null - } - - return this - }, - - // Get morphed path array at given position - at (pos) { - // make sure a destination is defined - if (!this.destination) return this - - var sourceArray = this - var destinationArray = this.destination.value - var array = [] - var pathArray = new PathArray() - var i, il, j, jl - - // Animate has specified in the SVG spec - // See: https://www.w3.org/TR/SVG11/paths.html#PathElement - for (i = 0, il = sourceArray.length; i < il; i++) { - array[i] = [sourceArray[i][0]] - for (j = 1, jl = sourceArray[i].length; j < jl; j++) { - array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos - } - // For the two flags of the elliptical arc command, the SVG spec say: - // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true - // Elliptical arc command as an array followed by corresponding indexes: - // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] - // 0 1 2 3 4 5 6 7 - if (array[i][0] === 'A') { - array[i][4] = +(array[i][4] !== 0) - array[i][5] = +(array[i][5] !== 0) - } - } - - // Directly modify the value of a path array, this is done this way for performance - pathArray.value = array - return pathArray - }, - - // Absolutize and parse path to array - parse (array = [['M', 0, 0]]) { - // if it's already a patharray, no need to parse it - if (array instanceof PathArray) return array - - // prepare for parsing - var s - var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 } - - if (typeof array === 'string') { - array = array - .replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 - .replace(pathLetters, ' $& ') // put some room between letters and numbers - .replace(hyphen, '$1 -') // add space before hyphen - .trim() // trim - .split(delimiter) // split into array - } else { - array = array.reduce(function (prev, curr) { - return [].concat.call(prev, curr) - }, []) - } - - // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] - var result = [] - var p = new Point() - var p0 = new Point() - var index = 0 - var len = array.length - - do { - // Test if we have a path letter - if (isPathLetter.test(array[index])) { - s = array[index] - ++index - // If last letter was a move command and we got no new, it defaults to [L]ine - } else if (s === 'M') { - s = 'L' - } else if (s === 'm') { - s = 'l' - } - - result.push(pathHandlers[s].call(null, - array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), - p, p0 - ) - ) - } while (len > index) - - return result - }, - - // Get bounding box of path - bbox () { - parser().path.setAttribute('d', this.toString()) - return parser.nodes.path.getBBox() - } -}) diff --git a/src/Pattern.js b/src/Pattern.js deleted file mode 100644 index 4a3e1ad..0000000 --- a/src/Pattern.js +++ /dev/null @@ -1,73 +0,0 @@ -import Container from './Container.js' -import { nodeOrNew } from './tools.js' -// import attr from './attr.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' -import Box from './Box.js' -import { find } from './selector.js' - -export default class Pattern extends Container { - // Initialize node - constructor (node) { - super(nodeOrNew('pattern', node), Pattern) - } - - // Return the fill id - url () { - return 'url(#' + this.id() + ')' - } - - // Update pattern by rebuilding - update (block) { - // remove content - this.clear() - - // invoke passed block - 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) - } - - targets () { - return find('svg [fill*="' + this.id() + '"]') - } - - bbox () { - return new Box() - } -} - -registerMethods({ - Container: { - // Create pattern element in defs - pattern (width, height, block) { - return this.defs().pattern(width, height, block) - } - }, - Defs: { - pattern (width, height, block) { - return this.put(new Pattern()).update(block).attr({ - x: 0, - y: 0, - width: width, - height: height, - patternUnits: 'userSpaceOnUse' - }) - } - } -}) - -register(Pattern) diff --git a/src/Point.js b/src/Point.js deleted file mode 100644 index a2b119c..0000000 --- a/src/Point.js +++ /dev/null @@ -1,54 +0,0 @@ -import parser from './parser.js' -import { registerMethods } from './methods.js' - -export default class Point { - // Initialize - constructor (x, y, base) { - let source - base = base || { x: 0, y: 0 } - - // ensure source as object - source = Array.isArray(x) ? { x: x[0], y: x[1] } - : typeof x === 'object' ? { x: x.x, y: x.y } - : { x: x, y: y } - - // merge source - this.x = source.x == null ? base.x : source.x - this.y = source.y == null ? base.y : source.y - } - - // Clone point - clone () { - return new Point(this) - } - - // Convert to native SVGPoint - native () { - // create new point - var point = parser().svg.node.createSVGPoint() - - // update with current values - point.x = this.x - point.y = this.y - return point - } - - // transform point with matrix - transform (m) { - // Perform the matrix multiplication - var x = m.a * this.x + m.c * this.y + m.e - var y = m.b * this.x + m.d * this.y + m.f - - // Return the required point - return new Point(x, y) - } -} - -registerMethods({ - Element: { - // Get point - point: function (x, y) { - return new Point(x, y).transform(this.screenCTM().inverse()) - } - } -}) diff --git a/src/PointArray.js b/src/PointArray.js deleted file mode 100644 index 42299e0..0000000 --- a/src/PointArray.js +++ /dev/null @@ -1,120 +0,0 @@ -import SVGArray from './SVGArray.js' -import { delimiter } from './regex.js' -import { subClassArray } from './ArrayPolyfill.js' -import { extend } from './tools.js' - -const PointArray = subClassArray('PointArray', SVGArray) - -export default PointArray - -extend(PointArray, { - // Convert array to string - toString () { - // convert to a poly point string - for (var i = 0, il = this.length, array = []; i < il; i++) { - array.push(this[i].join(',')) - } - - return array.join(' ') - }, - - // Convert array to line object - toLine () { - return { - x1: this[0][0], - y1: this[0][1], - x2: this[1][0], - y2: this[1][1] - } - }, - - // Get morphed array at given position - at (pos) { - // make sure a destination is defined - if (!this.destination) return this - - // generate morphed point string - for (var i = 0, il = this.length, array = []; i < il; i++) { - array.push([ - this[i][0] + (this.destination[i][0] - this[i][0]) * pos, - this[i][1] + (this.destination[i][1] - this[i][1]) * pos - ]) - } - - return new PointArray(array) - }, - - // Parse point string and flat array - parse (array = [[0, 0]]) { - var points = [] - - // if it is an array - if (array instanceof Array) { - // and it is not flat, there is no need to parse it - if (array[0] instanceof Array) { - return array - } - } else { // Else, it is considered as a string - // parse points - array = array.trim().split(delimiter).map(parseFloat) - } - - // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints - // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. - if (array.length % 2 !== 0) array.pop() - - // wrap points in two-tuples and parse points as floats - for (var i = 0, len = array.length; i < len; i = i + 2) { - points.push([ array[i], array[i + 1] ]) - } - - return points - }, - - // Move point string - move (x, y) { - var box = this.bbox() - - // get relative offset - x -= box.x - y -= box.y - - // move every point - if (!isNaN(x) && !isNaN(y)) { - for (var i = this.length - 1; i >= 0; i--) { - this[i] = [this[i][0] + x, this[i][1] + y] - } - } - - return this - }, - - // Resize poly string - size (width, height) { - var i - var box = this.bbox() - - // recalculate position of all points according to new size - for (i = this.length - 1; i >= 0; i--) { - if (box.width) this[i][0] = ((this[i][0] - box.x) * width) / box.width + box.x - if (box.height) this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y - } - - return this - }, - - // Get bounding box of points - bbox () { - var maxX = -Infinity - var maxY = -Infinity - var minX = Infinity - var minY = Infinity - this.forEach(function (el) { - maxX = Math.max(el[0], maxX) - maxY = Math.max(el[1], maxY) - minX = Math.min(el[0], minX) - minY = Math.min(el[1], minY) - }) - return { x: minX, y: minY, width: maxX - minX, height: maxY - minY } - } -}) diff --git a/src/Polygon.js b/src/Polygon.js deleted file mode 100644 index c4afac6..0000000 --- a/src/Polygon.js +++ /dev/null @@ -1,28 +0,0 @@ -import Shape from './Shape.js' -import { nodeOrNew, extend } from './tools.js' -import * as pointed from './pointed.js' -import * as poly from './poly.js' -import PointArray from './PointArray.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Polygon extends Shape { - // Initialize node - constructor (node) { - super(nodeOrNew('polygon', node), Polygon) - } -} - -registerMethods({ - Container: { - // Create a wrapped polygon element - polygon (p) { - // make sure plot is called as a setter - return this.put(new Polygon()).plot(p || new PointArray()) - } - } -}) - -extend(Polygon, pointed) -extend(Polygon, poly) -register(Polygon) diff --git a/src/Polyline.js b/src/Polyline.js deleted file mode 100644 index 7d1664e..0000000 --- a/src/Polyline.js +++ /dev/null @@ -1,28 +0,0 @@ -import Shape from './Shape.js' -import { nodeOrNew, extend } from './tools.js' -import PointArray from './PointArray.js' -import * as pointed from './pointed.js' -import * as poly from './poly.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Polyline extends Shape { - // Initialize node - constructor (node) { - super(nodeOrNew('polyline', node), Polyline) - } -} - -registerMethods({ - Container: { - // Create a wrapped polygon element - polyline (p) { - // make sure plot is called as a setter - return this.put(new Polyline()).plot(p || new PointArray()) - } - } -}) - -extend(Polyline, pointed) -extend(Polyline, poly) -register(Polyline) diff --git a/src/Queue.js b/src/Queue.js deleted file mode 100644 index 14b92b4..0000000 --- a/src/Queue.js +++ /dev/null @@ -1,59 +0,0 @@ -export default class Queue { - constructor () { - this._first = null - this._last = null - } - - push (value) { - // An item stores an id and the provided value - var item = value.next ? value : { value: value, next: null, prev: null } - - // Deal with the queue being empty or populated - if (this._last) { - item.prev = this._last - this._last.next = item - this._last = item - } else { - this._last = item - this._first = item - } - - // Update the length and return the current item - return item - } - - shift () { - // Check if we have a value - var remove = this._first - if (!remove) return null - - // If we do, remove it and relink things - this._first = remove.next - if (this._first) this._first.prev = null - this._last = this._first ? this._last : null - return remove.value - } - - // Shows us the first item in the list - first () { - return this._first && this._first.value - } - - // Shows us the last item in the list - last () { - return this._last && this._last.value - } - - // Removes the item that was returned from the push - remove (item) { - // Relink the previous item - if (item.prev) item.prev.next = item.next - if (item.next) item.next.prev = item.prev - if (item === this._last) this._last = item.prev - if (item === this._first) this._first = item.next - - // Invalidate item - item.prev = null - item.next = null - } -} diff --git a/src/Rect.js b/src/Rect.js deleted file mode 100644 index 535f562..0000000 --- a/src/Rect.js +++ /dev/null @@ -1,33 +0,0 @@ -import Shape from './Shape.js' -import { nodeOrNew } from './tools.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Rect extends Shape { - // Initialize node - constructor (node) { - super(nodeOrNew('rect', node), Rect) - } - - // FIXME: unify with circle - // Radius x value - rx (rx) { - return this.attr('rx', rx) - } - - // Radius y value - ry (ry) { - return this.attr('ry', ry) - } -} - -registerMethods({ - Container: { - // Create a rect element - rect (width, height) { - return this.put(new Rect()).size(width, height) - } - } -}) - -register(Rect) diff --git a/src/Runner.js b/src/Runner.js deleted file mode 100644 index 00ddf97..0000000 --- a/src/Runner.js +++ /dev/null @@ -1,936 +0,0 @@ -import { isMatrixLike, getOrigin } from './helpers.js' -import Matrix from './Matrix.js' -import Morphable, { TransformBag } from './Morphable.js' -import SVGNumber from './SVGNumber.js' -import Timeline from './Timeline.js' -import { Controller, Ease, Stepper } from './Controller.js' -import { noop, timeline } from './defaults.js' -import { extend } from './tools.js' -import Animator from './Animator.js' -import Point from './Point.js' -import { registerMethods } from './methods.js' -import EventTarget from './EventTarget.js' -import Box from './Box.js' - -// FIXME: What is this doing here? -// easing = { -// '-': function (pos) { return pos }, -// '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, -// '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, -// '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } -// } - -export default class Runner extends EventTarget { - constructor (options) { - super() - - // Store a unique id on the runner, so that we can identify it later - this.id = Runner.id++ - - // Ensure a default value - options = options == null - ? timeline.duration - : options - - // Ensure that we get a controller - options = typeof options === 'function' - ? new Controller(options) - : options - - // Declare all of the variables - this._element = null - this._timeline = null - this.done = false - this._queue = [] - - // Work out the stepper and the duration - this._duration = typeof options === 'number' && options - this._isDeclarative = options instanceof Controller - this._stepper = this._isDeclarative ? options : new Ease() - - // We copy the current values from the timeline because they can change - this._history = {} - - // Store the state of the runner - this.enabled = true - this._time = 0 - this._last = 0 - - // Save transforms applied to this runner - this.transforms = new Matrix() - this.transformId = 1 - - // Looping variables - this._haveReversed = false - this._reverse = false - this._loopsDone = 0 - this._swing = false - this._wait = 0 - this._times = 1 - } - - /* - Runner Definitions - ================== - These methods help us define the runtime behaviour of the Runner or they - help us make new runners from the current runner - */ - - element (element) { - if (element == null) return this._element - this._element = element - element._prepareRunner() - return this - } - - timeline (timeline) { - // check explicitly for undefined so we can set the timeline to null - if (typeof timeline === 'undefined') return this._timeline - this._timeline = timeline - return this - } - - animate (duration, delay, when) { - var o = Runner.sanitise(duration, delay, when) - var runner = new Runner(o.duration) - if (this._timeline) runner.timeline(this._timeline) - if (this._element) runner.element(this._element) - return runner.loop(o).schedule(delay, when) - } - - schedule (timeline, delay, when) { - // The user doesn't need to pass a timeline if we already have one - if (!(timeline instanceof Timeline)) { - when = delay - delay = timeline - timeline = this.timeline() - } - - // If there is no timeline, yell at the user... - if (!timeline) { - throw Error('Runner cannot be scheduled without timeline') - } - - // Schedule the runner on the timeline provided - timeline.schedule(this, delay, when) - return this - } - - unschedule () { - var timeline = this.timeline() - timeline && timeline.unschedule(this) - return this - } - - loop (times, swing, wait) { - // Deal with the user passing in an object - if (typeof times === 'object') { - swing = times.swing - wait = times.wait - times = times.times - } - - // Sanitise the values and store them - this._times = times || Infinity - this._swing = swing || false - this._wait = wait || 0 - return this - } - - delay (delay) { - return this.animate(0, delay) - } - - /* - Basic Functionality - =================== - These methods allow us to attach basic functions to the runner directly - */ - - queue (initFn, runFn, isTransform) { - this._queue.push({ - initialiser: initFn || noop, - runner: runFn || noop, - isTransform: isTransform, - initialised: false, - finished: false - }) - var timeline = this.timeline() - timeline && this.timeline()._continue() - return this - } - - during (fn) { - return this.queue(null, fn) - } - - after (fn) { - return this.on('finish', fn) - } - - /* - Runner animation methods - ======================== - Control how the animation plays - */ - - time (time) { - if (time == null) { - return this._time - } - let dt = time - this._time - this.step(dt) - return this - } - - duration () { - return this._times * (this._wait + this._duration) - this._wait - } - - loops (p) { - var loopDuration = this._duration + this._wait - if (p == null) { - var loopsDone = Math.floor(this._time / loopDuration) - var relativeTime = (this._time - loopsDone * loopDuration) - var position = relativeTime / this._duration - return Math.min(loopsDone + position, this._times) - } - var whole = Math.floor(p) - var partial = p % 1 - var time = loopDuration * whole + this._duration * partial - return this.time(time) - } - - position (p) { - // Get all of the variables we need - var x = this._time - var d = this._duration - var w = this._wait - var t = this._times - var s = this._swing - var r = this._reverse - var position - - if (p == null) { - /* - This function converts a time to a position in the range [0, 1] - The full explanation can be found in this desmos demonstration - https://www.desmos.com/calculator/u4fbavgche - The logic is slightly simplified here because we can use booleans - */ - - // Figure out the value without thinking about the start or end time - const f = function (x) { - var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)) - var backwards = (swinging && !r) || (!swinging && r) - var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards - var clipped = Math.max(Math.min(uncliped, 1), 0) - return clipped - } - - // Figure out the value by incorporating the start time - var endTime = t * (w + d) - w - position = x <= 0 ? Math.round(f(1e-5)) - : x < endTime ? f(x) - : Math.round(f(endTime - 1e-5)) - return position - } - - // Work out the loops done and add the position to the loops done - var loopsDone = Math.floor(this.loops()) - var swingForward = s && (loopsDone % 2 === 0) - var forwards = (swingForward && !r) || (r && swingForward) - position = loopsDone + (forwards ? p : 1 - p) - return this.loops(position) - } - - progress (p) { - if (p == null) { - return Math.min(1, this._time / this.duration()) - } - return this.time(p * this.duration()) - } - - step (dt) { - // If we are inactive, this stepper just gets skipped - if (!this.enabled) return this - - // Update the time and get the new position - dt = dt == null ? 16 : dt - this._time += dt - var position = this.position() - - // Figure out if we need to run the stepper in this frame - var running = this._lastPosition !== position && this._time >= 0 - this._lastPosition = position - - // Figure out if we just started - var duration = this.duration() - var justStarted = this._lastTime < 0 && this._time > 0 - var justFinished = this._lastTime < this._time && this.time > duration - this._lastTime = this._time - if (justStarted) { - this.fire('start', this) - } - - // Work out if the runner is finished set the done flag here so animations - // know, that they are running in the last step (this is good for - // transformations which can be merged) - var declarative = this._isDeclarative - this.done = !declarative && !justFinished && this._time >= duration - - // Call initialise and the run function - if (running || declarative) { - this._initialise(running) - - // clear the transforms on this runner so they dont get added again and again - this.transforms = new Matrix() - var converged = this._run(declarative ? dt : position) - this.fire('step', this) - } - // correct the done flag here - // declaritive animations itself know when they converged - this.done = this.done || (converged && declarative) - if (this.done) { - this.fire('finish', this) - } - return this - } - - finish () { - return this.step(Infinity) - } - - reverse (reverse) { - this._reverse = reverse == null ? !this._reverse : reverse - return this - } - - ease (fn) { - this._stepper = new Ease(fn) - return this - } - - active (enabled) { - if (enabled == null) return this.enabled - this.enabled = enabled - return this - } - - /* - Private Methods - =============== - Methods that shouldn't be used externally - */ - - // Save a morpher to the morpher list so that we can retarget it later - _rememberMorpher (method, morpher) { - this._history[method] = { - morpher: morpher, - caller: this._queue[this._queue.length - 1] - } - } - - // Try to set the target for a morpher if the morpher exists, otherwise - // do nothing and return false - _tryRetarget (method, target) { - if (this._history[method]) { - // if the last method wasnt even initialised, throw it away - if (!this._history[method].caller.initialised) { - let index = this._queue.indexOf(this._history[method].caller) - this._queue.splice(index, 1) - return false - } - - // for the case of transformations, we use the special retarget function - // which has access to the outer scope - if (this._history[method].caller.isTransform) { - this._history[method].caller.isTransform(target) - // for everything else a simple morpher change is sufficient - } else { - this._history[method].morpher.to(target) - } - - this._history[method].caller.finished = false - var timeline = this.timeline() - timeline && timeline._continue() - return true - } - return false - } - - // Run each initialise function in the runner if required - _initialise (running) { - // If we aren't running, we shouldn't initialise when not declarative - if (!running && !this._isDeclarative) return - - // Loop through all of the initialisers - for (var i = 0, len = this._queue.length; i < len; ++i) { - // Get the current initialiser - var current = this._queue[i] - - // Determine whether we need to initialise - var needsIt = this._isDeclarative || (!current.initialised && running) - running = !current.finished - - // Call the initialiser if we need to - if (needsIt && running) { - current.initialiser.call(this) - current.initialised = true - } - } - } - - // Run each run function for the position or dt given - _run (positionOrDt) { - // Run all of the _queue directly - var allfinished = true - for (var i = 0, len = this._queue.length; i < len; ++i) { - // Get the current function to run - var current = this._queue[i] - - // Run the function if its not finished, we keep track of the finished - // flag for the sake of declarative _queue - var converged = current.runner.call(this, positionOrDt) - current.finished = current.finished || (converged === true) - allfinished = allfinished && current.finished - } - - // We report when all of the constructors are finished - return allfinished - } - - addTransform (transform, index) { - this.transforms.lmultiplyO(transform) - return this - } - - clearTransform () { - this.transforms = new Matrix() - return this - } - - static sanitise (duration, delay, when) { - // Initialise the default parameters - var times = 1 - var swing = false - var wait = 0 - duration = duration || timeline.duration - delay = delay || timeline.delay - when = when || 'last' - - // If we have an object, unpack the values - if (typeof duration === 'object' && !(duration instanceof Stepper)) { - delay = duration.delay || delay - when = duration.when || when - swing = duration.swing || swing - times = duration.times || times - wait = duration.wait || wait - duration = duration.duration || timeline.duration - } - - return { - duration: duration, - delay: delay, - swing: swing, - times: times, - wait: wait, - when: when - } - } -} - -Runner.id = 0 - -class FakeRunner { - constructor (transforms = new Matrix(), id = -1, done = true) { - this.transforms = transforms - this.id = id - this.done = done - } -} - -extend([Runner, FakeRunner], { - mergeWith (runner) { - return new FakeRunner( - runner.transforms.lmultiply(this.transforms), - runner.id - ) - } -}) - -// FakeRunner.emptyRunner = new FakeRunner() - -const lmultiply = (last, curr) => last.lmultiplyO(curr) -const getRunnerTransform = (runner) => runner.transforms - -function mergeTransforms () { - // Find the matrix to apply to the element and apply it - let runners = this._transformationRunners.runners - let netTransform = runners - .map(getRunnerTransform) - .reduce(lmultiply, new Matrix()) - - this.transform(netTransform) - - this._transformationRunners.merge() - - if (this._transformationRunners.length() === 1) { - this._frameId = null - } -} - -class RunnerArray { - constructor () { - this.runners = [] - this.ids = [] - } - - add (runner) { - if (this.runners.includes(runner)) return - - let id = runner.id + 1 - - let leftSibling = this.ids.reduce((last, curr) => { - if (curr > last && curr < id) return curr - return last - }, 0) - - let index = this.ids.indexOf(leftSibling) + 1 - - this.ids.splice(index, 0, id) - this.runners.splice(index, 0, runner) - - return this - } - - getByID (id) { - return this.runners[this.ids.indexOf(id + 1)] - } - - remove (id) { - let index = this.ids.indexOf(id + 1) - this.ids.splice(index, 1) - this.runners.splice(index, 1) - return this - } - - merge () { - let lastRunner = null - this.runners.forEach((runner, i) => { - if (lastRunner && runner.done && lastRunner.done) { - this.remove(runner.id) - this.edit(lastRunner.id, runner.mergeWith(lastRunner)) - } - - lastRunner = runner - }) - - return this - } - - edit (id, newRunner) { - let index = this.ids.indexOf(id + 1) - this.ids.splice(index, 1, id) - this.runners.splice(index, 1, newRunner) - return this - } - - length () { - return this.ids.length - } - - clearBefore (id) { - let deleteCnt = this.ids.indexOf(id + 1) || 1 - this.ids.splice(0, deleteCnt, 0) - this.runners.splice(0, deleteCnt, new FakeRunner()) - return this - } -} - -let frameId = 0 -registerMethods({ - Element: { - animate (duration, delay, when) { - var o = Runner.sanitise(duration, delay, when) - var timeline = this.timeline() - return new Runner(o.duration) - .loop(o) - .element(this) - .timeline(timeline) - .schedule(delay, when) - }, - - delay (by, when) { - return this.animate(0, by, when) - }, - - // this function searches for all runners on the element and deletes the ones - // which run before the current one. This is because absolute transformations - // overwfrite anything anyway so there is no need to waste time computing - // other runners - _clearTransformRunnersBefore (currentRunner) { - this._transformationRunners.clearBefore(currentRunner.id) - }, - - _currentTransform (current) { - return this._transformationRunners.runners - // we need the equal sign here to make sure, that also transformations - // on the same runner which execute before the current transformation are - // taken into account - .filter((runner) => runner.id <= current.id) - .map(getRunnerTransform) - .reduce(lmultiply, new Matrix()) - }, - - addRunner (runner) { - this._transformationRunners.add(runner) - - Animator.transform_frame( - mergeTransforms.bind(this), this._frameId - ) - }, - - _prepareRunner () { - if (this._frameId == null) { - this._transformationRunners = new RunnerArray() - .add(new FakeRunner(new Matrix(this))) - - this._frameId = frameId++ - } - } - } -}) - -extend(Runner, { - attr (a, v) { - return this.styleAttr('attr', a, v) - }, - - // Add animatable styles - css (s, v) { - return this.styleAttr('css', s, v) - }, - - styleAttr (type, name, val) { - // apply attributes individually - if (typeof name === 'object') { - for (var key in val) { - this.styleAttr(type, key, val[key]) - } - } - - var morpher = new Morphable(this._stepper).to(val) - - this.queue(function () { - morpher = morpher.from(this.element()[type](name)) - }, function (pos) { - this.element()[type](name, morpher.at(pos)) - return morpher.done() - }) - - return this - }, - - zoom (level, point) { - var morpher = new Morphable(this._stepper).to(new SVGNumber(level)) - - this.queue(function () { - morpher = morpher.from(this.zoom()) - }, function (pos) { - this.element().zoom(morpher.at(pos), point) - return morpher.done() - }) - - return this - }, - - /** - ** absolute transformations - **/ - - // - // M v -----|-----(D M v = F v)------|-----> T v - // - // 1. define the final state (T) and decompose it (once) - // t = [tx, ty, the, lam, sy, sx] - // 2. on every frame: pull the current state of all previous transforms - // (M - m can change) - // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] - // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) - // - Note F(0) = M - // - Note F(1) = T - // 4. Now you get the delta matrix as a result: D = F * inv(M) - - transform (transforms, relative, affine) { - // If we have a declarative function, we should retarget it if possible - relative = transforms.relative || relative - if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { - return this - } - - // Parse the parameters - var isMatrix = isMatrixLike(transforms) - affine = transforms.affine != null - ? transforms.affine - : (affine != null ? affine : !isMatrix) - - // Create a morepher and set its type - const morpher = new Morphable() - .type(affine ? TransformBag : Matrix) - .stepper(this._stepper) - - let origin - let element - let current - let currentAngle - let startTransform - - function setup () { - // make sure element and origin is defined - element = element || this.element() - origin = origin || getOrigin(transforms, element) - - startTransform = new Matrix(relative ? undefined : element) - - // add the runner to the element so it can merge transformations - element.addRunner(this) - - // Deactivate all transforms that have run so far if we are absolute - if (!relative) { - element._clearTransformRunnersBefore(this) - } - } - - function run (pos) { - // clear all other transforms before this in case something is saved - // on this runner. We are absolute. We dont need these! - if (!relative) this.clearTransform() - - let { x, y } = new Point(origin).transform(element._currentTransform(this)) - - let target = new Matrix({ ...transforms, origin: [x, y] }) - let start = this._isDeclarative && current - ? current - : startTransform - - if (affine) { - target = target.decompose(x, y) - start = start.decompose(x, y) - - // Get the current and target angle as it was set - const rTarget = target.rotate - const rCurrent = start.rotate - - // Figure out the shortest path to rotate directly - const possibilities = [rTarget - 360, rTarget, rTarget + 360] - const distances = possibilities.map(a => Math.abs(a - rCurrent)) - const shortest = Math.min(...distances) - const index = distances.indexOf(shortest) - target.rotate = possibilities[index] - } - - if (relative) { - // we have to be careful here not to overwrite the rotation - // with the rotate method of Matrix - if (!isMatrix) { - target.rotate = transforms.rotate || 0 - } - if (this._isDeclarative && currentAngle) { - start.rotate = currentAngle - } - } - - morpher.from(start) - morpher.to(target) - - let affineParameters = morpher.at(pos) - currentAngle = affineParameters.rotate - current = new Matrix(affineParameters) - - this.addTransform(current) - return morpher.done() - } - - function retarget (newTransforms) { - // only get a new origin if it changed since the last call - if ( - (newTransforms.origin || 'center').toString() !== - (transforms.origin || 'center').toString() - ) { - origin = getOrigin(transforms, element) - } - - // overwrite the old transformations with the new ones - transforms = { ...newTransforms, origin } - } - - this.queue(setup, run, retarget) - this._isDeclarative && this._rememberMorpher('transform', morpher) - return this - }, - - // Animatable x-axis - x (x, relative) { - return this._queueNumber('x', x) - }, - - // Animatable y-axis - y (y) { - return this._queueNumber('y', y) - }, - - dx (x) { - return this._queueNumberDelta('dx', x) - }, - - dy (y) { - return this._queueNumberDelta('dy', y) - }, - - _queueNumberDelta (method, to) { - to = new SVGNumber(to) - - // Try to change the target if we have this method already registerd - if (this._tryRetargetDelta(method, to)) return this - - // Make a morpher and queue the animation - var morpher = new Morphable(this._stepper).to(to) - this.queue(function () { - var from = this.element()[method]() - morpher.from(from) - morpher.to(from + to) - }, function (pos) { - this.element()[method](morpher.at(pos)) - return morpher.done() - }) - - // Register the morpher so that if it is changed again, we can retarget it - this._rememberMorpher(method, morpher) - return this - }, - - _queueObject (method, to) { - // Try to change the target if we have this method already registerd - if (this._tryRetarget(method, to)) return this - - // Make a morpher and queue the animation - var morpher = new Morphable(this._stepper).to(to) - this.queue(function () { - morpher.from(this.element()[method]()) - }, function (pos) { - this.element()[method](morpher.at(pos)) - return morpher.done() - }) - - // Register the morpher so that if it is changed again, we can retarget it - this._rememberMorpher(method, morpher) - return this - }, - - _queueNumber (method, value) { - return this._queueObject(method, new SVGNumber(value)) - }, - - // Animatable center x-axis - cx (x) { - return this._queueNumber('cx', x) - }, - - // Animatable center y-axis - cy (y) { - return this._queueNumber('cy', y) - }, - - // Add animatable move - move (x, y) { - return this.x(x).y(y) - }, - - // Add animatable center - center (x, y) { - return this.cx(x).cy(y) - }, - - // Add animatable size - size (width, height) { - // animate bbox based size for all other elements - var box - - if (!width || !height) { - box = this._element.bbox() - } - - if (!width) { - width = box.width / box.height * height - } - - if (!height) { - height = box.height / box.width * width - } - - return this - .width(width) - .height(height) - }, - - // Add animatable width - width (width) { - return this._queueNumber('width', width) - }, - - // Add animatable height - height (height) { - return this._queueNumber('height', height) - }, - - // Add animatable plot - plot (a, b, c, d) { - // Lines can be plotted with 4 arguments - if (arguments.length === 4) { - return this.plot([a, b, c, d]) - } - - // FIXME: this needs to be rewritten such that the element is only accesed - // in the init function - return this._queueObject('plot', new this._element.MorphArray(a)) - - /* - var morpher = this._element.morphArray().to(a) - - this.queue(function () { - morpher.from(this._element.array()) - }, function (pos) { - this._element.plot(morpher.at(pos)) - }) - - return this - */ - }, - - // Add leading method - leading (value) { - return this._queueNumber('leading', value) - }, - - // Add animatable viewbox - viewbox (x, y, width, height) { - return this._queueObject('viewbox', new Box(x, y, width, height)) - }, - - update (o) { - if (typeof o !== 'object') { - return this.update({ - offset: arguments[0], - color: arguments[1], - opacity: arguments[2] - }) - } - - 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', o.offset) - - return this - } -}) diff --git a/src/SVGArray.js b/src/SVGArray.js deleted file mode 100644 index 351e166..0000000 --- a/src/SVGArray.js +++ /dev/null @@ -1,47 +0,0 @@ -import { delimiter } from './regex.js' -import { subClassArray } from './ArrayPolyfill.js' -import { extend } from './tools.js' - -const SVGArray = subClassArray('SVGArray', Array, function (...args) { - this.init(...args) -}) - -export default SVGArray - -extend(SVGArray, { - init (...args) { - this.length = 0 - this.push(...this.parse(...args)) - }, - - toArray () { - return Array.prototype.concat.apply([], this) - }, - - toString () { - return this.join(' ') - }, - - // Flattens the array if needed - valueOf () { - const ret = [] - ret.push(...this) - return ret - }, - - // Parse whitespace separated string - parse (array = []) { - // If already is an array, no need to parse it - if (array instanceof Array) return array - - return array.trim().split(delimiter).map(parseFloat) - }, - - clone () { - return new this.constructor(this) - }, - - toSet () { - return new Set(this) - } -}) diff --git a/src/SVGNumber.js b/src/SVGNumber.js deleted file mode 100644 index 095e2e7..0000000 --- a/src/SVGNumber.js +++ /dev/null @@ -1,87 +0,0 @@ -import { numberAndUnit } from './regex.js' - -// Module for unit convertions -export default class SVGNumber { - // Initialize - constructor (...args) { - this.init(...args) - } - - init (value, unit) { - unit = Array.isArray(value) ? value[1] : unit - value = Array.isArray(value) ? value[0] : value - - // initialize defaults - this.value = 0 - this.unit = unit || '' - - // parse value - if (typeof value === 'number') { - // ensure a valid numeric value - this.value = isNaN(value) ? 0 : !isFinite(value) ? (value < 0 ? -3.4e+38 : +3.4e+38) : value - } else if (typeof value === 'string') { - unit = value.match(numberAndUnit) - - if (unit) { - // make value numeric - this.value = parseFloat(unit[1]) - - // normalize - if (unit[5] === '%') { this.value /= 100 } else if (unit[5] === 's') { - this.value *= 1000 - } - - // store unit - this.unit = unit[5] - } - } else { - if (value instanceof SVGNumber) { - this.value = value.valueOf() - this.unit = value.unit - } - } - } - - toString () { - return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 - : this.unit === 's' ? this.value / 1e3 - : this.value - ) + this.unit - } - - toJSON () { - return this.toString() - } - - toArray () { - return [this.value, this.unit] - } - - valueOf () { - return this.value - } - - // Add number - plus (number) { - number = new SVGNumber(number) - return new SVGNumber(this + number, this.unit || number.unit) - } - - // Subtract number - minus (number) { - number = new SVGNumber(number) - return new SVGNumber(this - number, this.unit || number.unit) - } - - // Multiply number - times (number) { - number = new SVGNumber(number) - return new SVGNumber(this * number, this.unit || number.unit) - } - - // Divide number - divide (number) { - number = new SVGNumber(number) - return new SVGNumber(this / number, this.unit || number.unit) - } -} diff --git a/src/Shape.js b/src/Shape.js deleted file mode 100644 index f02fec2..0000000 --- a/src/Shape.js +++ /dev/null @@ -1,2 +0,0 @@ -import Element from './Element.js' -export default class Shape extends Element {} diff --git a/src/Stop.js b/src/Stop.js deleted file mode 100644 index df33dbf..0000000 --- a/src/Stop.js +++ /dev/null @@ -1,30 +0,0 @@ -import Element from './Element.js' -import SVGNumber from './SVGNumber.js' -import { nodeOrNew } from './tools.js' -import { register } from './adopter.js' - -export default class Stop extends Element { - constructor (node) { - super(nodeOrNew('stop', node), Stop) - } - - // add color stops - 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)) - - return this - } -} - -register(Stop) diff --git a/src/Symbol.js b/src/Symbol.js deleted file mode 100644 index 9efb86c..0000000 --- a/src/Symbol.js +++ /dev/null @@ -1,21 +0,0 @@ -import Container from './Container.js' -import { nodeOrNew } from './tools.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Symbol extends Container { - // Initialize node - constructor (node) { - super(nodeOrNew('symbol', node), Symbol) - } -} - -registerMethods({ - Container: { - symbol () { - return this.put(new Symbol()) - } - } -}) - -register(Symbol) diff --git a/src/Text.js b/src/Text.js deleted file mode 100644 index 1b4c442..0000000 --- a/src/Text.js +++ /dev/null @@ -1,178 +0,0 @@ -import Shape from './Shape.js' -import SVGNumber from './SVGNumber.js' -import { nodeOrNew, extend } from './tools.js' -import { attrs } from './defaults.js' -import * as textable from './textable.js' -import { register, adopt } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Text extends Shape { - // Initialize node - constructor (node) { - super(nodeOrNew('text', node), Text) - - 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']) - } - - // Move over x-axis - x (x) { - // act as getter - if (x == null) { - return this.attr('x') - } - - return this.attr('x', x) - } - - // Move over y-axis - y (y) { - var oy = this.attr('y') - var o = typeof oy === 'number' ? oy - this.bbox().y : 0 - - // act as getter - if (y == null) { - return typeof oy === 'number' ? oy - o : oy - } - - 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) - } - - // Move center over y-axis - cy (y) { - return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2) - } - - // Set the text content - text (text) { - // act as getter - if (text === undefined) { - // FIXME use children() or each() - var children = this.node.childNodes - var firstLine = 0 - text = '' - - 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 - 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) { - text += '\n' - } - - // add content of this node - text += children[i].textContent - } - - return text - } - - // remove existing content - this.clear().build(true) - - if (typeof text === 'function') { - // call block - text.call(this, this) - } else { - // store text and make sure text is not blank - text = text.split('\n') - - // build new lines - 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() - } - - // Set / get leading - leading (value) { - // act as getter - if (value == null) { - return this.dom.leading - } - - // act as setter - this.dom.leading = new SVGNumber(value) - - return this.rebuild() - } - - // Rebuild appearance type - rebuild (rebuild) { - // store new rebuild flag if given - if (typeof rebuild === 'boolean') { - this._rebuild = rebuild - } - - // define position of all lines - if (this._rebuild) { - var self = this - var blankLineOffset = 0 - var dy = this.dom.leading * new SVGNumber(this.attr('font-size')) - - this.each(function () { - if (this.dom.newLined) { - this.attr('x', self.attr('x')) - - if (this.text() === '\n') { - blankLineOffset += dy - } else { - this.attr('dy', dy + blankLineOffset) - blankLineOffset = 0 - } - } - }) - - this.fire('rebuild') - } - - return this - } - - // Enable / disable build mode - build (build) { - this._build = !!build - return this - } - - // overwrite method from parent to set data properly - setData (o) { - this.dom = o - this.dom.leading = new SVGNumber(o.leading || 1.3) - return this - } -} - -extend(Text, textable) - -registerMethods({ - Container: { - // Create text element - text (text) { - return this.put(new Text()).text(text) - }, - - // Create plain text element - plain (text) { - return this.put(new Text()).plain(text) - } - } -}) - -register(Text) diff --git a/src/TextPath.js b/src/TextPath.js deleted file mode 100644 index ce5115b..0000000 --- a/src/TextPath.js +++ /dev/null @@ -1,84 +0,0 @@ -import Path from './Path.js' -import Text from './Text.js' -import PathArray from './PathArray.js' -import { nodeOrNew } from './tools.js' -import { xlink } from './namespaces.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class TextPath extends Text { - // Initialize node - constructor (node) { - super(nodeOrNew('textPath', node), TextPath) - } - - // return the array of the path track element - array () { - var track = this.track() - - return track ? track.array() : null - } - - // Plot path if any - plot (d) { - var track = this.track() - var pathArray = null - - if (track) { - pathArray = track.plot(d) - } - - return (d == null) ? pathArray : this - } - - // Get the path element - track () { - return this.reference('href') - } -} - -registerMethods({ - Container: { - textPath (text, path) { - return this.defs().path(path).text(text).addTo(this) - } - }, - Text: { - // Create path for text to run on - path: function (track) { - var path = new TextPath() - - // if d is a path, reuse it - if (!(track instanceof Path)) { - // create path element - track = this.doc().defs().path(track) - } - - // link textPath to path and add content - path.attr('href', '#' + track, xlink) - - // add textPath element as child node and return textPath - return this.put(path) - }, - - // FIXME: make this plural? - // Get the textPath children - textPath: function () { - return this.find('textPath') - } - }, - Path: { - // creates a textPath from this path - text: function (text) { - if (text instanceof Text) { - var txt = text.text() - return text.clear().path(this).text(txt) - } - return this.parent().put(new Text()).path(this).text(text) - } - // FIXME: Maybe add `targets` to get all textPaths associated with this path - } -}) - -TextPath.prototype.MorphArray = PathArray -register(TextPath) diff --git a/src/Timeline.js b/src/Timeline.js deleted file mode 100644 index c5ce9d3..0000000 --- a/src/Timeline.js +++ /dev/null @@ -1,271 +0,0 @@ -import Animator from './Animator.js' -import { registerMethods } from './methods.js' - -var time = window.performance || Date - -var makeSchedule = function (runnerInfo) { - var start = runnerInfo.start - var duration = runnerInfo.runner.duration() - var end = start + duration - return { start: start, duration: duration, end: end, runner: runnerInfo.runner } -} - -export default class Timeline { - // Construct a new timeline on the given element - constructor () { - this._timeSource = function () { - return time.now() - } - - this._dispatcher = document.createElement('div') - - // Store the timing variables - this._startTime = 0 - this._speed = 1.0 - - // Play control variables control how the animation proceeds - this._reverse = false - this._persist = 0 - - // Keep track of the running animations and their starting parameters - this._nextFrame = null - this._paused = false - this._runners = [] - this._order = [] - this._time = 0 - this._lastSourceTime = 0 - this._lastStepTime = 0 - } - - getEventTarget () { - return this._dispatcher - } - - /** - * - */ - - // schedules a runner on the timeline - schedule (runner, delay, when) { - if (runner == null) { - return this._runners.map(makeSchedule).sort(function (a, b) { - return (a.start - b.start) || (a.duration - b.duration) - }) - } - - if (!this.active()) { - this._step() - if (when == null) { - when = 'now' - } - } - - // The start time for the next animation can either be given explicitly, - // derived from the current timeline time or it can be relative to the - // last start time to chain animations direclty - var absoluteStartTime = 0 - delay = delay || 0 - - // Work out when to start the animation - if (when == null || when === 'last' || when === 'after') { - // Take the last time and increment - absoluteStartTime = this._startTime - } else if (when === 'absolute' || when === 'start') { - absoluteStartTime = delay - delay = 0 - } else if (when === 'now') { - absoluteStartTime = this._time - } else if (when === 'relative') { - let runnerInfo = this._runners[runner.id] - if (runnerInfo) { - absoluteStartTime = runnerInfo.start + delay - delay = 0 - } - } else { - throw new Error('Invalid value for the "when" parameter') - } - - // Manage runner - runner.unschedule() - runner.timeline(this) - runner.time(-delay) - - // Save startTime for next runner - this._startTime = absoluteStartTime + runner.duration() + delay - - // Save runnerInfo - this._runners[runner.id] = { - persist: this.persist(), - runner: runner, - start: absoluteStartTime - } - - // Save order and continue - this._order.push(runner.id) - this._continue() - return this - } - - // Remove the runner from this timeline - unschedule (runner) { - var index = this._order.indexOf(runner.id) - if (index < 0) return this - - delete this._runners[runner.id] - this._order.splice(index, 1) - runner.timeline(null) - return this - } - - play () { - // Now make sure we are not paused and continue the animation - this._paused = false - return this._continue() - } - - pause () { - // Cancel the next animation frame and pause - this._nextFrame = null - this._paused = true - return this - } - - stop () { - // Cancel the next animation frame and go to start - this.seek(-this._time) - return this.pause() - } - - finish () { - this.seek(Infinity) - return this.pause() - } - - speed (speed) { - if (speed == null) return this._speed - this._speed = speed - return this - } - - reverse (yes) { - var currentSpeed = this.speed() - if (yes == null) return this.speed(-currentSpeed) - - var positive = Math.abs(currentSpeed) - return this.speed(yes ? positive : -positive) - } - - seek (dt) { - this._time += dt - return this._continue() - } - - time (time) { - if (time == null) return this._time - this._time = time - return this - } - - persist (dtOrForever) { - if (dtOrForever == null) return this._persist - this._persist = dtOrForever - return this - } - - source (fn) { - if (fn == null) return this._timeSource - this._timeSource = fn - return this - } - - _step () { - // If the timeline is paused, just do nothing - if (this._paused) return - - // Get the time delta from the last time and update the time - // TODO: Deal with window.blur window.focus to pause animations - var time = this._timeSource() - var dtSource = time - this._lastSourceTime - var dtTime = this._speed * dtSource + (this._time - this._lastStepTime) - this._lastSourceTime = time - - // Update the time - this._time += dtTime - this._lastStepTime = this._time - // this.fire('time', this._time) - - // Run all of the runners directly - var runnersLeft = false - for (var i = 0, len = this._order.length; i < len; i++) { - // Get and run the current runner and ignore it if its inactive - var runnerInfo = this._runners[this._order[i]] - var runner = runnerInfo.runner - let dt = dtTime - - // Make sure that we give the actual difference - // between runner start time and now - let dtToStart = this._time - runnerInfo.start - - // Dont run runner if not started yet - if (dtToStart < 0) { - runnersLeft = true - continue - } else if (dtToStart < dt) { - // Adjust dt to make sure that animation is on point - dt = dtToStart - } - - if (!runner.active()) continue - - // If this runner is still going, signal that we need another animation - // frame, otherwise, remove the completed runner - var finished = runner.step(dt).done - if (!finished) { - runnersLeft = true - // continue - } else if (runnerInfo.persist !== true) { - // runner is finished. And runner might get removed - - // TODO: Figure out end time of runner - var endTime = runner.duration() - runner.time() + this._time - - if (endTime + this._persist < this._time) { - // Delete runner and correct index - delete this._runners[this._order[i]] - this._order.splice(i--, 1) && --len - runner.timeline(null) - } - } - } - - // Get the next animation frame to keep the simulation going - if (runnersLeft) { - this._nextFrame = Animator.frame(this._step.bind(this)) - } else { - this._nextFrame = null - } - return this - } - - // Checks if we are running and continues the animation - _continue () { - if (this._paused) return this - if (!this._nextFrame) { - this._nextFrame = Animator.frame(this._step.bind(this)) - } - return this - } - - active () { - return !!this._nextFrame - } -} - -registerMethods({ - Element: { - timeline: function () { - this._timeline = (this._timeline || new Timeline()) - return this._timeline - } - } -}) diff --git a/src/Tspan.js b/src/Tspan.js deleted file mode 100644 index f3a9469..0000000 --- a/src/Tspan.js +++ /dev/null @@ -1,65 +0,0 @@ -import Text from './Text.js' -import { nodeOrNew, extend } from './tools.js' -import * as textable from './textable.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' - -export default class Tspan extends Text { - // Initialize node - constructor (node) { - super(nodeOrNew('tspan', node), Tspan) - } - - // Set text content - text (text) { - if (text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '') - - typeof text === 'function' ? text.call(this, this) : this.plain(text) - - return this - } - - // Shortcut dx - dx (dx) { - return this.attr('dx', dx) - } - - // Shortcut dy - dy (dy) { - return this.attr('dy', dy) - } - - // Create new line - newLine () { - // fetch text parent - 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()) - } -} - -extend(Tspan, textable) - -registerMethods({ - Tspan: { - tspan (text) { - var tspan = new Tspan() - - // clear if build mode is disabled - if (!this._build) { - this.clear() - } - - // add new tspan - this.node.appendChild(tspan.node) - - return tspan.text(text) - } - } -}) - -register(Tspan) diff --git a/src/Use.js b/src/Use.js deleted file mode 100644 index 5d4b5f4..0000000 --- a/src/Use.js +++ /dev/null @@ -1,28 +0,0 @@ -import Shape from './Shape.js' -import { xlink } from './namespaces.js' -import { register } from './adopter.js' -import { registerMethods } from './methods.js' -import { nodeOrNew } from './tools.js' - -export default class Use extends Shape { - constructor (node) { - super(nodeOrNew('use', node), Use) - } - - // Use element as a reference - element (element, file) { - // Set lined element - return this.attr('href', (file || '') + '#' + element, xlink) - } -} - -registerMethods({ - Container: { - // Create a use element - use: function (element, file) { - return this.put(new Use()).element(element, file) - } - } -}) - -register(Use) diff --git a/src/adopter.js b/src/adopter.js deleted file mode 100644 index ed692b8..0000000 --- a/src/adopter.js +++ /dev/null @@ -1,92 +0,0 @@ -import Base from './Base.js' -import { capitalize } from './helpers.js' -import { makeNode } from './tools.js' - -const elements = {} -export const root = Symbol('root') - -export function makeInstance (element) { - if (element instanceof Base) return element - - if (typeof element === 'object') { - return adopt(element) - } - - if (element == null) { - return new elements[root]() - } - - if (typeof element === 'string' && element.charAt(0) !== '<') { - return adopt(document.querySelector(element)) - } - - var node = makeNode('svg') - node.innerHTML = element - - // We can use firstChild here because we know, - // that the first char is < and thus an element - element = adopt(node.firstChild) - - return element -} - -// Adopt existing svg elements -export function adopt (node) { - // check for presence of node - if (!node) return null - - // make sure a node isn't already adopted - if (node.instance instanceof Base) return node.instance - - if (!(node instanceof window.SVGElement)) { - return new elements.HtmlNode(node) - } - - // initialize variables - var element - - // adopt with element-specific settings - if (node.nodeName === 'svg') { - element = new elements[root](node) - } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') { - element = new elements.Gradient(node) - } else if (elements[capitalize(node.nodeName)]) { - element = new elements[capitalize(node.nodeName)](node) - } else { - element = new elements.Bare(node) - } - - return element -} - -export function register (element, name = element.name, asRoot = false) { - elements[name] = element - if (asRoot) elements[root] = element - return element -} - -export function getClass (name) { - return elements[name] -} - -// Element id sequence -let did = 1000 - -// Get next named element id -export function eid (name) { - return 'Svgjs' + capitalize(name) + (did++) -} - -// Deep new id assignment -export function assignNewId (node) { - // do the same for SVG child nodes as well - for (var i = node.children.length - 1; i >= 0; i--) { - assignNewId(node.children[i]) - } - - if (node.id) { - return adopt(node).id(eid(node.nodeName)) - } - - return adopt(node) -} diff --git a/src/animation/Animator.js b/src/animation/Animator.js new file mode 100644 index 0000000..fdb2326 --- /dev/null +++ b/src/animation/Animator.js @@ -0,0 +1,85 @@ +import Queue from './Queue.js' + +const Animator = { + nextDraw: null, + frames: new Queue(), + timeouts: new Queue(), + timer: window.performance || window.Date, + transforms: [], + + frame (fn) { + // Store the node + var node = Animator.frames.push({ run: fn }) + + // Request an animation frame if we don't have one + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw) + } + + // Return the node so we can remove it easily + return node + }, + + transform_frame (fn, id) { + Animator.transforms[id] = fn + }, + + timeout (fn, delay) { + delay = delay || 0 + + // Work out when the event should fire + var time = Animator.timer.now() + delay + + // Add the timeout to the end of the queue + var node = Animator.timeouts.push({ run: fn, time: time }) + + // Request another animation frame if we need one + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw) + } + + return node + }, + + cancelFrame (node) { + Animator.frames.remove(node) + }, + + clearTimeout (node) { + Animator.timeouts.remove(node) + }, + + _draw (now) { + // Run all the timeouts we can run, if they are not ready yet, add them + // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) + var nextTimeout = null + var lastTimeout = Animator.timeouts.last() + while ((nextTimeout = Animator.timeouts.shift())) { + // Run the timeout if its time, or push it to the end + if (now >= nextTimeout.time) { + nextTimeout.run() + } else { + Animator.timeouts.push(nextTimeout) + } + + // If we hit the last item, we should stop shifting out more items + if (nextTimeout === lastTimeout) break + } + + // Run all of the animation frames + var nextFrame = null + var lastFrame = Animator.frames.last() + while ((nextFrame !== lastFrame) && (nextFrame = Animator.frames.shift())) { + nextFrame.run() + } + + Animator.transforms.forEach(function (el) { el() }) + + // If we have remaining timeouts or frames, draw until we don't anymore + Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() + ? window.requestAnimationFrame(Animator._draw) + : null + } +} + +export default Animator diff --git a/src/animation/Controller.js b/src/animation/Controller.js new file mode 100644 index 0000000..1716545 --- /dev/null +++ b/src/animation/Controller.js @@ -0,0 +1,173 @@ +import { timeline } from '../modules/core/defaults.js' +import { extend } from '../utils/adopter.js' + +/*** +Base Class +========== +The base stepper class that will be +***/ + +function makeSetterGetter (k, f) { + return function (v) { + if (v == null) return this[v] + this[k] = v + if (f) f.call(this) + return this + } +} + +export let easing = { + '-': function (pos) { return pos }, + '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, + '>': function (pos) { return Math.sin(pos * Math.PI / 2) }, + '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }, + bezier: function (t0, x0, t1, x1) { + return function (t) { + // TODO: FINISH + } + } +} + +export class Stepper { + done () { return false } +} + +/*** +Easing Functions +================ +***/ + +export class Ease extends Stepper { + constructor (fn) { + super() + this.ease = easing[fn || timeline.ease] || fn + } + + step (from, to, pos) { + if (typeof from !== 'number') { + return pos < 1 ? from : to + } + return from + (to - from) * this.ease(pos) + } +} + +/*** +Controller Types +================ +***/ + +export class Controller extends Stepper { + constructor (fn) { + super() + this.stepper = fn + } + + step (current, target, dt, c) { + return this.stepper(current, target, dt, c) + } + + done (c) { + return c.done + } +} + +function recalculate () { + // Apply the default parameters + var duration = (this._duration || 500) / 1000 + var overshoot = this._overshoot || 0 + + // Calculate the PID natural response + var eps = 1e-10 + var pi = Math.PI + var os = Math.log(overshoot / 100 + eps) + var zeta = -os / Math.sqrt(pi * pi + os * os) + var wn = 3.9 / (zeta * duration) + + // Calculate the Spring values + this.d = 2 * zeta * wn + this.k = wn * wn +} + +export class Spring extends Controller { + constructor (duration, overshoot) { + super() + this.duration(duration || 500) + .overshoot(overshoot || 0) + } + + step (current, target, dt, c) { + if (typeof current === 'string') return current + c.done = dt === Infinity + if (dt === Infinity) return target + if (dt === 0) return current + + if (dt > 100) dt = 16 + + dt /= 1000 + + // Get the previous velocity + var velocity = c.velocity || 0 + + // Apply the control to get the new position and store it + var acceleration = -this.d * velocity - this.k * (current - target) + var newPosition = current + + velocity * dt + + acceleration * dt * dt / 2 + + // Store the velocity + c.velocity = velocity + acceleration * dt + + // Figure out if we have converged, and if so, pass the value + c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002 + return c.done ? target : newPosition + } +} + +extend(Spring, { + duration: makeSetterGetter('_duration', recalculate), + overshoot: makeSetterGetter('_overshoot', recalculate) +}) + +export class PID extends Controller { + constructor (p, i, d, windup) { + super() + + p = p == null ? 0.1 : p + i = i == null ? 0.01 : i + d = d == null ? 0 : d + windup = windup == null ? 1000 : windup + this.p(p).i(i).d(d).windup(windup) + } + + step (current, target, dt, c) { + if (typeof current === 'string') return current + c.done = dt === Infinity + + if (dt === Infinity) return target + if (dt === 0) return current + + var p = target - current + var i = (c.integral || 0) + p * dt + var d = (p - (c.error || 0)) / dt + var windup = this.windup + + // antiwindup + if (windup !== false) { + i = Math.max(-windup, Math.min(i, windup)) + } + + c.error = p + c.integral = i + + c.done = Math.abs(p) < 0.001 + + return c.done ? target : current + (this.P * p + this.I * i + this.D * d) + } +} + +extend(PID, { + windup: makeSetterGetter('windup'), + p: makeSetterGetter('P'), + i: makeSetterGetter('I'), + d: makeSetterGetter('D') +}) diff --git a/src/animation/Queue.js b/src/animation/Queue.js new file mode 100644 index 0000000..14b92b4 --- /dev/null +++ b/src/animation/Queue.js @@ -0,0 +1,59 @@ +export default class Queue { + constructor () { + this._first = null + this._last = null + } + + push (value) { + // An item stores an id and the provided value + var item = value.next ? value : { value: value, next: null, prev: null } + + // Deal with the queue being empty or populated + if (this._last) { + item.prev = this._last + this._last.next = item + this._last = item + } else { + this._last = item + this._first = item + } + + // Update the length and return the current item + return item + } + + shift () { + // Check if we have a value + var remove = this._first + if (!remove) return null + + // If we do, remove it and relink things + this._first = remove.next + if (this._first) this._first.prev = null + this._last = this._first ? this._last : null + return remove.value + } + + // Shows us the first item in the list + first () { + return this._first && this._first.value + } + + // Shows us the last item in the list + last () { + return this._last && this._last.value + } + + // Removes the item that was returned from the push + remove (item) { + // Relink the previous item + if (item.prev) item.prev.next = item.next + if (item.next) item.next.prev = item.prev + if (item === this._last) this._last = item.prev + if (item === this._first) this._first = item.next + + // Invalidate item + item.prev = null + item.next = null + } +} diff --git a/src/animation/Runner.js b/src/animation/Runner.js new file mode 100644 index 0000000..f752185 --- /dev/null +++ b/src/animation/Runner.js @@ -0,0 +1,928 @@ +import { Controller, Ease, Stepper } from './Controller.js' +import { extend } from '../utils/adopter.js' +import { getOrigin } from '../utils/utils.js' +import { noop, timeline } from '../modules/core/defaults.js' +import { registerMethods } from '../utils/methods.js' +import Animator from './Animator.js' +import Box from '../types/Box.js' +import EventTarget from '../types/EventTarget.js' +import Matrix from '../types/Matrix.js' +import Morphable, { TransformBag } from '../types/Morphable.js' +import Point from '../types/Point.js' +import SVGNumber from '../types/SVGNumber.js' +import Timeline from './Timeline.js' + +export default class Runner extends EventTarget { + constructor (options) { + super() + + // Store a unique id on the runner, so that we can identify it later + this.id = Runner.id++ + + // Ensure a default value + options = options == null + ? timeline.duration + : options + + // Ensure that we get a controller + options = typeof options === 'function' + ? new Controller(options) + : options + + // Declare all of the variables + this._element = null + this._timeline = null + this.done = false + this._queue = [] + + // Work out the stepper and the duration + this._duration = typeof options === 'number' && options + this._isDeclarative = options instanceof Controller + this._stepper = this._isDeclarative ? options : new Ease() + + // We copy the current values from the timeline because they can change + this._history = {} + + // Store the state of the runner + this.enabled = true + this._time = 0 + this._last = 0 + + // Save transforms applied to this runner + this.transforms = new Matrix() + this.transformId = 1 + + // Looping variables + this._haveReversed = false + this._reverse = false + this._loopsDone = 0 + this._swing = false + this._wait = 0 + this._times = 1 + } + + /* + Runner Definitions + ================== + These methods help us define the runtime behaviour of the Runner or they + help us make new runners from the current runner + */ + + element (element) { + if (element == null) return this._element + this._element = element + element._prepareRunner() + return this + } + + timeline (timeline) { + // check explicitly for undefined so we can set the timeline to null + if (typeof timeline === 'undefined') return this._timeline + this._timeline = timeline + return this + } + + animate (duration, delay, when) { + var o = Runner.sanitise(duration, delay, when) + var runner = new Runner(o.duration) + if (this._timeline) runner.timeline(this._timeline) + if (this._element) runner.element(this._element) + return runner.loop(o).schedule(delay, when) + } + + schedule (timeline, delay, when) { + // The user doesn't need to pass a timeline if we already have one + if (!(timeline instanceof Timeline)) { + when = delay + delay = timeline + timeline = this.timeline() + } + + // If there is no timeline, yell at the user... + if (!timeline) { + throw Error('Runner cannot be scheduled without timeline') + } + + // Schedule the runner on the timeline provided + timeline.schedule(this, delay, when) + return this + } + + unschedule () { + var timeline = this.timeline() + timeline && timeline.unschedule(this) + return this + } + + loop (times, swing, wait) { + // Deal with the user passing in an object + if (typeof times === 'object') { + swing = times.swing + wait = times.wait + times = times.times + } + + // Sanitise the values and store them + this._times = times || Infinity + this._swing = swing || false + this._wait = wait || 0 + return this + } + + delay (delay) { + return this.animate(0, delay) + } + + /* + Basic Functionality + =================== + These methods allow us to attach basic functions to the runner directly + */ + + queue (initFn, runFn, isTransform) { + this._queue.push({ + initialiser: initFn || noop, + runner: runFn || noop, + isTransform: isTransform, + initialised: false, + finished: false + }) + var timeline = this.timeline() + timeline && this.timeline()._continue() + return this + } + + during (fn) { + return this.queue(null, fn) + } + + after (fn) { + return this.on('finish', fn) + } + + /* + Runner animation methods + ======================== + Control how the animation plays + */ + + time (time) { + if (time == null) { + return this._time + } + let dt = time - this._time + this.step(dt) + return this + } + + duration () { + return this._times * (this._wait + this._duration) - this._wait + } + + loops (p) { + var loopDuration = this._duration + this._wait + if (p == null) { + var loopsDone = Math.floor(this._time / loopDuration) + var relativeTime = (this._time - loopsDone * loopDuration) + var position = relativeTime / this._duration + return Math.min(loopsDone + position, this._times) + } + var whole = Math.floor(p) + var partial = p % 1 + var time = loopDuration * whole + this._duration * partial + return this.time(time) + } + + position (p) { + // Get all of the variables we need + var x = this._time + var d = this._duration + var w = this._wait + var t = this._times + var s = this._swing + var r = this._reverse + var position + + if (p == null) { + /* + This function converts a time to a position in the range [0, 1] + The full explanation can be found in this desmos demonstration + https://www.desmos.com/calculator/u4fbavgche + The logic is slightly simplified here because we can use booleans + */ + + // Figure out the value without thinking about the start or end time + const f = function (x) { + var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)) + var backwards = (swinging && !r) || (!swinging && r) + var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards + var clipped = Math.max(Math.min(uncliped, 1), 0) + return clipped + } + + // Figure out the value by incorporating the start time + var endTime = t * (w + d) - w + position = x <= 0 ? Math.round(f(1e-5)) + : x < endTime ? f(x) + : Math.round(f(endTime - 1e-5)) + return position + } + + // Work out the loops done and add the position to the loops done + var loopsDone = Math.floor(this.loops()) + var swingForward = s && (loopsDone % 2 === 0) + var forwards = (swingForward && !r) || (r && swingForward) + position = loopsDone + (forwards ? p : 1 - p) + return this.loops(position) + } + + progress (p) { + if (p == null) { + return Math.min(1, this._time / this.duration()) + } + return this.time(p * this.duration()) + } + + step (dt) { + // If we are inactive, this stepper just gets skipped + if (!this.enabled) return this + + // Update the time and get the new position + dt = dt == null ? 16 : dt + this._time += dt + var position = this.position() + + // Figure out if we need to run the stepper in this frame + var running = this._lastPosition !== position && this._time >= 0 + this._lastPosition = position + + // Figure out if we just started + var duration = this.duration() + var justStarted = this._lastTime < 0 && this._time > 0 + var justFinished = this._lastTime < this._time && this.time > duration + this._lastTime = this._time + if (justStarted) { + this.fire('start', this) + } + + // Work out if the runner is finished set the done flag here so animations + // know, that they are running in the last step (this is good for + // transformations which can be merged) + var declarative = this._isDeclarative + this.done = !declarative && !justFinished && this._time >= duration + + // Call initialise and the run function + if (running || declarative) { + this._initialise(running) + + // clear the transforms on this runner so they dont get added again and again + this.transforms = new Matrix() + var converged = this._run(declarative ? dt : position) + this.fire('step', this) + } + // correct the done flag here + // declaritive animations itself know when they converged + this.done = this.done || (converged && declarative) + if (this.done) { + this.fire('finish', this) + } + return this + } + + finish () { + return this.step(Infinity) + } + + reverse (reverse) { + this._reverse = reverse == null ? !this._reverse : reverse + return this + } + + ease (fn) { + this._stepper = new Ease(fn) + return this + } + + active (enabled) { + if (enabled == null) return this.enabled + this.enabled = enabled + return this + } + + /* + Private Methods + =============== + Methods that shouldn't be used externally + */ + + // Save a morpher to the morpher list so that we can retarget it later + _rememberMorpher (method, morpher) { + this._history[method] = { + morpher: morpher, + caller: this._queue[this._queue.length - 1] + } + } + + // Try to set the target for a morpher if the morpher exists, otherwise + // do nothing and return false + _tryRetarget (method, target) { + if (this._history[method]) { + // if the last method wasnt even initialised, throw it away + if (!this._history[method].caller.initialised) { + let index = this._queue.indexOf(this._history[method].caller) + this._queue.splice(index, 1) + return false + } + + // for the case of transformations, we use the special retarget function + // which has access to the outer scope + if (this._history[method].caller.isTransform) { + this._history[method].caller.isTransform(target) + // for everything else a simple morpher change is sufficient + } else { + this._history[method].morpher.to(target) + } + + this._history[method].caller.finished = false + var timeline = this.timeline() + timeline && timeline._continue() + return true + } + return false + } + + // Run each initialise function in the runner if required + _initialise (running) { + // If we aren't running, we shouldn't initialise when not declarative + if (!running && !this._isDeclarative) return + + // Loop through all of the initialisers + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current initialiser + var current = this._queue[i] + + // Determine whether we need to initialise + var needsIt = this._isDeclarative || (!current.initialised && running) + running = !current.finished + + // Call the initialiser if we need to + if (needsIt && running) { + current.initialiser.call(this) + current.initialised = true + } + } + } + + // Run each run function for the position or dt given + _run (positionOrDt) { + // Run all of the _queue directly + var allfinished = true + for (var i = 0, len = this._queue.length; i < len; ++i) { + // Get the current function to run + var current = this._queue[i] + + // Run the function if its not finished, we keep track of the finished + // flag for the sake of declarative _queue + var converged = current.runner.call(this, positionOrDt) + current.finished = current.finished || (converged === true) + allfinished = allfinished && current.finished + } + + // We report when all of the constructors are finished + return allfinished + } + + addTransform (transform, index) { + this.transforms.lmultiplyO(transform) + return this + } + + clearTransform () { + this.transforms = new Matrix() + return this + } + + static sanitise (duration, delay, when) { + // Initialise the default parameters + var times = 1 + var swing = false + var wait = 0 + duration = duration || timeline.duration + delay = delay || timeline.delay + when = when || 'last' + + // If we have an object, unpack the values + if (typeof duration === 'object' && !(duration instanceof Stepper)) { + delay = duration.delay || delay + when = duration.when || when + swing = duration.swing || swing + times = duration.times || times + wait = duration.wait || wait + duration = duration.duration || timeline.duration + } + + return { + duration: duration, + delay: delay, + swing: swing, + times: times, + wait: wait, + when: when + } + } +} + +Runner.id = 0 + +class FakeRunner { + constructor (transforms = new Matrix(), id = -1, done = true) { + this.transforms = transforms + this.id = id + this.done = done + } +} + +extend([Runner, FakeRunner], { + mergeWith (runner) { + return new FakeRunner( + runner.transforms.lmultiply(this.transforms), + runner.id + ) + } +}) + +// FakeRunner.emptyRunner = new FakeRunner() + +const lmultiply = (last, curr) => last.lmultiplyO(curr) +const getRunnerTransform = (runner) => runner.transforms + +function mergeTransforms () { + // Find the matrix to apply to the element and apply it + let runners = this._transformationRunners.runners + let netTransform = runners + .map(getRunnerTransform) + .reduce(lmultiply, new Matrix()) + + this.transform(netTransform) + + this._transformationRunners.merge() + + if (this._transformationRunners.length() === 1) { + this._frameId = null + } +} + +class RunnerArray { + constructor () { + this.runners = [] + this.ids = [] + } + + add (runner) { + if (this.runners.includes(runner)) return + + let id = runner.id + 1 + + let leftSibling = this.ids.reduce((last, curr) => { + if (curr > last && curr < id) return curr + return last + }, 0) + + let index = this.ids.indexOf(leftSibling) + 1 + + this.ids.splice(index, 0, id) + this.runners.splice(index, 0, runner) + + return this + } + + getByID (id) { + return this.runners[this.ids.indexOf(id + 1)] + } + + remove (id) { + let index = this.ids.indexOf(id + 1) + this.ids.splice(index, 1) + this.runners.splice(index, 1) + return this + } + + merge () { + let lastRunner = null + this.runners.forEach((runner, i) => { + if (lastRunner && runner.done && lastRunner.done) { + this.remove(runner.id) + this.edit(lastRunner.id, runner.mergeWith(lastRunner)) + } + + lastRunner = runner + }) + + return this + } + + edit (id, newRunner) { + let index = this.ids.indexOf(id + 1) + this.ids.splice(index, 1, id) + this.runners.splice(index, 1, newRunner) + return this + } + + length () { + return this.ids.length + } + + clearBefore (id) { + let deleteCnt = this.ids.indexOf(id + 1) || 1 + this.ids.splice(0, deleteCnt, 0) + this.runners.splice(0, deleteCnt, new FakeRunner()) + return this + } +} + +let frameId = 0 +registerMethods({ + Element: { + animate (duration, delay, when) { + var o = Runner.sanitise(duration, delay, when) + var timeline = this.timeline() + return new Runner(o.duration) + .loop(o) + .element(this) + .timeline(timeline) + .schedule(delay, when) + }, + + delay (by, when) { + return this.animate(0, by, when) + }, + + // this function searches for all runners on the element and deletes the ones + // which run before the current one. This is because absolute transformations + // overwfrite anything anyway so there is no need to waste time computing + // other runners + _clearTransformRunnersBefore (currentRunner) { + this._transformationRunners.clearBefore(currentRunner.id) + }, + + _currentTransform (current) { + return this._transformationRunners.runners + // we need the equal sign here to make sure, that also transformations + // on the same runner which execute before the current transformation are + // taken into account + .filter((runner) => runner.id <= current.id) + .map(getRunnerTransform) + .reduce(lmultiply, new Matrix()) + }, + + addRunner (runner) { + this._transformationRunners.add(runner) + + Animator.transform_frame( + mergeTransforms.bind(this), this._frameId + ) + }, + + _prepareRunner () { + if (this._frameId == null) { + this._transformationRunners = new RunnerArray() + .add(new FakeRunner(new Matrix(this))) + + this._frameId = frameId++ + } + } + } +}) + +extend(Runner, { + attr (a, v) { + return this.styleAttr('attr', a, v) + }, + + // Add animatable styles + css (s, v) { + return this.styleAttr('css', s, v) + }, + + styleAttr (type, name, val) { + // apply attributes individually + if (typeof name === 'object') { + for (var key in val) { + this.styleAttr(type, key, val[key]) + } + } + + var morpher = new Morphable(this._stepper).to(val) + + this.queue(function () { + morpher = morpher.from(this.element()[type](name)) + }, function (pos) { + this.element()[type](name, morpher.at(pos)) + return morpher.done() + }) + + return this + }, + + zoom (level, point) { + var morpher = new Morphable(this._stepper).to(new SVGNumber(level)) + + this.queue(function () { + morpher = morpher.from(this.zoom()) + }, function (pos) { + this.element().zoom(morpher.at(pos), point) + return morpher.done() + }) + + return this + }, + + /** + ** absolute transformations + **/ + + // + // M v -----|-----(D M v = F v)------|-----> T v + // + // 1. define the final state (T) and decompose it (once) + // t = [tx, ty, the, lam, sy, sx] + // 2. on every frame: pull the current state of all previous transforms + // (M - m can change) + // and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0] + // 3. Find the interpolated matrix F(pos) = m + pos * (t - m) + // - Note F(0) = M + // - Note F(1) = T + // 4. Now you get the delta matrix as a result: D = F * inv(M) + + transform (transforms, relative, affine) { + // If we have a declarative function, we should retarget it if possible + relative = transforms.relative || relative + if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { + return this + } + + // Parse the parameters + var isMatrix = Matrix.isMatrixLike(transforms) + affine = transforms.affine != null + ? transforms.affine + : (affine != null ? affine : !isMatrix) + + // Create a morepher and set its type + const morpher = new Morphable() + .type(affine ? TransformBag : Matrix) + .stepper(this._stepper) + + let origin + let element + let current + let currentAngle + let startTransform + + function setup () { + // make sure element and origin is defined + element = element || this.element() + origin = origin || getOrigin(transforms, element) + + startTransform = new Matrix(relative ? undefined : element) + + // add the runner to the element so it can merge transformations + element.addRunner(this) + + // Deactivate all transforms that have run so far if we are absolute + if (!relative) { + element._clearTransformRunnersBefore(this) + } + } + + function run (pos) { + // clear all other transforms before this in case something is saved + // on this runner. We are absolute. We dont need these! + if (!relative) this.clearTransform() + + let { x, y } = new Point(origin).transform(element._currentTransform(this)) + + let target = new Matrix({ ...transforms, origin: [x, y] }) + let start = this._isDeclarative && current + ? current + : startTransform + + if (affine) { + target = target.decompose(x, y) + start = start.decompose(x, y) + + // Get the current and target angle as it was set + const rTarget = target.rotate + const rCurrent = start.rotate + + // Figure out the shortest path to rotate directly + const possibilities = [rTarget - 360, rTarget, rTarget + 360] + const distances = possibilities.map(a => Math.abs(a - rCurrent)) + const shortest = Math.min(...distances) + const index = distances.indexOf(shortest) + target.rotate = possibilities[index] + } + + if (relative) { + // we have to be careful here not to overwrite the rotation + // with the rotate method of Matrix + if (!isMatrix) { + target.rotate = transforms.rotate || 0 + } + if (this._isDeclarative && currentAngle) { + start.rotate = currentAngle + } + } + + morpher.from(start) + morpher.to(target) + + let affineParameters = morpher.at(pos) + currentAngle = affineParameters.rotate + current = new Matrix(affineParameters) + + this.addTransform(current) + return morpher.done() + } + + function retarget (newTransforms) { + // only get a new origin if it changed since the last call + if ( + (newTransforms.origin || 'center').toString() !== + (transforms.origin || 'center').toString() + ) { + origin = getOrigin(transforms, element) + } + + // overwrite the old transformations with the new ones + transforms = { ...newTransforms, origin } + } + + this.queue(setup, run, retarget) + this._isDeclarative && this._rememberMorpher('transform', morpher) + return this + }, + + // Animatable x-axis + x (x, relative) { + return this._queueNumber('x', x) + }, + + // Animatable y-axis + y (y) { + return this._queueNumber('y', y) + }, + + dx (x) { + return this._queueNumberDelta('dx', x) + }, + + dy (y) { + return this._queueNumberDelta('dy', y) + }, + + _queueNumberDelta (method, to) { + to = new SVGNumber(to) + + // Try to change the target if we have this method already registerd + if (this._tryRetargetDelta(method, to)) return this + + // Make a morpher and queue the animation + var morpher = new Morphable(this._stepper).to(to) + this.queue(function () { + var from = this.element()[method]() + morpher.from(from) + morpher.to(from + to) + }, function (pos) { + this.element()[method](morpher.at(pos)) + return morpher.done() + }) + + // Register the morpher so that if it is changed again, we can retarget it + this._rememberMorpher(method, morpher) + return this + }, + + _queueObject (method, to) { + // Try to change the target if we have this method already registerd + if (this._tryRetarget(method, to)) return this + + // Make a morpher and queue the animation + var morpher = new Morphable(this._stepper).to(to) + this.queue(function () { + morpher.from(this.element()[method]()) + }, function (pos) { + this.element()[method](morpher.at(pos)) + return morpher.done() + }) + + // Register the morpher so that if it is changed again, we can retarget it + this._rememberMorpher(method, morpher) + return this + }, + + _queueNumber (method, value) { + return this._queueObject(method, new SVGNumber(value)) + }, + + // Animatable center x-axis + cx (x) { + return this._queueNumber('cx', x) + }, + + // Animatable center y-axis + cy (y) { + return this._queueNumber('cy', y) + }, + + // Add animatable move + move (x, y) { + return this.x(x).y(y) + }, + + // Add animatable center + center (x, y) { + return this.cx(x).cy(y) + }, + + // Add animatable size + size (width, height) { + // animate bbox based size for all other elements + var box + + if (!width || !height) { + box = this._element.bbox() + } + + if (!width) { + width = box.width / box.height * height + } + + if (!height) { + height = box.height / box.width * width + } + + return this + .width(width) + .height(height) + }, + + // Add animatable width + width (width) { + return this._queueNumber('width', width) + }, + + // Add animatable height + height (height) { + return this._queueNumber('height', height) + }, + + // Add animatable plot + plot (a, b, c, d) { + // Lines can be plotted with 4 arguments + if (arguments.length === 4) { + return this.plot([a, b, c, d]) + } + + // FIXME: this needs to be rewritten such that the element is only accesed + // in the init function + return this._queueObject('plot', new this._element.MorphArray(a)) + + /* + var morpher = this._element.morphArray().to(a) + + this.queue(function () { + morpher.from(this._element.array()) + }, function (pos) { + this._element.plot(morpher.at(pos)) + }) + + return this + */ + }, + + // Add leading method + leading (value) { + return this._queueNumber('leading', value) + }, + + // Add animatable viewbox + viewbox (x, y, width, height) { + return this._queueObject('viewbox', new Box(x, y, width, height)) + }, + + update (o) { + if (typeof o !== 'object') { + return this.update({ + offset: arguments[0], + color: arguments[1], + opacity: arguments[2] + }) + } + + 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', o.offset) + + return this + } +}) diff --git a/src/animation/Timeline.js b/src/animation/Timeline.js new file mode 100644 index 0000000..619e50a --- /dev/null +++ b/src/animation/Timeline.js @@ -0,0 +1,271 @@ +import { registerMethods } from '../utils/methods.js' +import Animator from './Animator.js' + +var time = window.performance || Date + +var makeSchedule = function (runnerInfo) { + var start = runnerInfo.start + var duration = runnerInfo.runner.duration() + var end = start + duration + return { start: start, duration: duration, end: end, runner: runnerInfo.runner } +} + +export default class Timeline { + // Construct a new timeline on the given element + constructor () { + this._timeSource = function () { + return time.now() + } + + this._dispatcher = document.createElement('div') + + // Store the timing variables + this._startTime = 0 + this._speed = 1.0 + + // Play control variables control how the animation proceeds + this._reverse = false + this._persist = 0 + + // Keep track of the running animations and their starting parameters + this._nextFrame = null + this._paused = false + this._runners = [] + this._order = [] + this._time = 0 + this._lastSourceTime = 0 + this._lastStepTime = 0 + } + + getEventTarget () { + return this._dispatcher + } + + /** + * + */ + + // schedules a runner on the timeline + schedule (runner, delay, when) { + if (runner == null) { + return this._runners.map(makeSchedule).sort(function (a, b) { + return (a.start - b.start) || (a.duration - b.duration) + }) + } + + if (!this.active()) { + this._step() + if (when == null) { + when = 'now' + } + } + + // The start time for the next animation can either be given explicitly, + // derived from the current timeline time or it can be relative to the + // last start time to chain animations direclty + var absoluteStartTime = 0 + delay = delay || 0 + + // Work out when to start the animation + if (when == null || when === 'last' || when === 'after') { + // Take the last time and increment + absoluteStartTime = this._startTime + } else if (when === 'absolute' || when === 'start') { + absoluteStartTime = delay + delay = 0 + } else if (when === 'now') { + absoluteStartTime = this._time + } else if (when === 'relative') { + let runnerInfo = this._runners[runner.id] + if (runnerInfo) { + absoluteStartTime = runnerInfo.start + delay + delay = 0 + } + } else { + throw new Error('Invalid value for the "when" parameter') + } + + // Manage runner + runner.unschedule() + runner.timeline(this) + runner.time(-delay) + + // Save startTime for next runner + this._startTime = absoluteStartTime + runner.duration() + delay + + // Save runnerInfo + this._runners[runner.id] = { + persist: this.persist(), + runner: runner, + start: absoluteStartTime + } + + // Save order and continue + this._order.push(runner.id) + this._continue() + return this + } + + // Remove the runner from this timeline + unschedule (runner) { + var index = this._order.indexOf(runner.id) + if (index < 0) return this + + delete this._runners[runner.id] + this._order.splice(index, 1) + runner.timeline(null) + return this + } + + play () { + // Now make sure we are not paused and continue the animation + this._paused = false + return this._continue() + } + + pause () { + // Cancel the next animation frame and pause + this._nextFrame = null + this._paused = true + return this + } + + stop () { + // Cancel the next animation frame and go to start + this.seek(-this._time) + return this.pause() + } + + finish () { + this.seek(Infinity) + return this.pause() + } + + speed (speed) { + if (speed == null) return this._speed + this._speed = speed + return this + } + + reverse (yes) { + var currentSpeed = this.speed() + if (yes == null) return this.speed(-currentSpeed) + + var positive = Math.abs(currentSpeed) + return this.speed(yes ? positive : -positive) + } + + seek (dt) { + this._time += dt + return this._continue() + } + + time (time) { + if (time == null) return this._time + this._time = time + return this + } + + persist (dtOrForever) { + if (dtOrForever == null) return this._persist + this._persist = dtOrForever + return this + } + + source (fn) { + if (fn == null) return this._timeSource + this._timeSource = fn + return this + } + + _step () { + // If the timeline is paused, just do nothing + if (this._paused) return + + // Get the time delta from the last time and update the time + // TODO: Deal with window.blur window.focus to pause animations + var time = this._timeSource() + var dtSource = time - this._lastSourceTime + var dtTime = this._speed * dtSource + (this._time - this._lastStepTime) + this._lastSourceTime = time + + // Update the time + this._time += dtTime + this._lastStepTime = this._time + // this.fire('time', this._time) + + // Run all of the runners directly + var runnersLeft = false + for (var i = 0, len = this._order.length; i < len; i++) { + // Get and run the current runner and ignore it if its inactive + var runnerInfo = this._runners[this._order[i]] + var runner = runnerInfo.runner + let dt = dtTime + + // Make sure that we give the actual difference + // between runner start time and now + let dtToStart = this._time - runnerInfo.start + + // Dont run runner if not started yet + if (dtToStart < 0) { + runnersLeft = true + continue + } else if (dtToStart < dt) { + // Adjust dt to make sure that animation is on point + dt = dtToStart + } + + if (!runner.active()) continue + + // If this runner is still going, signal that we need another animation + // frame, otherwise, remove the completed runner + var finished = runner.step(dt).done + if (!finished) { + runnersLeft = true + // continue + } else if (runnerInfo.persist !== true) { + // runner is finished. And runner might get removed + + // TODO: Figure out end time of runner + var endTime = runner.duration() - runner.time() + this._time + + if (endTime + this._persist < this._time) { + // Delete runner and correct index + delete this._runners[this._order[i]] + this._order.splice(i--, 1) && --len + runner.timeline(null) + } + } + } + + // Get the next animation frame to keep the simulation going + if (runnersLeft) { + this._nextFrame = Animator.frame(this._step.bind(this)) + } else { + this._nextFrame = null + } + return this + } + + // Checks if we are running and continues the animation + _continue () { + if (this._paused) return this + if (!this._nextFrame) { + this._nextFrame = Animator.frame(this._step.bind(this)) + } + return this + } + + active () { + return !!this._nextFrame + } +} + +registerMethods({ + Element: { + timeline: function () { + this._timeline = (this._timeline || new Timeline()) + return this._timeline + } + } +}) diff --git a/src/arrange.js b/src/arrange.js deleted file mode 100644 index 169cf93..0000000 --- a/src/arrange.js +++ /dev/null @@ -1,99 +0,0 @@ -// ### This module adds backward / forward functionality to elements. -import { registerMethods } from './methods.js' - -// Get all siblings, including myself -export function siblings () { - return this.parent().children() -} - -// Get the curent position siblings -export function position () { - return this.parent().index(this) -} - -// Get the next element (will return null if there is none) -export function next () { - return this.siblings()[this.position() + 1] -} - -// Get the next element (will return null if there is none) -export function prev () { - return this.siblings()[this.position() - 1] -} - -// Send given element one step forward -export function forward () { - var i = this.position() + 1 - 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) - } - - return this -} - -// Send given element one step backward -export function backward () { - var i = this.position() - - if (i > 0) { - this.parent().removeElement(this).add(this, i - 1) - } - - return this -} - -// Send given element all the way to the front -export function front () { - var p = this.parent() - - // Move node forward - p.node.appendChild(this.node) - - // Make sure defs node is always at the top - if (typeof p.isRoot === 'function' && p.isRoot()) { - p.node.appendChild(p.defs().node) - } - - return this -} - -// Send given element all the way to the back -export function back () { - if (this.position() > 0) { - this.parent().removeElement(this).add(this, 0) - } - - return this -} - -// Inserts a given element before the targeted element -export function before (element) { - element.remove() - - var i = this.position() - - this.parent().add(element, i) - - return this -} - -// Inserts a given element after the targeted element -export function after (element) { - element.remove() - - var i = this.position() - - this.parent().add(element, i + 1) - - return this -} - -registerMethods('Dom', { - siblings, position, next, prev, forward, backward, front, back, before, after -}) diff --git a/src/attr.js b/src/attr.js deleted file mode 100644 index f3aa230..0000000 --- a/src/attr.js +++ /dev/null @@ -1,81 +0,0 @@ -import { isNumber, isImage } from './regex.js' -import { attrs as defaults } from './defaults.js' -import Color from './Color.js' -import SVGArray from './SVGArray.js' -import SVGNumber from './SVGNumber.js' -// import {registerMethods} from './methods.js' - -// Set svg element attribute -export default function attr (attr, val, ns) { - // act as full getter - if (attr == null) { - // get an object of attributes - attr = {} - val = this.node.attributes - - for (let node of val) { - attr[node.nodeName] = isNumber.test(node.nodeValue) - ? parseFloat(node.nodeValue) - : node.nodeValue - } - - return attr - } else if (Array.isArray(attr)) { - // FIXME: implement - } else if (typeof attr === 'object') { - // apply every attribute individually if an object is passed - for (val in attr) this.attr(val, attr[val]) - } else if (val === null) { - // remove value - this.node.removeAttribute(attr) - } else if (val == null) { - // act as a getter if the first and only argument is not an object - val = this.node.getAttribute(attr) - return val == null ? defaults[attr] // FIXME: do we need to return defaults? - : isNumber.test(val) ? parseFloat(val) - : val - } else { - // convert image fill and stroke to patterns - if (attr === 'fill' || attr === 'stroke') { - if (isImage.test(val)) { - val = this.doc().defs().image(val) - } - } - - // FIXME: This is fine, but what about the lines above? - // How does attr know about image()? - while (typeof val.attrHook === 'function') { - val = val.attrHook(this, attr) - } - - // ensure correct numeric values (also accepts NaN and Infinity) - if (typeof val === 'number') { - val = new SVGNumber(val) - } else if (Color.isColor(val)) { - // ensure full hex color - val = new Color(val) - } else if (val.constructor === Array) { - // Check for plain arrays and parse array values - val = new SVGArray(val) - } - - // if the passed attribute is leading... - if (attr === 'leading') { - // ... call the leading method instead - if (this.leading) { - this.leading(val) - } - } else { - // set given attribute on node - typeof ns === 'string' ? this.node.setAttributeNS(ns, attr, val.toString()) - : this.node.setAttribute(attr, val.toString()) - } - - // rebuild if required - if (this.rebuild && (attr === 'font-size' || attr === 'x')) { - this.rebuild() - } - } - - return this -} diff --git a/src/circled.js b/src/circled.js deleted file mode 100644 index 7df7a5b..0000000 --- a/src/circled.js +++ /dev/null @@ -1,64 +0,0 @@ -// FIXME: import this to runner -import { proportionalSize } from './helpers.js' -import SVGNumber from './SVGNumber.js' - -// Radius x value -export function rx (rx) { - return this.attr('rx', rx) -} - -// Radius y value -export function ry (ry) { - return this.attr('ry', ry) -} - -// Move over x-axis -export function x (x) { - return x == null - ? this.cx() - this.rx() - : this.cx(x + this.rx()) -} - -// Move over y-axis -export function y (y) { - return y == null - ? this.cy() - this.ry() - : this.cy(y + this.ry()) -} - -// Move by center over x-axis -export function cx (x) { - return x == null - ? this.attr('cx') - : this.attr('cx', x) -} - -// Move by center over y-axis -export function cy (y) { - return y == null - ? this.attr('cy') - : this.attr('cy', y) -} - -// Set width of element -export function width (width) { - return width == null - ? this.rx() * 2 - : this.rx(new SVGNumber(width).divide(2)) -} - -// Set height of element -export function height (height) { - return height == null - ? this.ry() * 2 - : this.ry(new SVGNumber(height).divide(2)) -} - -// Custom size function -export function 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)) -} diff --git a/src/classHandling.js b/src/classHandling.js deleted file mode 100644 index fd148b7..0000000 --- a/src/classHandling.js +++ /dev/null @@ -1,44 +0,0 @@ -import { registerMethods } from './methods.js' -import { delimiter } from './regex.js' - -// Return array of classes on the node -function classes () { - var attr = this.attr('class') - return attr == null ? [] : attr.trim().split(delimiter) -} - -// Return true if class exists on the node, false otherwise -function hasClass (name) { - return this.classes().indexOf(name) !== -1 -} - -// Add class to the node -function addClass (name) { - if (!this.hasClass(name)) { - var array = this.classes() - array.push(name) - this.attr('class', array.join(' ')) - } - - return this -} - -// Remove class from the node -function removeClass (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 -function toggleClass (name) { - return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) -} - -registerMethods('Dom', { - classes, hasClass, addClass, removeClass, toggleClass -}) diff --git a/src/classes.js b/src/classes.js deleted file mode 100644 index 8e1b866..0000000 --- a/src/classes.js +++ /dev/null @@ -1,44 +0,0 @@ -export { default as Animator } from './Animator.js' -export { default as SVGArray } from './SVGArray.js' -export { default as Bare } from './Bare.js' -export { default as Box } from './Box.js' -export { default as Circle } from './Circle.js' -export { default as ClipPath } from './ClipPath.js' -export { default as Color } from './Color.js' -export { default as Container } from './Container.js' -export { Controller, Ease, PID, Spring } from './Controller.js' -export { default as Defs } from './Defs.js' -export { default as Doc } from './Doc.js' -export { default as Dom } from './Dom.js' -export { default as Element } from './Element.js' -export { default as Ellipse } from './Ellipse.js' -export { default as EventTarget } from './EventTarget.js' -export { default as Gradient } from './Gradient.js' -export { default as G } from './G.js' -export { default as HtmlNode } from './HtmlNode.js' -export { default as A } from './A.js' -export { default as Image } from './Image.js' -export { default as Line } from './Line.js' -export { default as Marker } from './Marker.js' -export { default as Mask } from './Mask.js' -export { default as Matrix } from './Matrix.js' -export { default as Morphable } from './Morphable.js' -export { default as SVGNumber } from './SVGNumber.js' -export { default as Path } from './Path.js' -export { default as PathArray } from './PathArray.js' -export { default as Pattern } from './Pattern.js' -export { default as Point } from './Point.js' -export { default as PointArray } from './PointArray.js' -export { default as Polygon } from './Polygon.js' -export { default as Polyline } from './Polyline.js' -export { default as Queue } from './Queue.js' -export { default as Rect } from './Rect.js' -export { default as Runner } from './Runner.js' -export { default as Shape } from './Shape.js' -export { default as Stop } from './Stop.js' -export { default as Symbol } from './Symbol.js' -export { default as Text } from './Text.js' -export { default as TextPath } from './TextPath.js' -export { default as Timeline } from './Timeline.js' -export { default as Tspan } from './Tspan.js' -export { default as Use } from './Use.js' diff --git a/src/css.js b/src/css.js deleted file mode 100644 index a7d38a6..0000000 --- a/src/css.js +++ /dev/null @@ -1,72 +0,0 @@ -import { camelCase } from './helpers.js' -import { isBlank } from './regex.js' -import { registerMethods } from './methods.js' - -// FIXME: We dont need exports - -// Dynamic style generator -export function css (style, val) { - let ret = {} - if (arguments.length === 0) { - // get full style as object - this.node.style.cssText.split(/\s*;\s*/) - .filter(function (el) { return !!el.length }) - .forEach(function (el) { - let t = el.split(/\s*:\s*/) - ret[t[0]] = t[1] - }) - return ret - } - - if (arguments.length < 2) { - // get style properties in the array - if (Array.isArray(style)) { - for (let name of style) { - let cased = camelCase(name) - ret[cased] = this.node.style[cased] - } - return ret - } - - // get style for property - if (typeof style === 'string') { - return this.node.style[camelCase(style)] - } - - // set styles in object - if (typeof style === 'object') { - for (let name in style) { - // set empty string if null/undefined/'' was given - this.node.style[camelCase(name)] = - (style[name] == null || isBlank.test(style[name])) ? '' : style[name] - } - } - } - - // set style for property - if (arguments.length === 2) { - this.node.style[camelCase(style)] = - (val == null || isBlank.test(val)) ? '' : val - } - - return this -} - -// Show element -export function show () { - return this.css('display', '') -} - -// Hide element -export function hide () { - return this.css('display', 'none') -} - -// Is element visible? -export function visible () { - return this.css('display') !== 'none' -} - -registerMethods('Dom', { - css, show, hide, visible -}) diff --git a/src/data.js b/src/data.js deleted file mode 100644 index ce50abb..0000000 --- a/src/data.js +++ /dev/null @@ -1,26 +0,0 @@ -import { registerMethods } from './methods.js' - -// Store data values on svg nodes -export function data (a, v, r) { - if (typeof a === 'object') { - for (v in a) { - this.data(v, a[v]) - } - } else if (arguments.length < 2) { - try { - return JSON.parse(this.attr('data-' + a)) - } catch (e) { - return this.attr('data-' + a) - } - } else { - this.attr('data-' + a, - v === null ? null - : r === true || typeof v === 'string' || typeof v === 'number' ? v - : JSON.stringify(v) - ) - } - - return this -} - -registerMethods('Dom', { data }) diff --git a/src/defaults.js b/src/defaults.js deleted file mode 100644 index 0d496bc..0000000 --- a/src/defaults.js +++ /dev/null @@ -1,48 +0,0 @@ - -export function noop () {} - -// Default animation values -export let timeline = { - duration: 400, - ease: '>', - delay: 0 -} - -// Default attribute values -export let attrs = { - - // fill and stroke - 'fill-opacity': 1, - 'stroke-opacity': 1, - 'stroke-width': 0, - 'stroke-linejoin': 'miter', - 'stroke-linecap': 'butt', - fill: '#000000', - stroke: '#000000', - opacity: 1, - - // position - x: 0, - y: 0, - cx: 0, - cy: 0, - - // size - width: 0, - height: 0, - - // radius - r: 0, - rx: 0, - ry: 0, - - // gradient - offset: 0, - 'stop-opacity': 1, - 'stop-color': '#000000', - - // text - 'font-size': 16, - 'font-family': 'Helvetica, Arial, sans-serif', - 'text-anchor': 'start' -} diff --git a/src/elements/A.js b/src/elements/A.js new file mode 100644 index 0000000..68da597 --- /dev/null +++ b/src/elements/A.js @@ -0,0 +1,43 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import { xlink } from '../modules/core/namespaces.js' +import Container from './Container.js' + +export default class A extends Container { + constructor (node) { + super(nodeOrNew('a', node), A) + } + + // Link url + to (url) { + return this.attr('href', url, xlink) + } + + // Link target attribute + target (target) { + return this.attr('target', target) + } +} + +registerMethods({ + Container: { + // Create a hyperlink element + link: function (url) { + return this.put(new A()).to(url) + } + }, + Element: { + // Create a hyperlink element + linkTo: function (url) { + var link = new A() + + if (typeof url === 'function') { url.call(link, link) } else { + link.to(url) + } + + return this.parent().put(link).put(this) + } + } +}) + +register(A) diff --git a/src/elements/Bare.js b/src/elements/Bare.js new file mode 100644 index 0000000..43fc075 --- /dev/null +++ b/src/elements/Bare.js @@ -0,0 +1,30 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import Container from './Container.js' + +export default class Bare extends Container { + constructor (node) { + super(nodeOrNew(node, typeof node === 'string' ? null : node), Bare) + } + + words (text) { + // remove contents + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild) + } + + // create text node + this.node.appendChild(document.createTextNode(text)) + + return this + } +} + +register(Bare) + +registerMethods('Container', { + // Create an element that is not described by SVG.js + element (node, inherit) { + return this.put(new Bare(node, inherit)) + } +}) diff --git a/src/elements/Circle.js b/src/elements/Circle.js new file mode 100644 index 0000000..c296885 --- /dev/null +++ b/src/elements/Circle.js @@ -0,0 +1,40 @@ +import { cx, cy, height, size, width, x, y } from '../modules/core/circled.js' +import { extend, nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import SVGNumber from '../types/SVGNumber.js' +import Shape from './Shape.js' + +export default class Circle extends Shape { + constructor (node) { + super(nodeOrNew('circle', node), Circle) + } + + radius (r) { + return this.attr('r', r) + } + + // Radius x value + rx (rx) { + return this.attr('r', rx) + } + + // Alias radius x value + ry (ry) { + return this.rx(ry) + } +} + +extend(Circle, { x, y, cx, cy, width, height, size }) + +registerMethods({ + Element: { + // Create circle element + circle (size) { + return this.put(new Circle()) + .radius(new SVGNumber(size).divide(2)) + .move(0, 0) + } + } +}) + +register(Circle) diff --git a/src/elements/ClipPath.js b/src/elements/ClipPath.js new file mode 100644 index 0000000..2828d6e --- /dev/null +++ b/src/elements/ClipPath.js @@ -0,0 +1,57 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import Container from './Container.js' +import baseFind from '../modules/core/selector.js' + +export default class ClipPath extends Container { + constructor (node) { + super(nodeOrNew('clipPath', node), ClipPath) + } + + // Unclip all clipped elements and remove itself + remove () { + // unclip all targets + this.targets().forEach(function (el) { + el.unclip() + }) + + // remove clipPath from parent + return super.remove() + } + + targets () { + return baseFind('svg [clip-path*="' + this.id() + '"]') + } +} + +registerMethods({ + Container: { + // Create clipping element + clip: function () { + return this.defs().put(new ClipPath()) + } + }, + Element: { + // Distribute clipPath to svg element + clipWith (element) { + // use given clip or create a new one + let clipper = element instanceof ClipPath + ? element + : this.parent().clip().add(element) + + // apply mask + return this.attr('clip-path', 'url("#' + clipper.id() + '")') + }, + + // Unclip element + unclip () { + return this.attr('clip-path', null) + }, + + clipper () { + return this.reference('clip-path') + } + } +}) + +register(ClipPath) diff --git a/src/elements/Container.js b/src/elements/Container.js new file mode 100644 index 0000000..cdf8495 --- /dev/null +++ b/src/elements/Container.js @@ -0,0 +1,27 @@ +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) + }) + + // we need this so that Doc does not get removed + this.node.firstElementChild || this.remove() + + return this + } + + ungroup (parent) { + parent = parent || this.parent() + + this.each(function () { + return this.toParent(parent) + }) + + this.remove() + + return this + } +} diff --git a/src/elements/Defs.js b/src/elements/Defs.js new file mode 100644 index 0000000..58932cb --- /dev/null +++ b/src/elements/Defs.js @@ -0,0 +1,13 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import Container from './Container.js' + +export default class Defs extends Container { + constructor (node) { + super(nodeOrNew('defs', node), Defs) + } + + flatten () { return this } + ungroup () { return this } +} + +register(Defs) diff --git a/src/elements/Doc.js b/src/elements/Doc.js new file mode 100644 index 0000000..8d450ce --- /dev/null +++ b/src/elements/Doc.js @@ -0,0 +1,72 @@ +import { adopt, nodeOrNew, register } from '../utils/adopter.js' +import { ns, svgjs, xlink, xmlns } from '../modules/core/namespaces.js' +import { registerMethods } from '../utils/methods.js' +import Container from './Container.js' +import Defs from './Defs.js' + +export default class Doc extends Container { + constructor (node) { + super(nodeOrNew('svg', node), Doc) + this.namespace() + } + + isRoot () { + return !this.node.parentNode || + !(this.node.parentNode instanceof window.SVGElement) || + this.node.parentNode.nodeName === '#document' + } + + // Check if this is a root svg + // If not, call docs from this element + doc () { + if (this.isRoot()) return this + return super.doc() + } + + // Add namespaces + namespace () { + if (!this.isRoot()) return this.doc().namespace() + return this + .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.doc().defs() + + return adopt(this.node.getElementsByTagName('defs')[0]) || + this.put(new Defs()) + } + + // custom parent method + parent (type) { + if (this.isRoot()) { + return this.node.parentNode.nodeName === '#document' + ? null + : adopt(this.node.parentNode) + } + + return super.parent(type) + } + + clear () { + // remove children + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild) + } + return this + } +} + +registerMethods({ + Container: { + // Create nested svg document + nested () { + return this.put(new Doc()) + } + } +}) + +register(Doc, 'Doc', true) diff --git a/src/elements/Dom.js b/src/elements/Dom.js new file mode 100644 index 0000000..eab3f0d --- /dev/null +++ b/src/elements/Dom.js @@ -0,0 +1,242 @@ +import { + adopt, + assignNewId, + eid, + extend, + makeInstance +} from '../utils/adopter.js' +import { map } from '../utils/utils.js' +import { ns } from '../modules/core/namespaces.js' +import EventTarget from '../types/EventTarget.js' +import attr from '../modules/core/attr.js' + +export default class Dom extends EventTarget { + constructor (node) { + super(node) + this.node = node + this.type = node.nodeName + } + + // Add given element at a position + 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]) + } + + return this + } + + // Add element to given container and return self + addTo (parent) { + return makeInstance(parent).put(this) + } + + // Returns all child elements + children () { + return 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) + } + + // remove defs reference + delete this._defs + + return this + } + + // Clone element + clone (parent) { + // write dom data to the dom so the clone can pickup the data + this.writeDataToDom() + + // clone element and assign new id + let clone = assignNewId(this.node.cloneNode(true)) + + // insert the clone in the given parent or after myself + if (parent) parent.add(clone) + // FIXME: after might not be available here + else this.after(clone) + + return clone + } + + // Iterates over all children and invokes a given block + 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]) + + if (deep) { + children[i].each(block, deep) + } + } + + return this + } + + // Get first child + first () { + return adopt(this.node.firstChild) + } + + // Get a element at the given index + 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 + } + + // Get / set id + id (id) { + // generate new id if no id set + 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) + } + + // Gets index of given element + index (element) { + return [].slice.call(this.node.childNodes).indexOf(element.node) + } + + // Get the last child + last () { + return adopt(this.node.lastChild) + } + + // matches the element vs a css selector + matches (selector) { + const el = this.node + return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector) + } + + // Returns the svg node to call native svg methods on it + native () { + return this.node + } + + // Returns the parent element instance + parent (type) { + var parent = this + + // check for parent + if (!parent.node.parentNode) return null + + // get parent element + parent = adopt(parent.node.parentNode) + + if (!type) return parent + + // loop trough ancestors if type is given + while (parent && parent.node instanceof window.SVGElement) { + 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) + return element + } + + // Add element to given container and return container + putIn (parent) { + return makeInstance(parent).add(this) + } + + // Remove element + remove () { + if (this.parent()) { + this.parent().removeElement(this) + } + + return this + } + + // Remove a given child + removeElement (element) { + this.node.removeChild(element.node) + + return this + } + + // Replace element + replace (element) { + // FIXME: after() might not be available here + this.after(element).remove() + + return element + } + + // Return id on string conversion + toString () { + return this.id() + } + + // Import raw svg + svg (svg) { + var well, len + + // act as a setter if svg is given + if (svg) { + // create temporary holder + well = document.createElementNS(ns, 'svg') + // dump raw svg + well.innerHTML = svg + + // transplant nodes + for (len = well.children.length; len--;) { + this.node.appendChild(well.firstElementChild) + } + + // otherwise act as a getter + } else { + // write svgjs data to the dom + this.writeDataToDom() + + return this.node.outerHTML + } + + return this + } + + // write svgjs data to the dom + writeDataToDom () { + // dump variables recursively + this.each(function () { + this.writeDataToDom() + }) + + return this + } +} + +extend(Dom, { attr }) diff --git a/src/elements/Element.js b/src/elements/Element.js new file mode 100644 index 0000000..a38b2ac --- /dev/null +++ b/src/elements/Element.js @@ -0,0 +1,142 @@ +import { getClass, makeInstance, root } from '../utils/adopter.js' +import { proportionalSize } from '../utils/utils.js' +import { reference } from '../modules/core/regex.js' +import Dom from './Dom.js' +import SVGNumber from '../types/SVGNumber.js' + +const Doc = getClass(root) + +export default class Element extends Dom { + constructor (node) { + super(node) + + // initialize data object + this.dom = {} + + // create circular reference + this.node.instance = this + + 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')) || {}) + } + } + + // Move element by its center + 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) + } + + // Move by center over y-axis + cy (y) { + return y == null + ? this.y() + this.height() / 2 + : this.y(y - this.height() / 2) + } + + // Get defs + defs () { + return this.doc().defs() + } + + // Get parent document + doc () { + let p = this.parent(Doc) + return p && p.doc() + } + + getEventHolder () { + return this + } + + // Set height of element + height (height) { + return this.attr('height', height) + } + + // Checks whether the given point inside the bounding box of the element + inside (x, y) { + let box = this.bbox() + + 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) + } + + // return array of all ancestors of given type up to the root svg + parents (type) { + let parents = [] + let parent = this + + do { + parent = parent.parent(type) + if (!parent || parent instanceof getClass('HtmlNode')) break + + parents.push(parent) + } while (parent.parent) + + return parents + } + + // Get referenced element form attribute value + reference (attr) { + attr = this.attr(attr) + if (!attr) return null + + const m = attr.match(reference) + return m ? makeInstance(m[1]) : null + } + + // set given data to the elements data property + setData (o) { + this.dom = o + return this + } + + // Set element size to given width and height + size (width, height) { + let p = proportionalSize(this, width, height) + + return this + .width(new SVGNumber(p.width)) + .height(new SVGNumber(p.height)) + } + + // Set width of element + width (width) { + return this.attr('width', width) + } + + // write svgjs data to the dom + 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 super.writeDataToDom() + } + + // Move over x-axis + x (x) { + return this.attr('x', x) + } + + // Move over y-axis + y (y) { + return this.attr('y', y) + } +} diff --git a/src/elements/Ellipse.js b/src/elements/Ellipse.js new file mode 100644 index 0000000..40b9369 --- /dev/null +++ b/src/elements/Ellipse.js @@ -0,0 +1,21 @@ +import { extend, nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +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), Ellipse) + } +} + +extend(Ellipse, circled) + +registerMethods('Container', { + // Create an ellipse + ellipse: function (width, height) { + return this.put(new Ellipse()).size(width, height).move(0, 0) + } +}) + +register(Ellipse) diff --git a/src/elements/G.js b/src/elements/G.js new file mode 100644 index 0000000..00803c0 --- /dev/null +++ b/src/elements/G.js @@ -0,0 +1,20 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import Container from './Container.js' + +export default class G extends Container { + constructor (node) { + super(nodeOrNew('g', node), G) + } +} + +registerMethods({ + Element: { + // Create a group element + group: function () { + return this.put(new G()) + } + } +}) + +register(G) diff --git a/src/elements/Gradient.js b/src/elements/Gradient.js new file mode 100644 index 0000000..cf8aeaa --- /dev/null +++ b/src/elements/Gradient.js @@ -0,0 +1,77 @@ +import { extend, nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import Box from '../types/Box.js' +import Container from './Container.js' +import Stop from './Stop.js' +import baseFind from '../modules/core/selector.js' +import * as gradiented from '../modules/core/gradiented.js' + +export default class Gradient extends Container { + constructor (type) { + super( + nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type), + Gradient + ) + } + + // Add a color stop + stop (offset, color, opacity) { + return this.put(new Stop()).update(offset, color, opacity) + } + + // Update gradient + update (block) { + // remove all stops + this.clear() + + // invoke passed block + 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) + } + + targets () { + return baseFind('svg [fill*="' + this.id() + '"]') + } + + bbox () { + return new Box() + } +} + +extend(Gradient, gradiented) + +registerMethods({ + Container: { + // Create gradient element in defs + gradient (type, block) { + return this.defs().gradient(type, block) + } + }, + // define gradient + Defs: { + gradient (type, block) { + return this.put(new Gradient(type)).update(block) + } + } +}) + +register(Gradient) diff --git a/src/elements/HtmlNode.js b/src/elements/HtmlNode.js new file mode 100644 index 0000000..59152d3 --- /dev/null +++ b/src/elements/HtmlNode.js @@ -0,0 +1,10 @@ +import { register } from '../utils/adopter.js' +import Dom from './Dom.js' + +export default class HtmlNode extends Dom { + constructor (node) { + super(node, HtmlNode) + } +} + +register(HtmlNode) diff --git a/src/elements/Image.js b/src/elements/Image.js new file mode 100644 index 0000000..5e672f4 --- /dev/null +++ b/src/elements/Image.js @@ -0,0 +1,68 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import { off, on } from '../modules/core/event.js' +import { registerMethods } from '../utils/methods.js' +import { xlink } from '../modules/core/namespaces.js' +import Pattern from './Pattern.js' +import Shape from './Shape.js' + +export default class Image extends Shape { + constructor (node) { + super(nodeOrNew('image', node), Image) + } + + // (re)load image + load (url, callback) { + if (!url) return this + + var img = new window.Image() + + 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 (p instanceof Pattern) { + // ensure pattern size if not set + if (p.width() === 0 && p.height() === 0) { + p.size(this.width(), this.height()) + } + } + + if (typeof callback === 'function') { + callback.call(this, { + width: img.width, + height: img.height, + ratio: img.width / img.height, + url: url + }) + } + }, this) + + on(img, 'load error', function () { + // dont forget to unbind memory leaking events + off(img) + }) + + return this.attr('href', (img.src = url), xlink) + } + + attrHook (obj) { + return obj.doc().defs().pattern(0, 0, (pattern) => { + pattern.add(this) + }) + } +} + +registerMethods({ + Container: { + // create image element, load image and set its size + image (source, callback) { + return this.put(new Image()).size(0, 0).load(source, callback) + } + } +}) + +register(Image) diff --git a/src/elements/Line.js b/src/elements/Line.js new file mode 100644 index 0000000..b9bc4e8 --- /dev/null +++ b/src/elements/Line.js @@ -0,0 +1,63 @@ +import { extend, nodeOrNew, register } from '../utils/adopter.js' +import { proportionalSize } from '../utils/utils.js' +import { registerMethods } from '../utils/methods.js' +import PointArray from '../types/PointArray.js' +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), Line) + } + + // Get array + array () { + 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) { + return this.array() + } else if (typeof y1 !== 'undefined') { + x1 = { x1: x1, y1: y1, x2: x2, y2: y2 } + } else { + x1 = new PointArray(x1).toLine() + } + + return this.attr(x1) + } + + // Move by left top corner + 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()) + } +} + +extend(Line, pointed) + +registerMethods({ + Container: { + // Create a line element + line (...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] + ) + } + } +}) + +register(Line) diff --git a/src/elements/Marker.js b/src/elements/Marker.js new file mode 100644 index 0000000..2b0541b --- /dev/null +++ b/src/elements/Marker.js @@ -0,0 +1,81 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +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), Marker) + } + + // Set width of element + width (width) { + return this.attr('markerWidth', width) + } + + // Set height of element + height (height) { + return this.attr('markerHeight', height) + } + + // Set marker refX and refY + ref (x, y) { + return this.attr('refX', x).attr('refY', y) + } + + // Update marker + update (block) { + // remove all content + this.clear() + + // invoke passed block + if (typeof block === 'function') { block.call(this, this) } + + return this + } + + // Return the fill id + toString () { + return 'url(#' + this.id() + ')' + } +} + +registerMethods({ + Container: { + marker (width, height, block) { + // Create marker element in defs + return this.defs().marker(width, height, block) + } + }, + Defs: { + // Create marker + marker (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) + } + }, + marker: { + // Create and attach markers + marker (marker, width, height, block) { + var attr = ['marker'] + + // Build attribute name + 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) + + return this.attr(attr, marker) + } + } +}) + +register(Marker) diff --git a/src/elements/Mask.js b/src/elements/Mask.js new file mode 100644 index 0000000..1ed5a8b --- /dev/null +++ b/src/elements/Mask.js @@ -0,0 +1,57 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +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), Mask) + } + + // Unmask all masked elements and remove itself + remove () { + // unmask all targets + this.targets().forEach(function (el) { + el.unmask() + }) + + // remove mask from parent + return super.remove() + } + + targets () { + return baseFind('svg [mask*="' + this.id() + '"]') + } +} + +registerMethods({ + Container: { + mask () { + return this.defs().put(new Mask()) + } + }, + Element: { + // Distribute mask to svg element + maskWith (element) { + // use given mask or create a new one + var masker = element instanceof Mask + ? element + : this.parent().mask().add(element) + + // apply mask + return this.attr('mask', 'url("#' + masker.id() + '")') + }, + + // Unmask element + unmask () { + return this.attr('mask', null) + }, + + masker () { + return this.reference('mask') + } + } +}) + +register(Mask) diff --git a/src/elements/Path.js b/src/elements/Path.js new file mode 100644 index 0000000..71be8a1 --- /dev/null +++ b/src/elements/Path.js @@ -0,0 +1,81 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import { proportionalSize } from '../utils/utils.js' +import { registerMethods } from '../utils/methods.js' +import PathArray from '../types/PathArray.js' +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), Path) + } + + // Get array + array () { + 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))) + } + + // 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 by left top corner over x-axis + 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) + } + + // 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)) + } + + // Set width of element + 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) + } + + targets () { + return baseFind('svg textpath [href*="' + this.id() + '"]') + } +} + +// Define morphable array +Path.prototype.MorphArray = PathArray + +// Add parent method +registerMethods({ + Container: { + // Create a wrapped path element + path (d) { + // make sure plot is called as a setter + return this.put(new Path()).plot(d || new PathArray()) + } + } +}) + +register(Path) diff --git a/src/elements/Pattern.js b/src/elements/Pattern.js new file mode 100644 index 0000000..9111837 --- /dev/null +++ b/src/elements/Pattern.js @@ -0,0 +1,71 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import Box from '../types/Box.js' +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), Pattern) + } + + // Return the fill id + url () { + return 'url(#' + this.id() + ')' + } + + // Update pattern by rebuilding + update (block) { + // remove content + this.clear() + + // invoke passed block + 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) + } + + targets () { + return baseFind('svg [fill*="' + this.id() + '"]') + } + + bbox () { + return new Box() + } +} + +registerMethods({ + Container: { + // Create pattern element in defs + pattern (width, height, block) { + return this.defs().pattern(width, height, block) + } + }, + Defs: { + pattern (width, height, block) { + return this.put(new Pattern()).update(block).attr({ + x: 0, + y: 0, + width: width, + height: height, + patternUnits: 'userSpaceOnUse' + }) + } + } +}) + +register(Pattern) diff --git a/src/elements/Polygon.js b/src/elements/Polygon.js new file mode 100644 index 0000000..6097977 --- /dev/null +++ b/src/elements/Polygon.js @@ -0,0 +1,27 @@ +import { extend, nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import PointArray from '../types/PointArray.js' +import Shape from './Shape.js' +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), Polygon) + } +} + +registerMethods({ + Container: { + // Create a wrapped polygon element + polygon (p) { + // make sure plot is called as a setter + return this.put(new Polygon()).plot(p || new PointArray()) + } + } +}) + +extend(Polygon, pointed) +extend(Polygon, poly) +register(Polygon) diff --git a/src/elements/Polyline.js b/src/elements/Polyline.js new file mode 100644 index 0000000..b2cb15b --- /dev/null +++ b/src/elements/Polyline.js @@ -0,0 +1,27 @@ +import { extend, nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import PointArray from '../types/PointArray.js' +import Shape from './Shape.js' +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), Polyline) + } +} + +registerMethods({ + Container: { + // Create a wrapped polygon element + polyline (p) { + // make sure plot is called as a setter + return this.put(new Polyline()).plot(p || new PointArray()) + } + } +}) + +extend(Polyline, pointed) +extend(Polyline, poly) +register(Polyline) diff --git a/src/elements/Rect.js b/src/elements/Rect.js new file mode 100644 index 0000000..9d6163c --- /dev/null +++ b/src/elements/Rect.js @@ -0,0 +1,32 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import Shape from './Shape.js' + +export default class Rect extends Shape { + // Initialize node + constructor (node) { + super(nodeOrNew('rect', node), Rect) + } + + // FIXME: unify with circle + // Radius x value + rx (rx) { + return this.attr('rx', rx) + } + + // Radius y value + ry (ry) { + return this.attr('ry', ry) + } +} + +registerMethods({ + Container: { + // Create a rect element + rect (width, height) { + return this.put(new Rect()).size(width, height) + } + } +}) + +register(Rect) diff --git a/src/elements/Shape.js b/src/elements/Shape.js new file mode 100644 index 0000000..bf68a8d --- /dev/null +++ b/src/elements/Shape.js @@ -0,0 +1,3 @@ +import Element from './Element.js' + +export default class Shape extends Element {} diff --git a/src/elements/Stop.js b/src/elements/Stop.js new file mode 100644 index 0000000..bf919e8 --- /dev/null +++ b/src/elements/Stop.js @@ -0,0 +1,29 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import Element from './Element.js' +import SVGNumber from '../types/SVGNumber.js' + +export default class Stop extends Element { + constructor (node) { + super(nodeOrNew('stop', node), Stop) + } + + // add color stops + 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)) + + return this + } +} + +register(Stop) diff --git a/src/elements/Symbol.js b/src/elements/Symbol.js new file mode 100644 index 0000000..183f449 --- /dev/null +++ b/src/elements/Symbol.js @@ -0,0 +1,20 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +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), Symbol) + } +} + +registerMethods({ + Container: { + symbol () { + return this.put(new Symbol()) + } + } +}) + +register(Symbol) diff --git a/src/elements/Text.js b/src/elements/Text.js new file mode 100644 index 0000000..58d50a3 --- /dev/null +++ b/src/elements/Text.js @@ -0,0 +1,177 @@ +import { adopt, extend, nodeOrNew, register } from '../utils/adopter.js' +import { attrs } from '../modules/core/defaults.js' +import { registerMethods } from '../utils/methods.js' +import SVGNumber from '../types/SVGNumber.js' +import Shape from './Shape.js' +import * as textable from '../modules/core/textable.js' + +export default class Text extends Shape { + // Initialize node + constructor (node) { + super(nodeOrNew('text', node), Text) + + 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']) + } + + // Move over x-axis + x (x) { + // act as getter + if (x == null) { + return this.attr('x') + } + + return this.attr('x', x) + } + + // Move over y-axis + y (y) { + var oy = this.attr('y') + var o = typeof oy === 'number' ? oy - this.bbox().y : 0 + + // act as getter + if (y == null) { + return typeof oy === 'number' ? oy - o : oy + } + + 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) + } + + // Move center over y-axis + cy (y) { + return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2) + } + + // Set the text content + text (text) { + // act as getter + if (text === undefined) { + // FIXME use children() or each() + var children = this.node.childNodes + var firstLine = 0 + text = '' + + 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 + 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) { + text += '\n' + } + + // add content of this node + text += children[i].textContent + } + + return text + } + + // remove existing content + this.clear().build(true) + + if (typeof text === 'function') { + // call block + text.call(this, this) + } else { + // store text and make sure text is not blank + text = text.split('\n') + + // build new lines + 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() + } + + // Set / get leading + leading (value) { + // act as getter + if (value == null) { + return this.dom.leading + } + + // act as setter + this.dom.leading = new SVGNumber(value) + + return this.rebuild() + } + + // Rebuild appearance type + rebuild (rebuild) { + // store new rebuild flag if given + if (typeof rebuild === 'boolean') { + this._rebuild = rebuild + } + + // define position of all lines + if (this._rebuild) { + var self = this + var blankLineOffset = 0 + var dy = this.dom.leading * new SVGNumber(this.attr('font-size')) + + this.each(function () { + if (this.dom.newLined) { + this.attr('x', self.attr('x')) + + if (this.text() === '\n') { + blankLineOffset += dy + } else { + this.attr('dy', dy + blankLineOffset) + blankLineOffset = 0 + } + } + }) + + this.fire('rebuild') + } + + return this + } + + // Enable / disable build mode + build (build) { + this._build = !!build + return this + } + + // overwrite method from parent to set data properly + setData (o) { + this.dom = o + this.dom.leading = new SVGNumber(o.leading || 1.3) + return this + } +} + +extend(Text, textable) + +registerMethods({ + Container: { + // Create text element + text (text) { + return this.put(new Text()).text(text) + }, + + // Create plain text element + plain (text) { + return this.put(new Text()).plain(text) + } + } +}) + +register(Text) diff --git a/src/elements/TextPath.js b/src/elements/TextPath.js new file mode 100644 index 0000000..04146bc --- /dev/null +++ b/src/elements/TextPath.js @@ -0,0 +1,83 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import { xlink } from '../modules/core/namespaces.js' +import Path from './Path.js' +import PathArray from '../types/PathArray.js' +import Text from './Text.js' + +export default class TextPath extends Text { + // Initialize node + constructor (node) { + super(nodeOrNew('textPath', node), TextPath) + } + + // return the array of the path track element + array () { + var track = this.track() + + return track ? track.array() : null + } + + // Plot path if any + plot (d) { + var track = this.track() + var pathArray = null + + if (track) { + pathArray = track.plot(d) + } + + return (d == null) ? pathArray : this + } + + // Get the path element + track () { + return this.reference('href') + } +} + +registerMethods({ + Container: { + textPath (text, path) { + return this.defs().path(path).text(text).addTo(this) + } + }, + Text: { + // Create path for text to run on + path: function (track) { + var path = new TextPath() + + // if d is a path, reuse it + if (!(track instanceof Path)) { + // create path element + track = this.doc().defs().path(track) + } + + // link textPath to path and add content + path.attr('href', '#' + track, xlink) + + // add textPath element as child node and return textPath + return this.put(path) + }, + + // FIXME: make this plural? + // Get the textPath children + textPath: function () { + return this.find('textPath') + } + }, + Path: { + // creates a textPath from this path + text: function (text) { + if (text instanceof Text) { + var txt = text.text() + return text.clear().path(this).text(txt) + } + return this.parent().put(new Text()).path(this).text(text) + } + // FIXME: Maybe add `targets` to get all textPaths associated with this path + } +}) + +TextPath.prototype.MorphArray = PathArray +register(TextPath) diff --git a/src/elements/Tspan.js b/src/elements/Tspan.js new file mode 100644 index 0000000..69815d4 --- /dev/null +++ b/src/elements/Tspan.js @@ -0,0 +1,64 @@ +import { extend, nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +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), Tspan) + } + + // Set text content + text (text) { + if (text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '') + + typeof text === 'function' ? text.call(this, this) : this.plain(text) + + return this + } + + // Shortcut dx + dx (dx) { + return this.attr('dx', dx) + } + + // Shortcut dy + dy (dy) { + return this.attr('dy', dy) + } + + // Create new line + newLine () { + // fetch text parent + 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()) + } +} + +extend(Tspan, textable) + +registerMethods({ + Tspan: { + tspan (text) { + var tspan = new Tspan() + + // clear if build mode is disabled + if (!this._build) { + this.clear() + } + + // add new tspan + this.node.appendChild(tspan.node) + + return tspan.text(text) + } + } +}) + +register(Tspan) diff --git a/src/elements/Use.js b/src/elements/Use.js new file mode 100644 index 0000000..43a4e9b --- /dev/null +++ b/src/elements/Use.js @@ -0,0 +1,27 @@ +import { nodeOrNew, register } from '../utils/adopter.js' +import { registerMethods } from '../utils/methods.js' +import { xlink } from '../modules/core/namespaces.js' +import Shape from './Shape.js' + +export default class Use extends Shape { + constructor (node) { + super(nodeOrNew('use', node), Use) + } + + // Use element as a reference + element (element, file) { + // Set lined element + return this.attr('href', (file || '') + '#' + element, xlink) + } +} + +registerMethods({ + Container: { + // Create a use element + use: function (element, file) { + return this.put(new Use()).element(element, file) + } + } +}) + +register(Use) diff --git a/src/event.js b/src/event.js deleted file mode 100644 index d3cf26d..0000000 --- a/src/event.js +++ /dev/null @@ -1,119 +0,0 @@ -import { delimiter } from './regex.js' -import { makeInstance } from './adopter.js' - -let listenerId = 0 - -function getEvents (node) { - const n = makeInstance(node).getEventHolder() - if (!n.events) n.events = {} - return n.events -} - -function getEventTarget (node) { - return makeInstance(node).getEventTarget() -} - -function clearEvents (node) { - const n = makeInstance(node).getEventHolder() - if (n.events) n.events = {} -} - -// Add event binder in the SVG namespace -export function on (node, events, listener, binding, options) { - var l = listener.bind(binding || node) - var bag = getEvents(node) - var n = getEventTarget(node) - - // events can be an array of events or a string of events - events = Array.isArray(events) ? events : events.split(delimiter) - - // add id to listener - if (!listener._svgjsListenerId) { - listener._svgjsListenerId = ++listenerId - } - - events.forEach(function (event) { - var ev = event.split('.')[0] - var ns = event.split('.')[1] || '*' - - // ensure valid object - bag[ev] = bag[ev] || {} - bag[ev][ns] = bag[ev][ns] || {} - - // reference listener - bag[ev][ns][listener._svgjsListenerId] = l - - // add listener - n.addEventListener(ev, l, options || false) - }) -} - -// Add event unbinder in the SVG namespace -export function off (node, events, listener, options) { - var bag = getEvents(node) - var n = getEventTarget(node) - - // listener can be a function or a number - if (typeof listener === 'function') { - listener = listener._svgjsListenerId - if (!listener) return - } - - // events can be an array of events or a string or undefined - events = Array.isArray(events) ? events : (events || '').split(delimiter) - - events.forEach(function (event) { - var ev = event && event.split('.')[0] - var ns = event && event.split('.')[1] - var namespace, l - - if (listener) { - // remove listener reference - if (bag[ev] && bag[ev][ns || '*']) { - // removeListener - n.removeEventListener(ev, bag[ev][ns || '*'][listener], options || false) - - delete bag[ev][ns || '*'][listener] - } - } else if (ev && ns) { - // remove all listeners for a namespaced event - if (bag[ev] && bag[ev][ns]) { - for (l in bag[ev][ns]) { off(n, [ev, ns].join('.'), l) } - - delete bag[ev][ns] - } - } else if (ns) { - // remove all listeners for a specific namespace - for (event in bag) { - for (namespace in bag[event]) { - if (ns === namespace) { off(n, [event, ns].join('.')) } - } - } - } else if (ev) { - // remove all listeners for the event - if (bag[ev]) { - for (namespace in bag[ev]) { off(n, [ev, namespace].join('.')) } - - delete bag[ev] - } - } else { - // remove all listeners on a given node - for (event in bag) { off(n, event) } - - clearEvents(node) - } - }) -} - -export function dispatch (node, event, data) { - var n = getEventTarget(node) - - // Dispatch event - if (event instanceof window.Event) { - n.dispatchEvent(event) - } else { - event = new window.CustomEvent(event, { detail: data, cancelable: true }) - n.dispatchEvent(event) - } - return event -} diff --git a/src/gradiented.js b/src/gradiented.js deleted file mode 100644 index da2bc41..0000000 --- a/src/gradiented.js +++ /dev/null @@ -1,14 +0,0 @@ -// FIXME: add to runner -import SVGNumber from './SVGNumber.js' - -export function from (x, y) { - return (this._element || this).type === 'radialGradient' - ? this.attr({ fx: new SVGNumber(x), fy: new SVGNumber(y) }) - : this.attr({ x1: new SVGNumber(x), y1: new SVGNumber(y) }) -} - -export function to (x, y) { - return (this._element || this).type === 'radialGradient' - ? this.attr({ cx: new SVGNumber(x), cy: new SVGNumber(y) }) - : this.attr({ x2: new SVGNumber(x), y2: new SVGNumber(y) }) -} diff --git a/src/helpers.js b/src/helpers.js deleted file mode 100644 index 9bf393c..0000000 --- a/src/helpers.js +++ /dev/null @@ -1,206 +0,0 @@ -import { dots, reference } from './regex.js' - -export function isNulledBox (box) { - return !box.w && !box.h && !box.x && !box.y -} - -export function domContains (node) { - return (document.documentElement.contains || function (node) { - // This is IE - it does not support contains() for top-level SVGs - while (node.parentNode) { - node = node.parentNode - } - return node === document - }).call(document.documentElement, node) -} - -export function pathRegReplace (a, b, c, d) { - return c + d.replace(dots, ' .') -} - -// creates deep clone of array -export function arrayClone (arr) { - var clone = arr.slice(0) - for (var i = clone.length; i--;) { - if (Array.isArray(clone[i])) { - clone[i] = arrayClone(clone[i]) - } - } - return clone -} - -// tests if a given selector matches an element -export function matcher (el, selector) { - return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector) -} - -// Convert dash-separated-string to camelCase -export function camelCase (s) { - return s.toLowerCase().replace(/-(.)/g, function (m, g) { - return g.toUpperCase() - }) -} - -// Capitalize first letter of a string -export function capitalize (s) { - return s.charAt(0).toUpperCase() + s.slice(1) -} - -// Ensure to six-based hex -export function fullHex (hex) { - return hex.length === 4 - ? [ '#', - hex.substring(1, 2), hex.substring(1, 2), - hex.substring(2, 3), hex.substring(2, 3), - hex.substring(3, 4), hex.substring(3, 4) - ].join('') - : hex -} - -// Component to hex value -export function compToHex (comp) { - var hex = comp.toString(16) - return hex.length === 1 ? '0' + hex : hex -} - -// Calculate proportional width and height values when necessary -export function proportionalSize (element, width, height) { - if (width == null || height == null) { - var box = element.bbox() - - if (width == null) { - width = box.width / box.height * height - } else if (height == null) { - height = box.height / box.width * width - } - } - - return { - width: width, - height: height - } -} - -// Map matrix array to object -export function arrayToMatrix (a) { - return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] } -} - -// Add centre point to transform object -export function ensureCentre (o, target) { - o.cx = o.cx == null ? target.bbox().cx : o.cx - o.cy = o.cy == null ? target.bbox().cy : o.cy -} - -// PathArray Helpers -export function arrayToString (a) { - for (var i = 0, il = a.length, s = ''; i < il; i++) { - s += a[i][0] - - if (a[i][1] != null) { - s += a[i][1] - - if (a[i][2] != null) { - s += ' ' - s += a[i][2] - - if (a[i][3] != null) { - s += ' ' - s += a[i][3] - s += ' ' - s += a[i][4] - - if (a[i][5] != null) { - s += ' ' - s += a[i][5] - s += ' ' - s += a[i][6] - - if (a[i][7] != null) { - s += ' ' - s += a[i][7] - } - } - } - } - } - } - - return s + ' ' -} - -// Add more bounding box properties -export function fullBox (b) { - if (b.x == null) { - b.x = 0 - b.y = 0 - b.width = 0 - b.height = 0 - } - - b.w = b.width - b.h = b.height - b.x2 = b.x + b.width - b.y2 = b.y + b.height - b.cx = b.x + b.width / 2 - b.cy = b.y + b.height / 2 - - return b -} - -// Get id from reference string -export function idFromReference (url) { - var m = (url || '').toString().match(reference) - - if (m) return m[1] -} - -// Create matrix array for looping -export let abcdef = 'abcdef'.split('') - -export function closeEnough (a, b, threshold) { - return Math.abs(b - a) < (threshold || 1e-6) -} - -// move this to static matrix method -export function isMatrixLike (o) { - return ( - o.a != null || - o.b != null || - o.c != null || - o.d != null || - o.e != null || - o.f != null - ) -} - -export function getOrigin (o, element) { - // Allow origin or around as the names - let origin = o.origin // o.around == null ? o.origin : o.around - let ox, oy - - // Allow the user to pass a string to rotate around a given point - if (typeof origin === 'string' || origin == null) { - // Get the bounding box of the element with no transformations applied - const string = (origin || 'center').toLowerCase().trim() - const { height, width, x, y } = element.bbox() - - // Calculate the transformed x and y coordinates - let bx = string.includes('left') ? x - : string.includes('right') ? x + width - : x + width / 2 - let by = string.includes('top') ? y - : string.includes('bottom') ? y + height - : y + height / 2 - - // Set the bounds eg : "bottom-left", "Top right", "middle" etc... - ox = o.ox != null ? o.ox : bx - oy = o.oy != null ? o.oy : by - } else { - ox = origin[0] - oy = origin[1] - } - - // Return the origin as it is if it wasn't a string - return [ ox, oy ] -} diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..278e8fd --- /dev/null +++ b/src/main.js @@ -0,0 +1,163 @@ +/* Optional Modules */ +import './modules/optional/arrange.js' +import './modules/optional/class.js' +import './modules/optional/css.js' +import './modules/optional/data.js' +import './modules/optional/memory.js' +import './modules/optional/sugar.js' +import './modules/optional/transform.js' + +import Morphable, { + NonMorphable, + ObjectBag, + TransformBag, + makeMorphable, + registerMorphableType +} from './types/Morphable.js' +import { extend } from './utils/adopter.js' +import { getMethodsFor } from './utils/methods.js' +import Box from './types/Box.js' +import Circle from './elements/Circle.js' +import Color from './types/Color.js' +import Container from './elements/Container.js' +import Defs from './elements/Defs.js' +import Doc from './elements/Doc.js' +import Dom from './elements/Dom.js' +import Element from './elements/Element.js' +import Ellipse from './elements/Ellipse.js' +import EventTarget from './types/EventTarget.js' +import Gradient from './elements/Gradient.js' +import Image from './elements/Image.js' +import Line from './elements/Line.js' +import Marker from './elements/Marker.js' +import Matrix from './types/Matrix.js' +import Path from './elements/Path.js' +import PathArray from './types/PathArray.js' +import Pattern from './elements/Pattern.js' +import PointArray from './types/PointArray.js' +import Polygon from './elements/Polygon.js' +import Polyline from './elements/Polyline.js' +import Rect from './elements/Rect.js' +import SVGArray from './types/SVGArray.js' +import SVGNumber from './types/SVGNumber.js' +import Shape from './elements/Shape.js' +import Text from './elements/Text.js' +import Tspan from './elements/Tspan.js' +import * as defaults from './modules/core/defaults.js' + +export { + Morphable, + registerMorphableType, + makeMorphable, + TransformBag, + ObjectBag, + NonMorphable +} + +export { defaults } +export * from './utils/utils.js' +export * from './modules/core/namespaces.js' +export { default as parser } from './modules/core/parser.js' +export { default as find } from './modules/core/selector.js' +export * from './modules/core/event.js' +export * from './utils/adopter.js' + +/* Animation Modules */ +export { default as Animator } from './animation/Animator.js' +export { Controller, Ease, PID, Spring, easing } from './animation/Controller.js' +export { default as Queue } from './animation/Queue.js' +export { default as Runner } from './animation/Runner.js' +export { default as Timeline } from './animation/Timeline.js' + +/* Types */ +export { default as SVGArray } from './types/SVGArray.js' +export { default as Box } from './types/Box.js' +export { default as Color } from './types/Color.js' +export { default as EventTarget } from './types/EventTarget.js' +export { default as Matrix } from './types/Matrix.js' +export { default as SVGNumber } from './types/SVGNumber.js' +export { default as PathArray } from './types/PathArray.js' +export { default as Point } from './types/Point.js' +export { default as PointArray } from './types/PointArray.js' + +/* Elements */ +export { default as Bare } from './elements/Bare.js' +export { default as Circle } from './elements/Circle.js' +export { default as ClipPath } from './elements/ClipPath.js' +export { default as Container } from './elements/Container.js' +export { default as Defs } from './elements/Defs.js' +export { default as Doc } from './elements/Doc.js' +export { default as Dom } from './elements/Dom.js' +export { default as Element } from './elements/Element.js' +export { default as Ellipse } from './elements/Ellipse.js' +export { default as Gradient } from './elements/Gradient.js' +export { default as G } from './elements/G.js' +export { default as HtmlNode } from './elements/HtmlNode.js' +export { default as A } from './elements/A.js' +export { default as Image } from './elements/Image.js' +export { default as Line } from './elements/Line.js' +export { default as Marker } from './elements/Marker.js' +export { default as Mask } from './elements/Mask.js' +export { default as Path } from './elements/Path.js' +export { default as Pattern } from './elements/Pattern.js' +export { default as Polygon } from './elements/Polygon.js' +export { default as Polyline } from './elements/Polyline.js' +export { default as Rect } from './elements/Rect.js' +export { default as Shape } from './elements/Shape.js' +export { default as Stop } from './elements/Stop.js' +export { default as Symbol } from './elements/Symbol.js' +export { default as Text } from './elements/Text.js' +export { default as TextPath } from './elements/TextPath.js' +export { default as Tspan } from './elements/Tspan.js' +export { default as Use } from './elements/Use.js' + +extend([ + Doc, + Symbol, + Image, + Pattern, + Marker +], getMethodsFor('viewbox')) + +extend([ + Line, + Polyline, + Polygon, + Path +], getMethodsFor('marker')) + +extend(Text, getMethodsFor('Text')) +extend(Path, getMethodsFor('Path')) + +extend(Defs, getMethodsFor('Defs')) + +extend([ + Text, + Tspan +], getMethodsFor('Tspan')) + +extend([ + Rect, + Ellipse, + Circle, + Gradient +], getMethodsFor('radius')) + +extend(EventTarget, getMethodsFor('EventTarget')) +extend(Dom, getMethodsFor('Dom')) +extend(Element, getMethodsFor('Element')) +extend(Shape, getMethodsFor('Shape')) +// extend(Element, getConstructor('Memory')) +extend(Container, getMethodsFor('Container')) + +registerMorphableType([ + SVGNumber, + Color, + Box, + Matrix, + SVGArray, + PointArray, + PathArray +]) + +makeMorphable() diff --git a/src/memory.js b/src/memory.js deleted file mode 100644 index 9c826a2..0000000 --- a/src/memory.js +++ /dev/null @@ -1,40 +0,0 @@ -import { registerMethods } from './methods.js' - -// FIXME: We need a constructor to set this up - -// Remember arbitrary data -export function remember (k, v) { - // remember every item in an object individually - if (typeof arguments[0] === 'object') { - for (var key in k) { - this.remember(key, k[key]) - } - } else if (arguments.length === 1) { - // retrieve memory - return this.memory()[k] - } else { - // store memory - this.memory()[k] = v - } - - return this -} - -// Erase a given memory -export function forget () { - if (arguments.length === 0) { - this._memory = {} - } else { - for (var i = arguments.length - 1; i >= 0; i--) { - delete this.memory()[arguments[i]] - } - } - return this -} - -// return local memory object -export function memory () { - return (this._memory = this._memory || {}) -} - -registerMethods('Dom', { remember, forget, memory }) diff --git a/src/methods.js b/src/methods.js deleted file mode 100644 index 2373445..0000000 --- a/src/methods.js +++ /dev/null @@ -1,32 +0,0 @@ -const methods = {} -const constructors = {} - -export function registerMethods (name, m) { - if (Array.isArray(name)) { - for (let _name of name) { - registerMethods(_name, m) - } - return - } - - if (typeof name === 'object') { - for (let [_name, _m] of Object.entries(name)) { - registerMethods(_name, _m) - } - return - } - - methods[name] = Object.assign(methods[name] || {}, m) -} - -export function getMethodsFor (name) { - return methods[name] || {} -} - -export function registerConstructor (name, setup) { - constructors[name] = setup -} - -export function getConstructor (name) { - return constructors[name] ? { setup: constructors[name], name } : {} -} diff --git a/src/modules/core/attr.js b/src/modules/core/attr.js new file mode 100644 index 0000000..ed34dc9 --- /dev/null +++ b/src/modules/core/attr.js @@ -0,0 +1,80 @@ +import { isImage, isNumber } from './regex.js' +import { attrs as defaults } from './defaults.js' +import Color from '../../types/Color.js' +import SVGArray from '../../types/SVGArray.js' +import SVGNumber from '../../types/SVGNumber.js' + +// Set svg element attribute +export default function attr (attr, val, ns) { + // act as full getter + if (attr == null) { + // get an object of attributes + attr = {} + val = this.node.attributes + + for (let node of val) { + attr[node.nodeName] = isNumber.test(node.nodeValue) + ? parseFloat(node.nodeValue) + : node.nodeValue + } + + return attr + } else if (Array.isArray(attr)) { + // FIXME: implement + } else if (typeof attr === 'object') { + // apply every attribute individually if an object is passed + for (val in attr) this.attr(val, attr[val]) + } else if (val === null) { + // remove value + this.node.removeAttribute(attr) + } else if (val == null) { + // act as a getter if the first and only argument is not an object + val = this.node.getAttribute(attr) + return val == null ? defaults[attr] // FIXME: do we need to return defaults? + : isNumber.test(val) ? parseFloat(val) + : val + } else { + // convert image fill and stroke to patterns + if (attr === 'fill' || attr === 'stroke') { + if (isImage.test(val)) { + val = this.doc().defs().image(val) + } + } + + // FIXME: This is fine, but what about the lines above? + // How does attr know about image()? + while (typeof val.attrHook === 'function') { + val = val.attrHook(this, attr) + } + + // ensure correct numeric values (also accepts NaN and Infinity) + if (typeof val === 'number') { + val = new SVGNumber(val) + } else if (Color.isColor(val)) { + // ensure full hex color + val = new Color(val) + } else if (val.constructor === Array) { + // Check for plain arrays and parse array values + val = new SVGArray(val) + } + + // if the passed attribute is leading... + if (attr === 'leading') { + // ... call the leading method instead + if (this.leading) { + this.leading(val) + } + } else { + // set given attribute on node + typeof ns === 'string' ? this.node.setAttributeNS(ns, attr, val.toString()) + : this.node.setAttribute(attr, val.toString()) + } + + // rebuild if required + if (this.rebuild && (attr === 'font-size' || attr === 'x')) { + this.rebuild() + } + } + + return this +} diff --git a/src/modules/core/circled.js b/src/modules/core/circled.js new file mode 100644 index 0000000..9a3b1ad --- /dev/null +++ b/src/modules/core/circled.js @@ -0,0 +1,64 @@ +// FIXME: import this to runner +import { proportionalSize } from '../../utils/utils.js' +import SVGNumber from '../../types/SVGNumber.js' + +// Radius x value +export function rx (rx) { + return this.attr('rx', rx) +} + +// Radius y value +export function ry (ry) { + return this.attr('ry', ry) +} + +// Move over x-axis +export function x (x) { + return x == null + ? this.cx() - this.rx() + : this.cx(x + this.rx()) +} + +// Move over y-axis +export function y (y) { + return y == null + ? this.cy() - this.ry() + : this.cy(y + this.ry()) +} + +// Move by center over x-axis +export function cx (x) { + return x == null + ? this.attr('cx') + : this.attr('cx', x) +} + +// Move by center over y-axis +export function cy (y) { + return y == null + ? this.attr('cy') + : this.attr('cy', y) +} + +// Set width of element +export function width (width) { + return width == null + ? this.rx() * 2 + : this.rx(new SVGNumber(width).divide(2)) +} + +// Set height of element +export function height (height) { + return height == null + ? this.ry() * 2 + : this.ry(new SVGNumber(height).divide(2)) +} + +// Custom size function +export function 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)) +} diff --git a/src/modules/core/defaults.js b/src/modules/core/defaults.js new file mode 100644 index 0000000..0d496bc --- /dev/null +++ b/src/modules/core/defaults.js @@ -0,0 +1,48 @@ + +export function noop () {} + +// Default animation values +export let timeline = { + duration: 400, + ease: '>', + delay: 0 +} + +// Default attribute values +export let attrs = { + + // fill and stroke + 'fill-opacity': 1, + 'stroke-opacity': 1, + 'stroke-width': 0, + 'stroke-linejoin': 'miter', + 'stroke-linecap': 'butt', + fill: '#000000', + stroke: '#000000', + opacity: 1, + + // position + x: 0, + y: 0, + cx: 0, + cy: 0, + + // size + width: 0, + height: 0, + + // radius + r: 0, + rx: 0, + ry: 0, + + // gradient + offset: 0, + 'stop-opacity': 1, + 'stop-color': '#000000', + + // text + 'font-size': 16, + 'font-family': 'Helvetica, Arial, sans-serif', + 'text-anchor': 'start' +} diff --git a/src/modules/core/event.js b/src/modules/core/event.js new file mode 100644 index 0000000..2fcaf58 --- /dev/null +++ b/src/modules/core/event.js @@ -0,0 +1,119 @@ +import { delimiter } from './regex.js' +import { makeInstance } from '../../utils/adopter.js' + +let listenerId = 0 + +function getEvents (node) { + const n = makeInstance(node).getEventHolder() + if (!n.events) n.events = {} + return n.events +} + +function getEventTarget (node) { + return makeInstance(node).getEventTarget() +} + +function clearEvents (node) { + const n = makeInstance(node).getEventHolder() + if (n.events) n.events = {} +} + +// Add event binder in the SVG namespace +export function on (node, events, listener, binding, options) { + var l = listener.bind(binding || node) + var bag = getEvents(node) + var n = getEventTarget(node) + + // events can be an array of events or a string of events + events = Array.isArray(events) ? events : events.split(delimiter) + + // add id to listener + if (!listener._svgjsListenerId) { + listener._svgjsListenerId = ++listenerId + } + + events.forEach(function (event) { + var ev = event.split('.')[0] + var ns = event.split('.')[1] || '*' + + // ensure valid object + bag[ev] = bag[ev] || {} + bag[ev][ns] = bag[ev][ns] || {} + + // reference listener + bag[ev][ns][listener._svgjsListenerId] = l + + // add listener + n.addEventListener(ev, l, options || false) + }) +} + +// Add event unbinder in the SVG namespace +export function off (node, events, listener, options) { + var bag = getEvents(node) + var n = getEventTarget(node) + + // listener can be a function or a number + if (typeof listener === 'function') { + listener = listener._svgjsListenerId + if (!listener) return + } + + // events can be an array of events or a string or undefined + events = Array.isArray(events) ? events : (events || '').split(delimiter) + + events.forEach(function (event) { + var ev = event && event.split('.')[0] + var ns = event && event.split('.')[1] + var namespace, l + + if (listener) { + // remove listener reference + if (bag[ev] && bag[ev][ns || '*']) { + // removeListener + n.removeEventListener(ev, bag[ev][ns || '*'][listener], options || false) + + delete bag[ev][ns || '*'][listener] + } + } else if (ev && ns) { + // remove all listeners for a namespaced event + if (bag[ev] && bag[ev][ns]) { + for (l in bag[ev][ns]) { off(n, [ev, ns].join('.'), l) } + + delete bag[ev][ns] + } + } else if (ns) { + // remove all listeners for a specific namespace + for (event in bag) { + for (namespace in bag[event]) { + if (ns === namespace) { off(n, [event, ns].join('.')) } + } + } + } else if (ev) { + // remove all listeners for the event + if (bag[ev]) { + for (namespace in bag[ev]) { off(n, [ev, namespace].join('.')) } + + delete bag[ev] + } + } else { + // remove all listeners on a given node + for (event in bag) { off(n, event) } + + clearEvents(node) + } + }) +} + +export function dispatch (node, event, data) { + var n = getEventTarget(node) + + // Dispatch event + if (event instanceof window.Event) { + n.dispatchEvent(event) + } else { + event = new window.CustomEvent(event, { detail: data, cancelable: true }) + n.dispatchEvent(event) + } + return event +} diff --git a/src/modules/core/gradiented.js b/src/modules/core/gradiented.js new file mode 100644 index 0000000..d34a9fe --- /dev/null +++ b/src/modules/core/gradiented.js @@ -0,0 +1,14 @@ +// FIXME: add to runner +import SVGNumber from '../../types/SVGNumber.js' + +export function from (x, y) { + return (this._element || this).type === 'radialGradient' + ? this.attr({ fx: new SVGNumber(x), fy: new SVGNumber(y) }) + : this.attr({ x1: new SVGNumber(x), y1: new SVGNumber(y) }) +} + +export function to (x, y) { + return (this._element || this).type === 'radialGradient' + ? this.attr({ cx: new SVGNumber(x), cy: new SVGNumber(y) }) + : this.attr({ x2: new SVGNumber(x), y2: new SVGNumber(y) }) +} diff --git a/src/modules/core/namespaces.js b/src/modules/core/namespaces.js new file mode 100644 index 0000000..3791298 --- /dev/null +++ b/src/modules/core/namespaces.js @@ -0,0 +1,5 @@ +// Default namespaces +export let ns = 'http://www.w3.org/2000/svg' +export let xmlns = 'http://www.w3.org/2000/xmlns/' +export let xlink = 'http://www.w3.org/1999/xlink' +export let svgjs = 'http://svgjs.com/svgjs' diff --git a/src/modules/core/parser.js b/src/modules/core/parser.js new file mode 100644 index 0000000..7a656ef --- /dev/null +++ b/src/modules/core/parser.js @@ -0,0 +1,26 @@ +import Doc from '../../elements/Doc.js' + +export default function parser () { + // Reuse cached element if possible + if (!parser.nodes) { + let svg = new Doc().size(2, 0) + svg.node.cssText = [ + 'opacity: 0', + 'position: absolute', + 'left: -100%', + 'top: -100%', + 'overflow: hidden' + ].join(';') + + let path = svg.path().node + + parser.nodes = { svg, path } + } + + if (!parser.nodes.svg.node.parentNode) { + let b = document.body || document.documentElement + parser.nodes.svg.addTo(b) + } + + return parser.nodes +} diff --git a/src/modules/core/pointed.js b/src/modules/core/pointed.js new file mode 100644 index 0000000..95e6819 --- /dev/null +++ b/src/modules/core/pointed.js @@ -0,0 +1,25 @@ +import PointArray from '../../types/PointArray.js' + +export let MorphArray = PointArray + +// Move by left top corner over x-axis +export function x (x) { + return x == null ? this.bbox().x : this.move(x, this.bbox().y) +} + +// Move by left top corner over y-axis +export function y (y) { + return y == null ? this.bbox().y : this.move(this.bbox().x, y) +} + +// Set width of element +export function width (width) { + let b = this.bbox() + return width == null ? b.width : this.size(width, b.height) +} + +// Set height of element +export function height (height) { + let b = this.bbox() + return height == null ? b.height : this.size(b.width, height) +} diff --git a/src/modules/core/poly.js b/src/modules/core/poly.js new file mode 100644 index 0000000..ad12020 --- /dev/null +++ b/src/modules/core/poly.js @@ -0,0 +1,31 @@ +import { proportionalSize } from '../../utils/utils.js' +import PointArray from '../../types/PointArray.js' + +// Get array +export function array () { + return this._array || (this._array = new PointArray(this.attr('points'))) +} + +// Plot new path +export function plot (p) { + return (p == null) ? this.array() + : this.clear().attr('points', typeof p === 'string' ? p + : (this._array = new PointArray(p))) +} + +// Clear array cache +export function clear () { + delete this._array + return this +} + +// Move by left top corner +export function move (x, y) { + return this.attr('points', this.array().move(x, y)) +} + +// Set element size to given width and height +export function size (width, height) { + let p = proportionalSize(this, width, height) + return this.attr('points', this.array().size(p.width, p.height)) +} diff --git a/src/modules/core/regex.js b/src/modules/core/regex.js new file mode 100644 index 0000000..1056554 --- /dev/null +++ b/src/modules/core/regex.js @@ -0,0 +1,58 @@ +// Parse unit value +export let numberAndUnit = /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i + +// Parse hex value +export let hex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i + +// Parse rgb value +export let rgb = /rgb\((\d+),(\d+),(\d+)\)/ + +// Parse reference id +export let reference = /(#[a-z0-9\-_]+)/i + +// splits a transformation chain +export let transforms = /\)\s*,?\s*/ + +// Whitespace +export let whitespace = /\s/g + +// Test hex value +export let isHex = /^#[a-f0-9]{3,6}$/i + +// Test rgb value +export let isRgb = /^rgb\(/ + +// Test css declaration +export let isCss = /[^:]+:[^;]+;?/ + +// Test for blank string +export let isBlank = /^(\s+)?$/ + +// Test for numeric string +export let isNumber = /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i + +// Test for percent value +export let isPercent = /^-?[\d.]+%$/ + +// Test for image url +export let isImage = /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i + +// split at whitespace and comma +export let delimiter = /[\s,]+/ + +// The following regex are used to parse the d attribute of a path + +// Matches all hyphens which are not after an exponent +export let hyphen = /([^e])-/gi + +// Replaces and tests for all path letters +export let pathLetters = /[MLHVCSQTAZ]/gi + +// yes we need this one, too +export let isPathLetter = /[MLHVCSQTAZ]/i + +// matches 0.154.23.45 +export let numbersWithDots = /((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi + +// matches . +export let dots = /\./g diff --git a/src/modules/core/selector.js b/src/modules/core/selector.js new file mode 100644 index 0000000..1e0b55e --- /dev/null +++ b/src/modules/core/selector.js @@ -0,0 +1,16 @@ +import { adopt } from '../../utils/adopter.js' +import { map } from '../../utils/utils.js' +import { registerMethods } from '../../utils/methods.js' + +export default function baseFind (query, parent) { + return map((parent || document).querySelectorAll(query), function (node) { + return adopt(node) + }) +} + +// Scoped find method +export function find (query) { + return baseFind(query, this.node) +} + +registerMethods('Dom', { find }) diff --git a/src/modules/core/textable.js b/src/modules/core/textable.js new file mode 100644 index 0000000..c9a90db --- /dev/null +++ b/src/modules/core/textable.js @@ -0,0 +1,18 @@ +// Create plain text node +export function plain (text) { + // clear if build mode is disabled + if (this._build === false) { + this.clear() + } + + // create text node + this.node.appendChild(document.createTextNode(text)) + + return this +} + +// FIXME: Does this also work for textpath? +// Get length of text element +export function length () { + return this.node.getComputedTextLength() +} diff --git a/src/modules/optional/arrange.js b/src/modules/optional/arrange.js new file mode 100644 index 0000000..ca0e074 --- /dev/null +++ b/src/modules/optional/arrange.js @@ -0,0 +1,98 @@ +import { registerMethods } from '../../utils/methods.js' + +// Get all siblings, including myself +export function siblings () { + return this.parent().children() +} + +// Get the curent position siblings +export function position () { + return this.parent().index(this) +} + +// Get the next element (will return null if there is none) +export function next () { + return this.siblings()[this.position() + 1] +} + +// Get the next element (will return null if there is none) +export function prev () { + return this.siblings()[this.position() - 1] +} + +// Send given element one step forward +export function forward () { + var i = this.position() + 1 + 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) + } + + return this +} + +// Send given element one step backward +export function backward () { + var i = this.position() + + if (i > 0) { + this.parent().removeElement(this).add(this, i - 1) + } + + return this +} + +// Send given element all the way to the front +export function front () { + var p = this.parent() + + // Move node forward + p.node.appendChild(this.node) + + // Make sure defs node is always at the top + if (typeof p.isRoot === 'function' && p.isRoot()) { + p.node.appendChild(p.defs().node) + } + + return this +} + +// Send given element all the way to the back +export function back () { + if (this.position() > 0) { + this.parent().removeElement(this).add(this, 0) + } + + return this +} + +// Inserts a given element before the targeted element +export function before (element) { + element.remove() + + var i = this.position() + + this.parent().add(element, i) + + return this +} + +// Inserts a given element after the targeted element +export function after (element) { + element.remove() + + var i = this.position() + + this.parent().add(element, i + 1) + + return this +} + +registerMethods('Dom', { + siblings, position, next, prev, forward, backward, front, back, before, after +}) diff --git a/src/modules/optional/class.js b/src/modules/optional/class.js new file mode 100644 index 0000000..1d28fd5 --- /dev/null +++ b/src/modules/optional/class.js @@ -0,0 +1,44 @@ +import { delimiter } from '../core/regex.js' +import { registerMethods } from '../../utils/methods.js' + +// Return array of classes on the node +function classes () { + var attr = this.attr('class') + return attr == null ? [] : attr.trim().split(delimiter) +} + +// Return true if class exists on the node, false otherwise +function hasClass (name) { + return this.classes().indexOf(name) !== -1 +} + +// Add class to the node +function addClass (name) { + if (!this.hasClass(name)) { + var array = this.classes() + array.push(name) + this.attr('class', array.join(' ')) + } + + return this +} + +// Remove class from the node +function removeClass (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 +function toggleClass (name) { + return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) +} + +registerMethods('Dom', { + classes, hasClass, addClass, removeClass, toggleClass +}) diff --git a/src/modules/optional/css.js b/src/modules/optional/css.js new file mode 100644 index 0000000..924b13d --- /dev/null +++ b/src/modules/optional/css.js @@ -0,0 +1,71 @@ +// FIXME: We dont need exports +import { camelCase } from '../../utils/utils.js' +import { isBlank } from '../core/regex.js' +import { registerMethods } from '../../utils/methods.js' + +// Dynamic style generator +export function css (style, val) { + let ret = {} + if (arguments.length === 0) { + // get full style as object + this.node.style.cssText.split(/\s*;\s*/) + .filter(function (el) { return !!el.length }) + .forEach(function (el) { + let t = el.split(/\s*:\s*/) + ret[t[0]] = t[1] + }) + return ret + } + + if (arguments.length < 2) { + // get style properties in the array + if (Array.isArray(style)) { + for (let name of style) { + let cased = camelCase(name) + ret[cased] = this.node.style[cased] + } + return ret + } + + // get style for property + if (typeof style === 'string') { + return this.node.style[camelCase(style)] + } + + // set styles in object + if (typeof style === 'object') { + for (let name in style) { + // set empty string if null/undefined/'' was given + this.node.style[camelCase(name)] = + (style[name] == null || isBlank.test(style[name])) ? '' : style[name] + } + } + } + + // set style for property + if (arguments.length === 2) { + this.node.style[camelCase(style)] = + (val == null || isBlank.test(val)) ? '' : val + } + + return this +} + +// Show element +export function show () { + return this.css('display', '') +} + +// Hide element +export function hide () { + return this.css('display', 'none') +} + +// Is element visible? +export function visible () { + return this.css('display') !== 'none' +} + +registerMethods('Dom', { + css, show, hide, visible +}) diff --git a/src/modules/optional/data.js b/src/modules/optional/data.js new file mode 100644 index 0000000..341d129 --- /dev/null +++ b/src/modules/optional/data.js @@ -0,0 +1,26 @@ +import { registerMethods } from '../../utils/methods.js' + +// Store data values on svg nodes +export function data (a, v, r) { + if (typeof a === 'object') { + for (v in a) { + this.data(v, a[v]) + } + } else if (arguments.length < 2) { + try { + return JSON.parse(this.attr('data-' + a)) + } catch (e) { + return this.attr('data-' + a) + } + } else { + this.attr('data-' + a, + v === null ? null + : r === true || typeof v === 'string' || typeof v === 'number' ? v + : JSON.stringify(v) + ) + } + + return this +} + +registerMethods('Dom', { data }) diff --git a/src/modules/optional/memory.js b/src/modules/optional/memory.js new file mode 100644 index 0000000..d1bf7cf --- /dev/null +++ b/src/modules/optional/memory.js @@ -0,0 +1,39 @@ +import { registerMethods } from '../../utils/methods.js' +// FIXME: We need a constructor to set this up + +// Remember arbitrary data +export function remember (k, v) { + // remember every item in an object individually + if (typeof arguments[0] === 'object') { + for (var key in k) { + this.remember(key, k[key]) + } + } else if (arguments.length === 1) { + // retrieve memory + return this.memory()[k] + } else { + // store memory + this.memory()[k] = v + } + + return this +} + +// Erase a given memory +export function forget () { + if (arguments.length === 0) { + this._memory = {} + } else { + for (var i = arguments.length - 1; i >= 0; i--) { + delete this.memory()[arguments[i]] + } + } + return this +} + +// return local memory object +export function memory () { + return (this._memory = this._memory || {}) +} + +registerMethods('Dom', { remember, forget, memory }) diff --git a/src/modules/optional/sugar.js b/src/modules/optional/sugar.js new file mode 100644 index 0000000..904e353 --- /dev/null +++ b/src/modules/optional/sugar.js @@ -0,0 +1,159 @@ +import { registerMethods } from '../../utils/methods.js' +import Color from '../../types/Color.js' +import Element from '../../elements/Element.js' +import Matrix from '../../types/Matrix.js' +import Point from '../../types/Point.js' +import Runner from '../../animation/Runner.js' +import SVGNumber from '../../types/SVGNumber.js' + +// Define list of available attributes for stroke and fill +var sugar = { + stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], + fill: ['color', 'opacity', 'rule'], + prefix: function (t, a) { + return a === 'color' ? t : t + '-' + a + } +} + +// Add sugar for fill and stroke +;['fill', 'stroke'].forEach(function (m) { + var extension = {} + var i + + extension[m] = function (o) { + if (typeof o === 'undefined') { + return this + } + if (typeof o === 'string' || Color.isRgb(o) || (o instanceof Element)) { + this.attr(m, o) + } else { + // set all attributes from sugar.fill and sugar.stroke list + for (i = sugar[m].length - 1; i >= 0; i--) { + if (o[sugar[m][i]] != null) { + this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]]) + } + } + } + + return this + } + + registerMethods(['Shape', 'Runner'], extension) +}) + +registerMethods(['Element', 'Runner'], { + // Let the user set the matrix directly + matrix: function (mat, b, c, d, e, f) { + // Act as a getter + if (mat == null) { + return new Matrix(this) + } + + // Act as a setter, the user can pass a matrix or a set of numbers + return this.attr('transform', new Matrix(mat, b, c, d, e, f)) + }, + + // Map rotation to transform + rotate: function (angle, cx, cy) { + return this.transform({ rotate: angle, ox: cx, oy: cy }, true) + }, + + // Map skew to transform + skew: function (x, y, cx, cy) { + return arguments.length === 1 || arguments.length === 3 + ? this.transform({ skew: x, ox: y, oy: cx }, true) + : this.transform({ skew: [x, y], ox: cx, oy: cy }, true) + }, + + shear: function (lam, cx, cy) { + return this.transform({ shear: lam, ox: cx, oy: cy }, true) + }, + + // Map scale to transform + scale: function (x, y, cx, cy) { + return arguments.length === 1 || arguments.length === 3 + ? this.transform({ scale: x, ox: y, oy: cx }, true) + : this.transform({ scale: [x, y], ox: cx, oy: cy }, true) + }, + + // Map translate to transform + translate: function (x, y) { + return this.transform({ translate: [x, y] }, true) + }, + + // Map relative translations to transform + relative: function (x, y) { + return this.transform({ relative: [x, y] }, true) + }, + + // Map flip to transform + flip: function (direction, around) { + var directionString = typeof direction === 'string' ? direction + : isFinite(direction) ? 'both' + : 'both' + var origin = (direction === 'both' && isFinite(around)) ? [around, around] + : (direction === 'x') ? [around, 0] + : (direction === 'y') ? [0, around] + : isFinite(direction) ? [direction, direction] + : [0, 0] + this.transform({ flip: directionString, origin: origin }, true) + }, + + // Opacity + opacity: function (value) { + return this.attr('opacity', value) + }, + + // Relative move over x axis + dx: function (x) { + return this.x(new SVGNumber(x).plus(this instanceof Runner ? 0 : this.x()), true) + }, + + // Relative move over y axis + dy: function (y) { + return this.y(new SVGNumber(y).plus(this instanceof Runner ? 0 : this.y()), true) + }, + + // Relative move over x and y axes + dmove: function (x, y) { + return this.dx(x).dy(y) + } +}) + +registerMethods('radius', { + // Add x and y radius + radius: function (x, y) { + var type = (this._element || this).type + return type === 'radialGradient' || type === 'radialGradient' + ? this.attr('r', new SVGNumber(x)) + : this.rx(x).ry(y == null ? x : y) + } +}) + +registerMethods('Path', { + // Get path length + length: function () { + return this.node.getTotalLength() + }, + // Get point at length + pointAt: function (length) { + return new Point(this.node.getPointAtLength(length)) + } +}) + +registerMethods(['Element', 'Runner'], { + // Set font + font: function (a, v) { + if (typeof a === 'object') { + for (v in a) this.font(v, a[v]) + } + + return a === 'leading' + ? this.leading(v) + : a === 'anchor' + ? this.attr('text-anchor', v) + : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style' + ? this.attr('font-' + a, v) + : this.attr(a, v) + } +}) diff --git a/src/modules/optional/transform.js b/src/modules/optional/transform.js new file mode 100644 index 0000000..7535fdc --- /dev/null +++ b/src/modules/optional/transform.js @@ -0,0 +1,72 @@ +import { getOrigin } from '../../utils/utils.js' +import { delimiter, transforms } from '../core/regex.js' +import { registerMethods } from '../../utils/methods.js' +import Matrix from '../../types/Matrix.js' + +// Reset all transformations +export function untransform () { + return this.attr('transform', null) +} + +// merge the whole transformation chain into one matrix and returns it +export function matrixify () { + var matrix = (this.attr('transform') || '') + // split transformations + .split(transforms).slice(0, -1).map(function (str) { + // generate key => value pairs + var kv = str.trim().split('(') + return [kv[0], + kv[1].split(delimiter) + .map(function (str) { return parseFloat(str) }) + ] + }) + .reverse() + // merge every transformation into one matrix + .reduce(function (matrix, transform) { + if (transform[0] === 'matrix') { + return matrix.lmultiply(Matrix.fromArray(transform[1])) + } + return matrix[transform[0]].apply(matrix, transform[1]) + }, new Matrix()) + + return matrix +} + +// add an element to another parent without changing the visual representation on the screen +export function toParent (parent) { + if (this === parent) return this + var ctm = this.screenCTM() + var pCtm = parent.screenCTM().inverse() + + this.addTo(parent).untransform().transform(pCtm.multiply(ctm)) + + return this +} + +// same as above with parent equals root-svg +export function toDoc () { + return this.toParent(this.doc()) +} + +// Add transformations +export function transform (o, relative) { + // Act as a getter if no object was passed + if (o == null || typeof o === 'string') { + var decomposed = new Matrix(this).decompose() + return decomposed[o] || decomposed + } + + if (!Matrix.isMatrixLike(o)) { + // Set the origin according to the defined transform + o = { ...o, origin: getOrigin(o, this) } + } + + // The user can pass a boolean, an Element or an Matrix or nothing + var cleanRelative = relative === true ? this : (relative || false) + var result = new Matrix(cleanRelative).transform(o) + return this.attr('transform', result) +} + +registerMethods('Element', { + untransform, matrixify, toParent, toDoc, transform +}) diff --git a/src/namespaces.js b/src/namespaces.js deleted file mode 100644 index 3791298..0000000 --- a/src/namespaces.js +++ /dev/null @@ -1,5 +0,0 @@ -// Default namespaces -export let ns = 'http://www.w3.org/2000/svg' -export let xmlns = 'http://www.w3.org/2000/xmlns/' -export let xlink = 'http://www.w3.org/1999/xlink' -export let svgjs = 'http://svgjs.com/svgjs' diff --git a/src/parser.js b/src/parser.js deleted file mode 100644 index aa58db4..0000000 --- a/src/parser.js +++ /dev/null @@ -1,25 +0,0 @@ -import Doc from './Doc.js' - -export default function parser () { - // Reuse cached element if possible - if (!parser.nodes) { - let svg = new Doc().size(2, 0).css({ - opacity: 0, - position: 'absolute', - left: '-100%', - top: '-100%', - overflow: 'hidden' - }) - - let path = svg.path().node - - parser.nodes = { svg, path } - } - - if (!parser.nodes.svg.node.parentNode) { - let b = document.body || document.documentElement - parser.nodes.svg.addTo(b) - } - - return parser.nodes -} diff --git a/src/pointed.js b/src/pointed.js deleted file mode 100644 index d5deaf1..0000000 --- a/src/pointed.js +++ /dev/null @@ -1,25 +0,0 @@ -import PointArray from './PointArray.js' - -export let MorphArray = PointArray - -// Move by left top corner over x-axis -export function x (x) { - return x == null ? this.bbox().x : this.move(x, this.bbox().y) -} - -// Move by left top corner over y-axis -export function y (y) { - return y == null ? this.bbox().y : this.move(this.bbox().x, y) -} - -// Set width of element -export function width (width) { - let b = this.bbox() - return width == null ? b.width : this.size(width, b.height) -} - -// Set height of element -export function height (height) { - let b = this.bbox() - return height == null ? b.height : this.size(b.width, height) -} diff --git a/src/poly.js b/src/poly.js deleted file mode 100644 index 269b0c9..0000000 --- a/src/poly.js +++ /dev/null @@ -1,32 +0,0 @@ -// Add polygon-specific functions -import PointArray from './PointArray.js' -import { proportionalSize } from './helpers.js' - -// Get array -export function array () { - return this._array || (this._array = new PointArray(this.attr('points'))) -} - -// Plot new path -export function plot (p) { - return (p == null) ? this.array() - : this.clear().attr('points', typeof p === 'string' ? p - : (this._array = new PointArray(p))) -} - -// Clear array cache -export function clear () { - delete this._array - return this -} - -// Move by left top corner -export function move (x, y) { - return this.attr('points', this.array().move(x, y)) -} - -// Set element size to given width and height -export function size (width, height) { - let p = proportionalSize(this, width, height) - return this.attr('points', this.array().size(p.width, p.height)) -} diff --git a/src/regex.js b/src/regex.js deleted file mode 100644 index 1056554..0000000 --- a/src/regex.js +++ /dev/null @@ -1,58 +0,0 @@ -// Parse unit value -export let numberAndUnit = /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i - -// Parse hex value -export let hex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i - -// Parse rgb value -export let rgb = /rgb\((\d+),(\d+),(\d+)\)/ - -// Parse reference id -export let reference = /(#[a-z0-9\-_]+)/i - -// splits a transformation chain -export let transforms = /\)\s*,?\s*/ - -// Whitespace -export let whitespace = /\s/g - -// Test hex value -export let isHex = /^#[a-f0-9]{3,6}$/i - -// Test rgb value -export let isRgb = /^rgb\(/ - -// Test css declaration -export let isCss = /[^:]+:[^;]+;?/ - -// Test for blank string -export let isBlank = /^(\s+)?$/ - -// Test for numeric string -export let isNumber = /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i - -// Test for percent value -export let isPercent = /^-?[\d.]+%$/ - -// Test for image url -export let isImage = /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i - -// split at whitespace and comma -export let delimiter = /[\s,]+/ - -// The following regex are used to parse the d attribute of a path - -// Matches all hyphens which are not after an exponent -export let hyphen = /([^e])-/gi - -// Replaces and tests for all path letters -export let pathLetters = /[MLHVCSQTAZ]/gi - -// yes we need this one, too -export let isPathLetter = /[MLHVCSQTAZ]/i - -// matches 0.154.23.45 -export let numbersWithDots = /((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi - -// matches . -export let dots = /\./g diff --git a/src/selector.js b/src/selector.js deleted file mode 100644 index 7208153..0000000 --- a/src/selector.js +++ /dev/null @@ -1,16 +0,0 @@ -import { map } from './utils.js' -import { adopt } from './adopter.js' -import { registerMethods } from './methods.js' - -export default function baseFind (query, parent) { - return map((parent || document).querySelectorAll(query), function (node) { - return adopt(node) - }) -} - -// Scoped find method -export function find (query) { - return baseFind(query, this.node) -} - -registerMethods('Dom', { find }) diff --git a/src/set.js b/src/set.js deleted file mode 100644 index c755c2c..0000000 --- a/src/set.js +++ /dev/null @@ -1,18 +0,0 @@ -/* eslint no-unused-vars: "off" */ -class SVGSet extends Set { - // constructor (arr) { - // super(arr) - // } - - each (cbOrName, ...args) { - if (typeof cbOrName === 'function') { - this.forEach((el) => { cbOrName.call(el, el) }) - } else { - this.forEach((el) => { - el[cbOrName](...args) - }) - } - - return this - } -} diff --git a/src/sugar.js b/src/sugar.js deleted file mode 100644 index 7d34cee..0000000 --- a/src/sugar.js +++ /dev/null @@ -1,159 +0,0 @@ -import Color from './Color.js' -import Runner from './Runner.js' -import SVGNumber from './SVGNumber.js' -import Matrix from './Matrix.js' -import Point from './Point.js' -import Element from './Element.js' -import { registerMethods } from './methods.js' - -// Define list of available attributes for stroke and fill -var sugar = { - stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], - fill: ['color', 'opacity', 'rule'], - prefix: function (t, a) { - return a === 'color' ? t : t + '-' + a - } -} - -// Add sugar for fill and stroke -;['fill', 'stroke'].forEach(function (m) { - var extension = {} - var i - - extension[m] = function (o) { - if (typeof o === 'undefined') { - return this - } - if (typeof o === 'string' || Color.isRgb(o) || (o instanceof Element)) { - this.attr(m, o) - } else { - // set all attributes from sugar.fill and sugar.stroke list - for (i = sugar[m].length - 1; i >= 0; i--) { - if (o[sugar[m][i]] != null) { - this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]]) - } - } - } - - return this - } - - registerMethods(['Shape', 'Runner'], extension) -}) - -registerMethods(['Element', 'Runner'], { - // Let the user set the matrix directly - matrix: function (mat, b, c, d, e, f) { - // Act as a getter - if (mat == null) { - return new Matrix(this) - } - - // Act as a setter, the user can pass a matrix or a set of numbers - return this.attr('transform', new Matrix(mat, b, c, d, e, f)) - }, - - // Map rotation to transform - rotate: function (angle, cx, cy) { - return this.transform({ rotate: angle, ox: cx, oy: cy }, true) - }, - - // Map skew to transform - skew: function (x, y, cx, cy) { - return arguments.length === 1 || arguments.length === 3 - ? this.transform({ skew: x, ox: y, oy: cx }, true) - : this.transform({ skew: [x, y], ox: cx, oy: cy }, true) - }, - - shear: function (lam, cx, cy) { - return this.transform({ shear: lam, ox: cx, oy: cy }, true) - }, - - // Map scale to transform - scale: function (x, y, cx, cy) { - return arguments.length === 1 || arguments.length === 3 - ? this.transform({ scale: x, ox: y, oy: cx }, true) - : this.transform({ scale: [x, y], ox: cx, oy: cy }, true) - }, - - // Map translate to transform - translate: function (x, y) { - return this.transform({ translate: [x, y] }, true) - }, - - // Map relative translations to transform - relative: function (x, y) { - return this.transform({ relative: [x, y] }, true) - }, - - // Map flip to transform - flip: function (direction, around) { - var directionString = typeof direction === 'string' ? direction - : isFinite(direction) ? 'both' - : 'both' - var origin = (direction === 'both' && isFinite(around)) ? [around, around] - : (direction === 'x') ? [around, 0] - : (direction === 'y') ? [0, around] - : isFinite(direction) ? [direction, direction] - : [0, 0] - this.transform({ flip: directionString, origin: origin }, true) - }, - - // Opacity - opacity: function (value) { - return this.attr('opacity', value) - }, - - // Relative move over x axis - dx: function (x) { - return this.x(new SVGNumber(x).plus(this instanceof Runner ? 0 : this.x()), true) - }, - - // Relative move over y axis - dy: function (y) { - return this.y(new SVGNumber(y).plus(this instanceof Runner ? 0 : this.y()), true) - }, - - // Relative move over x and y axes - dmove: function (x, y) { - return this.dx(x).dy(y) - } -}) - -registerMethods('radius', { - // Add x and y radius - radius: function (x, y) { - var type = (this._element || this).type - return type === 'radialGradient' || type === 'radialGradient' - ? this.attr('r', new SVGNumber(x)) - : this.rx(x).ry(y == null ? x : y) - } -}) - -registerMethods('Path', { - // Get path length - length: function () { - return this.node.getTotalLength() - }, - // Get point at length - pointAt: function (length) { - return new Point(this.node.getPointAtLength(length)) - } -}) - -registerMethods(['Element', 'Runner'], { - // Set font - font: function (a, v) { - if (typeof a === 'object') { - for (v in a) this.font(v, a[v]) - } - - return a === 'leading' - ? this.leading(v) - : a === 'anchor' - ? this.attr('text-anchor', v) - : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style' - ? this.attr('font-' + a, v) - : this.attr(a, v) - } -}) diff --git a/src/svg.js b/src/svg.js index a7e92d0..4026598 100644 --- a/src/svg.js +++ b/src/svg.js @@ -1,101 +1,14 @@ -import * as Classes from './classes.js' -import * as adopter from './adopter.js' -import * as tools from './tools.js' -import './attr.js' -import './arrange.js' -import './data.js' -import './classHandling.js' -import find from './selector.js' -import './css.js' -import './transform.js' -import './memory.js' -import './sugar.js' -import { getMethodsFor } from './methods.js' -import { registerMorphableType, makeMorphable, TransformBag, ObjectBag, NonMorphable } from './Morphable.js' - -import './EventTarget.js' -import './Element.js' - -import * as utils from './utils.js' - -import * as regex from './regex.js' - -// satisfy tests, fix later -import * as ns from './namespaces.js' -import { easing } from './Controller.js' -import * as events from './event.js' -import parser from './parser.js' -import * as defaults from './defaults.js' -const extend = tools.extend - -extend([ - Classes.Doc, - Classes.Symbol, - Classes.Image, - Classes.Pattern, - Classes.Marker -], getMethodsFor('viewbox')) - -extend([ - Classes.Line, - Classes.Polyline, - Classes.Polygon, - Classes.Path -], getMethodsFor('marker')) - -extend(Classes.Text, getMethodsFor('Text')) -extend(Classes.Path, getMethodsFor('Path')) - -extend(Classes.Defs, getMethodsFor('Defs')) - -extend([ - Classes.Text, - Classes.Tspan -], getMethodsFor('Tspan')) - -extend([ - Classes.Rect, - Classes.Ellipse, - Classes.Circle, - Classes.Gradient -], getMethodsFor('radius')) - -extend(Classes.EventTarget, getMethodsFor('EventTarget')) -extend(Classes.Dom, getMethodsFor('Dom')) -extend(Classes.Element, getMethodsFor('Element')) -extend(Classes.Shape, getMethodsFor('Shape')) -// extend(Classes.Element, getConstructor('Memory')) -extend(Classes.Container, getMethodsFor('Container')) - -registerMorphableType([ - Classes.SVGNumber, - Classes.Color, - Classes.Box, - Classes.Matrix, - Classes.SVGArray, - Classes.PointArray, - Classes.PathArray -]) - -makeMorphable() +import * as svgMembers from './main.js' +import * as regex from './modules/core/regex.js' +import { makeInstance } from './utils/adopter' // The main wrapping element export default function SVG (element) { - return adopter.makeInstance(element) + return makeInstance(element) } -Object.assign(SVG, Classes) -Object.assign(SVG, tools) -Object.assign(SVG, adopter) -SVG.utils = utils +Object.assign(SVG, svgMembers) + +SVG.utils = SVG SVG.regex = regex SVG.get = SVG -SVG.find = find -Object.assign(SVG, ns) -SVG.easing = easing -Object.assign(SVG, events) -SVG.TransformBag = TransformBag -SVG.ObjectBag = ObjectBag -SVG.NonMorphable = NonMorphable -SVG.parser = parser -SVG.defaults = defaults diff --git a/src/textable.js b/src/textable.js deleted file mode 100644 index c9a90db..0000000 --- a/src/textable.js +++ /dev/null @@ -1,18 +0,0 @@ -// Create plain text node -export function plain (text) { - // clear if build mode is disabled - if (this._build === false) { - this.clear() - } - - // create text node - this.node.appendChild(document.createTextNode(text)) - - return this -} - -// FIXME: Does this also work for textpath? -// Get length of text element -export function length () { - return this.node.getComputedTextLength() -} diff --git a/src/tools.js b/src/tools.js deleted file mode 100644 index 14e19a3..0000000 --- a/src/tools.js +++ /dev/null @@ -1,56 +0,0 @@ -import { ns } from './namespaces.js' -import { getClass } from './adopter.js' - -export function nodeOrNew (name, node) { - return node || makeNode(name) -} - -// Method for element creation -export function makeNode (name) { - // create element - return document.createElementNS(ns, name) -} - -// Method for extending objects -export function extend (modules, methods) { - var key, i - - modules = Array.isArray(modules) ? modules : [modules] - - for (i = modules.length - 1; i >= 0; i--) { - for (key in methods) { - modules[i].prototype[key] = methods[key] - } - } -} - -// FIXME: enhanced constructors here -export function addFactory (modules, methods) { - extend(modules, methods) -} - -// Invent new element -export function invent (config) { - // Create element initializer - var initializer = typeof config.create === 'function' ? config.create - : function (node) { - config.inherit.call(this, node || makeNode(config.create)) - } - - // Inherit prototype - if (config.inherit) { - /* eslint new-cap: "off" */ - initializer.prototype = new config.inherit() - initializer.prototype.constructor = initializer - } - - // Extend with methods - if (config.extend) { - extend(initializer, config.extend) - } - - // Attach construct method to parent - if (config.construct) { extend(config.parent || getClass('Container'), config.construct) } - - return initializer -} diff --git a/src/transform.js b/src/transform.js deleted file mode 100644 index ff3364e..0000000 --- a/src/transform.js +++ /dev/null @@ -1,72 +0,0 @@ -import { arrayToMatrix, getOrigin, isMatrixLike } from './helpers.js' -import Matrix from './Matrix.js' -import { delimiter, transforms } from './regex.js' -import { registerMethods } from './methods.js' - -// Reset all transformations -export function untransform () { - return this.attr('transform', null) -} - -// merge the whole transformation chain into one matrix and returns it -export function matrixify () { - var matrix = (this.attr('transform') || '') - // split transformations - .split(transforms).slice(0, -1).map(function (str) { - // generate key => value pairs - var kv = str.trim().split('(') - return [kv[0], - kv[1].split(delimiter) - .map(function (str) { return parseFloat(str) }) - ] - }) - .reverse() - // merge every transformation into one matrix - .reduce(function (matrix, transform) { - if (transform[0] === 'matrix') { - return matrix.lmultiply(arrayToMatrix(transform[1])) - } - return matrix[transform[0]].apply(matrix, transform[1]) - }, new Matrix()) - - return matrix -} - -// add an element to another parent without changing the visual representation on the screen -export function toParent (parent) { - if (this === parent) return this - var ctm = this.screenCTM() - var pCtm = parent.screenCTM().inverse() - - this.addTo(parent).untransform().transform(pCtm.multiply(ctm)) - - return this -} - -// same as above with parent equals root-svg -export function toDoc () { - return this.toParent(this.doc()) -} - -// Add transformations -export function transform (o, relative) { - // Act as a getter if no object was passed - if (o == null || typeof o === 'string') { - var decomposed = new Matrix(this).decompose() - return decomposed[o] || decomposed - } - - if (!isMatrixLike(o)) { - // Set the origin according to the defined transform - o = { ...o, origin: getOrigin(o, this) } - } - - // The user can pass a boolean, an Element or an Matrix or nothing - var cleanRelative = relative === true ? this : (relative || false) - var result = new Matrix(cleanRelative).transform(o) - return this.attr('transform', result) -} - -registerMethods('Element', { - untransform, matrixify, toParent, toDoc, transform -}) diff --git a/src/types/ArrayPolyfill.js b/src/types/ArrayPolyfill.js new file mode 100644 index 0000000..cf95d54 --- /dev/null +++ b/src/types/ArrayPolyfill.js @@ -0,0 +1,30 @@ +/* eslint no-new-func: "off" */ +export const subClassArray = (function () { + try { + // try es6 subclassing + return Function('name', 'baseClass', '_constructor', [ + 'baseClass = baseClass || Array', + 'return {', + '[name]: class extends baseClass {', + 'constructor (...args) {', + 'super(...args)', + '_constructor && _constructor.apply(this, args)', + '}', + '}', + '}[name]' + ].join('\n')) + } catch (e) { + // Use es5 approach + return (name, baseClass = Array, _constructor) => { + const Arr = function () { + baseClass.apply(this, arguments) + _constructor && _constructor.apply(this, arguments) + } + + Arr.prototype = Object.create(baseClass.prototype) + Arr.prototype.constructor = Arr + + return Arr + } + } +})() diff --git a/src/types/Base.js b/src/types/Base.js new file mode 100644 index 0000000..d2897a1 --- /dev/null +++ b/src/types/Base.js @@ -0,0 +1,10 @@ +export default class Base { + // constructor (node/*, {extensions = []} */) { + // // this.tags = [] + // // + // // for (let extension of extensions) { + // // extension.setup.call(this, node) + // // this.tags.push(extension.name) + // // } + // } +} diff --git a/src/types/Box.js b/src/types/Box.js new file mode 100644 index 0000000..b51415f --- /dev/null +++ b/src/types/Box.js @@ -0,0 +1,147 @@ +import { delimiter } from '../modules/core/regex.js' +import { registerMethods } from '../utils/methods.js' +import Point from './Point.js' +import parser from '../modules/core/parser.js' + +function isNulledBox (box) { + return !box.w && !box.h && !box.x && !box.y +} + +function domContains (node) { + return (document.documentElement.contains || function (node) { + // This is IE - it does not support contains() for top-level SVGs + while (node.parentNode) { + node = node.parentNode + } + return node === document + }).call(document.documentElement, node) +} + +export default class Box { + constructor (...args) { + this.init(...args) + } + + init (source) { + var base = [0, 0, 0, 0] + source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) + : Array.isArray(source) ? source + : typeof source === 'object' ? [source.left != null ? source.left + : source.x, source.top != null ? source.top : source.y, source.width, source.height] + : arguments.length === 4 ? [].slice.call(arguments) + : base + + this.x = source[0] || 0 + this.y = source[1] || 0 + this.width = this.w = source[2] || 0 + this.height = this.h = source[3] || 0 + + // Add more bounding box properties + this.x2 = this.x + this.w + this.y2 = this.y + this.h + this.cx = this.x + this.w / 2 + this.cy = this.y + this.h / 2 + } + + // Merge rect box with another, return a new instance + merge (box) { + let x = Math.min(this.x, box.x) + let y = Math.min(this.y, box.y) + let width = Math.max(this.x + this.width, box.x + box.width) - x + let height = Math.max(this.y + this.height, box.y + box.height) - y + + return new Box(x, y, width, height) + } + + transform (m) { + let xMin = Infinity + let xMax = -Infinity + let yMin = Infinity + let yMax = -Infinity + + let pts = [ + new Point(this.x, this.y), + new Point(this.x2, this.y), + new Point(this.x, this.y2), + new Point(this.x2, this.y2) + ] + + pts.forEach(function (p) { + p = p.transform(m) + xMin = Math.min(xMin, p.x) + xMax = Math.max(xMax, p.x) + yMin = Math.min(yMin, p.y) + yMax = Math.max(yMax, p.y) + }) + + return new Box( + xMin, yMin, + xMax - xMin, + yMax - yMin + ) + } + + addOffset () { + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset + this.y += window.pageYOffset + return this + } + + toString () { + return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height + } + + toArray () { + return [this.x, this.y, this.width, this.height] + } + + isNulled () { + return isNulledBox(this) + } +} + +function getBox (cb) { + let box + + try { + box = cb(this.node) + + if (isNulledBox(box) && !domContains(this.node)) { + throw new Error('Element not in the dom') + } + } catch (e) { + try { + let clone = this.clone(parser().svg).show() + box = cb(clone.node) + clone.remove() + } catch (e) { + console.warn('Getting a bounding box of this element is not possible') + } + } + return box +} + +registerMethods({ + Element: { + // Get bounding box + bbox () { + return new Box(getBox.call(this, (node) => node.getBBox())) + }, + + rbox (el) { + let box = new Box(getBox.call(this, (node) => node.getBoundingClientRect())) + if (el) return box.transform(el.screenCTM().inverse()) + return box.addOffset() + } + }, + viewbox: { + viewbox (x, y, width, height) { + // act as getter + if (x == null) return new Box(this.attr('viewBox')) + + // act as setter + return this.attr('viewBox', new Box(x, y, width, height)) + } + } +}) diff --git a/src/types/Color.js b/src/types/Color.js new file mode 100644 index 0000000..6bbfd82 --- /dev/null +++ b/src/types/Color.js @@ -0,0 +1,146 @@ +/* + +Color { + constructor (a, b, c, space) { + space: 'hsl' + a: 30 + b: 20 + c: 10 + }, + + toRgb () { return new Color in rgb space } + toHsl () { return new Color in hsl space } + toLab () { return new Color in lab space } + + toArray () { [space, a, b, c] } + fromArray () { convert it back } +} + +// Conversions aren't always exact because of monitor profiles etc... +new Color(h, s, l, 'hsl') !== new Color(r, g, b).hsl() +new Color(100, 100, 100, [space]) +new Color('hsl(30, 20, 10)') + +// Sugar +SVG.rgb(30, 20, 50).lab() +SVG.hsl() +SVG.lab('rgb(100, 100, 100)') +*/ + +import { hex, isHex, isRgb, rgb, whitespace } from '../modules/core/regex.js' + +// Ensure to six-based hex +function fullHex (hex) { + return hex.length === 4 + ? [ '#', + hex.substring(1, 2), hex.substring(1, 2), + hex.substring(2, 3), hex.substring(2, 3), + hex.substring(3, 4), hex.substring(3, 4) + ].join('') + : hex +} + +// Component to hex value +function compToHex (comp) { + var hex = comp.toString(16) + return hex.length === 1 ? '0' + hex : hex +} + +export default class Color { + constructor (...args) { + this.init(...args) + } + + init (color, g, b) { + let match + + // initialize defaults + this.r = 0 + this.g = 0 + this.b = 0 + + if (!color) return + + // parse color + if (typeof color === 'string') { + if (isRgb.test(color)) { + // get rgb values + match = rgb.exec(color.replace(whitespace, '')) + + // parse numeric values + this.r = parseInt(match[1]) + this.g = parseInt(match[2]) + this.b = parseInt(match[3]) + } else if (isHex.test(color)) { + // get hex values + match = hex.exec(fullHex(color)) + + // parse numeric values + this.r = parseInt(match[1], 16) + this.g = parseInt(match[2], 16) + this.b = parseInt(match[3], 16) + } + } else if (Array.isArray(color)) { + this.r = color[0] + this.g = color[1] + this.b = color[2] + } else if (typeof color === 'object') { + this.r = color.r + this.g = color.g + this.b = color.b + } else if (arguments.length === 3) { + this.r = color + this.g = g + this.b = b + } + } + + // Default to hex conversion + toString () { + return this.toHex() + } + + toArray () { + return [this.r, this.g, this.b] + } + + // Build hex value + toHex () { + return '#' + + compToHex(Math.round(this.r)) + + compToHex(Math.round(this.g)) + + compToHex(Math.round(this.b)) + } + + // Build rgb value + toRgb () { + return 'rgb(' + [this.r, this.g, this.b].join() + ')' + } + + // Calculate true brightness + brightness () { + return (this.r / 255 * 0.30) + + (this.g / 255 * 0.59) + + (this.b / 255 * 0.11) + } + + // Testers + + // Test if given value is a color string + static test (color) { + color += '' + return isHex.test(color) || isRgb.test(color) + } + + // Test if given value is a rgb object + static isRgb (color) { + return color && typeof color.r === 'number' && + typeof color.g === 'number' && + typeof color.b === 'number' + } + + // Test if given value is a color + static isColor (color) { + return this.isRgb(color) || this.test(color) + } +} diff --git a/src/types/EventTarget.js b/src/types/EventTarget.js new file mode 100644 index 0000000..a32a1f1 --- /dev/null +++ b/src/types/EventTarget.js @@ -0,0 +1,90 @@ +import { dispatch, off, on } from '../modules/core/event.js' +import { registerMethods } from '../utils/methods.js' +import Base from './Base.js' + +export default class EventTarget extends Base { + constructor ({ events = {} } = {}) { + super() + this.events = events + } + + addEventListener () {} + + // Bind given event to listener + on (event, listener, binding, options) { + on(this, event, listener, binding, options) + return this + } + + // Unbind event from listener + off (event, listener) { + off(this, event, listener) + return this + } + + dispatch (event, data) { + return dispatch(this, event, data) + } + + dispatchEvent (event) { + const bag = this.getEventHolder().events + if (!bag) return true + + const events = bag[event.type] + + for (let i in events) { + for (let j in events[i]) { + events[i][j](event) + } + } + + return !event.defaultPrevented + } + + // Fire given event + fire (event, data) { + this.dispatch(event, data) + return this + } + + getEventHolder () { + return this + } + + getEventTarget () { + return this + } + + removeEventListener () {} +} + +// Add events to elements +const methods = [ 'click', + 'dblclick', + 'mousedown', + 'mouseup', + 'mouseover', + 'mouseout', + 'mousemove', + 'mouseenter', + 'mouseleave', + 'touchstart', + 'touchmove', + 'touchleave', + 'touchend', + 'touchcancel' ].reduce(function (last, event) { + // add event to Element + const fn = function (f) { + if (f === null) { + off(this, event) + } else { + on(this, event, f) + } + return this + } + + last[event] = fn + return last +}, {}) + +registerMethods('Element', methods) diff --git a/src/types/Matrix.js b/src/types/Matrix.js new file mode 100644 index 0000000..963fd1a --- /dev/null +++ b/src/types/Matrix.js @@ -0,0 +1,522 @@ +import { delimiter } from '../modules/core/regex.js' +import { radians } from '../utils/utils.js' +import { registerMethods } from '../utils/methods.js' +import Element from '../elements/Element.js' +import Point from './Point.js' +import parser from '../modules/core/parser.js' + +// Create matrix array for looping +const abcdef = 'abcdef'.split('') + +function closeEnough (a, b, threshold) { + return Math.abs(b - a) < (threshold || 1e-6) +} + +export default class Matrix { + constructor (...args) { + this.init(...args) + } + + // Initialize + init (source) { + var base = Matrix.fromArray([1, 0, 0, 1, 0, 0]) + + // ensure source as object + source = source instanceof Element ? source.matrixify() + : typeof source === 'string' ? Matrix.fromArray(source.split(delimiter).map(parseFloat)) + : Array.isArray(source) ? Matrix.fromArray(source) + : (typeof source === 'object' && Matrix.isMatrixLike(source)) ? source + : (typeof source === 'object') ? new Matrix().transform(source) + : arguments.length === 6 ? Matrix.fromArray([].slice.call(arguments)) + : base + + // Merge the source matrix with the base matrix + this.a = source.a != null ? source.a : base.a + this.b = source.b != null ? source.b : base.b + this.c = source.c != null ? source.c : base.c + this.d = source.d != null ? source.d : base.d + this.e = source.e != null ? source.e : base.e + this.f = source.f != null ? source.f : base.f + } + + // Clones this matrix + clone () { + return new Matrix(this) + } + + // Transform a matrix into another matrix by manipulating the space + transform (o) { + // Check if o is a matrix and then left multiply it directly + if (Matrix.isMatrixLike(o)) { + var matrix = new Matrix(o) + return matrix.multiplyO(this) + } + + // Get the proposed transformations and the current transformations + var t = Matrix.formatTransforms(o) + var current = this + let { x: ox, y: oy } = new Point(t.ox, t.oy).transform(current) + + // Construct the resulting matrix + var transformer = new Matrix() + .translateO(t.rx, t.ry) + .lmultiplyO(current) + .translateO(-ox, -oy) + .scaleO(t.scaleX, t.scaleY) + .skewO(t.skewX, t.skewY) + .shearO(t.shear) + .rotateO(t.theta) + .translateO(ox, oy) + + // If we want the origin at a particular place, we force it there + if (isFinite(t.px) || isFinite(t.py)) { + const origin = new Point(ox, oy).transform(transformer) + // TODO: Replace t.px with isFinite(t.px) + const dx = t.px ? t.px - origin.x : 0 + const dy = t.py ? t.py - origin.y : 0 + transformer.translateO(dx, dy) + } + + // Translate now after positioning + transformer.translateO(t.tx, t.ty) + return transformer + } + + // Applies a matrix defined by its affine parameters + compose (o) { + if (o.origin) { + o.originX = o.origin[0] + o.originY = o.origin[1] + } + // Get the parameters + var ox = o.originX || 0 + var oy = o.originY || 0 + var sx = o.scaleX || 1 + var sy = o.scaleY || 1 + var lam = o.shear || 0 + var theta = o.rotate || 0 + var tx = o.translateX || 0 + var ty = o.translateY || 0 + + // Apply the standard matrix + var result = new Matrix() + .translateO(-ox, -oy) + .scaleO(sx, sy) + .shearO(lam) + .rotateO(theta) + .translateO(tx, ty) + .lmultiplyO(this) + .translateO(ox, oy) + return result + } + + // Decomposes this matrix into its affine parameters + decompose (cx = 0, cy = 0) { + // Get the parameters from the matrix + var a = this.a + var b = this.b + var c = this.c + var d = this.d + var e = this.e + var f = this.f + + // Figure out if the winding direction is clockwise or counterclockwise + var determinant = a * d - b * c + var ccw = determinant > 0 ? 1 : -1 + + // Since we only shear in x, we can use the x basis to get the x scale + // and the rotation of the resulting matrix + var sx = ccw * Math.sqrt(a * a + b * b) + var thetaRad = Math.atan2(ccw * b, ccw * a) + var theta = 180 / Math.PI * thetaRad + var ct = Math.cos(thetaRad) + var st = Math.sin(thetaRad) + + // We can then solve the y basis vector simultaneously to get the other + // two affine parameters directly from these parameters + var lam = (a * c + b * d) / determinant + var sy = ((c * sx) / (lam * a - b)) || ((d * sx) / (lam * b + a)) + + // Use the translations + let tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy) + let ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy) + + // Construct the decomposition and return it + return { + // Return the affine parameters + scaleX: sx, + scaleY: sy, + shear: lam, + rotate: theta, + translateX: tx, + translateY: ty, + originX: cx, + originY: cy, + + // Return the matrix parameters + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + } + } + + // Left multiplies by the given matrix + multiply (matrix) { + return this.clone().multiplyO(matrix) + } + + multiplyO (matrix) { + // Get the matrices + var l = this + var r = matrix instanceof Matrix + ? matrix + : new Matrix(matrix) + + return Matrix.matrixMultiply(l, r, this) + } + + lmultiply (matrix) { + return this.clone().lmultiplyO(matrix) + } + + lmultiplyO (matrix) { + var r = this + var l = matrix instanceof Matrix + ? matrix + : new Matrix(matrix) + + return Matrix.matrixMultiply(l, r, this) + } + + // Inverses matrix + inverseO () { + // Get the current parameters out of the matrix + var a = this.a + var b = this.b + var c = this.c + var d = this.d + var e = this.e + var f = this.f + + // Invert the 2x2 matrix in the top left + var det = a * d - b * c + if (!det) throw new Error('Cannot invert ' + this) + + // Calculate the top 2x2 matrix + var na = d / det + var nb = -b / det + var nc = -c / det + var nd = a / det + + // Apply the inverted matrix to the top right + var ne = -(na * e + nc * f) + var nf = -(nb * e + nd * f) + + // Construct the inverted matrix + this.a = na + this.b = nb + this.c = nc + this.d = nd + this.e = ne + this.f = nf + + return this + } + + inverse () { + return this.clone().inverseO() + } + + // Translate matrix + translate (x, y) { + return this.clone().translateO(x, y) + } + + translateO (x, y) { + this.e += x || 0 + this.f += y || 0 + return this + } + + // Scale matrix + scale (x, y, cx, cy) { + return this.clone().scaleO(...arguments) + } + + scaleO (x, y = x, cx = 0, cy = 0) { + // Support uniform scaling + if (arguments.length === 3) { + cy = cx + cx = y + y = x + } + + let { a, b, c, d, e, f } = this + + this.a = a * x + this.b = b * y + this.c = c * x + this.d = d * y + this.e = e * x - cx * x + cx + this.f = f * y - cy * y + cy + + return this + } + + // Rotate matrix + rotate (r, cx, cy) { + return this.clone().rotateO(r, cx, cy) + } + + rotateO (r, cx = 0, cy = 0) { + // Convert degrees to radians + r = radians(r) + + let cos = Math.cos(r) + let sin = Math.sin(r) + + let { a, b, c, d, e, f } = this + + this.a = a * cos - b * sin + this.b = b * cos + a * sin + this.c = c * cos - d * sin + this.d = d * cos + c * sin + this.e = e * cos - f * sin + cy * sin - cx * cos + cx + this.f = f * cos + e * sin - cx * sin - cy * cos + cy + + return this + } + + // Flip matrix on x or y, at a given offset + flip (axis, around) { + return this.clone().flipO(axis, around) + } + + flipO (axis, around) { + return axis === 'x' ? this.scaleO(-1, 1, around, 0) + : axis === 'y' ? this.scaleO(1, -1, 0, around) + : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point + } + + // Shear matrix + shear (a, cx, cy) { + return this.clone().shearO(a, cx, cy) + } + + shearO (lx, cx = 0, cy = 0) { + let { a, b, c, d, e, f } = this + + this.a = a + b * lx + this.c = c + d * lx + this.e = e + f * lx - cy * lx + + return this + } + + // Skew Matrix + skew (x, y, cx, cy) { + return this.clone().skewO(...arguments) + } + + skewO (x, y = x, cx = 0, cy = 0) { + // support uniformal skew + if (arguments.length === 3) { + cy = cx + cx = y + y = x + } + + // Convert degrees to radians + x = radians(x) + y = radians(y) + + let lx = Math.tan(x) + let ly = Math.tan(y) + + let { a, b, c, d, e, f } = this + + this.a = a + b * lx + this.b = b + a * ly + this.c = c + d * lx + this.d = d + c * ly + this.e = e + f * lx - cy * lx + this.f = f + e * ly - cx * ly + + return this + } + + // SkewX + skewX (x, cx, cy) { + return this.skew(x, 0, cx, cy) + } + + skewXO (x, cx, cy) { + return this.skewO(x, 0, cx, cy) + } + + // SkewY + skewY (y, cx, cy) { + return this.skew(0, y, cx, cy) + } + + skewYO (y, cx, cy) { + return this.skewO(0, y, cx, cy) + } + + // Transform around a center point + aroundO (cx, cy, matrix) { + var dx = cx || 0 + var dy = cy || 0 + return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy) + } + + around (cx, cy, matrix) { + return this.clone().aroundO(cx, cy, matrix) + } + + // Convert to native SVGMatrix + native () { + // create new matrix + var matrix = parser().svg.node.createSVGMatrix() + + // update with current values + for (var i = abcdef.length - 1; i >= 0; i--) { + matrix[abcdef[i]] = this[abcdef[i]] + } + + return matrix + } + + // Check if two matrices are equal + equals (other) { + var comp = new Matrix(other) + return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && + closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && + closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f) + } + + // Convert matrix to string + toString () { + return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')' + } + + toArray () { + return [this.a, this.b, this.c, this.d, this.e, this.f] + } + + valueOf () { + return { + a: this.a, + b: this.b, + c: this.c, + d: this.d, + e: this.e, + f: this.f + } + } + + static fromArray (a) { + return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] } + } + + static isMatrixLike (o) { + return ( + o.a != null || + o.b != null || + o.c != null || + o.d != null || + o.e != null || + o.f != null + ) + } + + static formatTransforms (o) { + // Get all of the parameters required to form the matrix + var flipBoth = o.flip === 'both' || o.flip === true + var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1 + var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1 + var skewX = o.skew && o.skew.length ? o.skew[0] + : isFinite(o.skew) ? o.skew + : isFinite(o.skewX) ? o.skewX + : 0 + var skewY = o.skew && o.skew.length ? o.skew[1] + : isFinite(o.skew) ? o.skew + : isFinite(o.skewY) ? o.skewY + : 0 + var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX + : isFinite(o.scale) ? o.scale * flipX + : isFinite(o.scaleX) ? o.scaleX * flipX + : flipX + var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY + : isFinite(o.scale) ? o.scale * flipY + : isFinite(o.scaleY) ? o.scaleY * flipY + : flipY + var shear = o.shear || 0 + var theta = o.rotate || o.theta || 0 + var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY) + var ox = origin.x + var oy = origin.y + var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY) + var px = position.x + var py = position.y + var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY) + var tx = translate.x + var ty = translate.y + var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY) + var rx = relative.x + var ry = relative.y + + // Populate all of the values + return { + scaleX, scaleY, skewX, skewY, shear, theta, rx, ry, tx, ty, ox, oy, px, py + } + } + + // left matrix, right matrix, target matrix which is overwritten + static matrixMultiply (l, r, o) { + // Work out the product directly + var a = l.a * r.a + l.c * r.b + var b = l.b * r.a + l.d * r.b + var c = l.a * r.c + l.c * r.d + var d = l.b * r.c + l.d * r.d + var e = l.e + l.a * r.e + l.c * r.f + var f = l.f + l.b * r.e + l.d * r.f + + // make sure to use local variables because l/r and o could be the same + o.a = a + o.b = b + o.c = c + o.d = d + o.e = e + o.f = f + + return o + } +} + +registerMethods({ + Element: { + // Get current matrix + ctm () { + return new Matrix(this.node.getCTM()) + }, + + // Get current screen matrix + screenCTM () { + /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 + This is needed because FF does not return the transformation matrix + for the inner coordinate system when getScreenCTM() is called on nested svgs. + However all other Browsers do that */ + if (typeof this.isRoot === 'function' && !this.isRoot()) { + var rect = this.rect(1, 1) + var m = rect.node.getScreenCTM() + rect.remove() + return new Matrix(m) + } + return new Matrix(this.node.getScreenCTM()) + } + } +}) diff --git a/src/types/Morphable.js b/src/types/Morphable.js new file mode 100644 index 0000000..2b12375 --- /dev/null +++ b/src/types/Morphable.js @@ -0,0 +1,244 @@ +import { Ease } from '../animation/Controller.js' +import { + delimiter, + numberAndUnit, + pathLetters +} from '../modules/core/regex.js' +import { extend } from '../utils/adopter.js' +import Color from './Color.js' +import PathArray from './PathArray.js' +import SVGArray from './SVGArray.js' +import SVGNumber from './SVGNumber.js' + +export default class Morphable { + constructor (stepper) { + // FIXME: the default stepper does not know about easing + this._stepper = stepper || new Ease('-') + + this._from = null + this._to = null + this._type = null + this._context = null + this._morphObj = null + } + + from (val) { + if (val == null) { + return this._from + } + + this._from = this._set(val) + return this + } + + to (val) { + if (val == null) { + return this._to + } + + this._to = this._set(val) + return this + } + + type (type) { + // getter + if (type == null) { + return this._type + } + + // setter + this._type = type + return this + } + + _set (value) { + if (!this._type) { + var type = typeof value + + if (type === 'number') { + this.type(SVGNumber) + } else if (type === 'string') { + if (Color.isColor(value)) { + this.type(Color) + } else if (delimiter.test(value)) { + this.type(pathLetters.test(value) + ? PathArray + : SVGArray + ) + } else if (numberAndUnit.test(value)) { + this.type(SVGNumber) + } else { + this.type(NonMorphable) + } + } else if (morphableTypes.indexOf(value.constructor) > -1) { + this.type(value.constructor) + } else if (Array.isArray(value)) { + this.type(SVGArray) + } else if (type === 'object') { + this.type(ObjectBag) + } else { + this.type(NonMorphable) + } + } + + var result = (new this._type(value)).toArray() + this._morphObj = this._morphObj || new this._type() + this._context = this._context || + Array.apply(null, Array(result.length)).map(Object) + return result + } + + stepper (stepper) { + if (stepper == null) return this._stepper + this._stepper = stepper + return this + } + + done () { + var complete = this._context + .map(this._stepper.done) + .reduce(function (last, curr) { + return last && curr + }, true) + return complete + } + + at (pos) { + var _this = this + + return this._morphObj.fromArray( + this._from.map(function (i, index) { + return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context) + }) + ) + } +} + +export class NonMorphable { + constructor (...args) { + this.init(...args) + } + + init (val) { + val = Array.isArray(val) ? val[0] : val + this.value = val + } + + valueOf () { + return this.value + } + + toArray () { + return [this.value] + } +} + +export class TransformBag { + constructor (...args) { + this.init(...args) + } + + init (obj) { + if (Array.isArray(obj)) { + obj = { + scaleX: obj[0], + scaleY: obj[1], + shear: obj[2], + rotate: obj[3], + translateX: obj[4], + translateY: obj[5], + originX: obj[6], + originY: obj[7] + } + } + + Object.assign(this, TransformBag.defaults, obj) + } + + toArray () { + var v = this + + return [ + v.scaleX, + v.scaleY, + v.shear, + v.rotate, + v.translateX, + v.translateY, + v.originX, + v.originY + ] + } +} + +TransformBag.defaults = { + scaleX: 1, + scaleY: 1, + shear: 0, + rotate: 0, + translateX: 0, + translateY: 0, + originX: 0, + originY: 0 +} + +export class ObjectBag { + constructor (...args) { + this.init(...args) + } + + init (objOrArr) { + this.values = [] + + if (Array.isArray(objOrArr)) { + this.values = objOrArr + return + } + + var entries = Object.entries(objOrArr || {}).sort((a, b) => { + return a[0] - b[0] + }) + + this.values = entries.reduce((last, curr) => last.concat(curr), []) + } + + valueOf () { + var obj = {} + var arr = this.values + + for (var i = 0, len = arr.length; i < len; i += 2) { + obj[arr[i]] = arr[i + 1] + } + + return obj + } + + toArray () { + return this.values + } +} + +const morphableTypes = [ + NonMorphable, + TransformBag, + ObjectBag +] + +export function registerMorphableType (type = []) { + morphableTypes.push(...[].concat(type)) +} + +export function makeMorphable () { + extend(morphableTypes, { + to (val, args) { + return new Morphable() + .type(this.constructor) + .from(this.valueOf()) + .to(val, args) + }, + fromArray (arr) { + this.init(arr) + return this + } + }) +} diff --git a/src/types/PathArray.js b/src/types/PathArray.js new file mode 100644 index 0000000..989cd8f --- /dev/null +++ b/src/types/PathArray.js @@ -0,0 +1,337 @@ +import { + delimiter, + dots, + hyphen, + isPathLetter, + numbersWithDots, + pathLetters +} from '../modules/core/regex.js' +import { extend } from '../utils/adopter.js' +import { subClassArray } from './ArrayPolyfill.js' +import Point from './Point.js' +import SVGArray from './SVGArray.js' +import parser from '../modules/core/parser.js' + +const PathArray = subClassArray('PathArray', SVGArray) + +export default PathArray + +export function pathRegReplace (a, b, c, d) { + return c + d.replace(dots, ' .') +} + +function arrayToString (a) { + for (var i = 0, il = a.length, s = ''; i < il; i++) { + s += a[i][0] + + if (a[i][1] != null) { + s += a[i][1] + + if (a[i][2] != null) { + s += ' ' + s += a[i][2] + + if (a[i][3] != null) { + s += ' ' + s += a[i][3] + s += ' ' + s += a[i][4] + + if (a[i][5] != null) { + s += ' ' + s += a[i][5] + s += ' ' + s += a[i][6] + + if (a[i][7] != null) { + s += ' ' + s += a[i][7] + } + } + } + } + } + } + + return s + ' ' +} + +const pathHandlers = { + M: function (c, p, p0) { + p.x = p0.x = c[0] + p.y = p0.y = c[1] + + return ['M', p.x, p.y] + }, + L: function (c, p) { + p.x = c[0] + p.y = c[1] + return ['L', c[0], c[1]] + }, + H: function (c, p) { + p.x = c[0] + return ['H', c[0]] + }, + V: function (c, p) { + p.y = c[0] + return ['V', c[0]] + }, + C: function (c, p) { + p.x = c[4] + p.y = c[5] + return ['C', c[0], c[1], c[2], c[3], c[4], c[5]] + }, + S: function (c, p) { + p.x = c[2] + p.y = c[3] + return ['S', c[0], c[1], c[2], c[3]] + }, + Q: function (c, p) { + p.x = c[2] + p.y = c[3] + return ['Q', c[0], c[1], c[2], c[3]] + }, + T: function (c, p) { + p.x = c[0] + p.y = c[1] + return ['T', c[0], c[1]] + }, + Z: function (c, p, p0) { + p.x = p0.x + p.y = p0.y + return ['Z'] + }, + A: function (c, p) { + p.x = c[5] + p.y = c[6] + return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]] + } +} + +let mlhvqtcsaz = 'mlhvqtcsaz'.split('') + +for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { + pathHandlers[mlhvqtcsaz[i]] = (function (i) { + return function (c, p, p0) { + if (i === 'H') c[0] = c[0] + p.x + else if (i === 'V') c[0] = c[0] + p.y + else if (i === 'A') { + c[5] = c[5] + p.x + c[6] = c[6] + p.y + } else { + for (var j = 0, jl = c.length; j < jl; ++j) { + c[j] = c[j] + (j % 2 ? p.y : p.x) + } + } + + return pathHandlers[i](c, p, p0) + } + })(mlhvqtcsaz[i].toUpperCase()) +} + +extend(PathArray, { + // Convert array to string + toString () { + return arrayToString(this) + }, + + // Move path string + move (x, y) { + // get bounding box of current situation + var box = this.bbox() + + // get relative offset + x -= box.x + y -= box.y + + if (!isNaN(x) && !isNaN(y)) { + // move every point + for (var l, i = this.length - 1; i >= 0; i--) { + l = this[i][0] + + if (l === 'M' || l === 'L' || l === 'T') { + this[i][1] += x + this[i][2] += y + } else if (l === 'H') { + this[i][1] += x + } else if (l === 'V') { + this[i][1] += y + } else if (l === 'C' || l === 'S' || l === 'Q') { + this[i][1] += x + this[i][2] += y + this[i][3] += x + this[i][4] += y + + if (l === 'C') { + this[i][5] += x + this[i][6] += y + } + } else if (l === 'A') { + this[i][6] += x + this[i][7] += y + } + } + } + + return this + }, + + // Resize path string + size (width, height) { + // get bounding box of current situation + var box = this.bbox() + var i, l + + // recalculate position of all points according to new size + for (i = this.length - 1; i >= 0; i--) { + l = this[i][0] + + if (l === 'M' || l === 'L' || l === 'T') { + this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x + this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y + } else if (l === 'H') { + this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x + } else if (l === 'V') { + this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y + } else if (l === 'C' || l === 'S' || l === 'Q') { + this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x + this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y + this[i][3] = ((this[i][3] - box.x) * width) / box.width + box.x + this[i][4] = ((this[i][4] - box.y) * height) / box.height + box.y + + if (l === 'C') { + this[i][5] = ((this[i][5] - box.x) * width) / box.width + box.x + this[i][6] = ((this[i][6] - box.y) * height) / box.height + box.y + } + } else if (l === 'A') { + // resize radii + this[i][1] = (this[i][1] * width) / box.width + this[i][2] = (this[i][2] * height) / box.height + + // move position values + this[i][6] = ((this[i][6] - box.x) * width) / box.width + box.x + this[i][7] = ((this[i][7] - box.y) * height) / box.height + box.y + } + } + + return this + }, + + // Test if the passed path array use the same path data commands as this path array + equalCommands (pathArray) { + var i, il, equalCommands + + pathArray = new PathArray(pathArray) + + equalCommands = this.length === pathArray.length + for (i = 0, il = this.length; equalCommands && i < il; i++) { + equalCommands = this[i][0] === pathArray[i][0] + } + + return equalCommands + }, + + // Make path array morphable + morph (pathArray) { + pathArray = new PathArray(pathArray) + + if (this.equalCommands(pathArray)) { + this.destination = pathArray + } else { + this.destination = null + } + + return this + }, + + // Get morphed path array at given position + at (pos) { + // make sure a destination is defined + if (!this.destination) return this + + var sourceArray = this + var destinationArray = this.destination.value + var array = [] + var pathArray = new PathArray() + var i, il, j, jl + + // Animate has specified in the SVG spec + // See: https://www.w3.org/TR/SVG11/paths.html#PathElement + for (i = 0, il = sourceArray.length; i < il; i++) { + array[i] = [sourceArray[i][0]] + for (j = 1, jl = sourceArray[i].length; j < jl; j++) { + array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos + } + // For the two flags of the elliptical arc command, the SVG spec say: + // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true + // Elliptical arc command as an array followed by corresponding indexes: + // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // 0 1 2 3 4 5 6 7 + if (array[i][0] === 'A') { + array[i][4] = +(array[i][4] !== 0) + array[i][5] = +(array[i][5] !== 0) + } + } + + // Directly modify the value of a path array, this is done this way for performance + pathArray.value = array + return pathArray + }, + + // Absolutize and parse path to array + parse (array = [['M', 0, 0]]) { + // if it's already a patharray, no need to parse it + if (array instanceof PathArray) return array + + // prepare for parsing + var s + var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 } + + if (typeof array === 'string') { + array = array + .replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 + .replace(pathLetters, ' $& ') // put some room between letters and numbers + .replace(hyphen, '$1 -') // add space before hyphen + .trim() // trim + .split(delimiter) // split into array + } else { + array = array.reduce(function (prev, curr) { + return [].concat.call(prev, curr) + }, []) + } + + // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] + var result = [] + var p = new Point() + var p0 = new Point() + var index = 0 + var len = array.length + + do { + // Test if we have a path letter + if (isPathLetter.test(array[index])) { + s = array[index] + ++index + // If last letter was a move command and we got no new, it defaults to [L]ine + } else if (s === 'M') { + s = 'L' + } else if (s === 'm') { + s = 'l' + } + + result.push(pathHandlers[s].call(null, + array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), + p, p0 + ) + ) + } while (len > index) + + return result + }, + + // Get bounding box of path + bbox () { + parser().path.setAttribute('d', this.toString()) + return parser.nodes.path.getBBox() + } +}) diff --git a/src/types/Point.js b/src/types/Point.js new file mode 100644 index 0000000..0adcd90 --- /dev/null +++ b/src/types/Point.js @@ -0,0 +1,54 @@ +import { registerMethods } from '../utils/methods.js' +import parser from '../modules/core/parser.js' + +export default class Point { + // Initialize + constructor (x, y, base) { + let source + base = base || { x: 0, y: 0 } + + // ensure source as object + source = Array.isArray(x) ? { x: x[0], y: x[1] } + : typeof x === 'object' ? { x: x.x, y: x.y } + : { x: x, y: y } + + // merge source + this.x = source.x == null ? base.x : source.x + this.y = source.y == null ? base.y : source.y + } + + // Clone point + clone () { + return new Point(this) + } + + // Convert to native SVGPoint + native () { + // create new point + var point = parser().svg.node.createSVGPoint() + + // update with current values + point.x = this.x + point.y = this.y + return point + } + + // transform point with matrix + transform (m) { + // Perform the matrix multiplication + var x = m.a * this.x + m.c * this.y + m.e + var y = m.b * this.x + m.d * this.y + m.f + + // Return the required point + return new Point(x, y) + } +} + +registerMethods({ + Element: { + // Get point + point: function (x, y) { + return new Point(x, y).transform(this.screenCTM().inverse()) + } + } +}) diff --git a/src/types/PointArray.js b/src/types/PointArray.js new file mode 100644 index 0000000..b246b2f --- /dev/null +++ b/src/types/PointArray.js @@ -0,0 +1,120 @@ +import { delimiter } from '../modules/core/regex.js' +import { extend } from '../utils/adopter.js' +import { subClassArray } from './ArrayPolyfill.js' +import SVGArray from './SVGArray.js' + +const PointArray = subClassArray('PointArray', SVGArray) + +export default PointArray + +extend(PointArray, { + // Convert array to string + toString () { + // convert to a poly point string + for (var i = 0, il = this.length, array = []; i < il; i++) { + array.push(this[i].join(',')) + } + + return array.join(' ') + }, + + // Convert array to line object + toLine () { + return { + x1: this[0][0], + y1: this[0][1], + x2: this[1][0], + y2: this[1][1] + } + }, + + // Get morphed array at given position + at (pos) { + // make sure a destination is defined + if (!this.destination) return this + + // generate morphed point string + for (var i = 0, il = this.length, array = []; i < il; i++) { + array.push([ + this[i][0] + (this.destination[i][0] - this[i][0]) * pos, + this[i][1] + (this.destination[i][1] - this[i][1]) * pos + ]) + } + + return new PointArray(array) + }, + + // Parse point string and flat array + parse (array = [[0, 0]]) { + var points = [] + + // if it is an array + if (array instanceof Array) { + // and it is not flat, there is no need to parse it + if (array[0] instanceof Array) { + return array + } + } else { // Else, it is considered as a string + // parse points + array = array.trim().split(delimiter).map(parseFloat) + } + + // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints + // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. + if (array.length % 2 !== 0) array.pop() + + // wrap points in two-tuples and parse points as floats + for (var i = 0, len = array.length; i < len; i = i + 2) { + points.push([ array[i], array[i + 1] ]) + } + + return points + }, + + // Move point string + move (x, y) { + var box = this.bbox() + + // get relative offset + x -= box.x + y -= box.y + + // move every point + if (!isNaN(x) && !isNaN(y)) { + for (var i = this.length - 1; i >= 0; i--) { + this[i] = [this[i][0] + x, this[i][1] + y] + } + } + + return this + }, + + // Resize poly string + size (width, height) { + var i + var box = this.bbox() + + // recalculate position of all points according to new size + for (i = this.length - 1; i >= 0; i--) { + if (box.width) this[i][0] = ((this[i][0] - box.x) * width) / box.width + box.x + if (box.height) this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y + } + + return this + }, + + // Get bounding box of points + bbox () { + var maxX = -Infinity + var maxY = -Infinity + var minX = Infinity + var minY = Infinity + this.forEach(function (el) { + maxX = Math.max(el[0], maxX) + maxY = Math.max(el[1], maxY) + minX = Math.min(el[0], minX) + minY = Math.min(el[1], minY) + }) + return { x: minX, y: minY, width: maxX - minX, height: maxY - minY } + } +}) diff --git a/src/types/SVGArray.js b/src/types/SVGArray.js new file mode 100644 index 0000000..3894b22 --- /dev/null +++ b/src/types/SVGArray.js @@ -0,0 +1,47 @@ +import { delimiter } from '../modules/core/regex.js' +import { extend } from '../utils/adopter.js' +import { subClassArray } from './ArrayPolyfill.js' + +const SVGArray = subClassArray('SVGArray', Array, function (arr) { + this.init(arr) +}) + +export default SVGArray + +extend(SVGArray, { + init (arr) { + this.length = 0 + this.push(...this.parse(arr)) + }, + + toArray () { + return Array.prototype.concat.apply([], this) + }, + + toString () { + return this.join(' ') + }, + + // Flattens the array if needed + valueOf () { + const ret = [] + ret.push(...this) + return ret + }, + + // Parse whitespace separated string + parse (array = []) { + // If already is an array, no need to parse it + if (array instanceof Array) return array + + return array.trim().split(delimiter).map(parseFloat) + }, + + clone () { + return new this.constructor(this) + }, + + toSet () { + return new Set(this) + } +}) diff --git a/src/types/SVGNumber.js b/src/types/SVGNumber.js new file mode 100644 index 0000000..bba9741 --- /dev/null +++ b/src/types/SVGNumber.js @@ -0,0 +1,87 @@ +import { numberAndUnit } from '../modules/core/regex.js' + +// Module for unit convertions +export default class SVGNumber { + // Initialize + constructor (...args) { + this.init(...args) + } + + init (value, unit) { + unit = Array.isArray(value) ? value[1] : unit + value = Array.isArray(value) ? value[0] : value + + // initialize defaults + this.value = 0 + this.unit = unit || '' + + // parse value + if (typeof value === 'number') { + // ensure a valid numeric value + this.value = isNaN(value) ? 0 : !isFinite(value) ? (value < 0 ? -3.4e+38 : +3.4e+38) : value + } else if (typeof value === 'string') { + unit = value.match(numberAndUnit) + + if (unit) { + // make value numeric + this.value = parseFloat(unit[1]) + + // normalize + if (unit[5] === '%') { this.value /= 100 } else if (unit[5] === 's') { + this.value *= 1000 + } + + // store unit + this.unit = unit[5] + } + } else { + if (value instanceof SVGNumber) { + this.value = value.valueOf() + this.unit = value.unit + } + } + } + + toString () { + return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 + : this.unit === 's' ? this.value / 1e3 + : this.value + ) + this.unit + } + + toJSON () { + return this.toString() + } + + toArray () { + return [this.value, this.unit] + } + + valueOf () { + return this.value + } + + // Add number + plus (number) { + number = new SVGNumber(number) + return new SVGNumber(this + number, this.unit || number.unit) + } + + // Subtract number + minus (number) { + number = new SVGNumber(number) + return new SVGNumber(this - number, this.unit || number.unit) + } + + // Multiply number + times (number) { + number = new SVGNumber(number) + return new SVGNumber(this * number, this.unit || number.unit) + } + + // Divide number + divide (number) { + number = new SVGNumber(number) + return new SVGNumber(this / number, this.unit || number.unit) + } +} diff --git a/src/types/set.js b/src/types/set.js new file mode 100644 index 0000000..c755c2c --- /dev/null +++ b/src/types/set.js @@ -0,0 +1,18 @@ +/* eslint no-unused-vars: "off" */ +class SVGSet extends Set { + // constructor (arr) { + // super(arr) + // } + + each (cbOrName, ...args) { + if (typeof cbOrName === 'function') { + this.forEach((el) => { cbOrName.call(el, el) }) + } else { + this.forEach((el) => { + el[cbOrName](...args) + }) + } + + return this + } +} diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index c7407de..0000000 --- a/src/utils.js +++ /dev/null @@ -1,40 +0,0 @@ - -// Map function -export function map (array, block) { - var i - var il = array.length - var result = [] - - for (i = 0; i < il; i++) { - result.push(block(array[i])) - } - - return result -} - -// Filter function -export function filter (array, block) { - var i - var il = array.length - var result = [] - - for (i = 0; i < il; i++) { - if (block(array[i])) { result.push(array[i]) } - } - - return result -} - -// Degrees to radians -export function radians (d) { - return d % 360 * Math.PI / 180 -} - -// Radians to degrees -export function degrees (r) { - return r * 180 / Math.PI % 360 -} - -export function filterSVGElements (nodes) { - return this.filter(nodes, function (el) { return el instanceof window.SVGElement }) -} diff --git a/src/utils/adopter.js b/src/utils/adopter.js new file mode 100644 index 0000000..8017359 --- /dev/null +++ b/src/utils/adopter.js @@ -0,0 +1,115 @@ +import { capitalize } from './utils.js' +import { ns } from '../modules/core/namespaces.js' +import Base from '../types/Base.js' + +const elements = {} +export const root = Symbol('root') + +// Method for element creation +export function makeNode (name) { + // create element + return document.createElementNS(ns, name) +} + +export function makeInstance (element) { + if (element instanceof Base) return element + + if (typeof element === 'object') { + return adopt(element) + } + + if (element == null) { + return new elements[root]() + } + + if (typeof element === 'string' && element.charAt(0) !== '<') { + return adopt(document.querySelector(element)) + } + + var node = makeNode('svg') + node.innerHTML = element + + // We can use firstChild here because we know, + // that the first char is < and thus an element + element = adopt(node.firstChild) + + return element +} + +export function nodeOrNew (name, node) { + return node || makeNode(name) +} + +// Adopt existing svg elements +export function adopt (node) { + // check for presence of node + if (!node) return null + + // make sure a node isn't already adopted + if (node.instance instanceof Base) return node.instance + + if (!(node instanceof window.SVGElement)) { + return new elements.HtmlNode(node) + } + + // initialize variables + var element + + // adopt with element-specific settings + if (node.nodeName === 'svg') { + element = new elements[root](node) + } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') { + element = new elements.Gradient(node) + } else if (elements[capitalize(node.nodeName)]) { + element = new elements[capitalize(node.nodeName)](node) + } else { + element = new elements.Bare(node) + } + + return element +} + +export function register (element, name = element.name, asRoot = false) { + elements[name] = element + if (asRoot) elements[root] = element + return element +} + +export function getClass (name) { + return elements[name] +} + +// Element id sequence +let did = 1000 + +// Get next named element id +export function eid (name) { + return 'Svgjs' + capitalize(name) + (did++) +} + +// Deep new id assignment +export function assignNewId (node) { + // do the same for SVG child nodes as well + for (var i = node.children.length - 1; i >= 0; i--) { + assignNewId(node.children[i]) + } + + if (node.id) { + return adopt(node).id(eid(node.nodeName)) + } + + return adopt(node) +} + +// Method for extending objects +export function extend (modules, methods) { + var key, i + + modules = Array.isArray(modules) ? modules : [modules] + + for (i = modules.length - 1; i >= 0; i--) { + for (key in methods) { + modules[i].prototype[key] = methods[key] + } + } +} diff --git a/src/utils/methods.js b/src/utils/methods.js new file mode 100644 index 0000000..2373445 --- /dev/null +++ b/src/utils/methods.js @@ -0,0 +1,32 @@ +const methods = {} +const constructors = {} + +export function registerMethods (name, m) { + if (Array.isArray(name)) { + for (let _name of name) { + registerMethods(_name, m) + } + return + } + + if (typeof name === 'object') { + for (let [_name, _m] of Object.entries(name)) { + registerMethods(_name, _m) + } + return + } + + methods[name] = Object.assign(methods[name] || {}, m) +} + +export function getMethodsFor (name) { + return methods[name] || {} +} + +export function registerConstructor (name, setup) { + constructors[name] = setup +} + +export function getConstructor (name) { + return constructors[name] ? { setup: constructors[name], name } : {} +} diff --git a/src/utils/utils.js b/src/utils/utils.js new file mode 100644 index 0000000..e3c9111 --- /dev/null +++ b/src/utils/utils.js @@ -0,0 +1,96 @@ +// Map function +export function map (array, block) { + var i + var il = array.length + var result = [] + + for (i = 0; i < il; i++) { + result.push(block(array[i])) + } + + return result +} + +// Filter function +export function filter (array, block) { + var i + var il = array.length + var result = [] + + for (i = 0; i < il; i++) { + if (block(array[i])) { result.push(array[i]) } + } + + return result +} + +// Degrees to radians +export function radians (d) { + return d % 360 * Math.PI / 180 +} + +// Radians to degrees +export function degrees (r) { + return r * 180 / Math.PI % 360 +} + +// Convert dash-separated-string to camelCase +export function camelCase (s) { + return s.toLowerCase().replace(/-(.)/g, function (m, g) { + return g.toUpperCase() + }) +} + +// Capitalize first letter of a string +export function capitalize (s) { + return s.charAt(0).toUpperCase() + s.slice(1) +} + +// Calculate proportional width and height values when necessary +export function proportionalSize (element, width, height) { + if (width == null || height == null) { + var box = element.bbox() + + if (width == null) { + width = box.width / box.height * height + } else if (height == null) { + height = box.height / box.width * width + } + } + + return { + width: width, + height: height + } +} + +export function getOrigin (o, element) { + // Allow origin or around as the names + let origin = o.origin // o.around == null ? o.origin : o.around + let ox, oy + + // Allow the user to pass a string to rotate around a given point + if (typeof origin === 'string' || origin == null) { + // Get the bounding box of the element with no transformations applied + const string = (origin || 'center').toLowerCase().trim() + const { height, width, x, y } = element.bbox() + + // Calculate the transformed x and y coordinates + let bx = string.includes('left') ? x + : string.includes('right') ? x + width + : x + width / 2 + let by = string.includes('top') ? y + : string.includes('bottom') ? y + height + : y + height / 2 + + // Set the bounds eg : "bottom-left", "Top right", "middle" etc... + ox = o.ox != null ? o.ox : bx + oy = o.oy != null ? o.oy : by + } else { + ox = origin[0] + oy = origin[1] + } + + // Return the origin as it is if it wasn't a string + return [ ox, oy ] +} -- cgit v1.2.3