summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2018-11-08 10:05:28 +0100
committerUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2018-11-08 10:05:28 +0100
commit4702522137dac17a6312c521f3c1974eb839c5eb (patch)
tree97c158c2c4e8005d3e56e037eab16dfffcf3da42
parentdec70426b32ccf3979046e1637174b66bfdd1a8d (diff)
downloadsvg.js-4702522137dac17a6312c521f3c1974eb839c5eb.tar.gz
svg.js-4702522137dac17a6312c521f3c1974eb839c5eb.zip
added insertAfter/Before, introduce attrHooks, move few methods, SVG.Text.textPath returns first textPath child now
-rw-r--r--CHANGELOG.md2
-rw-r--r--dist/svg.js740
-rw-r--r--spec/spec/textpath.js5
-rw-r--r--src/elements/Image.js21
-rw-r--r--src/elements/TextPath.js17
-rw-r--r--src/modules/core/attr.js31
-rw-r--r--src/modules/core/textable.js1
-rw-r--r--src/modules/optional/arrange.js13
-rw-r--r--src/modules/optional/sugar.js32
-rw-r--r--src/types/EventTarget.js32
-rw-r--r--todo.md14
11 files changed, 483 insertions, 425 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6013e0e..fd8efd6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http:
- added a linter during the npm build process
- added `npm build:dev` to let you develop without getting too annoyed
- added `beziere()` and `steps()` to generate easing functions
+- added `insertAfter()` and `insertBefore`
### Removed
- removed `SVG.Array.split()` function
@@ -72,6 +73,7 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http:
- `Element.svg()` now can can replace the current node, can export the children of a node and can take an export modifier to change/replace the exported nodes
- `ungroup()` now breaks off one container and not more
- `clone()` does not add the clone to the dom anymore
+- `SVG.Text.textPath()` returns only the first textpath child
### Fixed
- fixed a bug in clipping and masking where empty nodes persists after removal -> __TODO!__
diff --git a/dist/svg.js b/dist/svg.js
index 7a9a297..5f91b01 100644
--- a/dist/svg.js
+++ b/dist/svg.js
@@ -6,7 +6,7 @@
* @copyright Wout Fierens <wout@mick-wout.com>
* @license MIT
*
-* BUILT: Wed Nov 07 2018 22:39:24 GMT+0100 (GMT+01:00)
+* BUILT: Thu Nov 08 2018 09:25:46 GMT+0100 (GMT+01:00)
*/;
var SVG = (function () {
'use strict';
@@ -216,6 +216,207 @@ var SVG = (function () {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
+ // 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];
+ }
+
+ // 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 methods = {};
function registerMethods(name, m) {
if (Array.isArray(name)) {
@@ -326,6 +527,7 @@ var SVG = (function () {
} // Inserts a given element before the targeted element
function before(element) {
+ element = makeInstance(element);
element.remove();
var i = this.position();
this.parent().add(element, i);
@@ -333,6 +535,7 @@ var SVG = (function () {
} // Inserts a given element after the targeted element
function after(element) {
+ element = makeInstance(element);
element.remove();
var i = this.position();
this.parent().add(element, i + 1);
@@ -458,98 +661,6 @@ var SVG = (function () {
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 = {};
@@ -696,228 +807,6 @@ var SVG = (function () {
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) {
@@ -1036,6 +925,119 @@ var SVG = (function () {
return event;
}
+ 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;
+ }();
+
var EventTarget =
/*#__PURE__*/
function (_Base) {
@@ -1117,23 +1119,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) {
- // 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);
+ }(Base);
function noop() {} // Default animation values
@@ -1338,7 +1324,14 @@ var SVG = (function () {
return SVGNumber;
}();
+ var hooks = [];
+ function registerAttrHook(fn) {
+ hooks.push(fn);
+ } // Set svg element attribute
+
function attr(attr, val, ns) {
+ var _this = this;
+
// act as full getter
if (attr == null) {
// get an object of attributes
@@ -1369,7 +1362,13 @@ var SVG = (function () {
}
return attr;
- } else if (Array.isArray(attr)) ; else if (_typeof(attr) === 'object') {
+ } else if (attr instanceof Array) {
+ // loop through array and get all values
+ return attr.reduce(function (last, curr) {
+ last[curr] = _this.attr(curr);
+ return last;
+ }, {});
+ } else if (_typeof(attr) === 'object') {
// apply every attribute individually if an object is passed
for (val in attr) {
this.attr(val, attr[val]);
@@ -1382,19 +1381,10 @@ var SVG = (function () {
val = this.node.getAttribute(attr);
return val == null ? attrs[attr] : 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)
-
+ // Loop through hooks and execute them to convert value
+ val = hooks.reduce(function (_val, hook) {
+ return hook(attr, _val, _this);
+ }, val); // ensure correct numeric values (also accepts NaN and Infinity)
if (typeof val === 'number') {
val = new SVGNumber(val);
@@ -5130,7 +5120,24 @@ var SVG = (function () {
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);
}
- });
+ }); // 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 untransform() {
return this.attr('transform', null);
@@ -5610,19 +5617,26 @@ var SVG = (function () {
});
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);
+ registerAttrHook(function (attr$$1, val, _this) {
+ // convert image fill and stroke to patterns
+ if (attr$$1 === 'fill' || attr$$1 === 'stroke') {
+ if (isImage.test(val)) {
+ val = _this.doc().defs().image(val);
+ }
+ }
+
+ if (val instanceof Image) {
+ val = _this.doc().defs().pattern(0, 0, function (pattern) {
+ pattern.add(val);
+ });
+ }
+
+ return val;
+ });
registerMethods({
Container: {
// create image element, load image and set its size
@@ -6142,8 +6156,7 @@ var SVG = (function () {
this.node.appendChild(document.createTextNode(text));
return this;
- } // FIXME: Does this also work for textpath?
- // Get length of text element
+ } // Get length of text element
function length() {
return this.node.getComputedTextLength();
@@ -6717,7 +6730,7 @@ var SVG = (function () {
Text: {
// Create path for text to run on
path: function path(track) {
- var path = new TextPath(); // if d is a path, reuse it
+ var path = new TextPath(); // if track is a path, reuse it
if (!(track instanceof Path)) {
// create path element
@@ -6729,10 +6742,9 @@ var SVG = (function () {
return this.put(path);
},
- // FIXME: make this plural?
// Get the textPath children
textPath: function textPath() {
- return this.find('textPath');
+ return this.find('textPath')[0];
}
},
Path: {
@@ -6745,8 +6757,10 @@ var SVG = (function () {
}
return this.parent().put(new Text()).path(this).text(_text);
- } // FIXME: Maybe add `targets` to get all textPaths associated with this path
-
+ },
+ targets: function targets() {
+ return baseFind('svg [href*="' + this.id() + '"]');
+ }
}
});
TextPath.prototype.MorphArray = PathArray;
diff --git a/spec/spec/textpath.js b/spec/spec/textpath.js
index e64f721..8a3d4c2 100644
--- a/spec/spec/textpath.js
+++ b/spec/spec/textpath.js
@@ -35,10 +35,9 @@ describe('TextPath', function() {
})
describe('textPath()', function() {
- it('returns all textPath elements in a text', function() {
+ it('returns only the first textPath element in a text', function() {
text.path(data)
- expect(text.textPath().length).toBe(1)
- expect(text.textPath()[0] instanceof SVG.TextPath).toBe(true)
+ expect(text.textPath() instanceof SVG.TextPath).toBe(true)
})
})
diff --git a/src/elements/Image.js b/src/elements/Image.js
index 5e672f4..ec9459f 100644
--- a/src/elements/Image.js
+++ b/src/elements/Image.js
@@ -1,5 +1,7 @@
+import { isImage } from '../modules/core/regex.js'
import { nodeOrNew, register } from '../utils/adopter.js'
import { off, on } from '../modules/core/event.js'
+import { registerAttrHook } from '../modules/core/attr.js'
import { registerMethods } from '../utils/methods.js'
import { xlink } from '../modules/core/namespaces.js'
import Pattern from './Pattern.js'
@@ -48,13 +50,24 @@ export default class Image extends Shape {
return this.attr('href', (img.src = url), xlink)
}
+}
+
+registerAttrHook(function (attr, val, _this) {
+ // convert image fill and stroke to patterns
+ if (attr === 'fill' || attr === 'stroke') {
+ if (isImage.test(val)) {
+ val = _this.doc().defs().image(val)
+ }
+ }
- attrHook (obj) {
- return obj.doc().defs().pattern(0, 0, (pattern) => {
- pattern.add(this)
+ if (val instanceof Image) {
+ val = _this.doc().defs().pattern(0, 0, (pattern) => {
+ pattern.add(val)
})
}
-}
+
+ return val
+})
registerMethods({
Container: {
diff --git a/src/elements/TextPath.js b/src/elements/TextPath.js
index 04146bc..480eca2 100644
--- a/src/elements/TextPath.js
+++ b/src/elements/TextPath.js
@@ -1,6 +1,7 @@
import { nodeOrNew, register } from '../utils/adopter.js'
import { registerMethods } from '../utils/methods.js'
import { xlink } from '../modules/core/namespaces.js'
+import baseFind from '../modules/core/selector.js'
import Path from './Path.js'
import PathArray from '../types/PathArray.js'
import Text from './Text.js'
@@ -44,10 +45,10 @@ registerMethods({
},
Text: {
// Create path for text to run on
- path: function (track) {
+ path (track) {
var path = new TextPath()
- // if d is a path, reuse it
+ // if track is a path, reuse it
if (!(track instanceof Path)) {
// create path element
track = this.doc().defs().path(track)
@@ -60,22 +61,24 @@ registerMethods({
return this.put(path)
},
- // FIXME: make this plural?
// Get the textPath children
- textPath: function () {
- return this.find('textPath')
+ textPath () {
+ return this.find('textPath')[0]
}
},
Path: {
// creates a textPath from this path
- text: function (text) {
+ 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)
+ },
+
+ targets () {
+ return baseFind('svg [href*="' + this.id() + '"]')
}
- // FIXME: Maybe add `targets` to get all textPaths associated with this path
}
})
diff --git a/src/modules/core/attr.js b/src/modules/core/attr.js
index 7c9e2c1..f90dcb9 100644
--- a/src/modules/core/attr.js
+++ b/src/modules/core/attr.js
@@ -1,9 +1,14 @@
-import { isImage, isNumber } from './regex.js'
import { attrs as defaults } from './defaults.js'
+import { isNumber } from './regex.js'
import Color from '../../types/Color.js'
import SVGArray from '../../types/SVGArray.js'
import SVGNumber from '../../types/SVGNumber.js'
+const hooks = []
+export function registerAttrHook (fn) {
+ hooks.push(fn)
+}
+
// Set svg element attribute
export default function attr (attr, val, ns) {
// act as full getter
@@ -19,8 +24,12 @@ export default function attr (attr, val, ns) {
}
return attr
- } else if (Array.isArray(attr)) {
- // FIXME: implement
+ } else if (attr instanceof Array) {
+ // loop through array and get all values
+ return attr.reduce((last, curr) => {
+ last[curr] = this.attr(curr)
+ return last
+ }, {})
} else if (typeof attr === 'object') {
// apply every attribute individually if an object is passed
for (val in attr) this.attr(val, attr[val])
@@ -34,18 +43,10 @@ export default function attr (attr, val, ns) {
: 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)
- }
+ // Loop through hooks and execute them to convert value
+ val = hooks.reduce((_val, hook) => {
+ return hook(attr, _val, this)
+ }, val)
// ensure correct numeric values (also accepts NaN and Infinity)
if (typeof val === 'number') {
diff --git a/src/modules/core/textable.js b/src/modules/core/textable.js
index c9a90db..139d056 100644
--- a/src/modules/core/textable.js
+++ b/src/modules/core/textable.js
@@ -11,7 +11,6 @@ export function plain (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
index ca0e074..6ce2eea 100644
--- a/src/modules/optional/arrange.js
+++ b/src/modules/optional/arrange.js
@@ -1,3 +1,4 @@
+import { makeInstance } from '../../utils/adopter.js'
import { registerMethods } from '../../utils/methods.js'
// Get all siblings, including myself
@@ -73,6 +74,7 @@ export function back () {
// Inserts a given element before the targeted element
export function before (element) {
+ element = makeInstance(element)
element.remove()
var i = this.position()
@@ -84,6 +86,7 @@ export function before (element) {
// Inserts a given element after the targeted element
export function after (element) {
+ element = makeInstance(element)
element.remove()
var i = this.position()
@@ -93,6 +96,16 @@ export function after (element) {
return this
}
+export function insertBefore (element) {
+ element = makeInstance(element)
+ element.before(this)
+}
+
+export function insertAfter (element) {
+ element = makeInstance(element)
+ element.after(this)
+}
+
registerMethods('Dom', {
siblings, position, next, prev, forward, backward, front, back, before, after
})
diff --git a/src/modules/optional/sugar.js b/src/modules/optional/sugar.js
index 904e353..9cdc662 100644
--- a/src/modules/optional/sugar.js
+++ b/src/modules/optional/sugar.js
@@ -1,3 +1,4 @@
+import { on, off } from '../core/event.js'
import { registerMethods } from '../../utils/methods.js'
import Color from '../../types/Color.js'
import Element from '../../elements/Element.js'
@@ -157,3 +158,34 @@ registerMethods(['Element', 'Runner'], {
: this.attr(a, v)
}
})
+
+// 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/EventTarget.js b/src/types/EventTarget.js
index a32a1f1..31d01df 100644
--- a/src/types/EventTarget.js
+++ b/src/types/EventTarget.js
@@ -1,5 +1,4 @@
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 {
@@ -57,34 +56,3 @@ export default class EventTarget extends Base {
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/todo.md b/todo.md
index 3a9d9ba..db0ee66 100644
--- a/todo.md
+++ b/todo.md
@@ -1,3 +1,17 @@
+# tests to write
+- sugar.js
+ - insertBefore
+ - insertAfter
+ - after
+ - before
+- Path.js
+ - targets
+- Element.js
+ - svg
+- attr.js
+
+
+
# Where We Left Off