svgedit/dist/index-umd.min.js.map

1 line
1.4 MiB

{"version":3,"file":"index-umd.min.js","sources":["../editor/touch.js","../editor/namespaces.js","../editor/svgpathseg.js","../editor/browser.js","../editor/jQuery.attr.js","../editor/svgtransformlist.js","../editor/units.js","../editor/history.js","../editor/path.js","../editor/math.js","../editor/utilities.js","../editor/contextmenu.js","../editor/external/dynamic-import-polyfill/importModule.js","../editor/external/deparam/deparam.esm.js","../editor/dbox.js","../editor/layer.js","../editor/historyrecording.js","../editor/draw.js","../editor/sanitize.js","../editor/recalculate.js","../editor/select.js","../editor/coords.js","../editor/svgcanvas.js","../editor/svgicons/jQuery.svgIcons.js","../editor/jgraduate/jQuery.jGraduate.js","../editor/jgraduate/jQuery.jPicker.js","../editor/locale/locale.js","../editor/external/load-stylesheets/index-es.js","../editor/svg-editor.js","../editor/js-hotkeys/jquery.hotkeys.min.js","../editor/spinbtn/jQuery.SpinButton.js","../editor/contextmenu/jQuery.contextMenu.js"],"sourcesContent":["// http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/\n/**\n *\n * @param {Event} ev\n * @returns {void}\n */\nfunction touchHandler (ev) {\n const {changedTouches} = ev,\n first = changedTouches[0];\n\n let type = '';\n switch (ev.type) {\n case 'touchstart': type = 'mousedown'; break;\n case 'touchmove': type = 'mousemove'; break;\n case 'touchend': type = 'mouseup'; break;\n default: return;\n }\n\n const {screenX, screenY, clientX, clientY} = first; // eslint-disable-line no-shadow\n const simulatedEvent = new MouseEvent(type, {\n // Event interface\n bubbles: true,\n cancelable: true,\n // UIEvent interface\n view: window,\n detail: 1, // click count\n // MouseEvent interface (customized)\n screenX, screenY, clientX, clientY,\n // MouseEvent interface (defaults) - these could be removed\n ctrlKey: false,\n altKey: false,\n shiftKey: false,\n metaKey: false,\n button: 0, // main button (usually left)\n relatedTarget: null\n });\n if (changedTouches.length < 2) {\n first.target.dispatchEvent(simulatedEvent);\n ev.preventDefault();\n }\n}\n\ndocument.addEventListener('touchstart', touchHandler, true);\ndocument.addEventListener('touchmove', touchHandler, true);\ndocument.addEventListener('touchend', touchHandler, true);\ndocument.addEventListener('touchcancel', touchHandler, true);\n","/**\n * Namespaces or tools therefor.\n * @module namespaces\n * @license MIT\n*/\n\n/**\n* Common namepaces constants in alpha order.\n* @enum {string}\n* @type {PlainObject}\n* @memberof module:namespaces\n*/\nexport const NS = {\n HTML: 'http://www.w3.org/1999/xhtml',\n MATH: 'http://www.w3.org/1998/Math/MathML',\n SE: 'http://svg-edit.googlecode.com',\n SVG: 'http://www.w3.org/2000/svg',\n XLINK: 'http://www.w3.org/1999/xlink',\n XML: 'http://www.w3.org/XML/1998/namespace',\n XMLNS: 'http://www.w3.org/2000/xmlns/' // see http://www.w3.org/TR/REC-xml-names/#xmlReserved\n};\n\n/**\n* @function module:namespaces.getReverseNS\n* @returns {string} The NS with key values switched and lowercase\n*/\nexport const getReverseNS = function () {\n const reverseNS = {};\n Object.entries(NS).forEach(([name, URI]) => {\n reverseNS[URI] = name.toLowerCase();\n });\n return reverseNS;\n};\n","/* globals SVGPathSeg, SVGPathSegMovetoRel, SVGPathSegMovetoAbs,\n SVGPathSegMovetoRel, SVGPathSegLinetoRel, SVGPathSegLinetoAbs,\n SVGPathSegLinetoHorizontalRel, SVGPathSegLinetoHorizontalAbs,\n SVGPathSegLinetoVerticalRel, SVGPathSegLinetoVerticalAbs,\n SVGPathSegClosePath, SVGPathSegCurvetoCubicRel,\n SVGPathSegCurvetoCubicAbs, SVGPathSegCurvetoCubicSmoothRel,\n SVGPathSegCurvetoCubicSmoothAbs, SVGPathSegCurvetoQuadraticRel,\n SVGPathSegCurvetoQuadraticAbs, SVGPathSegCurvetoQuadraticSmoothRel,\n SVGPathSegCurvetoQuadraticSmoothAbs, SVGPathSegArcRel, SVGPathSegArcAbs */\n/**\n* SVGPathSeg API polyfill\n* https://github.com/progers/pathseg\n*\n* This is a drop-in replacement for the `SVGPathSeg` and `SVGPathSegList` APIs\n* that were removed from SVG2 ({@link https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html}),\n* including the latest spec changes which were implemented in Firefox 43 and\n* Chrome 46.\n*/\n/* eslint-disable no-shadow, class-methods-use-this, jsdoc/require-jsdoc */\n// Linting: We avoid `no-shadow` as ESLint thinks these are still available globals\n// Linting: We avoid `class-methods-use-this` as this is a polyfill that must\n// follow the conventions\n(() => {\nif (!('SVGPathSeg' in window)) {\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg\n class SVGPathSeg {\n constructor (type, typeAsLetter, owningPathSegList) {\n this.pathSegType = type;\n this.pathSegTypeAsLetter = typeAsLetter;\n this._owningPathSegList = owningPathSegList;\n }\n // Notify owning PathSegList on any changes so they can be synchronized back to the path element.\n _segmentChanged () {\n if (this._owningPathSegList) {\n this._owningPathSegList.segmentChanged(this);\n }\n }\n }\n SVGPathSeg.prototype.classname = 'SVGPathSeg';\n\n SVGPathSeg.PATHSEG_UNKNOWN = 0;\n SVGPathSeg.PATHSEG_CLOSEPATH = 1;\n SVGPathSeg.PATHSEG_MOVETO_ABS = 2;\n SVGPathSeg.PATHSEG_MOVETO_REL = 3;\n SVGPathSeg.PATHSEG_LINETO_ABS = 4;\n SVGPathSeg.PATHSEG_LINETO_REL = 5;\n SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;\n SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;\n SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;\n SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;\n SVGPathSeg.PATHSEG_ARC_ABS = 10;\n SVGPathSeg.PATHSEG_ARC_REL = 11;\n SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;\n SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;\n SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;\n SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;\n SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;\n SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;\n SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;\n SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;\n\n class SVGPathSegClosePath extends SVGPathSeg {\n constructor (owningPathSegList) {\n super(SVGPathSeg.PATHSEG_CLOSEPATH, 'z', owningPathSegList);\n }\n toString () { return '[object SVGPathSegClosePath]'; }\n _asPathString () { return this.pathSegTypeAsLetter; }\n clone () { return new SVGPathSegClosePath(undefined); }\n }\n\n class SVGPathSegMovetoAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_MOVETO_ABS, 'M', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegMovetoAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegMovetoAbs(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegMovetoAbs.prototype, {\n x: {\n get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true\n },\n y: {\n get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true\n }\n });\n\n class SVGPathSegMovetoRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_MOVETO_REL, 'm', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegMovetoRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegMovetoRel(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegMovetoRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegLinetoAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_LINETO_ABS, 'L', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegLinetoAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegLinetoAbs(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegLinetoAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegLinetoRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_LINETO_REL, 'l', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegLinetoRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegLinetoRel(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegLinetoRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoCubicAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x1, y1, x2, y2) {\n super(SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, 'C', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x1 = x1;\n this._y1 = y1;\n this._x2 = x2;\n this._y2 = y2;\n }\n toString () { return '[object SVGPathSegCurvetoCubicAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }\n }\n Object.defineProperties(SVGPathSegCurvetoCubicAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x1: {get () { return this._x1; }, set (x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true},\n y1: {get () { return this._y1; }, set (y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true},\n x2: {get () { return this._x2; }, set (x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true},\n y2: {get () { return this._y2; }, set (y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoCubicRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x1, y1, x2, y2) {\n super(SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, 'c', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x1 = x1;\n this._y1 = y1;\n this._x2 = x2;\n this._y2 = y2;\n }\n toString () { return '[object SVGPathSegCurvetoCubicRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }\n }\n Object.defineProperties(SVGPathSegCurvetoCubicRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x1: {get () { return this._x1; }, set (x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true},\n y1: {get () { return this._y1; }, set (y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true},\n x2: {get () { return this._x2; }, set (x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true},\n y2: {get () { return this._y2; }, set (y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoQuadraticAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x1, y1) {\n super(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, 'Q', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x1 = x1;\n this._y1 = y1;\n }\n toString () { return '[object SVGPathSegCurvetoQuadraticAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); }\n }\n Object.defineProperties(SVGPathSegCurvetoQuadraticAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x1: {get () { return this._x1; }, set (x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true},\n y1: {get () { return this._y1; }, set (y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoQuadraticRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x1, y1) {\n super(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, 'q', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x1 = x1;\n this._y1 = y1;\n }\n toString () { return '[object SVGPathSegCurvetoQuadraticRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1); }\n }\n Object.defineProperties(SVGPathSegCurvetoQuadraticRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x1: {get () { return this._x1; }, set (x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true},\n y1: {get () { return this._y1; }, set (y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegArcAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {\n super(SVGPathSeg.PATHSEG_ARC_ABS, 'A', owningPathSegList);\n this._x = x;\n this._y = y;\n this._r1 = r1;\n this._r2 = r2;\n this._angle = angle;\n this._largeArcFlag = largeArcFlag;\n this._sweepFlag = sweepFlag;\n }\n toString () { return '[object SVGPathSegArcAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }\n }\n Object.defineProperties(SVGPathSegArcAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n r1: {get () { return this._r1; }, set (r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true},\n r2: {get () { return this._r2; }, set (r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true},\n angle: {get () { return this._angle; }, set (angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true},\n largeArcFlag: {get () { return this._largeArcFlag; }, set (largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true},\n sweepFlag: {get () { return this._sweepFlag; }, set (sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegArcRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {\n super(SVGPathSeg.PATHSEG_ARC_REL, 'a', owningPathSegList);\n this._x = x;\n this._y = y;\n this._r1 = r1;\n this._r2 = r2;\n this._angle = angle;\n this._largeArcFlag = largeArcFlag;\n this._sweepFlag = sweepFlag;\n }\n toString () { return '[object SVGPathSegArcRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }\n }\n Object.defineProperties(SVGPathSegArcRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n r1: {get () { return this._r1; }, set (r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true},\n r2: {get () { return this._r2; }, set (r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true},\n angle: {get () { return this._angle; }, set (angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true},\n largeArcFlag: {get () { return this._largeArcFlag; }, set (largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true},\n sweepFlag: {get () { return this._sweepFlag; }, set (sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegLinetoHorizontalAbs extends SVGPathSeg {\n constructor (owningPathSegList, x) {\n super(SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, 'H', owningPathSegList);\n this._x = x;\n }\n toString () { return '[object SVGPathSegLinetoHorizontalAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x; }\n clone () { return new SVGPathSegLinetoHorizontalAbs(undefined, this._x); }\n }\n Object.defineProperty(SVGPathSegLinetoHorizontalAbs.prototype, 'x', {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true});\n\n class SVGPathSegLinetoHorizontalRel extends SVGPathSeg {\n constructor (owningPathSegList, x) {\n super(SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, 'h', owningPathSegList);\n this._x = x;\n }\n toString () { return '[object SVGPathSegLinetoHorizontalRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x; }\n clone () { return new SVGPathSegLinetoHorizontalRel(undefined, this._x); }\n }\n Object.defineProperty(SVGPathSegLinetoHorizontalRel.prototype, 'x', {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true});\n\n class SVGPathSegLinetoVerticalAbs extends SVGPathSeg {\n constructor (owningPathSegList, y) {\n super(SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, 'V', owningPathSegList);\n this._y = y;\n }\n toString () { return '[object SVGPathSegLinetoVerticalAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._y; }\n clone () { return new SVGPathSegLinetoVerticalAbs(undefined, this._y); }\n }\n Object.defineProperty(SVGPathSegLinetoVerticalAbs.prototype, 'y', {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true});\n\n class SVGPathSegLinetoVerticalRel extends SVGPathSeg {\n constructor (owningPathSegList, y) {\n super(SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, 'v', owningPathSegList);\n this._y = y;\n }\n toString () { return '[object SVGPathSegLinetoVerticalRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._y; }\n clone () { return new SVGPathSegLinetoVerticalRel(undefined, this._y); }\n }\n Object.defineProperty(SVGPathSegLinetoVerticalRel.prototype, 'y', {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true});\n\n class SVGPathSegCurvetoCubicSmoothAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x2, y2) {\n super(SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, 'S', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x2 = x2;\n this._y2 = y2;\n }\n toString () { return '[object SVGPathSegCurvetoCubicSmoothAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); }\n }\n Object.defineProperties(SVGPathSegCurvetoCubicSmoothAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x2: {get () { return this._x2; }, set (x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true},\n y2: {get () { return this._y2; }, set (y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoCubicSmoothRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y, x2, y2) {\n super(SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, 's', owningPathSegList);\n this._x = x;\n this._y = y;\n this._x2 = x2;\n this._y2 = y2;\n }\n toString () { return '[object SVGPathSegCurvetoCubicSmoothRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2); }\n }\n Object.defineProperties(SVGPathSegCurvetoCubicSmoothRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true},\n x2: {get () { return this._x2; }, set (x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true},\n y2: {get () { return this._y2; }, set (y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoQuadraticSmoothAbs extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, 'T', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegCurvetoQuadraticSmoothAbs]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegCurvetoQuadraticSmoothAbs.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true}\n });\n\n class SVGPathSegCurvetoQuadraticSmoothRel extends SVGPathSeg {\n constructor (owningPathSegList, x, y) {\n super(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, 't', owningPathSegList);\n this._x = x;\n this._y = y;\n }\n toString () { return '[object SVGPathSegCurvetoQuadraticSmoothRel]'; }\n _asPathString () { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }\n clone () { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y); }\n }\n Object.defineProperties(SVGPathSegCurvetoQuadraticSmoothRel.prototype, {\n x: {get () { return this._x; }, set (x) { this._x = x; this._segmentChanged(); }, enumerable: true},\n y: {get () { return this._y; }, set (y) { this._y = y; this._segmentChanged(); }, enumerable: true}\n });\n\n // Add createSVGPathSeg* functions to SVGPathElement.\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathElement.\n SVGPathElement.prototype.createSVGPathSegClosePath = function () { return new SVGPathSegClosePath(undefined); };\n SVGPathElement.prototype.createSVGPathSegMovetoAbs = function (x, y) { return new SVGPathSegMovetoAbs(undefined, x, y); };\n SVGPathElement.prototype.createSVGPathSegMovetoRel = function (x, y) { return new SVGPathSegMovetoRel(undefined, x, y); };\n SVGPathElement.prototype.createSVGPathSegLinetoAbs = function (x, y) { return new SVGPathSegLinetoAbs(undefined, x, y); };\n SVGPathElement.prototype.createSVGPathSegLinetoRel = function (x, y) { return new SVGPathSegLinetoRel(undefined, x, y); };\n SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function (x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2); };\n SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function (x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2); };\n SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function (x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1); };\n SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function (x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1); };\n SVGPathElement.prototype.createSVGPathSegArcAbs = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); };\n SVGPathElement.prototype.createSVGPathSegArcRel = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); };\n SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function (x) { return new SVGPathSegLinetoHorizontalAbs(undefined, x); };\n SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function (x) { return new SVGPathSegLinetoHorizontalRel(undefined, x); };\n SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function (y) { return new SVGPathSegLinetoVerticalAbs(undefined, y); };\n SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function (y) { return new SVGPathSegLinetoVerticalRel(undefined, y); };\n SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function (x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2); };\n SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function (x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2); };\n SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function (x, y) { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y); };\n SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function (x, y) { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y); };\n\n if (!('getPathSegAtLength' in SVGPathElement.prototype)) {\n // Add getPathSegAtLength to SVGPathElement.\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-__svg__SVGPathElement__getPathSegAtLength\n // This polyfill requires SVGPathElement.getTotalLength to implement the distance-along-a-path algorithm.\n SVGPathElement.prototype.getPathSegAtLength = function (distance) {\n if (distance === undefined || !isFinite(distance)) {\n throw new Error('Invalid arguments.');\n }\n\n const measurementElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n measurementElement.setAttribute('d', this.getAttribute('d'));\n let lastPathSegment = measurementElement.pathSegList.numberOfItems - 1;\n\n // If the path is empty, return 0.\n if (lastPathSegment <= 0) {\n return 0;\n }\n\n do {\n measurementElement.pathSegList.removeItem(lastPathSegment);\n if (distance > measurementElement.getTotalLength()) {\n break;\n }\n lastPathSegment--;\n } while (lastPathSegment > 0);\n return lastPathSegment;\n };\n }\n\n window.SVGPathSeg = SVGPathSeg;\n window.SVGPathSegClosePath = SVGPathSegClosePath;\n window.SVGPathSegMovetoAbs = SVGPathSegMovetoAbs;\n window.SVGPathSegMovetoRel = SVGPathSegMovetoRel;\n window.SVGPathSegLinetoAbs = SVGPathSegLinetoAbs;\n window.SVGPathSegLinetoRel = SVGPathSegLinetoRel;\n window.SVGPathSegCurvetoCubicAbs = SVGPathSegCurvetoCubicAbs;\n window.SVGPathSegCurvetoCubicRel = SVGPathSegCurvetoCubicRel;\n window.SVGPathSegCurvetoQuadraticAbs = SVGPathSegCurvetoQuadraticAbs;\n window.SVGPathSegCurvetoQuadraticRel = SVGPathSegCurvetoQuadraticRel;\n window.SVGPathSegArcAbs = SVGPathSegArcAbs;\n window.SVGPathSegArcRel = SVGPathSegArcRel;\n window.SVGPathSegLinetoHorizontalAbs = SVGPathSegLinetoHorizontalAbs;\n window.SVGPathSegLinetoHorizontalRel = SVGPathSegLinetoHorizontalRel;\n window.SVGPathSegLinetoVerticalAbs = SVGPathSegLinetoVerticalAbs;\n window.SVGPathSegLinetoVerticalRel = SVGPathSegLinetoVerticalRel;\n window.SVGPathSegCurvetoCubicSmoothAbs = SVGPathSegCurvetoCubicSmoothAbs;\n window.SVGPathSegCurvetoCubicSmoothRel = SVGPathSegCurvetoCubicSmoothRel;\n window.SVGPathSegCurvetoQuadraticSmoothAbs = SVGPathSegCurvetoQuadraticSmoothAbs;\n window.SVGPathSegCurvetoQuadraticSmoothRel = SVGPathSegCurvetoQuadraticSmoothRel;\n}\n\n// Checking for SVGPathSegList in window checks for the case of an implementation without the\n// SVGPathSegList API.\n// The second check for appendItem is specific to Firefox 59+ which removed only parts of the\n// SVGPathSegList API (e.g., appendItem). In this case we need to re-implement the entire API\n// so the polyfill data (i.e., _list) is used throughout.\nif (!('SVGPathSegList' in window) || !('appendItem' in window.SVGPathSegList.prototype)) {\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList\n class SVGPathSegList {\n constructor (pathElement) {\n this._pathElement = pathElement;\n this._list = this._parsePath(this._pathElement.getAttribute('d'));\n\n // Use a MutationObserver to catch changes to the path's \"d\" attribute.\n this._mutationObserverConfig = {attributes: true, attributeFilter: ['d']};\n this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));\n this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);\n }\n // Process any pending mutations to the path element and update the list as needed.\n // This should be the first call of all public functions and is needed because\n // MutationObservers are not synchronous so we can have pending asynchronous mutations.\n _checkPathSynchronizedToList () {\n this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());\n }\n\n _updateListFromPathMutations (mutationRecords) {\n if (!this._pathElement) {\n return;\n }\n let hasPathMutations = false;\n mutationRecords.forEach((record) => {\n if (record.attributeName === 'd') {\n hasPathMutations = true;\n }\n });\n if (hasPathMutations) {\n this._list = this._parsePath(this._pathElement.getAttribute('d'));\n }\n }\n\n // Serialize the list and update the path's 'd' attribute.\n _writeListToPath () {\n this._pathElementMutationObserver.disconnect();\n this._pathElement.setAttribute('d', SVGPathSegList._pathSegArrayAsString(this._list));\n this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);\n }\n\n // When a path segment changes the list needs to be synchronized back to the path element.\n segmentChanged (pathSeg) {\n this._writeListToPath();\n }\n\n clear () {\n this._checkPathSynchronizedToList();\n\n this._list.forEach((pathSeg) => {\n pathSeg._owningPathSegList = null;\n });\n this._list = [];\n this._writeListToPath();\n }\n\n initialize (newItem) {\n this._checkPathSynchronizedToList();\n\n this._list = [newItem];\n newItem._owningPathSegList = this;\n this._writeListToPath();\n return newItem;\n }\n\n _checkValidIndex (index) {\n if (isNaN(index) || index < 0 || index >= this.numberOfItems) {\n throw new Error('INDEX_SIZE_ERR');\n }\n }\n\n getItem (index) {\n this._checkPathSynchronizedToList();\n\n this._checkValidIndex(index);\n return this._list[index];\n }\n\n insertItemBefore (newItem, index) {\n this._checkPathSynchronizedToList();\n\n // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.\n if (index > this.numberOfItems) {\n index = this.numberOfItems;\n }\n if (newItem._owningPathSegList) {\n // SVG2 spec says to make a copy.\n newItem = newItem.clone();\n }\n this._list.splice(index, 0, newItem);\n newItem._owningPathSegList = this;\n this._writeListToPath();\n return newItem;\n }\n\n replaceItem (newItem, index) {\n this._checkPathSynchronizedToList();\n\n if (newItem._owningPathSegList) {\n // SVG2 spec says to make a copy.\n newItem = newItem.clone();\n }\n this._checkValidIndex(index);\n this._list[index] = newItem;\n newItem._owningPathSegList = this;\n this._writeListToPath();\n return newItem;\n }\n\n removeItem (index) {\n this._checkPathSynchronizedToList();\n\n this._checkValidIndex(index);\n const item = this._list[index];\n this._list.splice(index, 1);\n this._writeListToPath();\n return item;\n }\n\n appendItem (newItem) {\n this._checkPathSynchronizedToList();\n\n if (newItem._owningPathSegList) {\n // SVG2 spec says to make a copy.\n newItem = newItem.clone();\n }\n this._list.push(newItem);\n newItem._owningPathSegList = this;\n // TODO: Optimize this to just append to the existing attribute.\n this._writeListToPath();\n return newItem;\n }\n\n // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.\n _parsePath (string) {\n if (!string || !string.length) {\n return [];\n }\n\n const owningPathSegList = this; // eslint-disable-line consistent-this\n\n class Builder {\n constructor () {\n this.pathSegList = [];\n }\n appendSegment (pathSeg) {\n this.pathSegList.push(pathSeg);\n }\n }\n\n class Source {\n constructor (string) {\n this._string = string;\n this._currentIndex = 0;\n this._endIndex = this._string.length;\n this._previousCommand = SVGPathSeg.PATHSEG_UNKNOWN;\n\n this._skipOptionalSpaces();\n }\n _isCurrentSpace () {\n const character = this._string[this._currentIndex];\n return character <= ' ' && (character === ' ' || character === '\\n' || character === '\\t' || character === '\\r' || character === '\\f');\n }\n\n _skipOptionalSpaces () {\n while (this._currentIndex < this._endIndex && this._isCurrentSpace()) {\n this._currentIndex++;\n }\n return this._currentIndex < this._endIndex;\n }\n\n _skipOptionalSpacesOrDelimiter () {\n if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) !== ',') {\n return false;\n }\n if (this._skipOptionalSpaces()) {\n if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === ',') {\n this._currentIndex++;\n this._skipOptionalSpaces();\n }\n }\n return this._currentIndex < this._endIndex;\n }\n\n hasMoreData () {\n return this._currentIndex < this._endIndex;\n }\n\n peekSegmentType () {\n const lookahead = this._string[this._currentIndex];\n return this._pathSegTypeFromChar(lookahead);\n }\n\n _pathSegTypeFromChar (lookahead) {\n switch (lookahead) {\n case 'Z':\n case 'z':\n return SVGPathSeg.PATHSEG_CLOSEPATH;\n case 'M':\n return SVGPathSeg.PATHSEG_MOVETO_ABS;\n case 'm':\n return SVGPathSeg.PATHSEG_MOVETO_REL;\n case 'L':\n return SVGPathSeg.PATHSEG_LINETO_ABS;\n case 'l':\n return SVGPathSeg.PATHSEG_LINETO_REL;\n case 'C':\n return SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;\n case 'c':\n return SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;\n case 'Q':\n return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;\n case 'q':\n return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;\n case 'A':\n return SVGPathSeg.PATHSEG_ARC_ABS;\n case 'a':\n return SVGPathSeg.PATHSEG_ARC_REL;\n case 'H':\n return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;\n case 'h':\n return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;\n case 'V':\n return SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;\n case 'v':\n return SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;\n case 'S':\n return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;\n case 's':\n return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;\n case 'T':\n return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;\n case 't':\n return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;\n default:\n return SVGPathSeg.PATHSEG_UNKNOWN;\n }\n }\n\n _nextCommandHelper (lookahead, previousCommand) {\n // Check for remaining coordinates in the current command.\n if ((lookahead === '+' || lookahead === '-' || lookahead === '.' || (lookahead >= '0' && lookahead <= '9')) && previousCommand !== SVGPathSeg.PATHSEG_CLOSEPATH) {\n if (previousCommand === SVGPathSeg.PATHSEG_MOVETO_ABS) {\n return SVGPathSeg.PATHSEG_LINETO_ABS;\n }\n if (previousCommand === SVGPathSeg.PATHSEG_MOVETO_REL) {\n return SVGPathSeg.PATHSEG_LINETO_REL;\n }\n return previousCommand;\n }\n return SVGPathSeg.PATHSEG_UNKNOWN;\n }\n\n initialCommandIsMoveTo () {\n // If the path is empty it is still valid, so return true.\n if (!this.hasMoreData()) {\n return true;\n }\n const command = this.peekSegmentType();\n // Path must start with moveTo.\n return command === SVGPathSeg.PATHSEG_MOVETO_ABS || command === SVGPathSeg.PATHSEG_MOVETO_REL;\n }\n\n // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF\n _parseNumber () {\n let exponent = 0;\n let integer = 0;\n let frac = 1;\n let decimal = 0;\n let sign = 1;\n let expsign = 1;\n\n const startIndex = this._currentIndex;\n\n this._skipOptionalSpaces();\n\n // Read the sign.\n if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '+') {\n this._currentIndex++;\n } else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '-') {\n this._currentIndex++;\n sign = -1;\n }\n\n if (this._currentIndex === this._endIndex || ((this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') && this._string.charAt(this._currentIndex) !== '.')) {\n // The first character of a number must be one of [0-9+-.].\n return undefined;\n }\n\n // Read the integer part, build right-to-left.\n const startIntPartIndex = this._currentIndex;\n while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') {\n this._currentIndex++; // Advance to first non-digit.\n }\n\n if (this._currentIndex !== startIntPartIndex) {\n let scanIntPartIndex = this._currentIndex - 1;\n let multiplier = 1;\n while (scanIntPartIndex >= startIntPartIndex) {\n integer += multiplier * (this._string.charAt(scanIntPartIndex--) - '0');\n multiplier *= 10;\n }\n }\n\n // Read the decimals.\n if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) === '.') {\n this._currentIndex++;\n\n // There must be a least one digit following the .\n if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') {\n return undefined;\n }\n while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') {\n frac *= 10;\n decimal += (this._string.charAt(this._currentIndex) - '0') / frac;\n this._currentIndex += 1;\n }\n }\n\n // Read the exponent part.\n if (this._currentIndex !== startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) === 'e' || this._string.charAt(this._currentIndex) === 'E') && (this._string.charAt(this._currentIndex + 1) !== 'x' && this._string.charAt(this._currentIndex + 1) !== 'm')) {\n this._currentIndex++;\n\n // Read the sign of the exponent.\n if (this._string.charAt(this._currentIndex) === '+') {\n this._currentIndex++;\n } else if (this._string.charAt(this._currentIndex) === '-') {\n this._currentIndex++;\n expsign = -1;\n }\n\n // There must be an exponent.\n if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') {\n return undefined;\n }\n\n while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') {\n exponent *= 10;\n exponent += (this._string.charAt(this._currentIndex) - '0');\n this._currentIndex++;\n }\n }\n\n let number = integer + decimal;\n number *= sign;\n\n if (exponent) {\n number *= 10 ** (expsign * exponent);\n }\n\n if (startIndex === this._currentIndex) {\n return undefined;\n }\n\n this._skipOptionalSpacesOrDelimiter();\n\n return number;\n }\n\n _parseArcFlag () {\n if (this._currentIndex >= this._endIndex) {\n return undefined;\n }\n let flag = false;\n const flagChar = this._string.charAt(this._currentIndex++);\n if (flagChar === '0') {\n flag = false;\n } else if (flagChar === '1') {\n flag = true;\n } else {\n return undefined;\n }\n\n this._skipOptionalSpacesOrDelimiter();\n return flag;\n }\n\n parseSegment () {\n const lookahead = this._string[this._currentIndex];\n let command = this._pathSegTypeFromChar(lookahead);\n if (command === SVGPathSeg.PATHSEG_UNKNOWN) {\n // Possibly an implicit command. Not allowed if this is the first command.\n if (this._previousCommand === SVGPathSeg.PATHSEG_UNKNOWN) {\n return null;\n }\n command = this._nextCommandHelper(lookahead, this._previousCommand);\n if (command === SVGPathSeg.PATHSEG_UNKNOWN) {\n return null;\n }\n } else {\n this._currentIndex++;\n }\n\n this._previousCommand = command;\n\n switch (command) {\n case SVGPathSeg.PATHSEG_MOVETO_REL:\n return new SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_MOVETO_ABS:\n return new SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_REL:\n return new SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_ABS:\n return new SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:\n return new SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:\n return new SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:\n return new SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());\n case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:\n return new SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());\n case SVGPathSeg.PATHSEG_CLOSEPATH:\n this._skipOptionalSpaces();\n return new SVGPathSegClosePath(owningPathSegList);\n case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);\n } case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);\n } case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL: {\n const points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);\n } case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: {\n const points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);\n } case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);\n } case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);\n } case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:\n return new SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:\n return new SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());\n case SVGPathSeg.PATHSEG_ARC_REL: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);\n } case SVGPathSeg.PATHSEG_ARC_ABS: {\n const points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};\n return new SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);\n } default:\n throw new Error('Unknown path seg type.');\n }\n }\n }\n\n const builder = new Builder();\n const source = new Source(string);\n\n if (!source.initialCommandIsMoveTo()) {\n return [];\n }\n while (source.hasMoreData()) {\n const pathSeg = source.parseSegment();\n if (!pathSeg) {\n return [];\n }\n builder.appendSegment(pathSeg);\n }\n\n return builder.pathSegList;\n }\n\n // STATIC\n static _pathSegArrayAsString (pathSegArray) {\n let string = '';\n let first = true;\n pathSegArray.forEach((pathSeg) => {\n if (first) {\n first = false;\n string += pathSeg._asPathString();\n } else {\n string += ' ' + pathSeg._asPathString();\n }\n });\n return string;\n }\n }\n\n SVGPathSegList.prototype.classname = 'SVGPathSegList';\n\n Object.defineProperty(SVGPathSegList.prototype, 'numberOfItems', {\n get () {\n this._checkPathSynchronizedToList();\n return this._list.length;\n },\n enumerable: true\n });\n\n // Add the pathSegList accessors to SVGPathElement.\n // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData\n Object.defineProperties(SVGPathElement.prototype, {\n pathSegList: {\n get () {\n if (!this._pathSegList) {\n this._pathSegList = new SVGPathSegList(this);\n }\n return this._pathSegList;\n },\n enumerable: true\n },\n // TODO: The following are not implemented and simply return SVGPathElement.pathSegList.\n normalizedPathSegList: {get () { return this.pathSegList; }, enumerable: true},\n animatedPathSegList: {get () { return this.pathSegList; }, enumerable: true},\n animatedNormalizedPathSegList: {get () { return this.pathSegList; }, enumerable: true}\n });\n window.SVGPathSegList = SVGPathSegList;\n}\n})();\n","/* globals jQuery */\n/**\n * Browser detection.\n * @module browser\n * @license MIT\n *\n * @copyright 2010 Jeff Schiller, 2010 Alexis Deveria\n */\n\n// Dependencies:\n// 1) jQuery (for $.alert())\n\nimport './svgpathseg.js';\nimport {NS} from './namespaces.js';\n\nconst $ = jQuery;\n\nconst supportsSVG_ = (function () {\nreturn Boolean(document.createElementNS && document.createElementNS(NS.SVG, 'svg').createSVGRect);\n}());\n\n/**\n * @function module:browser.supportsSvg\n * @returns {boolean}\n*/\nexport const supportsSvg = () => supportsSVG_;\n\nconst {userAgent} = navigator;\nconst svg = document.createElementNS(NS.SVG, 'svg');\n\n// Note: Browser sniffing should only be used if no other detection method is possible\nconst isOpera_ = Boolean(window.opera);\nconst isWebkit_ = userAgent.includes('AppleWebKit');\nconst isGecko_ = userAgent.includes('Gecko/');\nconst isIE_ = userAgent.includes('MSIE');\nconst isChrome_ = userAgent.includes('Chrome/');\nconst isWindows_ = userAgent.includes('Windows');\nconst isMac_ = userAgent.includes('Macintosh');\nconst isTouch_ = 'ontouchstart' in window;\n\nconst supportsSelectors_ = (function () {\nreturn Boolean(svg.querySelector);\n}());\n\nconst supportsXpath_ = (function () {\nreturn Boolean(document.evaluate);\n}());\n\n// segList functions (for FF1.5 and 2.0)\nconst supportsPathReplaceItem_ = (function () {\nconst path = document.createElementNS(NS.SVG, 'path');\npath.setAttribute('d', 'M0,0 10,10');\nconst seglist = path.pathSegList;\nconst seg = path.createSVGPathSegLinetoAbs(5, 5);\ntry {\n seglist.replaceItem(seg, 1);\n return true;\n} catch (err) {}\nreturn false;\n}());\n\nconst supportsPathInsertItemBefore_ = (function () {\nconst path = document.createElementNS(NS.SVG, 'path');\npath.setAttribute('d', 'M0,0 10,10');\nconst seglist = path.pathSegList;\nconst seg = path.createSVGPathSegLinetoAbs(5, 5);\ntry {\n seglist.insertItemBefore(seg, 1);\n return true;\n} catch (err) {}\nreturn false;\n}());\n\n// text character positioning (for IE9 and now Chrome)\nconst supportsGoodTextCharPos_ = (function () {\nconst svgroot = document.createElementNS(NS.SVG, 'svg');\nconst svgcontent = document.createElementNS(NS.SVG, 'svg');\ndocument.documentElement.append(svgroot);\nsvgcontent.setAttribute('x', 5);\nsvgroot.append(svgcontent);\nconst text = document.createElementNS(NS.SVG, 'text');\ntext.textContent = 'a';\nsvgcontent.append(text);\ntry { // Chrome now fails here\n const pos = text.getStartPositionOfChar(0).x;\n return (pos === 0);\n} catch (err) {\n return false;\n} finally {\n svgroot.remove();\n}\n}());\n\nconst supportsPathBBox_ = (function () {\nconst svgcontent = document.createElementNS(NS.SVG, 'svg');\ndocument.documentElement.append(svgcontent);\nconst path = document.createElementNS(NS.SVG, 'path');\npath.setAttribute('d', 'M0,0 C0,0 10,10 10,0');\nsvgcontent.append(path);\nconst bbox = path.getBBox();\nsvgcontent.remove();\nreturn (bbox.height > 4 && bbox.height < 5);\n}());\n\n// Support for correct bbox sizing on groups with horizontal/vertical lines\nconst supportsHVLineContainerBBox_ = (function () {\nconst svgcontent = document.createElementNS(NS.SVG, 'svg');\ndocument.documentElement.append(svgcontent);\nconst path = document.createElementNS(NS.SVG, 'path');\npath.setAttribute('d', 'M0,0 10,0');\nconst path2 = document.createElementNS(NS.SVG, 'path');\npath2.setAttribute('d', 'M5,0 15,0');\nconst g = document.createElementNS(NS.SVG, 'g');\ng.append(path, path2);\nsvgcontent.append(g);\nconst bbox = g.getBBox();\nsvgcontent.remove();\n// Webkit gives 0, FF gives 10, Opera (correctly) gives 15\nreturn (bbox.width === 15);\n}());\n\nconst supportsEditableText_ = (function () {\n// TODO: Find better way to check support for this\nreturn isOpera_;\n}());\n\nconst supportsGoodDecimals_ = (function () {\n// Correct decimals on clone attributes (Opera < 10.5/win/non-en)\nconst rect = document.createElementNS(NS.SVG, 'rect');\nrect.setAttribute('x', 0.1);\nconst crect = rect.cloneNode(false);\nconst retValue = (!crect.getAttribute('x').includes(','));\nif (!retValue) {\n // Todo: i18nize or remove\n $.alert(\n 'NOTE: This version of Opera is known to contain bugs in SVG-edit.\\n' +\n 'Please upgrade to the <a href=\"http://opera.com\">latest version</a> in which the problems have been fixed.'\n );\n}\nreturn retValue;\n}());\n\nconst supportsNonScalingStroke_ = (function () {\nconst rect = document.createElementNS(NS.SVG, 'rect');\nrect.setAttribute('style', 'vector-effect:non-scaling-stroke');\nreturn rect.style.vectorEffect === 'non-scaling-stroke';\n}());\n\nlet supportsNativeSVGTransformLists_ = (function () {\nconst rect = document.createElementNS(NS.SVG, 'rect');\nconst rxform = rect.transform.baseVal;\nconst t1 = svg.createSVGTransform();\nrxform.appendItem(t1);\nconst r1 = rxform.getItem(0);\nconst isSVGTransform = (o) => {\n // https://developer.mozilla.org/en-US/docs/Web/API/SVGTransform\n return o && typeof o === 'object' && typeof o.setMatrix === 'function' && 'angle' in o;\n};\nreturn isSVGTransform(r1) && isSVGTransform(t1) &&\n r1.type === t1.type && r1.angle === t1.angle &&\n r1.matrix.a === t1.matrix.a &&\n r1.matrix.b === t1.matrix.b &&\n r1.matrix.c === t1.matrix.c &&\n r1.matrix.d === t1.matrix.d &&\n r1.matrix.e === t1.matrix.e &&\n r1.matrix.f === t1.matrix.f;\n}());\n\n// Public API\n\n/**\n * @function module:browser.isOpera\n * @returns {boolean}\n*/\nexport const isOpera = () => isOpera_;\n/**\n * @function module:browser.isWebkit\n * @returns {boolean}\n*/\nexport const isWebkit = () => isWebkit_;\n/**\n * @function module:browser.isGecko\n * @returns {boolean}\n*/\nexport const isGecko = () => isGecko_;\n/**\n * @function module:browser.isIE\n * @returns {boolean}\n*/\nexport const isIE = () => isIE_;\n/**\n * @function module:browser.isChrome\n * @returns {boolean}\n*/\nexport const isChrome = () => isChrome_;\n/**\n * @function module:browser.isWindows\n * @returns {boolean}\n*/\nexport const isWindows = () => isWindows_;\n/**\n * @function module:browser.isMac\n * @returns {boolean}\n*/\nexport const isMac = () => isMac_;\n/**\n * @function module:browser.isTouch\n * @returns {boolean}\n*/\nexport const isTouch = () => isTouch_;\n\n/**\n * @function module:browser.supportsSelectors\n * @returns {boolean}\n*/\nexport const supportsSelectors = () => supportsSelectors_;\n\n/**\n * @function module:browser.supportsXpath\n * @returns {boolean}\n*/\nexport const supportsXpath = () => supportsXpath_;\n\n/**\n * @function module:browser.supportsPathReplaceItem\n * @returns {boolean}\n*/\nexport const supportsPathReplaceItem = () => supportsPathReplaceItem_;\n\n/**\n * @function module:browser.supportsPathInsertItemBefore\n * @returns {boolean}\n*/\nexport const supportsPathInsertItemBefore = () => supportsPathInsertItemBefore_;\n\n/**\n * @function module:browser.supportsPathBBox\n * @returns {boolean}\n*/\nexport const supportsPathBBox = () => supportsPathBBox_;\n\n/**\n * @function module:browser.supportsHVLineContainerBBox\n * @returns {boolean}\n*/\nexport const supportsHVLineContainerBBox = () => supportsHVLineContainerBBox_;\n\n/**\n * @function module:browser.supportsGoodTextCharPos\n * @returns {boolean}\n*/\nexport const supportsGoodTextCharPos = () => supportsGoodTextCharPos_;\n\n/**\n* @function module:browser.supportsEditableText\n * @returns {boolean}\n*/\nexport const supportsEditableText = () => supportsEditableText_;\n\n/**\n * @function module:browser.supportsGoodDecimals\n * @returns {boolean}\n*/\nexport const supportsGoodDecimals = () => supportsGoodDecimals_;\n\n/**\n* @function module:browser.supportsNonScalingStroke\n* @returns {boolean}\n*/\nexport const supportsNonScalingStroke = () => supportsNonScalingStroke_;\n\n/**\n* @function module:browser.supportsNativeTransformLists\n* @returns {boolean}\n*/\nexport const supportsNativeTransformLists = () => supportsNativeSVGTransformLists_;\n\n/**\n * Set `supportsNativeSVGTransformLists_` to `false` (for unit testing).\n * @function module:browser.disableSupportsNativeTransformLists\n * @returns {void}\n*/\nexport const disableSupportsNativeTransformLists = () => {\n supportsNativeSVGTransformLists_ = false;\n};\n","/**\n * A jQuery module to work with SVG attributes.\n * @module jQueryAttr\n * @license MIT\n */\n\n/**\n* This fixes `$(...).attr()` to work as expected with SVG elements.\n* Does not currently use `*AttributeNS()` since we rarely need that.\n* Adds {@link external:jQuery.fn.attr}.\n* See {@link https://api.jquery.com/attr/} for basic documentation of `.attr()`.\n*\n* Additional functionality:\n* - When getting attributes, a string that's a number is returned as type number.\n* - If an array is supplied as the first parameter, multiple values are returned\n* as an object with values for each given attribute.\n* @function module:jQueryAttr.jQueryAttr\n* @param {external:jQuery} $ The jQuery object to which to add the plug-in\n* @returns {external:jQuery}\n*/\nexport default function jQueryPluginSVG ($) {\n const proxied = $.fn.attr,\n svgns = 'http://www.w3.org/2000/svg';\n /**\n * @typedef {PlainObject<string, string|Float>} module:jQueryAttr.Attributes\n */\n /**\n * @function external:jQuery.fn.attr\n * @param {string|string[]|PlainObject<string, string>} key\n * @param {string} value\n * @returns {external:jQuery|module:jQueryAttr.Attributes}\n */\n $.fn.attr = function (key, value) {\n const len = this.length;\n if (!len) { return proxied.call(this, key, value); }\n for (let i = 0; i < len; ++i) {\n const elem = this[i];\n // set/get SVG attribute\n if (elem.namespaceURI === svgns) {\n // Setting attribute\n if (value !== undefined) {\n elem.setAttribute(key, value);\n } else if (Array.isArray(key)) {\n // Getting attributes from array\n const obj = {};\n let j = key.length;\n\n while (j--) {\n const aname = key[j];\n let attr = elem.getAttribute(aname);\n // This returns a number when appropriate\n if (attr || attr === '0') {\n attr = isNaN(attr) ? attr : (attr - 0);\n }\n obj[aname] = attr;\n }\n return obj;\n }\n if (typeof key === 'object') {\n // Setting attributes from object\n for (const [name, val] of Object.entries(key)) {\n elem.setAttribute(name, val);\n }\n // Getting attribute\n } else {\n let attr = elem.getAttribute(key);\n if (attr || attr === '0') {\n attr = isNaN(attr) ? attr : (attr - 0);\n }\n return attr;\n }\n } else {\n return proxied.call(this, key, value);\n }\n }\n return this;\n };\n return $;\n}\n","/**\n * Partial polyfill of `SVGTransformList`\n * @module SVGTransformList\n *\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\nimport {NS} from './namespaces.js';\nimport {supportsNativeTransformLists} from './browser.js';\n\nconst svgroot = document.createElementNS(NS.SVG, 'svg');\n\n/**\n * Helper function to convert `SVGTransform` to a string.\n * @param {SVGTransform} xform\n * @returns {string}\n */\nfunction transformToString (xform) {\n const m = xform.matrix;\n let text = '';\n switch (xform.type) {\n case 1: // MATRIX\n text = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')';\n break;\n case 2: // TRANSLATE\n text = 'translate(' + m.e + ',' + m.f + ')';\n break;\n case 3: // SCALE\n if (m.a === m.d) {\n text = 'scale(' + m.a + ')';\n } else {\n text = 'scale(' + m.a + ',' + m.d + ')';\n }\n break;\n case 4: { // ROTATE\n let cx = 0;\n let cy = 0;\n // this prevents divide by zero\n if (xform.angle !== 0) {\n const K = 1 - m.a;\n cy = (K * m.f + m.b * m.e) / (K * K + m.b * m.b);\n cx = (m.e - m.b * cy) / K;\n }\n text = 'rotate(' + xform.angle + ' ' + cx + ',' + cy + ')';\n break;\n }\n }\n return text;\n}\n\n/**\n * Map of SVGTransformList objects.\n */\nlet listMap_ = {};\n\n/**\n* @interface module:SVGTransformList.SVGEditTransformList\n* @property {Integer} numberOfItems unsigned long\n*/\n/**\n* @function module:SVGTransformList.SVGEditTransformList#clear\n* @returns {void}\n*/\n/**\n* @function module:SVGTransformList.SVGEditTransformList#initialize\n* @param {SVGTransform} newItem\n* @returns {SVGTransform}\n*/\n/**\n* DOES NOT THROW DOMException, INDEX_SIZE_ERR.\n* @function module:SVGTransformList.SVGEditTransformList#getItem\n* @param {Integer} index unsigned long\n* @returns {SVGTransform}\n*/\n/**\n* DOES NOT THROW DOMException, INDEX_SIZE_ERR.\n* @function module:SVGTransformList.SVGEditTransformList#insertItemBefore\n* @param {SVGTransform} newItem\n* @param {Integer} index unsigned long\n* @returns {SVGTransform}\n*/\n/**\n* DOES NOT THROW DOMException, INDEX_SIZE_ERR.\n* @function module:SVGTransformList.SVGEditTransformList#replaceItem\n* @param {SVGTransform} newItem\n* @param {Integer} index unsigned long\n* @returns {SVGTransform}\n*/\n/**\n* DOES NOT THROW DOMException, INDEX_SIZE_ERR.\n* @function module:SVGTransformList.SVGEditTransformList#removeItem\n* @param {Integer} index unsigned long\n* @returns {SVGTransform}\n*/\n/**\n* @function module:SVGTransformList.SVGEditTransformList#appendItem\n* @param {SVGTransform} newItem\n* @returns {SVGTransform}\n*/\n/**\n* NOT IMPLEMENTED.\n* @ignore\n* @function module:SVGTransformList.SVGEditTransformList#createSVGTransformFromMatrix\n* @param {SVGMatrix} matrix\n* @returns {SVGTransform}\n*/\n/**\n* NOT IMPLEMENTED.\n* @ignore\n* @function module:SVGTransformList.SVGEditTransformList#consolidate\n* @returns {SVGTransform}\n*/\n\n/**\n* SVGTransformList implementation for Webkit.\n* These methods do not currently raise any exceptions.\n* These methods also do not check that transforms are being inserted. This is basically\n* implementing as much of SVGTransformList that we need to get the job done.\n* @implements {module:SVGTransformList.SVGEditTransformList}\n*/\nexport class SVGTransformList { // eslint-disable-line no-shadow\n /**\n * @param {Element} elem\n * @returns {SVGTransformList}\n */\n constructor (elem) {\n this._elem = elem || null;\n this._xforms = [];\n // TODO: how do we capture the undo-ability in the changed transform list?\n this._update = function () {\n let tstr = '';\n // /* const concatMatrix = */ svgroot.createSVGMatrix();\n for (let i = 0; i < this.numberOfItems; ++i) {\n const xform = this._list.getItem(i);\n tstr += transformToString(xform) + ' ';\n }\n this._elem.setAttribute('transform', tstr);\n };\n this._list = this;\n this._init = function () {\n // Transform attribute parser\n let str = this._elem.getAttribute('transform');\n if (!str) { return; }\n\n // TODO: Add skew support in future\n const re = /\\s*((scale|matrix|rotate|translate)\\s*\\(.*?\\))\\s*,?\\s*/;\n // const re = /\\s*(?<xform>(?:scale|matrix|rotate|translate)\\s*\\(.*?\\))\\s*,?\\s*/;\n let m = true;\n while (m) {\n m = str.match(re);\n str = str.replace(re, '');\n if (m && m[1]) {\n const x = m[1];\n const bits = x.split(/\\s*\\(/);\n const name = bits[0];\n const valBits = bits[1].match(/\\s*(.*?)\\s*\\)/);\n valBits[1] = valBits[1].replace(/(\\d)-/g, '$1 -');\n const valArr = valBits[1].split(/[, ]+/);\n const letters = 'abcdef'.split('');\n /*\n if (m && m.groups.xform) {\n const x = m.groups.xform;\n const [name, bits] = x.split(/\\s*\\(/);\n const valBits = bits.match(/\\s*(?<nonWhitespace>.*?)\\s*\\)/);\n valBits.groups.nonWhitespace = valBits.groups.nonWhitespace.replace(\n /(?<digit>\\d)-/g, '$<digit> -'\n );\n const valArr = valBits.groups.nonWhitespace.split(/[, ]+/);\n const letters = [...'abcdef'];\n */\n const mtx = svgroot.createSVGMatrix();\n Object.values(valArr).forEach(function (item, i) {\n valArr[i] = parseFloat(item);\n if (name === 'matrix') {\n mtx[letters[i]] = valArr[i];\n }\n });\n const xform = svgroot.createSVGTransform();\n const fname = 'set' + name.charAt(0).toUpperCase() + name.slice(1);\n const values = name === 'matrix' ? [mtx] : valArr;\n\n if (name === 'scale' && values.length === 1) {\n values.push(values[0]);\n } else if (name === 'translate' && values.length === 1) {\n values.push(0);\n } else if (name === 'rotate' && values.length === 1) {\n values.push(0, 0);\n }\n xform[fname](...values);\n this._list.appendItem(xform);\n }\n }\n };\n this._removeFromOtherLists = function (item) {\n if (item) {\n // Check if this transform is already in a transformlist, and\n // remove it if so.\n Object.values(listMap_).some((tl) => {\n for (let i = 0, len = tl._xforms.length; i < len; ++i) {\n if (tl._xforms[i] === item) {\n tl.removeItem(i);\n return true;\n }\n }\n return false;\n });\n }\n };\n\n this.numberOfItems = 0;\n }\n /**\n * @returns {void}\n */\n clear () {\n this.numberOfItems = 0;\n this._xforms = [];\n }\n\n /**\n * @param {SVGTransform} newItem\n * @returns {void}\n */\n initialize (newItem) {\n this.numberOfItems = 1;\n this._removeFromOtherLists(newItem);\n this._xforms = [newItem];\n }\n\n /**\n * @param {Integer} index unsigned long\n * @throws {Error}\n * @returns {SVGTransform}\n */\n getItem (index) {\n if (index < this.numberOfItems && index >= 0) {\n return this._xforms[index];\n }\n const err = new Error('DOMException with code=INDEX_SIZE_ERR');\n err.code = 1;\n throw err;\n }\n\n /**\n * @param {SVGTransform} newItem\n * @param {Integer} index unsigned long\n * @returns {SVGTransform}\n */\n insertItemBefore (newItem, index) {\n let retValue = null;\n if (index >= 0) {\n if (index < this.numberOfItems) {\n this._removeFromOtherLists(newItem);\n const newxforms = new Array(this.numberOfItems + 1);\n // TODO: use array copying and slicing\n let i;\n for (i = 0; i < index; ++i) {\n newxforms[i] = this._xforms[i];\n }\n newxforms[i] = newItem;\n for (let j = i + 1; i < this.numberOfItems; ++j, ++i) {\n newxforms[j] = this._xforms[i];\n }\n this.numberOfItems++;\n this._xforms = newxforms;\n retValue = newItem;\n this._list._update();\n } else {\n retValue = this._list.appendItem(newItem);\n }\n }\n return retValue;\n }\n\n /**\n * @param {SVGTransform} newItem\n * @param {Integer} index unsigned long\n * @returns {SVGTransform}\n */\n replaceItem (newItem, index) {\n let retValue = null;\n if (index < this.numberOfItems && index >= 0) {\n this._removeFromOtherLists(newItem);\n this._xforms[index] = newItem;\n retValue = newItem;\n this._list._update();\n }\n return retValue;\n }\n\n /**\n * @param {Integer} index unsigned long\n * @throws {Error}\n * @returns {SVGTransform}\n */\n removeItem (index) {\n if (index < this.numberOfItems && index >= 0) {\n const retValue = this._xforms[index];\n const newxforms = new Array(this.numberOfItems - 1);\n let i;\n for (i = 0; i < index; ++i) {\n newxforms[i] = this._xforms[i];\n }\n for (let j = i; j < this.numberOfItems - 1; ++j, ++i) {\n newxforms[j] = this._xforms[i + 1];\n }\n this.numberOfItems--;\n this._xforms = newxforms;\n this._list._update();\n return retValue;\n }\n const err = new Error('DOMException with code=INDEX_SIZE_ERR');\n err.code = 1;\n throw err;\n }\n\n /**\n * @param {SVGTransform} newItem\n * @returns {SVGTransform}\n */\n appendItem (newItem) {\n this._removeFromOtherLists(newItem);\n this._xforms.push(newItem);\n this.numberOfItems++;\n this._list._update();\n return newItem;\n }\n}\n\n/**\n* @function module:SVGTransformList.resetListMap\n* @returns {void}\n*/\nexport const resetListMap = function () {\n listMap_ = {};\n};\n\n/**\n * Removes transforms of the given element from the map.\n * @function module:SVGTransformList.removeElementFromListMap\n * @param {Element} elem - a DOM Element\n * @returns {void}\n */\nexport let removeElementFromListMap = function (elem) { // eslint-disable-line import/no-mutable-exports\n if (elem.id && listMap_[elem.id]) {\n delete listMap_[elem.id];\n }\n};\n\n/**\n* Returns an object that behaves like a `SVGTransformList` for the given DOM element.\n* @function module:SVGTransformList.getTransformList\n* @param {Element} elem - DOM element to get a transformlist from\n* @todo The polyfill should have `SVGAnimatedTransformList` and this should use it\n* @returns {SVGAnimatedTransformList|SVGTransformList}\n*/\nexport const getTransformList = function (elem) {\n if (!supportsNativeTransformLists()) {\n const id = elem.id || 'temp';\n let t = listMap_[id];\n if (!t || id === 'temp') {\n listMap_[id] = new SVGTransformList(elem);\n listMap_[id]._init();\n t = listMap_[id];\n }\n return t;\n }\n if (elem.transform) {\n return elem.transform.baseVal;\n }\n if (elem.gradientTransform) {\n return elem.gradientTransform.baseVal;\n }\n if (elem.patternTransform) {\n return elem.patternTransform.baseVal;\n }\n\n return null;\n};\n\n/**\n* @callback module:SVGTransformList.removeElementFromListMap\n* @param {Element} elem\n* @returns {void}\n*/\n/**\n* Replace `removeElementFromListMap` for unit-testing.\n* @function module:SVGTransformList.changeRemoveElementFromListMap\n* @param {module:SVGTransformList.removeElementFromListMap} cb Passed a single argument `elem`\n* @returns {void}\n*/\n\nexport const changeRemoveElementFromListMap = function (cb) { // eslint-disable-line promise/prefer-await-to-callbacks\n removeElementFromListMap = cb;\n};\n","/**\n * Tools for working with units.\n * @module units\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\nimport {NS} from './namespaces.js';\nimport {isNullish} from './utilities.js';\n\nconst wAttrs = ['x', 'x1', 'cx', 'rx', 'width'];\nconst hAttrs = ['y', 'y1', 'cy', 'ry', 'height'];\nconst unitAttrs = ['r', 'radius', ...wAttrs, ...hAttrs];\n// unused\n/*\nconst unitNumMap = {\n '%': 2,\n em: 3,\n ex: 4,\n px: 5,\n cm: 6,\n mm: 7,\n in: 8,\n pt: 9,\n pc: 10\n};\n*/\n// Container of elements.\nlet elementContainer_;\n\n// Stores mapping of unit type to user coordinates.\nlet typeMap_ = {};\n\n/**\n * @interface module:units.ElementContainer\n */\n/**\n * @function module:units.ElementContainer#getBaseUnit\n * @returns {string} The base unit type of the container ('em')\n */\n/**\n * @function module:units.ElementContainer#getElement\n * @returns {?Element} An element in the container given an id\n */\n/**\n * @function module:units.ElementContainer#getHeight\n * @returns {Float} The container's height\n */\n/**\n * @function module:units.ElementContainer#getWidth\n * @returns {Float} The container's width\n */\n/**\n * @function module:units.ElementContainer#getRoundDigits\n * @returns {Integer} The number of digits number should be rounded to\n */\n\n/**\n * @typedef {PlainObject} module:units.TypeMap\n * @property {Float} em\n * @property {Float} ex\n * @property {Float} in\n * @property {Float} cm\n * @property {Float} mm\n * @property {Float} pt\n * @property {Float} pc\n * @property {Integer} px\n * @property {0} %\n */\n\n/**\n * Initializes this module.\n *\n * @function module:units.init\n * @param {module:units.ElementContainer} elementContainer - An object implementing the ElementContainer interface.\n * @returns {void}\n */\nexport const init = function (elementContainer) {\n elementContainer_ = elementContainer;\n\n // Get correct em/ex values by creating a temporary SVG.\n const svg = document.createElementNS(NS.SVG, 'svg');\n document.body.append(svg);\n const rect = document.createElementNS(NS.SVG, 'rect');\n rect.setAttribute('width', '1em');\n rect.setAttribute('height', '1ex');\n rect.setAttribute('x', '1in');\n svg.append(rect);\n const bb = rect.getBBox();\n svg.remove();\n\n const inch = bb.x;\n typeMap_ = {\n em: bb.width,\n ex: bb.height,\n in: inch,\n cm: inch / 2.54,\n mm: inch / 25.4,\n pt: inch / 72,\n pc: inch / 6,\n px: 1,\n '%': 0\n };\n};\n\n/**\n* Group: Unit conversion functions.\n*/\n\n/**\n * @function module:units.getTypeMap\n * @returns {module:units.TypeMap} The unit object with values for each unit\n*/\nexport const getTypeMap = function () {\n return typeMap_;\n};\n\n/**\n* @typedef {GenericArray} module:units.CompareNumbers\n* @property {Integer} length 2\n* @property {Float} 0\n* @property {Float} 1\n*/\n\n/**\n* Rounds a given value to a float with number of digits defined in\n* `round_digits` of `saveOptions`\n*\n* @function module:units.shortFloat\n* @param {string|Float|module:units.CompareNumbers} val - The value (or Array of two numbers) to be rounded\n* @returns {Float|string} If a string/number was given, returns a Float. If an array, return a string\n* with comma-separated floats\n*/\nexport const shortFloat = function (val) {\n const digits = elementContainer_.getRoundDigits();\n if (!isNaN(val)) {\n return Number(Number(val).toFixed(digits));\n }\n if (Array.isArray(val)) {\n return shortFloat(val[0]) + ',' + shortFloat(val[1]);\n }\n return parseFloat(val).toFixed(digits) - 0;\n};\n\n/**\n* Converts the number to given unit or baseUnit.\n* @function module:units.convertUnit\n* @param {string|Float} val\n* @param {\"em\"|\"ex\"|\"in\"|\"cm\"|\"mm\"|\"pt\"|\"pc\"|\"px\"|\"%\"} [unit]\n* @returns {Float}\n*/\nexport const convertUnit = function (val, unit) {\n unit = unit || elementContainer_.getBaseUnit();\n // baseVal.convertToSpecifiedUnits(unitNumMap[unit]);\n // const val = baseVal.valueInSpecifiedUnits;\n // baseVal.convertToSpecifiedUnits(1);\n return shortFloat(val / typeMap_[unit]);\n};\n\n/**\n* Sets an element's attribute based on the unit in its current value.\n*\n* @function module:units.setUnitAttr\n* @param {Element} elem - DOM element to be changed\n* @param {string} attr - Name of the attribute associated with the value\n* @param {string} val - Attribute value to convert\n* @returns {void}\n*/\nexport const setUnitAttr = function (elem, attr, val) {\n // if (!isNaN(val)) {\n // New value is a number, so check currently used unit\n // const oldVal = elem.getAttribute(attr);\n\n // Enable this for alternate mode\n // if (oldVal !== null && (isNaN(oldVal) || elementContainer_.getBaseUnit() !== 'px')) {\n // // Old value was a number, so get unit, then convert\n // let unit;\n // if (oldVal.substr(-1) === '%') {\n // const res = getResolution();\n // unit = '%';\n // val *= 100;\n // if (wAttrs.includes(attr)) {\n // val = val / res.w;\n // } else if (hAttrs.includes(attr)) {\n // val = val / res.h;\n // } else {\n // return val / Math.sqrt((res.w*res.w) + (res.h*res.h))/Math.sqrt(2);\n // }\n // } else {\n // if (elementContainer_.getBaseUnit() !== 'px') {\n // unit = elementContainer_.getBaseUnit();\n // } else {\n // unit = oldVal.substr(-2);\n // }\n // val = val / typeMap_[unit];\n // }\n //\n // val += unit;\n // }\n // }\n elem.setAttribute(attr, val);\n};\n\nconst attrsToConvert = {\n line: ['x1', 'x2', 'y1', 'y2'],\n circle: ['cx', 'cy', 'r'],\n ellipse: ['cx', 'cy', 'rx', 'ry'],\n foreignObject: ['x', 'y', 'width', 'height'],\n rect: ['x', 'y', 'width', 'height'],\n image: ['x', 'y', 'width', 'height'],\n use: ['x', 'y', 'width', 'height'],\n text: ['x', 'y']\n};\n\n/**\n* Converts all applicable attributes to the configured baseUnit.\n* @function module:units.convertAttrs\n* @param {Element} element - A DOM element whose attributes should be converted\n* @returns {void}\n*/\nexport const convertAttrs = function (element) {\n const elName = element.tagName;\n const unit = elementContainer_.getBaseUnit();\n const attrs = attrsToConvert[elName];\n if (!attrs) { return; }\n\n const len = attrs.length;\n for (let i = 0; i < len; i++) {\n const attr = attrs[i];\n const cur = element.getAttribute(attr);\n if (cur) {\n if (!isNaN(cur)) {\n element.setAttribute(attr, (cur / typeMap_[unit]) + unit);\n }\n // else {\n // Convert existing?\n // }\n }\n }\n};\n\n/**\n* Converts given values to numbers. Attributes must be supplied in\n* case a percentage is given.\n*\n* @function module:units.convertToNum\n* @param {string} attr - Name of the attribute associated with the value\n* @param {string} val - Attribute value to convert\n* @returns {Float} The converted number\n*/\nexport const convertToNum = function (attr, val) {\n // Return a number if that's what it already is\n if (!isNaN(val)) { return val - 0; }\n if (val.substr(-1) === '%') {\n // Deal with percentage, depends on attribute\n const num = val.substr(0, val.length - 1) / 100;\n const width = elementContainer_.getWidth();\n const height = elementContainer_.getHeight();\n\n if (wAttrs.includes(attr)) {\n return num * width;\n }\n if (hAttrs.includes(attr)) {\n return num * height;\n }\n return num * Math.sqrt((width * width) + (height * height)) / Math.sqrt(2);\n }\n const unit = val.substr(-2);\n const num = val.substr(0, val.length - 2);\n // Note that this multiplication turns the string into a number\n return num * typeMap_[unit];\n};\n\n/**\n* Check if an attribute's value is in a valid format.\n* @function module:units.isValidUnit\n* @param {string} attr - The name of the attribute associated with the value\n* @param {string} val - The attribute value to check\n* @param {Element} selectedElement\n* @returns {boolean} Whether the unit is valid\n*/\nexport const isValidUnit = function (attr, val, selectedElement) {\n if (unitAttrs.includes(attr)) {\n // True if it's just a number\n if (!isNaN(val)) {\n return true;\n }\n // Not a number, check if it has a valid unit\n val = val.toLowerCase();\n return Object.keys(typeMap_).some((unit) => {\n const re = new RegExp('^-?[\\\\d\\\\.]+' + unit + '$');\n return re.test(val);\n });\n }\n if (attr === 'id') {\n // if we're trying to change the id, make sure it's not already present in the doc\n // and the id value is valid.\n\n let result = false;\n // because getElem() can throw an exception in the case of an invalid id\n // (according to https://www.w3.org/TR/xml-id/ IDs must be a NCName)\n // we wrap it in an exception and only return true if the ID was valid and\n // not already present\n try {\n const elem = elementContainer_.getElement(val);\n result = (isNullish(elem) || elem === selectedElement);\n } catch (e) {}\n return result;\n }\n return true;\n};\n","/**\n * For command history tracking and undo functionality.\n * @module history\n * @license MIT\n * @copyright 2010 Jeff Schiller\n */\n\nimport {getHref, setHref, getRotationAngle, isNullish} from './utilities.js';\nimport {removeElementFromListMap} from './svgtransformlist.js';\n\n/**\n* Group: Undo/Redo history management.\n*/\nexport const HistoryEventTypes = {\n BEFORE_APPLY: 'before_apply',\n AFTER_APPLY: 'after_apply',\n BEFORE_UNAPPLY: 'before_unapply',\n AFTER_UNAPPLY: 'after_unapply'\n};\n\n// const removedElements = {};\n\n/**\n* Base class for commands.\n*/\nclass Command {\n /**\n * @returns {string}\n */\n getText () {\n return this.text;\n }\n}\n\n// Todo: Figure out why the interface members aren't showing\n// up (with or without modules applied), despite our apparently following\n// http://usejsdoc.org/tags-interface.html#virtual-comments\n\n/**\n * An interface that all command objects must implement.\n * @interface module:history.HistoryCommand\n*/\n/**\n * Applies.\n *\n * @function module:history.HistoryCommand#apply\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void|true}\n */\n/**\n *\n * Unapplies.\n * @function module:history.HistoryCommand#unapply\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void|true}\n */\n/**\n * Returns the elements.\n * @function module:history.HistoryCommand#elements\n * @returns {Element[]}\n */\n/**\n * Gets the text.\n * @function module:history.HistoryCommand#getText\n * @returns {string}\n */\n/**\n * Gives the type.\n * @function module:history.HistoryCommand.type\n * @returns {string}\n */\n/**\n * Gives the type.\n * @function module:history.HistoryCommand#type\n * @returns {string}\n*/\n\n/**\n * @event module:history~Command#event:history\n * @type {module:history.HistoryCommand}\n */\n\n/**\n * An interface for objects that will handle history events.\n * @interface module:history.HistoryEventHandler\n */\n/**\n *\n * @function module:history.HistoryEventHandler#handleHistoryEvent\n * @param {string} eventType One of the HistoryEvent types\n * @param {module:history~Command#event:history} command\n * @listens module:history~Command#event:history\n * @returns {void}\n *\n */\n\n/**\n * History command for an element that had its DOM position changed.\n * @implements {module:history.HistoryCommand}\n*/\nexport class MoveElementCommand extends Command {\n /**\n * @param {Element} elem - The DOM element that was moved\n * @param {Element} oldNextSibling - The element's next sibling before it was moved\n * @param {Element} oldParent - The element's parent before it was moved\n * @param {string} [text] - An optional string visible to user related to this change\n */\n constructor (elem, oldNextSibling, oldParent, text) {\n super();\n this.elem = elem;\n this.text = text ? ('Move ' + elem.tagName + ' to ' + text) : ('Move ' + elem.tagName);\n this.oldNextSibling = oldNextSibling;\n this.oldParent = oldParent;\n this.newNextSibling = elem.nextSibling;\n this.newParent = elem.parentNode;\n }\n /**\n * @returns {\"svgedit.history.MoveElementCommand\"}\n */\n type () { // eslint-disable-line class-methods-use-this\n return 'svgedit.history.MoveElementCommand';\n }\n\n /**\n * Re-positions the element.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n apply (handler) {\n // TODO(codedread): Refactor this common event code into a base HistoryCommand class.\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this);\n }\n\n this.elem = this.newParent.insertBefore(this.elem, this.newNextSibling);\n\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this);\n }\n }\n\n /**\n * Positions the element back to its original location.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n unapply (handler) {\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this);\n }\n\n this.elem = this.oldParent.insertBefore(this.elem, this.oldNextSibling);\n\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this);\n }\n }\n\n /**\n * @returns {Element[]} Array with element associated with this command\n */\n elements () {\n return [this.elem];\n }\n}\nMoveElementCommand.type = MoveElementCommand.prototype.type;\n\n/**\n* History command for an element that was added to the DOM.\n* @implements {module:history.HistoryCommand}\n*/\nexport class InsertElementCommand extends Command {\n /**\n * @param {Element} elem - The newly added DOM element\n * @param {string} text - An optional string visible to user related to this change\n */\n constructor (elem, text) {\n super();\n this.elem = elem;\n this.text = text || ('Create ' + elem.tagName);\n this.parent = elem.parentNode;\n this.nextSibling = this.elem.nextSibling;\n }\n\n /**\n * @returns {\"svgedit.history.InsertElementCommand\"}\n */\n type () { // eslint-disable-line class-methods-use-this\n return 'svgedit.history.InsertElementCommand';\n }\n\n /**\n * Re-inserts the new element.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n apply (handler) {\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this);\n }\n\n this.elem = this.parent.insertBefore(this.elem, this.nextSibling);\n\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this);\n }\n }\n\n /**\n * Removes the element.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n unapply (handler) {\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this);\n }\n\n this.parent = this.elem.parentNode;\n this.elem = this.elem.parentNode.removeChild(this.elem);\n\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this);\n }\n }\n\n /**\n * @returns {Element[]} Array with element associated with this command\n */\n elements () {\n return [this.elem];\n }\n}\nInsertElementCommand.type = InsertElementCommand.prototype.type;\n\n/**\n* History command for an element removed from the DOM.\n* @implements {module:history.HistoryCommand}\n*/\nexport class RemoveElementCommand extends Command {\n /**\n * @param {Element} elem - The removed DOM element\n * @param {Node} oldNextSibling - The DOM element's nextSibling when it was in the DOM\n * @param {Element} oldParent - The DOM element's parent\n * @param {string} [text] - An optional string visible to user related to this change\n */\n constructor (elem, oldNextSibling, oldParent, text) {\n super();\n this.elem = elem;\n this.text = text || ('Delete ' + elem.tagName);\n this.nextSibling = oldNextSibling;\n this.parent = oldParent;\n\n // special hack for webkit: remove this element's entry in the svgTransformLists map\n removeElementFromListMap(elem);\n }\n /**\n * @returns {\"svgedit.history.RemoveElementCommand\"}\n */\n type () { // eslint-disable-line class-methods-use-this\n return 'svgedit.history.RemoveElementCommand';\n }\n\n /**\n * Re-removes the new element.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n apply (handler) {\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this);\n }\n\n removeElementFromListMap(this.elem);\n this.parent = this.elem.parentNode;\n this.elem = this.parent.removeChild(this.elem);\n\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this);\n }\n }\n\n /**\n * Re-adds the new element.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n unapply (handler) {\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this);\n }\n\n removeElementFromListMap(this.elem);\n if (isNullish(this.nextSibling)) {\n if (window.console) {\n console.log('Error: reference element was lost'); // eslint-disable-line no-console\n }\n }\n this.parent.insertBefore(this.elem, this.nextSibling); // Don't use `before` or `prepend` as `this.nextSibling` may be `null`\n\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this);\n }\n }\n\n /**\n * @returns {Element[]} Array with element associated with this command\n */\n elements () {\n return [this.elem];\n }\n}\nRemoveElementCommand.type = RemoveElementCommand.prototype.type;\n\n/**\n* @typedef {\"#text\"|\"#href\"|string} module:history.CommandAttributeName\n*/\n/**\n* @typedef {PlainObject<module:history.CommandAttributeName, string>} module:history.CommandAttributes\n*/\n\n/**\n* History command to make a change to an element.\n* Usually an attribute change, but can also be textcontent.\n* @implements {module:history.HistoryCommand}\n*/\nexport class ChangeElementCommand extends Command {\n /**\n * @param {Element} elem - The DOM element that was changed\n * @param {module:history.CommandAttributes} attrs - Attributes to be changed with the values they had *before* the change\n * @param {string} text - An optional string visible to user related to this change\n */\n constructor (elem, attrs, text) {\n super();\n this.elem = elem;\n this.text = text ? ('Change ' + elem.tagName + ' ' + text) : ('Change ' + elem.tagName);\n this.newValues = {};\n this.oldValues = attrs;\n for (const attr in attrs) {\n if (attr === '#text') {\n this.newValues[attr] = elem.textContent;\n } else if (attr === '#href') {\n this.newValues[attr] = getHref(elem);\n } else {\n this.newValues[attr] = elem.getAttribute(attr);\n }\n }\n }\n /**\n * @returns {\"svgedit.history.ChangeElementCommand\"}\n */\n type () { // eslint-disable-line class-methods-use-this\n return 'svgedit.history.ChangeElementCommand';\n }\n\n /**\n * Performs the stored change action.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {true}\n */\n apply (handler) {\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this);\n }\n\n let bChangedTransform = false;\n Object.entries(this.newValues).forEach(([attr, value]) => {\n if (value) {\n if (attr === '#text') {\n this.elem.textContent = value;\n } else if (attr === '#href') {\n setHref(this.elem, value);\n } else {\n this.elem.setAttribute(attr, value);\n }\n } else if (attr === '#text') {\n this.elem.textContent = '';\n } else {\n this.elem.setAttribute(attr, '');\n this.elem.removeAttribute(attr);\n }\n\n if (attr === 'transform') { bChangedTransform = true; }\n });\n\n // relocate rotational transform, if necessary\n if (!bChangedTransform) {\n const angle = getRotationAngle(this.elem);\n if (angle) {\n const bbox = this.elem.getBBox();\n const cx = bbox.x + bbox.width / 2,\n cy = bbox.y + bbox.height / 2;\n const rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');\n if (rotate !== this.elem.getAttribute('transform')) {\n this.elem.setAttribute('transform', rotate);\n }\n }\n }\n\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this);\n }\n\n return true;\n }\n\n /**\n * Reverses the stored change action.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {true}\n */\n unapply (handler) {\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this);\n }\n\n let bChangedTransform = false;\n Object.entries(this.oldValues).forEach(([attr, value]) => {\n if (value) {\n if (attr === '#text') {\n this.elem.textContent = value;\n } else if (attr === '#href') {\n setHref(this.elem, value);\n } else {\n this.elem.setAttribute(attr, value);\n }\n } else if (attr === '#text') {\n this.elem.textContent = '';\n } else {\n this.elem.removeAttribute(attr);\n }\n if (attr === 'transform') { bChangedTransform = true; }\n });\n // relocate rotational transform, if necessary\n if (!bChangedTransform) {\n const angle = getRotationAngle(this.elem);\n if (angle) {\n const bbox = this.elem.getBBox();\n const cx = bbox.x + bbox.width / 2,\n cy = bbox.y + bbox.height / 2;\n const rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');\n if (rotate !== this.elem.getAttribute('transform')) {\n this.elem.setAttribute('transform', rotate);\n }\n }\n }\n\n // Remove transformlist to prevent confusion that causes bugs like 575.\n removeElementFromListMap(this.elem);\n\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this);\n }\n\n return true;\n }\n\n /**\n * @returns {Element[]} Array with element associated with this command\n */\n elements () {\n return [this.elem];\n }\n}\nChangeElementCommand.type = ChangeElementCommand.prototype.type;\n\n// TODO: create a 'typing' command object that tracks changes in text\n// if a new Typing command is created and the top command on the stack is also a Typing\n// and they both affect the same element, then collapse the two commands into one\n\n/**\n* History command that can contain/execute multiple other commands.\n* @implements {module:history.HistoryCommand}\n*/\nexport class BatchCommand extends Command {\n /**\n * @param {string} [text] - An optional string visible to user related to this change\n */\n constructor (text) {\n super();\n this.text = text || 'Batch Command';\n this.stack = [];\n }\n\n /**\n * @returns {\"svgedit.history.BatchCommand\"}\n */\n type () { // eslint-disable-line class-methods-use-this\n return 'svgedit.history.BatchCommand';\n }\n\n /**\n * Runs \"apply\" on all subcommands.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n apply (handler) {\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.BEFORE_APPLY, this);\n }\n\n const len = this.stack.length;\n for (let i = 0; i < len; ++i) {\n this.stack[i].apply(handler);\n }\n\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.AFTER_APPLY, this);\n }\n }\n\n /**\n * Runs \"unapply\" on all subcommands.\n * @param {module:history.HistoryEventHandler} handler\n * @fires module:history~Command#event:history\n * @returns {void}\n */\n unapply (handler) {\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.BEFORE_UNAPPLY, this);\n }\n\n for (let i = this.stack.length - 1; i >= 0; i--) {\n this.stack[i].unapply(handler);\n }\n\n if (handler) {\n handler.handleHistoryEvent(HistoryEventTypes.AFTER_UNAPPLY, this);\n }\n }\n\n /**\n * Iterate through all our subcommands.\n * @returns {Element[]} All the elements we are changing\n */\n elements () {\n const elems = [];\n let cmd = this.stack.length;\n while (cmd--) {\n const thisElems = this.stack[cmd].elements();\n let elem = thisElems.length;\n while (elem--) {\n if (!elems.includes(thisElems[elem])) { elems.push(thisElems[elem]); }\n }\n }\n return elems;\n }\n\n /**\n * Adds a given command to the history stack.\n * @param {Command} cmd - The undo command object to add\n * @returns {void}\n */\n addSubCommand (cmd) {\n this.stack.push(cmd);\n }\n\n /**\n * @returns {boolean} Indicates whether or not the batch command is empty\n */\n isEmpty () {\n return !this.stack.length;\n }\n}\nBatchCommand.type = BatchCommand.prototype.type;\n\n/**\n*\n*/\nexport class UndoManager {\n /**\n * @param {module:history.HistoryEventHandler} historyEventHandler\n */\n constructor (historyEventHandler) {\n this.handler_ = historyEventHandler || null;\n this.undoStackPointer = 0;\n this.undoStack = [];\n\n // this is the stack that stores the original values, the elements and\n // the attribute name for begin/finish\n this.undoChangeStackPointer = -1;\n this.undoableChangeStack = [];\n }\n\n /**\n * Resets the undo stack, effectively clearing the undo/redo history.\n * @returns {void}\n */\n resetUndoStack () {\n this.undoStack = [];\n this.undoStackPointer = 0;\n }\n\n /**\n * @returns {Integer} Current size of the undo history stack\n */\n getUndoStackSize () {\n return this.undoStackPointer;\n }\n\n /**\n * @returns {Integer} Current size of the redo history stack\n */\n getRedoStackSize () {\n return this.undoStack.length - this.undoStackPointer;\n }\n\n /**\n * @returns {string} String associated with the next undo command\n */\n getNextUndoCommandText () {\n return this.undoStackPointer > 0 ? this.undoStack[this.undoStackPointer - 1].getText() : '';\n }\n\n /**\n * @returns {string} String associated with the next redo command\n */\n getNextRedoCommandText () {\n return this.undoStackPointer < this.undoStack.length ? this.undoStack[this.undoStackPointer].getText() : '';\n }\n\n /**\n * Performs an undo step.\n * @returns {void}\n */\n undo () {\n if (this.undoStackPointer > 0) {\n const cmd = this.undoStack[--this.undoStackPointer];\n cmd.unapply(this.handler_);\n }\n }\n\n /**\n * Performs a redo step.\n * @returns {void}\n */\n redo () {\n if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) {\n const cmd = this.undoStack[this.undoStackPointer++];\n cmd.apply(this.handler_);\n }\n }\n\n /**\n * Adds a command object to the undo history stack.\n * @param {Command} cmd - The command object to add\n * @returns {void}\n */\n addCommandToHistory (cmd) {\n // TODO: we MUST compress consecutive text changes to the same element\n // (right now each keystroke is saved as a separate command that includes the\n // entire text contents of the text element)\n // TODO: consider limiting the history that we store here (need to do some slicing)\n\n // if our stack pointer is not at the end, then we have to remove\n // all commands after the pointer and insert the new command\n if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) {\n this.undoStack = this.undoStack.splice(0, this.undoStackPointer);\n }\n this.undoStack.push(cmd);\n this.undoStackPointer = this.undoStack.length;\n }\n\n /**\n * This function tells the canvas to remember the old values of the\n * `attrName` attribute for each element sent in. The elements and values\n * are stored on a stack, so the next call to `finishUndoableChange()` will\n * pop the elements and old values off the stack, gets the current values\n * from the DOM and uses all of these to construct the undo-able command.\n * @param {string} attrName - The name of the attribute being changed\n * @param {Element[]} elems - Array of DOM elements being changed\n * @returns {void}\n */\n beginUndoableChange (attrName, elems) {\n const p = ++this.undoChangeStackPointer;\n let i = elems.length;\n const oldValues = new Array(i), elements = new Array(i);\n while (i--) {\n const elem = elems[i];\n if (isNullish(elem)) { continue; }\n elements[i] = elem;\n oldValues[i] = elem.getAttribute(attrName);\n }\n this.undoableChangeStack[p] = {\n attrName,\n oldValues,\n elements\n };\n }\n\n /**\n * This function returns a `BatchCommand` object which summarizes the\n * change since `beginUndoableChange` was called. The command can then\n * be added to the command history.\n * @returns {BatchCommand} Batch command object with resulting changes\n */\n finishUndoableChange () {\n const p = this.undoChangeStackPointer--;\n const changeset = this.undoableChangeStack[p];\n const {attrName} = changeset;\n const batchCmd = new BatchCommand('Change ' + attrName);\n let i = changeset.elements.length;\n while (i--) {\n const elem = changeset.elements[i];\n if (isNullish(elem)) { continue; }\n const changes = {};\n changes[attrName] = changeset.oldValues[i];\n if (changes[attrName] !== elem.getAttribute(attrName)) {\n batchCmd.addSubCommand(new ChangeElementCommand(elem, changes, attrName));\n }\n }\n this.undoableChangeStack[p] = null;\n return batchCmd;\n }\n}\n","/* globals jQuery */\n/**\n * Path functionality.\n * @module path\n * @license MIT\n *\n * @copyright 2011 Alexis Deveria, 2011 Jeff Schiller\n */\n\nimport './svgpathseg.js';\nimport {NS} from './namespaces.js';\nimport {getTransformList} from './svgtransformlist.js';\nimport {shortFloat} from './units.js';\nimport {ChangeElementCommand, BatchCommand} from './history.js';\nimport {\n transformPoint, getMatrix, snapToAngle, rectsIntersect,\n transformListToTransform\n} from './math.js';\nimport {\n assignAttributes, getElem, getRotationAngle, getBBox,\n getRefElem, findDefs, snapToGrid, isNullish,\n getBBox as utilsGetBBox\n} from './utilities.js';\nimport {\n supportsPathInsertItemBefore, supportsPathReplaceItem, isWebkit\n} from './browser.js';\n\nconst $ = jQuery;\n\nconst segData = {\n 2: ['x', 'y'], // PATHSEG_MOVETO_ABS\n 4: ['x', 'y'], // PATHSEG_LINETO_ABS\n 6: ['x', 'y', 'x1', 'y1', 'x2', 'y2'], // PATHSEG_CURVETO_CUBIC_ABS\n 8: ['x', 'y', 'x1', 'y1'], // PATHSEG_CURVETO_QUADRATIC_ABS\n 10: ['x', 'y', 'r1', 'r2', 'angle', 'largeArcFlag', 'sweepFlag'], // PATHSEG_ARC_ABS\n 12: ['x'], // PATHSEG_LINETO_HORIZONTAL_ABS\n 14: ['y'], // PATHSEG_LINETO_VERTICAL_ABS\n 16: ['x', 'y', 'x2', 'y2'], // PATHSEG_CURVETO_CUBIC_SMOOTH_ABS\n 18: ['x', 'y'] // PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS\n};\n\n/**\n * @tutorial LocaleDocs\n * @typedef {module:locale.LocaleStrings|PlainObject} module:path.uiStrings\n * @property {PlainObject<string, string>} ui\n*/\n\nconst uiStrings = {};\n/**\n* @function module:path.setUiStrings\n* @param {module:path.uiStrings} strs\n* @returns {void}\n*/\nexport const setUiStrings = function (strs) {\n Object.assign(uiStrings, strs.ui);\n};\n\nlet pathFuncs = [];\n\nlet linkControlPts = true;\n\n// Stores references to paths via IDs.\n// TODO: Make this cross-document happy.\nlet pathData = {};\n\n/**\n* @function module:path.setLinkControlPoints\n* @param {boolean} lcp\n* @returns {void}\n*/\nexport const setLinkControlPoints = function (lcp) {\n linkControlPts = lcp;\n};\n\n/**\n * @name module:path.path\n * @type {null|module:path.Path}\n * @memberof module:path\n*/\nexport let path = null; // eslint-disable-line import/no-mutable-exports\n\nlet editorContext_ = null;\n\n/**\n* @external MouseEvent\n*/\n\n/**\n* Object with the following keys/values.\n* @typedef {PlainObject} module:path.SVGElementJSON\n* @property {string} element - Tag name of the SVG element to create\n* @property {PlainObject<string, string>} attr - Has key-value attributes to assign to the new element. An `id` should be set so that {@link module:utilities.EditorContext#addSVGElementFromJson} can later re-identify the element for modification or replacement.\n* @property {boolean} [curStyles=false] - Indicates whether current style attributes should be applied first\n* @property {module:path.SVGElementJSON[]} [children] - Data objects to be added recursively as children\n* @property {string} [namespace=\"http://www.w3.org/2000/svg\"] - Indicate a (non-SVG) namespace\n*/\n/**\n * @interface module:path.EditorContext\n * @property {module:select.SelectorManager} selectorManager\n * @property {module:svgcanvas.SvgCanvas} canvas\n */\n/**\n * @function module:path.EditorContext#call\n * @param {\"selected\"|\"changed\"} ev - String with the event name\n * @param {module:svgcanvas.SvgCanvas#event:selected|module:svgcanvas.SvgCanvas#event:changed} arg - Argument to pass through to the callback function. If the event is \"changed\", an array of `Element`s is passed; if \"selected\", a single-item array of `Element` is passed.\n * @returns {void}\n */\n/**\n * @function module:path.EditorContext#resetD\n * @param {SVGPathElement} p\n * @returns {void}\n*/\n/**\n * Note: This doesn't round to an integer necessarily.\n * @function module:path.EditorContext#round\n * @param {Float} val\n * @returns {Float} Rounded value to nearest value based on `currentZoom`\n */\n/**\n * @function module:path.EditorContext#clearSelection\n * @param {boolean} [noCall] - When `true`, does not call the \"selected\" handler\n * @returns {void}\n*/\n/**\n * @function module:path.EditorContext#addToSelection\n * @param {Element[]} elemsToAdd - An array of DOM elements to add to the selection\n * @param {boolean} showGrips - Indicates whether the resize grips should be shown\n * @returns {void}\n*/\n/**\n * @function module:path.EditorContext#addCommandToHistory\n * @param {Command} cmd\n * @returns {void}\n */\n/**\n * @function module:path.EditorContext#remapElement\n * @param {Element} selected - DOM element to be changed\n * @param {PlainObject<string, string>} changes - Object with changes to be remapped\n * @param {SVGMatrix} m - Matrix object to use for remapping coordinates\n * @returns {void}\n */\n/**\n * @function module:path.EditorContext#addSVGElementFromJson\n * @param {module:path.SVGElementJSON} data\n * @returns {Element} The new element\n*/\n/**\n * @function module:path.EditorContext#getGridSnapping\n * @returns {boolean}\n */\n/**\n * @function module:path.EditorContext#getOpacity\n * @returns {Float}\n */\n/**\n * @function module:path.EditorContext#getSelectedElements\n * @returns {Element[]} the array with selected DOM elements\n*/\n/**\n * @function module:path.EditorContext#getContainer\n * @returns {Element}\n */\n/**\n * @function module:path.EditorContext#setStarted\n * @param {boolean} s\n * @returns {void}\n */\n/**\n * @function module:path.EditorContext#getRubberBox\n * @returns {SVGRectElement}\n*/\n/**\n * @function module:path.EditorContext#setRubberBox\n * @param {SVGRectElement} rb\n * @returns {SVGRectElement} Same as parameter passed in\n */\n/**\n * @function module:path.EditorContext#addPtsToSelection\n * @param {PlainObject} cfg\n * @param {boolean} cfg.closedSubpath\n * @param {SVGCircleElement[]} cfg.grips\n * @returns {void}\n */\n/**\n * @function module:path.EditorContext#endChanges\n * @param {PlainObject} cfg\n * @param {string} cfg.cmd\n * @param {Element} cfg.elem\n * @returns {void}\n*/\n/**\n * @function module:path.EditorContext#getCurrentZoom\n * @returns {Float} The current zoom level\n */\n/**\n * Returns the last created DOM element ID string.\n * @function module:path.EditorContext#getId\n * @returns {string}\n */\n/**\n * Creates and returns a unique ID string for a DOM element.\n * @function module:path.EditorContext#getNextId\n * @returns {string}\n*/\n/**\n * Gets the desired element from a mouse event.\n * @function module:path.EditorContext#getMouseTarget\n * @param {external:MouseEvent} evt - Event object from the mouse event\n * @returns {Element} DOM element we want\n */\n/**\n * @function module:path.EditorContext#getCurrentMode\n * @returns {string}\n */\n/**\n * @function module:path.EditorContext#setCurrentMode\n * @param {string} cm The mode\n * @returns {string} The same mode as passed in\n*/\n/**\n * @function module:path.EditorContext#getDrawnPath\n * @returns {SVGPathElement|null}\n */\n/**\n * @function module:path.EditorContext#setDrawnPath\n * @param {SVGPathElement|null} dp\n * @returns {SVGPathElement|null} The same value as passed in\n */\n/**\n * @function module:path.EditorContext#getSVGRoot\n * @returns {SVGSVGElement}\n*/\n\n/**\n* @function module:path.init\n* @param {module:path.EditorContext} editorContext\n* @returns {void}\n*/\nexport const init = function (editorContext) {\n editorContext_ = editorContext;\n\n pathFuncs = [0, 'ClosePath'];\n const pathFuncsStrs = [\n 'Moveto', 'Lineto', 'CurvetoCubic', 'CurvetoQuadratic', 'Arc',\n 'LinetoHorizontal', 'LinetoVertical', 'CurvetoCubicSmooth', 'CurvetoQuadraticSmooth'\n ];\n $.each(pathFuncsStrs, function (i, s) {\n pathFuncs.push(s + 'Abs');\n pathFuncs.push(s + 'Rel');\n });\n};\n\n/**\n* @function module:path.insertItemBefore\n* @param {Element} elem\n* @param {Segment} newseg\n* @param {Integer} index\n* @returns {void}\n*/\nexport const insertItemBefore = function (elem, newseg, index) {\n // Support insertItemBefore on paths for FF2\n const list = elem.pathSegList;\n\n if (supportsPathInsertItemBefore()) {\n list.insertItemBefore(newseg, index);\n return;\n }\n const len = list.numberOfItems;\n const arr = [];\n for (let i = 0; i < len; i++) {\n const curSeg = list.getItem(i);\n arr.push(curSeg);\n }\n list.clear();\n for (let i = 0; i < len; i++) {\n if (i === index) { // index + 1\n list.appendItem(newseg);\n }\n list.appendItem(arr[i]);\n }\n};\n\n/**\n* @function module:path.ptObjToArr\n* @todo See if this should just live in `replacePathSeg`\n* @param {string} type\n* @param {SVGPathSegMovetoAbs|SVGPathSegLinetoAbs|SVGPathSegCurvetoCubicAbs|SVGPathSegCurvetoQuadraticAbs|SVGPathSegArcAbs|SVGPathSegLinetoHorizontalAbs|SVGPathSegLinetoVerticalAbs|SVGPathSegCurvetoCubicSmoothAbs|SVGPathSegCurvetoQuadraticSmoothAbs} segItem\n* @returns {ArgumentsArray}\n*/\nexport const ptObjToArr = function (type, segItem) {\n const props = segData[type];\n return props.map((prop) => {\n return segItem[prop];\n });\n};\n\n/**\n* @function module:path.getGripPt\n* @param {Segment} seg\n* @param {module:math.XYObject} altPt\n* @returns {module:math.XYObject}\n*/\nexport const getGripPt = function (seg, altPt) {\n const {path: pth} = seg;\n let out = {\n x: altPt ? altPt.x : seg.item.x,\n y: altPt ? altPt.y : seg.item.y\n };\n\n if (pth.matrix) {\n const pt = transformPoint(out.x, out.y, pth.matrix);\n out = pt;\n }\n\n const currentZoom = editorContext_.getCurrentZoom();\n out.x *= currentZoom;\n out.y *= currentZoom;\n\n return out;\n};\n\n/**\n* @function module:path.getPointFromGrip\n* @param {module:math.XYObject} pt\n* @param {module:path.Path} pth\n* @returns {module:math.XYObject}\n*/\nexport const getPointFromGrip = function (pt, pth) {\n const out = {\n x: pt.x,\n y: pt.y\n };\n\n if (pth.matrix) {\n pt = transformPoint(out.x, out.y, pth.imatrix);\n out.x = pt.x;\n out.y = pt.y;\n }\n\n const currentZoom = editorContext_.getCurrentZoom();\n out.x /= currentZoom;\n out.y /= currentZoom;\n\n return out;\n};\n\n/**\n* Requires prior call to `setUiStrings` if `xlink:title`\n* to be set on the grip.\n* @function module:path.addPointGrip\n* @param {Integer} index\n* @param {Integer} x\n* @param {Integer} y\n* @returns {SVGCircleElement}\n*/\nexport const addPointGrip = function (index, x, y) {\n // create the container of all the point grips\n const pointGripContainer = getGripContainer();\n\n let pointGrip = getElem('pathpointgrip_' + index);\n // create it\n if (!pointGrip) {\n pointGrip = document.createElementNS(NS.SVG, 'circle');\n const atts = {\n id: 'pathpointgrip_' + index,\n display: 'none',\n r: 4,\n fill: '#0FF',\n stroke: '#00F',\n 'stroke-width': 2,\n cursor: 'move',\n style: 'pointer-events:all'\n };\n if ('pathNodeTooltip' in uiStrings) { // May be empty if running path.js without svg-editor\n atts['xlink:title'] = uiStrings.pathNodeTooltip;\n }\n assignAttributes(pointGrip, atts);\n pointGrip = pointGripContainer.appendChild(pointGrip);\n\n const grip = $('#pathpointgrip_' + index);\n grip.dblclick(function () {\n if (path) {\n path.setSegType();\n }\n });\n }\n if (x && y) {\n // set up the point grip element and display it\n assignAttributes(pointGrip, {\n cx: x,\n cy: y,\n display: 'inline'\n });\n }\n return pointGrip;\n};\n\n/**\n* @function module:path.getGripContainer\n* @returns {Element}\n*/\nexport const getGripContainer = function () {\n let c = getElem('pathpointgrip_container');\n if (!c) {\n const parentElement = getElem('selectorParentGroup');\n c = parentElement.appendChild(document.createElementNS(NS.SVG, 'g'));\n c.id = 'pathpointgrip_container';\n }\n return c;\n};\n\n/**\n* Requires prior call to `setUiStrings` if `xlink:title`\n* to be set on the grip.\n* @function module:path.addCtrlGrip\n* @param {string} id\n* @returns {SVGCircleElement}\n*/\nexport const addCtrlGrip = function (id) {\n let pointGrip = getElem('ctrlpointgrip_' + id);\n if (pointGrip) { return pointGrip; }\n\n pointGrip = document.createElementNS(NS.SVG, 'circle');\n const atts = {\n id: 'ctrlpointgrip_' + id,\n display: 'none',\n r: 4,\n fill: '#0FF',\n stroke: '#55F',\n 'stroke-width': 1,\n cursor: 'move',\n style: 'pointer-events:all'\n };\n if ('pathCtrlPtTooltip' in uiStrings) { // May be empty if running path.js without svg-editor\n atts['xlink:title'] = uiStrings.pathCtrlPtTooltip;\n }\n assignAttributes(pointGrip, atts);\n getGripContainer().append(pointGrip);\n return pointGrip;\n};\n\n/**\n* @function module:path.getCtrlLine\n* @param {string} id\n* @returns {SVGLineElement}\n*/\nexport const getCtrlLine = function (id) {\n let ctrlLine = getElem('ctrlLine_' + id);\n if (ctrlLine) { return ctrlLine; }\n\n ctrlLine = document.createElementNS(NS.SVG, 'line');\n assignAttributes(ctrlLine, {\n id: 'ctrlLine_' + id,\n stroke: '#555',\n 'stroke-width': 1,\n style: 'pointer-events:none'\n });\n getGripContainer().append(ctrlLine);\n return ctrlLine;\n};\n\n/**\n* @function module:path.getPointGrip\n* @param {Segment} seg\n* @param {boolean} update\n* @returns {SVGCircleElement}\n*/\nexport const getPointGrip = function (seg, update) {\n const {index} = seg;\n const pointGrip = addPointGrip(index);\n\n if (update) {\n const pt = getGripPt(seg);\n assignAttributes(pointGrip, {\n cx: pt.x,\n cy: pt.y,\n display: 'inline'\n });\n }\n\n return pointGrip;\n};\n\n/**\n* @function module:path.getControlPoints\n* @param {Segment} seg\n* @returns {PlainObject<string, SVGLineElement|SVGCircleElement>}\n*/\nexport const getControlPoints = function (seg) {\n const {item, index} = seg;\n if (!('x1' in item) || !('x2' in item)) { return null; }\n const cpt = {};\n /* const pointGripContainer = */ getGripContainer();\n\n // Note that this is intentionally not seg.prev.item\n const prev = path.segs[index - 1].item;\n\n const segItems = [prev, item];\n\n for (let i = 1; i < 3; i++) {\n const id = index + 'c' + i;\n\n const ctrlLine = cpt['c' + i + '_line'] = getCtrlLine(id);\n\n const pt = getGripPt(seg, {x: item['x' + i], y: item['y' + i]});\n const gpt = getGripPt(seg, {x: segItems[i - 1].x, y: segItems[i - 1].y});\n\n assignAttributes(ctrlLine, {\n x1: pt.x,\n y1: pt.y,\n x2: gpt.x,\n y2: gpt.y,\n display: 'inline'\n });\n\n cpt['c' + i + '_line'] = ctrlLine;\n\n // create it\n const pointGrip = cpt['c' + i] = addCtrlGrip(id);\n\n assignAttributes(pointGrip, {\n cx: pt.x,\n cy: pt.y,\n display: 'inline'\n });\n cpt['c' + i] = pointGrip;\n }\n return cpt;\n};\n\n/**\n* This replaces the segment at the given index. Type is given as number.\n* @function module:path.replacePathSeg\n* @param {Integer} type Possible values set during {@link module:path.init}\n* @param {Integer} index\n* @param {ArgumentsArray} pts\n* @param {SVGPathElement} elem\n* @returns {void}\n*/\nexport const replacePathSeg = function (type, index, pts, elem) {\n const pth = elem || path.elem;\n\n const func = 'createSVGPathSeg' + pathFuncs[type];\n const seg = pth[func](...pts);\n\n if (supportsPathReplaceItem()) {\n pth.pathSegList.replaceItem(seg, index);\n } else {\n const segList = pth.pathSegList;\n const len = segList.numberOfItems;\n const arr = [];\n for (let i = 0; i < len; i++) {\n const curSeg = segList.getItem(i);\n arr.push(curSeg);\n }\n segList.clear();\n for (let i = 0; i < len; i++) {\n if (i === index) {\n segList.appendItem(seg);\n } else {\n segList.appendItem(arr[i]);\n }\n }\n }\n};\n\n/**\n* @function module:path.getSegSelector\n* @param {Segment} seg\n* @param {boolean} update\n* @returns {SVGPathElement}\n*/\nexport const getSegSelector = function (seg, update) {\n const {index} = seg;\n let segLine = getElem('segline_' + index);\n if (!segLine) {\n const pointGripContainer = getGripContainer();\n // create segline\n segLine = document.createElementNS(NS.SVG, 'path');\n assignAttributes(segLine, {\n id: 'segline_' + index,\n display: 'none',\n fill: 'none',\n stroke: '#0FF',\n 'stroke-width': 2,\n style: 'pointer-events:none',\n d: 'M0,0 0,0'\n });\n pointGripContainer.append(segLine);\n }\n\n if (update) {\n const {prev} = seg;\n if (!prev) {\n segLine.setAttribute('display', 'none');\n return segLine;\n }\n\n const pt = getGripPt(prev);\n // Set start point\n replacePathSeg(2, 0, [pt.x, pt.y], segLine);\n\n const pts = ptObjToArr(seg.type, seg.item); // , true);\n for (let i = 0; i < pts.length; i += 2) {\n const point = getGripPt(seg, {x: pts[i], y: pts[i + 1]});\n pts[i] = point.x;\n pts[i + 1] = point.y;\n }\n\n replacePathSeg(seg.type, 1, pts, segLine);\n }\n return segLine;\n};\n\n/**\n * @typedef {PlainObject} Point\n * @property {Integer} x The x value\n * @property {Integer} y The y value\n */\n\n/**\n* Takes three points and creates a smoother line based on them.\n* @function module:path.smoothControlPoints\n* @param {Point} ct1 - Object with x and y values (first control point)\n* @param {Point} ct2 - Object with x and y values (second control point)\n* @param {Point} pt - Object with x and y values (third point)\n* @returns {Point[]} Array of two \"smoothed\" point objects\n*/\nexport const smoothControlPoints = function (ct1, ct2, pt) {\n // each point must not be the origin\n const x1 = ct1.x - pt.x,\n y1 = ct1.y - pt.y,\n x2 = ct2.x - pt.x,\n y2 = ct2.y - pt.y;\n\n if ((x1 !== 0 || y1 !== 0) && (x2 !== 0 || y2 !== 0)) {\n const\n r1 = Math.sqrt(x1 * x1 + y1 * y1),\n r2 = Math.sqrt(x2 * x2 + y2 * y2),\n nct1 = editorContext_.getSVGRoot().createSVGPoint(),\n nct2 = editorContext_.getSVGRoot().createSVGPoint();\n let anglea = Math.atan2(y1, x1),\n angleb = Math.atan2(y2, x2);\n if (anglea < 0) { anglea += 2 * Math.PI; }\n if (angleb < 0) { angleb += 2 * Math.PI; }\n\n const angleBetween = Math.abs(anglea - angleb),\n angleDiff = Math.abs(Math.PI - angleBetween) / 2;\n\n let newAnglea, newAngleb;\n if (anglea - angleb > 0) {\n newAnglea = angleBetween < Math.PI ? (anglea + angleDiff) : (anglea - angleDiff);\n newAngleb = angleBetween < Math.PI ? (angleb - angleDiff) : (angleb + angleDiff);\n } else {\n newAnglea = angleBetween < Math.PI ? (anglea - angleDiff) : (anglea + angleDiff);\n newAngleb = angleBetween < Math.PI ? (angleb + angleDiff) : (angleb - angleDiff);\n }\n\n // rotate the points\n nct1.x = r1 * Math.cos(newAnglea) + pt.x;\n nct1.y = r1 * Math.sin(newAnglea) + pt.y;\n nct2.x = r2 * Math.cos(newAngleb) + pt.x;\n nct2.y = r2 * Math.sin(newAngleb) + pt.y;\n\n return [nct1, nct2];\n }\n return undefined;\n};\n\n/**\n*\n*/\nexport class Segment {\n /**\n * @param {Integer} index\n * @param {SVGPathSeg} item\n * @todo Is `item` be more constrained here?\n */\n constructor (index, item) {\n this.selected = false;\n this.index = index;\n this.item = item;\n this.type = item.pathSegType;\n\n this.ctrlpts = [];\n this.ptgrip = null;\n this.segsel = null;\n }\n\n /**\n * @param {boolean} y\n * @returns {void}\n */\n showCtrlPts (y) {\n for (const i in this.ctrlpts) {\n if ({}.hasOwnProperty.call(this.ctrlpts, i)) {\n this.ctrlpts[i].setAttribute('display', y ? 'inline' : 'none');\n }\n }\n }\n\n /**\n * @param {boolean} y\n * @returns {void}\n */\n selectCtrls (y) {\n $('#ctrlpointgrip_' + this.index + 'c1, #ctrlpointgrip_' + this.index + 'c2')\n .attr('fill', y ? '#0FF' : '#EEE');\n }\n\n /**\n * @param {boolean} y\n * @returns {void}\n */\n show (y) {\n if (this.ptgrip) {\n this.ptgrip.setAttribute('display', y ? 'inline' : 'none');\n this.segsel.setAttribute('display', y ? 'inline' : 'none');\n // Show/hide all control points if available\n this.showCtrlPts(y);\n }\n }\n\n /**\n * @param {boolean} y\n * @returns {void}\n */\n select (y) {\n if (this.ptgrip) {\n this.ptgrip.setAttribute('stroke', y ? '#0FF' : '#00F');\n this.segsel.setAttribute('display', y ? 'inline' : 'none');\n if (this.ctrlpts) {\n this.selectCtrls(y);\n }\n this.selected = y;\n }\n }\n\n /**\n * @returns {void}\n */\n addGrip () {\n this.ptgrip = getPointGrip(this, true);\n this.ctrlpts = getControlPoints(this); // , true);\n this.segsel = getSegSelector(this, true);\n }\n\n /**\n * @param {boolean} full\n * @returns {void}\n */\n update (full) {\n if (this.ptgrip) {\n const pt = getGripPt(this);\n assignAttributes(this.ptgrip, {\n cx: pt.x,\n cy: pt.y\n });\n\n getSegSelector(this, true);\n\n if (this.ctrlpts) {\n if (full) {\n this.item = path.elem.pathSegList.getItem(this.index);\n this.type = this.item.pathSegType;\n }\n getControlPoints(this);\n }\n // this.segsel.setAttribute('display', y ? 'inline' : 'none');\n }\n }\n\n /**\n * @param {Integer} dx\n * @param {Integer} dy\n * @returns {void}\n */\n move (dx, dy) {\n const {item} = this;\n\n const curPts = this.ctrlpts\n ? [\n item.x += dx, item.y += dy,\n item.x1, item.y1, item.x2 += dx, item.y2 += dy\n ]\n : [item.x += dx, item.y += dy];\n\n replacePathSeg(\n this.type,\n this.index,\n // type 10 means ARC\n this.type === 10 ? ptObjToArr(this.type, item) : curPts\n );\n\n if (this.next && this.next.ctrlpts) {\n const next = this.next.item;\n const nextPts = [\n next.x, next.y,\n next.x1 += dx, next.y1 += dy, next.x2, next.y2\n ];\n replacePathSeg(this.next.type, this.next.index, nextPts);\n }\n\n if (this.mate) {\n // The last point of a closed subpath has a 'mate',\n // which is the 'M' segment of the subpath\n const {item: itm} = this.mate;\n const pts = [itm.x += dx, itm.y += dy];\n replacePathSeg(this.mate.type, this.mate.index, pts);\n // Has no grip, so does not need 'updating'?\n }\n\n this.update(true);\n if (this.next) { this.next.update(true); }\n }\n\n /**\n * @param {Integer} num\n * @returns {void}\n */\n setLinked (num) {\n let seg, anum, pt;\n if (num === 2) {\n anum = 1;\n seg = this.next;\n if (!seg) { return; }\n pt = this.item;\n } else {\n anum = 2;\n seg = this.prev;\n if (!seg) { return; }\n pt = seg.item;\n }\n\n const {item} = seg;\n item['x' + anum] = pt.x + (pt.x - this.item['x' + num]);\n item['y' + anum] = pt.y + (pt.y - this.item['y' + num]);\n\n const pts = [\n item.x, item.y,\n item.x1, item.y1,\n item.x2, item.y2\n ];\n\n replacePathSeg(seg.type, seg.index, pts);\n seg.update(true);\n }\n\n /**\n * @param {Integer} num\n * @param {Integer} dx\n * @param {Integer} dy\n * @returns {void}\n */\n moveCtrl (num, dx, dy) {\n const {item} = this;\n item['x' + num] += dx;\n item['y' + num] += dy;\n\n const pts = [\n item.x, item.y,\n item.x1, item.y1, item.x2, item.y2\n ];\n\n replacePathSeg(this.type, this.index, pts);\n this.update(true);\n }\n\n /**\n * @param {Integer} newType Possible values set during {@link module:path.init}\n * @param {ArgumentsArray} pts\n * @returns {void}\n */\n setType (newType, pts) {\n replacePathSeg(newType, this.index, pts);\n this.type = newType;\n this.item = path.elem.pathSegList.getItem(this.index);\n this.showCtrlPts(newType === 6);\n this.ctrlpts = getControlPoints(this);\n this.update(true);\n }\n}\n\n/**\n*\n*/\nexport class Path {\n /**\n * @param {SVGPathElement} elem\n * @throws {Error} If constructed without a path element\n */\n constructor (elem) {\n if (!elem || elem.tagName !== 'path') {\n throw new Error('svgedit.path.Path constructed without a <path> element');\n }\n\n this.elem = elem;\n this.segs = [];\n this.selected_pts = [];\n path = this; // eslint-disable-line consistent-this\n\n this.init();\n }\n\n /**\n * Reset path data.\n * @returns {module:path.Path}\n */\n init () {\n // Hide all grips, etc\n\n // fixed, needed to work on all found elements, not just first\n $(getGripContainer()).find('*').each(function () {\n $(this).attr('display', 'none');\n });\n\n const segList = this.elem.pathSegList;\n const len = segList.numberOfItems;\n this.segs = [];\n this.selected_pts = [];\n this.first_seg = null;\n\n // Set up segs array\n for (let i = 0; i < len; i++) {\n const item = segList.getItem(i);\n const segment = new Segment(i, item);\n segment.path = this;\n this.segs.push(segment);\n }\n\n const {segs} = this;\n\n let startI = null;\n for (let i = 0; i < len; i++) {\n const seg = segs[i];\n const nextSeg = (i + 1) >= len ? null : segs[i + 1];\n const prevSeg = (i - 1) < 0 ? null : segs[i - 1];\n if (seg.type === 2) {\n if (prevSeg && prevSeg.type !== 1) {\n // New sub-path, last one is open,\n // so add a grip to last sub-path's first point\n const startSeg = segs[startI];\n startSeg.next = segs[startI + 1];\n startSeg.next.prev = startSeg;\n startSeg.addGrip();\n }\n // Remember that this is a starter seg\n startI = i;\n } else if (nextSeg && nextSeg.type === 1) {\n // This is the last real segment of a closed sub-path\n // Next is first seg after \"M\"\n seg.next = segs[startI + 1];\n\n // First seg after \"M\"'s prev is this\n seg.next.prev = seg;\n seg.mate = segs[startI];\n seg.addGrip();\n if (isNullish(this.first_seg)) {\n this.first_seg = seg;\n }\n } else if (!nextSeg) {\n if (seg.type !== 1) {\n // Last seg, doesn't close so add a grip\n // to last sub-path's first point\n const startSeg = segs[startI];\n startSeg.next = segs[startI + 1];\n startSeg.next.prev = startSeg;\n startSeg.addGrip();\n seg.addGrip();\n\n if (!this.first_seg) {\n // Open path, so set first as real first and add grip\n this.first_seg = segs[startI];\n }\n }\n } else if (seg.type !== 1) {\n // Regular segment, so add grip and its \"next\"\n seg.addGrip();\n\n // Don't set its \"next\" if it's an \"M\"\n if (nextSeg && nextSeg.type !== 2) {\n seg.next = nextSeg;\n seg.next.prev = seg;\n }\n }\n }\n return this;\n }\n\n /**\n * @callback module:path.PathEachSegCallback\n * @this module:path.Segment\n * @param {Integer} i The index of the seg being iterated\n * @returns {boolean|void} Will stop execution of `eachSeg` if returns `false`\n */\n /**\n * @param {module:path.PathEachSegCallback} fn\n * @returns {void}\n */\n eachSeg (fn) {\n const len = this.segs.length;\n for (let i = 0; i < len; i++) {\n const ret = fn.call(this.segs[i], i);\n if (ret === false) { break; }\n }\n }\n\n /**\n * @param {Integer} index\n * @returns {void}\n */\n addSeg (index) {\n // Adds a new segment\n const seg = this.segs[index];\n if (!seg.prev) { return; }\n\n const {prev} = seg;\n let newseg, newX, newY;\n switch (seg.item.pathSegType) {\n case 4: {\n newX = (seg.item.x + prev.item.x) / 2;\n newY = (seg.item.y + prev.item.y) / 2;\n newseg = this.elem.createSVGPathSegLinetoAbs(newX, newY);\n break;\n } case 6: { // make it a curved segment to preserve the shape (WRS)\n // https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm#Geometric_interpretation\n const p0x = (prev.item.x + seg.item.x1) / 2;\n const p1x = (seg.item.x1 + seg.item.x2) / 2;\n const p2x = (seg.item.x2 + seg.item.x) / 2;\n const p01x = (p0x + p1x) / 2;\n const p12x = (p1x + p2x) / 2;\n newX = (p01x + p12x) / 2;\n const p0y = (prev.item.y + seg.item.y1) / 2;\n const p1y = (seg.item.y1 + seg.item.y2) / 2;\n const p2y = (seg.item.y2 + seg.item.y) / 2;\n const p01y = (p0y + p1y) / 2;\n const p12y = (p1y + p2y) / 2;\n newY = (p01y + p12y) / 2;\n newseg = this.elem.createSVGPathSegCurvetoCubicAbs(newX, newY, p0x, p0y, p01x, p01y);\n const pts = [seg.item.x, seg.item.y, p12x, p12y, p2x, p2y];\n replacePathSeg(seg.type, index, pts);\n break;\n }\n }\n\n insertItemBefore(this.elem, newseg, index);\n }\n\n /**\n * @param {Integer} index\n * @returns {void}\n */\n deleteSeg (index) {\n const seg = this.segs[index];\n const list = this.elem.pathSegList;\n\n seg.show(false);\n const {next} = seg;\n if (seg.mate) {\n // Make the next point be the \"M\" point\n const pt = [next.item.x, next.item.y];\n replacePathSeg(2, next.index, pt);\n\n // Reposition last node\n replacePathSeg(4, seg.index, pt);\n\n list.removeItem(seg.mate.index);\n } else if (!seg.prev) {\n // First node of open path, make next point the M\n // const {item} = seg;\n const pt = [next.item.x, next.item.y];\n replacePathSeg(2, seg.next.index, pt);\n list.removeItem(index);\n } else {\n list.removeItem(index);\n }\n }\n\n /**\n * @param {Integer} index\n * @returns {void}\n */\n removePtFromSelection (index) {\n const pos = this.selected_pts.indexOf(index);\n if (pos === -1) {\n return;\n }\n this.segs[index].select(false);\n this.selected_pts.splice(pos, 1);\n }\n\n /**\n * @returns {void}\n */\n clearSelection () {\n this.eachSeg(function () {\n // 'this' is the segment here\n this.select(false);\n });\n this.selected_pts = [];\n }\n\n /**\n * @returns {void}\n */\n storeD () {\n this.last_d = this.elem.getAttribute('d');\n }\n\n /**\n * @param {Integer} y\n * @returns {Path}\n */\n show (y) {\n // Shows this path's segment grips\n this.eachSeg(function () {\n // 'this' is the segment here\n this.show(y);\n });\n if (y) {\n this.selectPt(this.first_seg.index);\n }\n return this;\n }\n\n /**\n * Move selected points.\n * @param {Integer} dx\n * @param {Integer} dy\n * @returns {void}\n */\n movePts (dx, dy) {\n let i = this.selected_pts.length;\n while (i--) {\n const seg = this.segs[this.selected_pts[i]];\n seg.move(dx, dy);\n }\n }\n\n /**\n * @param {Integer} dx\n * @param {Integer} dy\n * @returns {void}\n */\n moveCtrl (dx, dy) {\n const seg = this.segs[this.selected_pts[0]];\n seg.moveCtrl(this.dragctrl, dx, dy);\n if (linkControlPts) {\n seg.setLinked(this.dragctrl);\n }\n }\n\n /**\n * @param {?Integer} newType See {@link https://www.w3.org/TR/SVG/single-page.html#paths-InterfaceSVGPathSeg}\n * @returns {void}\n */\n setSegType (newType) {\n this.storeD();\n let i = this.selected_pts.length;\n let text;\n while (i--) {\n const selPt = this.selected_pts[i];\n\n // Selected seg\n const cur = this.segs[selPt];\n const {prev} = cur;\n if (!prev) { continue; }\n\n if (!newType) { // double-click, so just toggle\n text = 'Toggle Path Segment Type';\n\n // Toggle segment to curve/straight line\n const oldType = cur.type;\n\n newType = (oldType === 6) ? 4 : 6;\n }\n\n newType = Number(newType);\n\n const curX = cur.item.x;\n const curY = cur.item.y;\n const prevX = prev.item.x;\n const prevY = prev.item.y;\n let points;\n switch (newType) {\n case 6: {\n if (cur.olditem) {\n const old = cur.olditem;\n points = [curX, curY, old.x1, old.y1, old.x2, old.y2];\n } else {\n const diffX = curX - prevX;\n const diffY = curY - prevY;\n // get control points from straight line segment\n /*\n const ct1x = (prevX + (diffY/2));\n const ct1y = (prevY - (diffX/2));\n const ct2x = (curX + (diffY/2));\n const ct2y = (curY - (diffX/2));\n */\n // create control points on the line to preserve the shape (WRS)\n const ct1x = (prevX + (diffX / 3));\n const ct1y = (prevY + (diffY / 3));\n const ct2x = (curX - (diffX / 3));\n const ct2y = (curY - (diffY / 3));\n points = [curX, curY, ct1x, ct1y, ct2x, ct2y];\n }\n break;\n } case 4: {\n points = [curX, curY];\n\n // Store original prevve segment nums\n cur.olditem = cur.item;\n break;\n }\n }\n\n cur.setType(newType, points);\n }\n path.endChanges(text);\n }\n\n /**\n * @param {Integer} pt\n * @param {Integer} ctrlNum\n * @returns {void}\n */\n selectPt (pt, ctrlNum) {\n this.clearSelection();\n if (isNullish(pt)) {\n this.eachSeg(function (i) {\n // 'this' is the segment here.\n if (this.prev) {\n pt = i;\n }\n });\n }\n this.addPtsToSelection(pt);\n if (ctrlNum) {\n this.dragctrl = ctrlNum;\n\n if (linkControlPts) {\n this.segs[pt].setLinked(ctrlNum);\n }\n }\n }\n\n /**\n * Update position of all points.\n * @returns {Path}\n */\n update () {\n const {elem} = this;\n if (getRotationAngle(elem)) {\n this.matrix = getMatrix(elem);\n this.imatrix = this.matrix.inverse();\n } else {\n this.matrix = null;\n this.imatrix = null;\n }\n\n this.eachSeg(function (i) {\n this.item = elem.pathSegList.getItem(i);\n this.update();\n });\n\n return this;\n }\n\n /**\n * @param {string} text\n * @returns {void}\n */\n endChanges (text) {\n if (isWebkit()) { editorContext_.resetD(this.elem); }\n const cmd = new ChangeElementCommand(this.elem, {d: this.last_d}, text);\n editorContext_.endChanges({cmd, elem: this.elem});\n }\n\n /**\n * @param {Integer|Integer[]} indexes\n * @returns {void}\n */\n addPtsToSelection (indexes) {\n if (!Array.isArray(indexes)) { indexes = [indexes]; }\n indexes.forEach((index) => {\n const seg = this.segs[index];\n if (seg.ptgrip) {\n if (!this.selected_pts.includes(index) && index >= 0) {\n this.selected_pts.push(index);\n }\n }\n });\n this.selected_pts.sort();\n let i = this.selected_pts.length;\n const grips = [];\n grips.length = i;\n // Loop through points to be selected and highlight each\n while (i--) {\n const pt = this.selected_pts[i];\n const seg = this.segs[pt];\n seg.select(true);\n grips[i] = seg.ptgrip;\n }\n\n const closedSubpath = Path.subpathIsClosed(this.selected_pts[0]);\n editorContext_.addPtsToSelection({grips, closedSubpath});\n }\n\n // STATIC\n /**\n * @param {Integer} index\n * @returns {boolean}\n */\n static subpathIsClosed (index) {\n let clsd = false;\n // Check if subpath is already open\n path.eachSeg(function (i) {\n if (i <= index) { return true; }\n if (this.type === 2) {\n // Found M first, so open\n return false;\n }\n if (this.type === 1) {\n // Found Z first, so closed\n clsd = true;\n return false;\n }\n return true;\n });\n\n return clsd;\n }\n}\n\n/**\n* @function module:path.getPath_\n* @param {SVGPathElement} elem\n* @returns {module:path.Path}\n*/\nexport const getPath_ = function (elem) {\n let p = pathData[elem.id];\n if (!p) {\n p = pathData[elem.id] = new Path(elem);\n }\n return p;\n};\n\n/**\n* @function module:path.removePath_\n* @param {string} id\n* @returns {void}\n*/\nexport const removePath_ = function (id) {\n if (id in pathData) { delete pathData[id]; }\n};\n\nlet newcx, newcy, oldcx, oldcy, angle;\n\nconst getRotVals = function (x, y) {\n let dx = x - oldcx;\n let dy = y - oldcy;\n\n // rotate the point around the old center\n let r = Math.sqrt(dx * dx + dy * dy);\n let theta = Math.atan2(dy, dx) + angle;\n dx = r * Math.cos(theta) + oldcx;\n dy = r * Math.sin(theta) + oldcy;\n\n // dx,dy should now hold the actual coordinates of each\n // point after being rotated\n\n // now we want to rotate them around the new center in the reverse direction\n dx -= newcx;\n dy -= newcy;\n\n r = Math.sqrt(dx * dx + dy * dy);\n theta = Math.atan2(dy, dx) - angle;\n\n return {x: r * Math.cos(theta) + newcx,\n y: r * Math.sin(theta) + newcy};\n};\n\n// If the path was rotated, we must now pay the piper:\n// Every path point must be rotated into the rotated coordinate system of\n// its old center, then determine the new center, then rotate it back\n// This is because we want the path to remember its rotation\n\n/**\n* @function module:path.recalcRotatedPath\n* @todo This is still using ye olde transform methods, can probably\n* be optimized or even taken care of by `recalculateDimensions`\n* @returns {void}\n*/\nexport const recalcRotatedPath = function () {\n const currentPath = path.elem;\n angle = getRotationAngle(currentPath, true);\n if (!angle) { return; }\n // selectedBBoxes[0] = path.oldbbox;\n const oldbox = path.oldbbox; // selectedBBoxes[0],\n oldcx = oldbox.x + oldbox.width / 2;\n oldcy = oldbox.y + oldbox.height / 2;\n const box = getBBox(currentPath);\n newcx = box.x + box.width / 2;\n newcy = box.y + box.height / 2;\n\n // un-rotate the new center to the proper position\n const dx = newcx - oldcx,\n dy = newcy - oldcy,\n r = Math.sqrt(dx * dx + dy * dy),\n theta = Math.atan2(dy, dx) + angle;\n\n newcx = r * Math.cos(theta) + oldcx;\n newcy = r * Math.sin(theta) + oldcy;\n\n const list = currentPath.pathSegList;\n\n let i = list.numberOfItems;\n while (i) {\n i -= 1;\n const seg = list.getItem(i),\n type = seg.pathSegType;\n if (type === 1) { continue; }\n\n const rvals = getRotVals(seg.x, seg.y),\n points = [rvals.x, rvals.y];\n if (!isNullish(seg.x1) && !isNullish(seg.x2)) {\n const cVals1 = getRotVals(seg.x1, seg.y1);\n const cVals2 = getRotVals(seg.x2, seg.y2);\n points.splice(points.length, 0, cVals1.x, cVals1.y, cVals2.x, cVals2.y);\n }\n replacePathSeg(type, i, points);\n } // loop for each point\n\n /* box = */ getBBox(currentPath);\n // selectedBBoxes[0].x = box.x; selectedBBoxes[0].y = box.y;\n // selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height;\n\n // now we must set the new transform to be rotated around the new center\n const Rnc = editorContext_.getSVGRoot().createSVGTransform(),\n tlist = getTransformList(currentPath);\n Rnc.setRotate((angle * 180.0 / Math.PI), newcx, newcy);\n tlist.replaceItem(Rnc, 0);\n};\n\n// ====================================\n// Public API starts here\n\n/**\n* @function module:path.clearData\n* @returns {void}\n*/\nexport const clearData = function () {\n pathData = {};\n};\n\n// Making public for mocking\n/**\n* @function module:path.reorientGrads\n* @param {Element} elem\n* @param {SVGMatrix} m\n* @returns {void}\n*/\nexport const reorientGrads = function (elem, m) {\n const bb = utilsGetBBox(elem);\n for (let i = 0; i < 2; i++) {\n const type = i === 0 ? 'fill' : 'stroke';\n const attrVal = elem.getAttribute(type);\n if (attrVal && attrVal.startsWith('url(')) {\n const grad = getRefElem(attrVal);\n if (grad.tagName === 'linearGradient') {\n let x1 = grad.getAttribute('x1') || 0;\n let y1 = grad.getAttribute('y1') || 0;\n let x2 = grad.getAttribute('x2') || 1;\n let y2 = grad.getAttribute('y2') || 0;\n\n // Convert to USOU points\n x1 = (bb.width * x1) + bb.x;\n y1 = (bb.height * y1) + bb.y;\n x2 = (bb.width * x2) + bb.x;\n y2 = (bb.height * y2) + bb.y;\n\n // Transform those points\n const pt1 = transformPoint(x1, y1, m);\n const pt2 = transformPoint(x2, y2, m);\n\n // Convert back to BB points\n const gCoords = {\n x1: (pt1.x - bb.x) / bb.width,\n y1: (pt1.y - bb.y) / bb.height,\n x2: (pt2.x - bb.x) / bb.width,\n y2: (pt2.y - bb.y) / bb.height\n };\n\n const newgrad = grad.cloneNode(true);\n $(newgrad).attr(gCoords);\n\n newgrad.id = editorContext_.getNextId();\n findDefs().append(newgrad);\n elem.setAttribute(type, 'url(#' + newgrad.id + ')');\n }\n }\n }\n};\n\n/**\n* This is how we map paths to our preferred relative segment types.\n* @name module:path.pathMap\n* @type {GenericArray}\n*/\nconst pathMap = [\n 0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',\n 'H', 'h', 'V', 'v', 'S', 's', 'T', 't'\n];\n\n/**\n * Convert a path to one with only absolute or relative values.\n * @todo move to pathActions.js\n * @function module:path.convertPath\n * @param {SVGPathElement} pth - the path to convert\n * @param {boolean} toRel - true of convert to relative\n * @returns {string}\n */\nexport const convertPath = function (pth, toRel) {\n const {pathSegList} = pth;\n const len = pathSegList.numberOfItems;\n let curx = 0, cury = 0;\n let d = '';\n let lastM = null;\n\n for (let i = 0; i < len; ++i) {\n const seg = pathSegList.getItem(i);\n // if these properties are not in the segment, set them to zero\n let x = seg.x || 0,\n y = seg.y || 0,\n x1 = seg.x1 || 0,\n y1 = seg.y1 || 0,\n x2 = seg.x2 || 0,\n y2 = seg.y2 || 0;\n\n const type = seg.pathSegType;\n let letter = pathMap[type][toRel ? 'toLowerCase' : 'toUpperCase']();\n\n switch (type) {\n case 1: // z,Z closepath (Z/z)\n d += 'z';\n if (lastM && !toRel) {\n curx = lastM[0];\n cury = lastM[1];\n }\n break;\n case 12: // absolute horizontal line (H)\n x -= curx;\n // Fallthrough\n case 13: // relative horizontal line (h)\n if (toRel) {\n y = 0;\n curx += x;\n letter = 'l';\n } else {\n y = cury;\n x += curx;\n curx = x;\n letter = 'L';\n }\n // Convert to \"line\" for easier editing\n d += pathDSegment(letter, [[x, y]]);\n break;\n case 14: // absolute vertical line (V)\n y -= cury;\n // Fallthrough\n case 15: // relative vertical line (v)\n if (toRel) {\n x = 0;\n cury += y;\n letter = 'l';\n } else {\n x = curx;\n y += cury;\n cury = y;\n letter = 'L';\n }\n // Convert to \"line\" for easier editing\n d += pathDSegment(letter, [[x, y]]);\n break;\n case 2: // absolute move (M)\n case 4: // absolute line (L)\n case 18: // absolute smooth quad (T)\n x -= curx;\n y -= cury;\n // Fallthrough\n case 5: // relative line (l)\n case 3: // relative move (m)\n case 19: // relative smooth quad (t)\n if (toRel) {\n curx += x;\n cury += y;\n } else {\n x += curx;\n y += cury;\n curx = x;\n cury = y;\n }\n if (type === 2 || type === 3) { lastM = [curx, cury]; }\n\n d += pathDSegment(letter, [[x, y]]);\n break;\n case 6: // absolute cubic (C)\n x -= curx; x1 -= curx; x2 -= curx;\n y -= cury; y1 -= cury; y2 -= cury;\n // Fallthrough\n case 7: // relative cubic (c)\n if (toRel) {\n curx += x;\n cury += y;\n } else {\n x += curx; x1 += curx; x2 += curx;\n y += cury; y1 += cury; y2 += cury;\n curx = x;\n cury = y;\n }\n d += pathDSegment(letter, [[x1, y1], [x2, y2], [x, y]]);\n break;\n case 8: // absolute quad (Q)\n x -= curx; x1 -= curx;\n y -= cury; y1 -= cury;\n // Fallthrough\n case 9: // relative quad (q)\n if (toRel) {\n curx += x;\n cury += y;\n } else {\n x += curx; x1 += curx;\n y += cury; y1 += cury;\n curx = x;\n cury = y;\n }\n d += pathDSegment(letter, [[x1, y1], [x, y]]);\n break;\n // eslint-disable-next-line sonarjs/no-duplicated-branches\n case 10: // absolute elliptical arc (A)\n x -= curx;\n y -= cury;\n // Fallthrough\n case 11: // relative elliptical arc (a)\n if (toRel) {\n curx += x;\n cury += y;\n } else {\n x += curx;\n y += cury;\n curx = x;\n cury = y;\n }\n d += pathDSegment(letter, [[seg.r1, seg.r2]], [\n seg.angle,\n (seg.largeArcFlag ? 1 : 0),\n (seg.sweepFlag ? 1 : 0)\n ], [x, y]);\n break;\n case 16: // absolute smooth cubic (S)\n x -= curx; x2 -= curx;\n y -= cury; y2 -= cury;\n // Fallthrough\n case 17: // relative smooth cubic (s)\n if (toRel) {\n curx += x;\n cury += y;\n } else {\n x += curx; x2 += curx;\n y += cury; y2 += cury;\n curx = x;\n cury = y;\n }\n d += pathDSegment(letter, [[x2, y2], [x, y]]);\n break;\n } // switch on path segment type\n } // for each segment\n return d;\n};\n\n/**\n * TODO: refactor callers in `convertPath` to use `getPathDFromSegments` instead of this function.\n * Legacy code refactored from `svgcanvas.pathActions.convertPath`.\n * @param {string} letter - path segment command (letter in potentially either case from {@link module:path.pathMap}; see [SVGPathSeg#pathSegTypeAsLetter]{@link https://www.w3.org/TR/SVG/single-page.html#paths-__svg__SVGPathSeg__pathSegTypeAsLetter})\n * @param {GenericArray<GenericArray<Integer>>} points - x,y points\n * @param {GenericArray<GenericArray<Integer>>} [morePoints] - x,y points\n * @param {Integer[]} [lastPoint] - x,y point\n * @returns {string}\n */\nfunction pathDSegment (letter, points, morePoints, lastPoint) {\n $.each(points, function (i, pnt) {\n points[i] = shortFloat(pnt);\n });\n let segment = letter + points.join(' ');\n if (morePoints) {\n segment += ' ' + morePoints.join(' ');\n }\n if (lastPoint) {\n segment += ' ' + shortFloat(lastPoint);\n }\n return segment;\n}\n\n/* eslint-disable jsdoc/require-property */\n/**\n* Group: Path edit functions.\n* Functions relating to editing path elements.\n* @namespace {PlainObject} pathActions\n* @memberof module:path\n*/\nexport const pathActions = (function () {\n /* eslint-enable jsdoc/require-property */\n let subpath = false;\n let newPoint, firstCtrl;\n\n let currentPath = null;\n let hasMoved = false;\n // No `editorContext_` yet but should be ok as is `null` by default\n // editorContext_.setDrawnPath(null);\n\n /**\n * This function converts a polyline (created by the fh_path tool) into\n * a path element and coverts every three line segments into a single bezier\n * curve in an attempt to smooth out the free-hand.\n * @function smoothPolylineIntoPath\n * @param {Element} element\n * @returns {Element}\n */\n const smoothPolylineIntoPath = function (element) {\n let i;\n const {points} = element;\n const N = points.numberOfItems;\n if (N >= 4) {\n // loop through every 3 points and convert to a cubic bezier curve segment\n //\n // NOTE: this is cheating, it means that every 3 points has the potential to\n // be a corner instead of treating each point in an equal manner. In general,\n // this technique does not look that good.\n //\n // I am open to better ideas!\n //\n // Reading:\n // - http://www.efg2.com/Lab/Graphics/Jean-YvesQueinecBezierCurves.htm\n // - https://www.codeproject.com/KB/graphics/BezierSpline.aspx?msg=2956963\n // - https://www.ian-ko.com/ET_GeoWizards/UserGuide/smooth.htm\n // - https://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html\n let curpos = points.getItem(0), prevCtlPt = null;\n let d = [];\n d.push(['M', curpos.x, ',', curpos.y, ' C'].join(''));\n for (i = 1; i <= (N - 4); i += 3) {\n let ct1 = points.getItem(i);\n const ct2 = points.getItem(i + 1);\n const end = points.getItem(i + 2);\n\n // if the previous segment had a control point, we want to smooth out\n // the control points on both sides\n if (prevCtlPt) {\n const newpts = smoothControlPoints(prevCtlPt, ct1, curpos);\n if (newpts && newpts.length === 2) {\n const prevArr = d[d.length - 1].split(',');\n prevArr[2] = newpts[0].x;\n prevArr[3] = newpts[0].y;\n d[d.length - 1] = prevArr.join(',');\n ct1 = newpts[1];\n }\n }\n\n d.push([ct1.x, ct1.y, ct2.x, ct2.y, end.x, end.y].join(','));\n\n curpos = end;\n prevCtlPt = ct2;\n }\n // handle remaining line segments\n d.push('L');\n while (i < N) {\n const pt = points.getItem(i);\n d.push([pt.x, pt.y].join(','));\n i++;\n }\n d = d.join(' ');\n\n // create new path element\n element = editorContext_.addSVGElementFromJson({\n element: 'path',\n curStyles: true,\n attr: {\n id: editorContext_.getId(),\n d,\n fill: 'none'\n }\n });\n // No need to call \"changed\", as this is already done under mouseUp\n }\n return element;\n };\n\n return (/** @lends module:path.pathActions */ {\n /**\n * @param {MouseEvent} evt\n * @param {Element} mouseTarget\n * @param {Float} startX\n * @param {Float} startY\n * @returns {boolean|void}\n */\n mouseDown (evt, mouseTarget, startX, startY) {\n let id;\n if (editorContext_.getCurrentMode() === 'path') {\n let mouseX = startX; // Was this meant to work with the other `mouseX`? (was defined globally so adding `let` to at least avoid a global)\n let mouseY = startY; // Was this meant to work with the other `mouseY`? (was defined globally so adding `let` to at least avoid a global)\n\n const currentZoom = editorContext_.getCurrentZoom();\n let x = mouseX / currentZoom,\n y = mouseY / currentZoom,\n stretchy = getElem('path_stretch_line');\n newPoint = [x, y];\n\n if (editorContext_.getGridSnapping()) {\n x = snapToGrid(x);\n y = snapToGrid(y);\n mouseX = snapToGrid(mouseX);\n mouseY = snapToGrid(mouseY);\n }\n\n if (!stretchy) {\n stretchy = document.createElementNS(NS.SVG, 'path');\n assignAttributes(stretchy, {\n id: 'path_stretch_line',\n stroke: '#22C',\n 'stroke-width': '0.5',\n fill: 'none'\n });\n stretchy = getElem('selectorParentGroup').appendChild(stretchy);\n }\n stretchy.setAttribute('display', 'inline');\n\n let keep = null;\n let index;\n // if pts array is empty, create path element with M at current point\n const drawnPath = editorContext_.getDrawnPath();\n if (!drawnPath) {\n const dAttr = 'M' + x + ',' + y + ' '; // Was this meant to work with the other `dAttr`? (was defined globally so adding `var` to at least avoid a global)\n /* drawnPath = */ editorContext_.setDrawnPath(editorContext_.addSVGElementFromJson({\n element: 'path',\n curStyles: true,\n attr: {\n d: dAttr,\n id: editorContext_.getNextId(),\n opacity: editorContext_.getOpacity() / 2\n }\n }));\n // set stretchy line to first point\n stretchy.setAttribute('d', ['M', mouseX, mouseY, mouseX, mouseY].join(' '));\n index = subpath ? path.segs.length : 0;\n addPointGrip(index, mouseX, mouseY);\n } else {\n // determine if we clicked on an existing point\n const seglist = drawnPath.pathSegList;\n let i = seglist.numberOfItems;\n const FUZZ = 6 / currentZoom;\n let clickOnPoint = false;\n while (i) {\n i--;\n const item = seglist.getItem(i);\n const px = item.x, py = item.y;\n // found a matching point\n if (x >= (px - FUZZ) && x <= (px + FUZZ) &&\n y >= (py - FUZZ) && y <= (py + FUZZ)\n ) {\n clickOnPoint = true;\n break;\n }\n }\n\n // get path element that we are in the process of creating\n id = editorContext_.getId();\n\n // Remove previous path object if previously created\n removePath_(id);\n\n const newpath = getElem(id);\n let newseg;\n let sSeg;\n const len = seglist.numberOfItems;\n // if we clicked on an existing point, then we are done this path, commit it\n // (i, i+1) are the x,y that were clicked on\n if (clickOnPoint) {\n // if clicked on any other point but the first OR\n // the first point was clicked on and there are less than 3 points\n // then leave the path open\n // otherwise, close the path\n if (i <= 1 && len >= 2) {\n // Create end segment\n const absX = seglist.getItem(0).x;\n const absY = seglist.getItem(0).y;\n\n sSeg = stretchy.pathSegList.getItem(1);\n if (sSeg.pathSegType === 4) {\n newseg = drawnPath.createSVGPathSegLinetoAbs(absX, absY);\n } else {\n newseg = drawnPath.createSVGPathSegCurvetoCubicAbs(\n absX,\n absY,\n sSeg.x1 / currentZoom,\n sSeg.y1 / currentZoom,\n absX,\n absY\n );\n }\n\n const endseg = drawnPath.createSVGPathSegClosePath();\n seglist.appendItem(newseg);\n seglist.appendItem(endseg);\n } else if (len < 3) {\n keep = false;\n return keep;\n }\n $(stretchy).remove();\n\n // This will signal to commit the path\n // const element = newpath; // Other event handlers define own `element`, so this was probably not meant to interact with them or one which shares state (as there were none); I therefore adding a missing `var` to avoid a global\n /* drawnPath = */ editorContext_.setDrawnPath(null);\n editorContext_.setStarted(false);\n\n if (subpath) {\n if (path.matrix) {\n editorContext_.remapElement(newpath, {}, path.matrix.inverse());\n }\n\n const newD = newpath.getAttribute('d');\n const origD = $(path.elem).attr('d');\n $(path.elem).attr('d', origD + newD);\n $(newpath).remove();\n if (path.matrix) {\n recalcRotatedPath();\n }\n init();\n pathActions.toEditMode(path.elem);\n path.selectPt();\n return false;\n }\n // else, create a new point, update path element\n } else {\n // Checks if current target or parents are #svgcontent\n if (!$.contains(\n editorContext_.getContainer(),\n editorContext_.getMouseTarget(evt)\n )) {\n // Clicked outside canvas, so don't make point\n // console.log('Clicked outside canvas');\n return false;\n }\n\n const num = drawnPath.pathSegList.numberOfItems;\n const last = drawnPath.pathSegList.getItem(num - 1);\n const lastx = last.x, lasty = last.y;\n\n if (evt.shiftKey) {\n const xya = snapToAngle(lastx, lasty, x, y);\n ({x, y} = xya);\n }\n\n // Use the segment defined by stretchy\n sSeg = stretchy.pathSegList.getItem(1);\n if (sSeg.pathSegType === 4) {\n newseg = drawnPath.createSVGPathSegLinetoAbs(\n editorContext_.round(x),\n editorContext_.round(y)\n );\n } else {\n newseg = drawnPath.createSVGPathSegCurvetoCubicAbs(\n editorContext_.round(x),\n editorContext_.round(y),\n sSeg.x1 / currentZoom,\n sSeg.y1 / currentZoom,\n sSeg.x2 / currentZoom,\n sSeg.y2 / currentZoom\n );\n }\n\n drawnPath.pathSegList.appendItem(newseg);\n\n x *= currentZoom;\n y *= currentZoom;\n\n // set stretchy line to latest point\n stretchy.setAttribute('d', ['M', x, y, x, y].join(' '));\n index = num;\n if (subpath) { index += path.segs.length; }\n addPointGrip(index, x, y);\n }\n // keep = true;\n }\n\n return undefined;\n }\n\n // TODO: Make sure currentPath isn't null at this point\n if (!path) { return undefined; }\n\n path.storeD();\n\n ({id} = evt.target);\n let curPt;\n if (id.substr(0, 14) === 'pathpointgrip_') {\n // Select this point\n curPt = path.cur_pt = parseInt(id.substr(14));\n path.dragging = [startX, startY];\n const seg = path.segs[curPt];\n\n // only clear selection if shift is not pressed (otherwise, add\n // node to selection)\n if (!evt.shiftKey) {\n if (path.selected_pts.length <= 1 || !seg.selected) {\n path.clearSelection();\n }\n path.addPtsToSelection(curPt);\n } else if (seg.selected) {\n path.removePtFromSelection(curPt);\n } else {\n path.addPtsToSelection(curPt);\n }\n } else if (id.startsWith('ctrlpointgrip_')) {\n path.dragging = [startX, startY];\n\n const parts = id.split('_')[1].split('c');\n curPt = Number(parts[0]);\n const ctrlNum = Number(parts[1]);\n path.selectPt(curPt, ctrlNum);\n }\n\n // Start selection box\n if (!path.dragging) {\n let rubberBox = editorContext_.getRubberBox();\n if (isNullish(rubberBox)) {\n rubberBox = editorContext_.setRubberBox(\n editorContext_.selectorManager.getRubberBandBox()\n );\n }\n const currentZoom = editorContext_.getCurrentZoom();\n assignAttributes(rubberBox, {\n x: startX * currentZoom,\n y: startY * currentZoom,\n width: 0,\n height: 0,\n display: 'inline'\n }, 100);\n }\n return undefined;\n },\n /**\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {void}\n */\n mouseMove (mouseX, mouseY) {\n const currentZoom = editorContext_.getCurrentZoom();\n hasMoved = true;\n const drawnPath = editorContext_.getDrawnPath();\n if (editorContext_.getCurrentMode() === 'path') {\n if (!drawnPath) { return; }\n const seglist = drawnPath.pathSegList;\n const index = seglist.numberOfItems - 1;\n\n if (newPoint) {\n // First point\n // if (!index) { return; }\n\n // Set control points\n const pointGrip1 = addCtrlGrip('1c1');\n const pointGrip2 = addCtrlGrip('0c2');\n\n // dragging pointGrip1\n pointGrip1.setAttribute('cx', mouseX);\n pointGrip1.setAttribute('cy', mouseY);\n pointGrip1.setAttribute('display', 'inline');\n\n const ptX = newPoint[0];\n const ptY = newPoint[1];\n\n // set curve\n // const seg = seglist.getItem(index);\n const curX = mouseX / currentZoom;\n const curY = mouseY / currentZoom;\n const altX = (ptX + (ptX - curX));\n const altY = (ptY + (ptY - curY));\n\n pointGrip2.setAttribute('cx', altX * currentZoom);\n pointGrip2.setAttribute('cy', altY * currentZoom);\n pointGrip2.setAttribute('display', 'inline');\n\n const ctrlLine = getCtrlLine(1);\n assignAttributes(ctrlLine, {\n x1: mouseX,\n y1: mouseY,\n x2: altX * currentZoom,\n y2: altY * currentZoom,\n display: 'inline'\n });\n\n if (index === 0) {\n firstCtrl = [mouseX, mouseY];\n } else {\n const last = seglist.getItem(index - 1);\n let lastX = last.x;\n let lastY = last.y;\n\n if (last.pathSegType === 6) {\n lastX += (lastX - last.x2);\n lastY += (lastY - last.y2);\n } else if (firstCtrl) {\n lastX = firstCtrl[0] / currentZoom;\n lastY = firstCtrl[1] / currentZoom;\n }\n replacePathSeg(6, index, [ptX, ptY, lastX, lastY, altX, altY], drawnPath);\n }\n } else {\n const stretchy = getElem('path_stretch_line');\n if (stretchy) {\n const prev = seglist.getItem(index);\n if (prev.pathSegType === 6) {\n const prevX = prev.x + (prev.x - prev.x2);\n const prevY = prev.y + (prev.y - prev.y2);\n replacePathSeg(6, 1, [mouseX, mouseY, prevX * currentZoom, prevY * currentZoom, mouseX, mouseY], stretchy);\n } else if (firstCtrl) {\n replacePathSeg(6, 1, [mouseX, mouseY, firstCtrl[0], firstCtrl[1], mouseX, mouseY], stretchy);\n } else {\n replacePathSeg(4, 1, [mouseX, mouseY], stretchy);\n }\n }\n }\n return;\n }\n // if we are dragging a point, let's move it\n if (path.dragging) {\n const pt = getPointFromGrip({\n x: path.dragging[0],\n y: path.dragging[1]\n }, path);\n const mpt = getPointFromGrip({\n x: mouseX,\n y: mouseY\n }, path);\n const diffX = mpt.x - pt.x;\n const diffY = mpt.y - pt.y;\n path.dragging = [mouseX, mouseY];\n\n if (path.dragctrl) {\n path.moveCtrl(diffX, diffY);\n } else {\n path.movePts(diffX, diffY);\n }\n } else {\n path.selected_pts = [];\n path.eachSeg(function (i) {\n const seg = this; // eslint-disable-line consistent-this\n if (!seg.next && !seg.prev) { return; }\n\n // const {item} = seg;\n const rubberBox = editorContext_.getRubberBox();\n const rbb = rubberBox.getBBox();\n\n const pt = getGripPt(seg);\n const ptBb = {\n x: pt.x,\n y: pt.y,\n width: 0,\n height: 0\n };\n\n const sel = rectsIntersect(rbb, ptBb);\n\n this.select(sel);\n // Note that addPtsToSelection is not being run\n if (sel) { path.selected_pts.push(seg.index); }\n });\n }\n },\n /**\n * @typedef module:path.keepElement\n * @type {PlainObject}\n * @property {boolean} keep\n * @property {Element} element\n */\n /**\n * @param {Event} evt\n * @param {Element} element\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {module:path.keepElement|void}\n */\n mouseUp (evt, element, mouseX, mouseY) {\n const drawnPath = editorContext_.getDrawnPath();\n // Create mode\n if (editorContext_.getCurrentMode() === 'path') {\n newPoint = null;\n if (!drawnPath) {\n element = getElem(editorContext_.getId());\n editorContext_.setStarted(false);\n firstCtrl = null;\n }\n\n return {\n keep: true,\n element\n };\n }\n\n // Edit mode\n const rubberBox = editorContext_.getRubberBox();\n if (path.dragging) {\n const lastPt = path.cur_pt;\n\n path.dragging = false;\n path.dragctrl = false;\n path.update();\n\n if (hasMoved) {\n path.endChanges('Move path point(s)');\n }\n\n if (!evt.shiftKey && !hasMoved) {\n path.selectPt(lastPt);\n }\n } else if (rubberBox && rubberBox.getAttribute('display') !== 'none') {\n // Done with multi-node-select\n rubberBox.setAttribute('display', 'none');\n\n if (rubberBox.getAttribute('width') <= 2 && rubberBox.getAttribute('height') <= 2) {\n pathActions.toSelectMode(evt.target);\n }\n\n // else, move back to select mode\n } else {\n pathActions.toSelectMode(evt.target);\n }\n hasMoved = false;\n return undefined;\n },\n /**\n * @param {Element} element\n * @returns {void}\n */\n toEditMode (element) {\n path = getPath_(element);\n editorContext_.setCurrentMode('pathedit');\n editorContext_.clearSelection();\n path.show(true).update();\n path.oldbbox = utilsGetBBox(path.elem);\n subpath = false;\n },\n /**\n * @param {Element} elem\n * @fires module:svgcanvas.SvgCanvas#event:selected\n * @returns {void}\n */\n toSelectMode (elem) {\n const selPath = (elem === path.elem);\n editorContext_.setCurrentMode('select');\n path.show(false);\n currentPath = false;\n editorContext_.clearSelection();\n\n if (path.matrix) {\n // Rotated, so may need to re-calculate the center\n recalcRotatedPath();\n }\n\n if (selPath) {\n editorContext_.call('selected', [elem]);\n editorContext_.addToSelection([elem], true);\n }\n },\n /**\n * @param {boolean} on\n * @returns {void}\n */\n addSubPath (on) {\n if (on) {\n // Internally we go into \"path\" mode, but in the UI it will\n // still appear as if in \"pathedit\" mode.\n editorContext_.setCurrentMode('path');\n subpath = true;\n } else {\n pathActions.clear(true);\n pathActions.toEditMode(path.elem);\n }\n },\n /**\n * @param {Element} target\n * @returns {void}\n */\n select (target) {\n if (currentPath === target) {\n pathActions.toEditMode(target);\n editorContext_.setCurrentMode('pathedit');\n // going into pathedit mode\n } else {\n currentPath = target;\n }\n },\n /**\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @returns {void}\n */\n reorient () {\n const elem = editorContext_.getSelectedElements()[0];\n if (!elem) { return; }\n const angl = getRotationAngle(elem);\n if (angl === 0) { return; }\n\n const batchCmd = new BatchCommand('Reorient path');\n const changes = {\n d: elem.getAttribute('d'),\n transform: elem.getAttribute('transform')\n };\n batchCmd.addSubCommand(new ChangeElementCommand(elem, changes));\n editorContext_.clearSelection();\n this.resetOrientation(elem);\n\n editorContext_.addCommandToHistory(batchCmd);\n\n // Set matrix to null\n getPath_(elem).show(false).matrix = null;\n\n this.clear();\n\n editorContext_.addToSelection([elem], true);\n editorContext_.call('changed', editorContext_.getSelectedElements());\n },\n\n /**\n * @param {boolean} remove Not in use\n * @returns {void}\n */\n clear (remove) {\n const drawnPath = editorContext_.getDrawnPath();\n currentPath = null;\n if (drawnPath) {\n const elem = getElem(editorContext_.getId());\n $(getElem('path_stretch_line')).remove();\n $(elem).remove();\n $(getElem('pathpointgrip_container')).find('*').attr('display', 'none');\n firstCtrl = null;\n editorContext_.setDrawnPath(null);\n editorContext_.setStarted(false);\n } else if (editorContext_.getCurrentMode() === 'pathedit') {\n this.toSelectMode();\n }\n if (path) { path.init().show(false); }\n },\n /**\n * @param {?(Element|SVGPathElement)} pth\n * @returns {false|void}\n */\n resetOrientation (pth) {\n if (isNullish(pth) || pth.nodeName !== 'path') { return false; }\n const tlist = getTransformList(pth);\n const m = transformListToTransform(tlist).matrix;\n tlist.clear();\n pth.removeAttribute('transform');\n const segList = pth.pathSegList;\n\n // Opera/win/non-EN throws an error here.\n // TODO: Find out why!\n // Presumed fixed in Opera 10.5, so commented out for now\n\n // try {\n const len = segList.numberOfItems;\n // } catch(err) {\n // const fixed_d = pathActions.convertPath(pth);\n // pth.setAttribute('d', fixed_d);\n // segList = pth.pathSegList;\n // const len = segList.numberOfItems;\n // }\n // let lastX, lastY;\n for (let i = 0; i < len; ++i) {\n const seg = segList.getItem(i);\n const type = seg.pathSegType;\n if (type === 1) { continue; }\n const pts = [];\n $.each(['', 1, 2], function (j, n) {\n const x = seg['x' + n], y = seg['y' + n];\n if (x !== undefined && y !== undefined) {\n const pt = transformPoint(x, y, m);\n pts.splice(pts.length, 0, pt.x, pt.y);\n }\n });\n replacePathSeg(type, i, pts, pth);\n }\n\n reorientGrads(pth, m);\n return undefined;\n },\n /**\n * @returns {void}\n */\n zoomChange () {\n if (editorContext_.getCurrentMode() === 'pathedit') {\n path.update();\n }\n },\n /**\n * @typedef {PlainObject} module:path.NodePoint\n * @property {Float} x\n * @property {Float} y\n * @property {Integer} type\n */\n /**\n * @returns {module:path.NodePoint}\n */\n getNodePoint () {\n const selPt = path.selected_pts.length ? path.selected_pts[0] : 1;\n\n const seg = path.segs[selPt];\n return {\n x: seg.item.x,\n y: seg.item.y,\n type: seg.type\n };\n },\n /**\n * @param {boolean} linkPoints\n * @returns {void}\n */\n linkControlPoints (linkPoints) {\n setLinkControlPoints(linkPoints);\n },\n /**\n * @returns {void}\n */\n clonePathNode () {\n path.storeD();\n\n const selPts = path.selected_pts;\n // const {segs} = path;\n\n let i = selPts.length;\n const nums = [];\n\n while (i--) {\n const pt = selPts[i];\n path.addSeg(pt);\n\n nums.push(pt + i);\n nums.push(pt + i + 1);\n }\n path.init().addPtsToSelection(nums);\n\n path.endChanges('Clone path node(s)');\n },\n /**\n * @returns {void}\n */\n opencloseSubPath () {\n const selPts = path.selected_pts;\n // Only allow one selected node for now\n if (selPts.length !== 1) { return; }\n\n const {elem} = path;\n const list = elem.pathSegList;\n\n // const len = list.numberOfItems;\n\n const index = selPts[0];\n\n let openPt = null;\n let startItem = null;\n\n // Check if subpath is already open\n path.eachSeg(function (i) {\n if (this.type === 2 && i <= index) {\n startItem = this.item;\n }\n if (i <= index) { return true; }\n if (this.type === 2) {\n // Found M first, so open\n openPt = i;\n return false;\n }\n if (this.type === 1) {\n // Found Z first, so closed\n openPt = false;\n return false;\n }\n return true;\n });\n\n if (isNullish(openPt)) {\n // Single path, so close last seg\n openPt = path.segs.length - 1;\n }\n\n if (openPt !== false) {\n // Close this path\n\n // Create a line going to the previous \"M\"\n const newseg = elem.createSVGPathSegLinetoAbs(startItem.x, startItem.y);\n\n const closer = elem.createSVGPathSegClosePath();\n if (openPt === path.segs.length - 1) {\n list.appendItem(newseg);\n list.appendItem(closer);\n } else {\n insertItemBefore(elem, closer, openPt);\n insertItemBefore(elem, newseg, openPt);\n }\n\n path.init().selectPt(openPt + 1);\n return;\n }\n\n // M 1,1 L 2,2 L 3,3 L 1,1 z // open at 2,2\n // M 2,2 L 3,3 L 1,1\n\n // M 1,1 L 2,2 L 1,1 z M 4,4 L 5,5 L6,6 L 5,5 z\n // M 1,1 L 2,2 L 1,1 z [M 4,4] L 5,5 L(M)6,6 L 5,5 z\n\n const seg = path.segs[index];\n\n if (seg.mate) {\n list.removeItem(index); // Removes last \"L\"\n list.removeItem(index); // Removes the \"Z\"\n path.init().selectPt(index - 1);\n return;\n }\n\n let lastM, zSeg;\n\n // Find this sub-path's closing point and remove\n for (let i = 0; i < list.numberOfItems; i++) {\n const item = list.getItem(i);\n\n if (item.pathSegType === 2) {\n // Find the preceding M\n lastM = i;\n } else if (i === index) {\n // Remove it\n list.removeItem(lastM);\n // index--;\n } else if (item.pathSegType === 1 && index < i) {\n // Remove the closing seg of this subpath\n zSeg = i - 1;\n list.removeItem(i);\n break;\n }\n }\n\n let num = (index - lastM) - 1;\n\n while (num--) {\n insertItemBefore(elem, list.getItem(lastM), zSeg);\n }\n\n const pt = list.getItem(lastM);\n\n // Make this point the new \"M\"\n replacePathSeg(2, lastM, [pt.x, pt.y]);\n\n // i = index; // i is local here, so has no effect; what was the intent for this?\n\n path.init().selectPt(0);\n },\n /**\n * @returns {void}\n */\n deletePathNode () {\n if (!pathActions.canDeleteNodes) { return; }\n path.storeD();\n\n const selPts = path.selected_pts;\n\n let i = selPts.length;\n while (i--) {\n const pt = selPts[i];\n path.deleteSeg(pt);\n }\n\n // Cleanup\n const cleanup = function () {\n const segList = path.elem.pathSegList;\n let len = segList.numberOfItems;\n\n const remItems = function (pos, count) {\n while (count--) {\n segList.removeItem(pos);\n }\n };\n\n if (len <= 1) { return true; }\n\n while (len--) {\n const item = segList.getItem(len);\n if (item.pathSegType === 1) {\n const prev = segList.getItem(len - 1);\n const nprev = segList.getItem(len - 2);\n if (prev.pathSegType === 2) {\n remItems(len - 1, 2);\n cleanup();\n break;\n } else if (nprev.pathSegType === 2) {\n remItems(len - 2, 3);\n cleanup();\n break;\n }\n } else if (item.pathSegType === 2) {\n if (len > 0) {\n const prevType = segList.getItem(len - 1).pathSegType;\n // Path has M M\n if (prevType === 2) {\n remItems(len - 1, 1);\n cleanup();\n break;\n // Entire path ends with Z M\n } else if (prevType === 1 && segList.numberOfItems - 1 === len) {\n remItems(len, 1);\n cleanup();\n break;\n }\n }\n }\n }\n return false;\n };\n\n cleanup();\n\n // Completely delete a path with 1 or 0 segments\n if (path.elem.pathSegList.numberOfItems <= 1) {\n pathActions.toSelectMode(path.elem);\n editorContext_.canvas.deleteSelectedElements();\n return;\n }\n\n path.init();\n path.clearSelection();\n\n // TODO: Find right way to select point now\n // path.selectPt(selPt);\n if (window.opera) { // Opera repaints incorrectly\n const cp = $(path.elem);\n cp.attr('d', cp.attr('d'));\n }\n path.endChanges('Delete path node(s)');\n },\n /* eslint-disable jsdoc/require-returns */\n // Can't seem to use `@borrows` here, so using `@see`\n /**\n * Smooth polyline into path.\n * @function module:path.pathActions.smoothPolylineIntoPath\n * @see module:path~smoothPolylineIntoPath\n */\n smoothPolylineIntoPath,\n /* eslint-enable jsdoc/require-returns */\n /**\n * @param {?Integer} v See {@link https://www.w3.org/TR/SVG/single-page.html#paths-InterfaceSVGPathSeg}\n * @returns {void}\n */\n setSegType (v) {\n path.setSegType(v);\n },\n /**\n * @param {string} attr\n * @param {Float} newValue\n * @returns {void}\n */\n moveNode (attr, newValue) {\n const selPts = path.selected_pts;\n if (!selPts.length) { return; }\n\n path.storeD();\n\n // Get first selected point\n const seg = path.segs[selPts[0]];\n const diff = {x: 0, y: 0};\n diff[attr] = newValue - seg.item[attr];\n\n seg.move(diff.x, diff.y);\n path.endChanges('Move path point');\n },\n /**\n * @param {Element} elem\n * @returns {void}\n */\n fixEnd (elem) {\n // Adds an extra segment if the last seg before a Z doesn't end\n // at its M point\n // M0,0 L0,100 L100,100 z\n const segList = elem.pathSegList;\n const len = segList.numberOfItems;\n let lastM;\n for (let i = 0; i < len; ++i) {\n const item = segList.getItem(i);\n if (item.pathSegType === 2) {\n lastM = item;\n }\n\n if (item.pathSegType === 1) {\n const prev = segList.getItem(i - 1);\n if (prev.x !== lastM.x || prev.y !== lastM.y) {\n // Add an L segment here\n const newseg = elem.createSVGPathSegLinetoAbs(lastM.x, lastM.y);\n insertItemBefore(elem, newseg, i);\n // Can this be done better?\n pathActions.fixEnd(elem);\n break;\n }\n }\n }\n if (isWebkit()) { editorContext_.resetD(elem); }\n },\n /* eslint-disable jsdoc/require-returns */\n // Can't seem to use `@borrows` here, so using `@see`\n /**\n * Convert a path to one with only absolute or relative values.\n * @function module:path.pathActions.convertPath\n * @see module:path.convertPath\n */\n convertPath\n /* eslint-enable jsdoc/require-returns */\n });\n})();\n// end pathActions\n","/**\n * Mathematical utilities.\n * @module math\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\n/**\n* @typedef {PlainObject} module:math.AngleCoord45\n* @property {Float} x - The angle-snapped x value\n* @property {Float} y - The angle-snapped y value\n* @property {Integer} a - The angle at which to snap\n*/\n\n/**\n* @typedef {PlainObject} module:math.XYObject\n* @property {Float} x\n* @property {Float} y\n*/\n\nimport {NS} from './namespaces.js';\nimport {getTransformList} from './svgtransformlist.js';\nimport {isNullish} from './utilities.js';\n\n// Constants\nconst NEAR_ZERO = 1e-14;\n\n// Throw away SVGSVGElement used for creating matrices/transforms.\nconst svg = document.createElementNS(NS.SVG, 'svg');\n\n/**\n * A (hopefully) quicker function to transform a point by a matrix\n * (this function avoids any DOM calls and just does the math).\n * @function module:math.transformPoint\n * @param {Float} x - Float representing the x coordinate\n * @param {Float} y - Float representing the y coordinate\n * @param {SVGMatrix} m - Matrix object to transform the point with\n * @returns {module:math.XYObject} An x, y object representing the transformed point\n*/\nexport const transformPoint = function (x, y, m) {\n return {x: m.a * x + m.c * y + m.e, y: m.b * x + m.d * y + m.f};\n};\n\n/**\n * Helper function to check if the matrix performs no actual transform\n * (i.e. exists for identity purposes).\n * @function module:math.isIdentity\n * @param {SVGMatrix} m - The matrix object to check\n * @returns {boolean} Indicates whether or not the matrix is 1,0,0,1,0,0\n*/\nexport const isIdentity = function (m) {\n return (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0);\n};\n\n/**\n * This function tries to return a `SVGMatrix` that is the multiplication `m1 * m2`.\n * We also round to zero when it's near zero.\n * @function module:math.matrixMultiply\n * @param {...SVGMatrix} args - Matrix objects to multiply\n * @returns {SVGMatrix} The matrix object resulting from the calculation\n*/\nexport const matrixMultiply = function (...args) {\n const m = args.reduceRight((prev, m1) => {\n return m1.multiply(prev);\n });\n\n if (Math.abs(m.a) < NEAR_ZERO) { m.a = 0; }\n if (Math.abs(m.b) < NEAR_ZERO) { m.b = 0; }\n if (Math.abs(m.c) < NEAR_ZERO) { m.c = 0; }\n if (Math.abs(m.d) < NEAR_ZERO) { m.d = 0; }\n if (Math.abs(m.e) < NEAR_ZERO) { m.e = 0; }\n if (Math.abs(m.f) < NEAR_ZERO) { m.f = 0; }\n\n return m;\n};\n\n/**\n * See if the given transformlist includes a non-indentity matrix transform.\n * @function module:math.hasMatrixTransform\n * @param {SVGTransformList} [tlist] - The transformlist to check\n * @returns {boolean} Whether or not a matrix transform was found\n*/\nexport const hasMatrixTransform = function (tlist) {\n if (!tlist) { return false; }\n let num = tlist.numberOfItems;\n while (num--) {\n const xform = tlist.getItem(num);\n if (xform.type === 1 && !isIdentity(xform.matrix)) { return true; }\n }\n return false;\n};\n\n/**\n* @typedef {PlainObject} module:math.TransformedBox An object with the following values\n* @property {module:math.XYObject} tl - The top left coordinate\n* @property {module:math.XYObject} tr - The top right coordinate\n* @property {module:math.XYObject} bl - The bottom left coordinate\n* @property {module:math.XYObject} br - The bottom right coordinate\n* @property {PlainObject} aabox - Object with the following values:\n* @property {Float} aabox.x - Float with the axis-aligned x coordinate\n* @property {Float} aabox.y - Float with the axis-aligned y coordinate\n* @property {Float} aabox.width - Float with the axis-aligned width coordinate\n* @property {Float} aabox.height - Float with the axis-aligned height coordinate\n*/\n\n/**\n * Transforms a rectangle based on the given matrix.\n * @function module:math.transformBox\n * @param {Float} l - Float with the box's left coordinate\n * @param {Float} t - Float with the box's top coordinate\n * @param {Float} w - Float with the box width\n * @param {Float} h - Float with the box height\n * @param {SVGMatrix} m - Matrix object to transform the box by\n * @returns {module:math.TransformedBox}\n*/\nexport const transformBox = function (l, t, w, h, m) {\n const tl = transformPoint(l, t, m),\n tr = transformPoint((l + w), t, m),\n bl = transformPoint(l, (t + h), m),\n br = transformPoint((l + w), (t + h), m),\n\n minx = Math.min(tl.x, tr.x, bl.x, br.x),\n maxx = Math.max(tl.x, tr.x, bl.x, br.x),\n miny = Math.min(tl.y, tr.y, bl.y, br.y),\n maxy = Math.max(tl.y, tr.y, bl.y, br.y);\n\n return {\n tl,\n tr,\n bl,\n br,\n aabox: {\n x: minx,\n y: miny,\n width: (maxx - minx),\n height: (maxy - miny)\n }\n };\n};\n\n/**\n * This returns a single matrix Transform for a given Transform List\n * (this is the equivalent of `SVGTransformList.consolidate()` but unlike\n * that method, this one does not modify the actual `SVGTransformList`).\n * This function is very liberal with its `min`, `max` arguments.\n * @function module:math.transformListToTransform\n * @param {SVGTransformList} tlist - The transformlist object\n * @param {Integer} [min=0] - Optional integer indicating start transform position\n * @param {Integer} [max] - Optional integer indicating end transform position;\n * defaults to one less than the tlist's `numberOfItems`\n * @returns {SVGTransform} A single matrix transform object\n*/\nexport const transformListToTransform = function (tlist, min, max) {\n if (isNullish(tlist)) {\n // Or should tlist = null have been prevented before this?\n return svg.createSVGTransformFromMatrix(svg.createSVGMatrix());\n }\n min = min || 0;\n max = max || (tlist.numberOfItems - 1);\n min = parseInt(min);\n max = parseInt(max);\n if (min > max) { const temp = max; max = min; min = temp; }\n let m = svg.createSVGMatrix();\n for (let i = min; i <= max; ++i) {\n // if our indices are out of range, just use a harmless identity matrix\n const mtom = (i >= 0 && i < tlist.numberOfItems\n ? tlist.getItem(i).matrix\n : svg.createSVGMatrix());\n m = matrixMultiply(m, mtom);\n }\n return svg.createSVGTransformFromMatrix(m);\n};\n\n/**\n * Get the matrix object for a given element.\n * @function module:math.getMatrix\n * @param {Element} elem - The DOM element to check\n * @returns {SVGMatrix} The matrix object associated with the element's transformlist\n*/\nexport const getMatrix = function (elem) {\n const tlist = getTransformList(elem);\n return transformListToTransform(tlist).matrix;\n};\n\n/**\n * Returns a 45 degree angle coordinate associated with the two given\n * coordinates.\n * @function module:math.snapToAngle\n * @param {Integer} x1 - First coordinate's x value\n * @param {Integer} y1 - First coordinate's y value\n * @param {Integer} x2 - Second coordinate's x value\n * @param {Integer} y2 - Second coordinate's y value\n * @returns {module:math.AngleCoord45}\n*/\nexport const snapToAngle = function (x1, y1, x2, y2) {\n const snap = Math.PI / 4; // 45 degrees\n const dx = x2 - x1;\n const dy = y2 - y1;\n const angle = Math.atan2(dy, dx);\n const dist = Math.sqrt(dx * dx + dy * dy);\n const snapangle = Math.round(angle / snap) * snap;\n\n return {\n x: x1 + dist * Math.cos(snapangle),\n y: y1 + dist * Math.sin(snapangle),\n a: snapangle\n };\n};\n\n/**\n * Check if two rectangles (BBoxes objects) intersect each other.\n * @function module:math.rectsIntersect\n * @param {SVGRect} r1 - The first BBox-like object\n * @param {SVGRect} r2 - The second BBox-like object\n * @returns {boolean} True if rectangles intersect\n */\nexport const rectsIntersect = function (r1, r2) {\n return r2.x < (r1.x + r1.width) &&\n (r2.x + r2.width) > r1.x &&\n r2.y < (r1.y + r1.height) &&\n (r2.y + r2.height) > r1.y;\n};\n","/* globals jQuery */\n/**\n * Miscellaneous utilities.\n * @module utilities\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\nimport './svgpathseg.js';\nimport jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`\nimport {NS} from './namespaces.js';\nimport {getTransformList} from './svgtransformlist.js';\nimport {setUnitAttr, getTypeMap} from './units.js';\nimport {convertPath} from './path.js';\nimport {\n hasMatrixTransform, transformListToTransform, transformBox\n} from './math.js';\nimport {\n isWebkit, supportsHVLineContainerBBox, supportsPathBBox, supportsXpath,\n supportsSelectors\n} from './browser.js';\n\n// Constants\nconst $ = jQueryPluginSVG(jQuery);\n\n// String used to encode base64.\nconst KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n\n// Much faster than running getBBox() every time\nconst visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use';\nconst visElemsArr = visElems.split(',');\n// const hidElems = 'clipPath,defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath';\n\nlet editorContext_ = null;\nlet domdoc_ = null;\nlet domcontainer_ = null;\nlet svgroot_ = null;\n\n/**\n* Object with the following keys/values.\n* @typedef {PlainObject} module:utilities.SVGElementJSON\n* @property {string} element - Tag name of the SVG element to create\n* @property {PlainObject<string, string>} attr - Has key-value attributes to assign to the new element. An `id` should be set so that {@link module:utilities.EditorContext#addSVGElementFromJson} can later re-identify the element for modification or replacement.\n* @property {boolean} [curStyles=false] - Indicates whether current style attributes should be applied first\n* @property {module:utilities.SVGElementJSON[]} [children] - Data objects to be added recursively as children\n* @property {string} [namespace=\"http://www.w3.org/2000/svg\"] - Indicate a (non-SVG) namespace\n*/\n\n/**\n * An object that creates SVG elements for the canvas.\n *\n * @interface module:utilities.EditorContext\n * @property {module:path.pathActions} pathActions\n */\n/**\n * @function module:utilities.EditorContext#getSVGContent\n * @returns {SVGSVGElement}\n */\n/**\n * Create a new SVG element based on the given object keys/values and add it\n * to the current layer.\n * The element will be run through `cleanupElement` before being returned.\n * @function module:utilities.EditorContext#addSVGElementFromJson\n * @param {module:utilities.SVGElementJSON} data\n * @returns {Element} The new element\n*/\n/**\n * @function module:utilities.EditorContext#getSelectedElements\n * @returns {Element[]} the array with selected DOM elements\n*/\n/**\n * @function module:utilities.EditorContext#getDOMDocument\n * @returns {HTMLDocument}\n*/\n/**\n * @function module:utilities.EditorContext#getDOMContainer\n * @returns {HTMLElement}\n*/\n/**\n * @function module:utilities.EditorContext#getSVGRoot\n * @returns {SVGSVGElement}\n*/\n/**\n * @function module:utilities.EditorContext#getBaseUnit\n * @returns {string}\n*/\n/**\n * @function module:utilities.EditorContext#getSnappingStep\n * @returns {Float|string}\n*/\n\n/**\n* @function module:utilities.init\n* @param {module:utilities.EditorContext} editorContext\n* @returns {void}\n*/\nexport const init = function (editorContext) {\n editorContext_ = editorContext;\n domdoc_ = editorContext.getDOMDocument();\n domcontainer_ = editorContext.getDOMContainer();\n svgroot_ = editorContext.getSVGRoot();\n};\n\n/**\n * Used to prevent the [Billion laughs attack]{@link https://en.wikipedia.org/wiki/Billion_laughs_attack}.\n * @function module:utilities.dropXMLInternalSubset\n * @param {string} str String to be processed\n * @returns {string} The string with entity declarations in the internal subset removed\n * @todo This might be needed in other places `parseFromString` is used even without LGTM flagging\n */\nexport const dropXMLInternalSubset = (str) => {\n return str.replace(/(<!DOCTYPE\\s+\\w*\\s*\\[).*(\\?]>)/, '$1$2');\n // return str.replace(/(?<doctypeOpen><!DOCTYPE\\s+\\w*\\s*\\[).*(?<doctypeClose>\\?\\]>)/, '$<doctypeOpen>$<doctypeClose>');\n};\n\n/**\n* Converts characters in a string to XML-friendly entities.\n* @function module:utilities.toXml\n* @example `&` becomes `&amp;`\n* @param {string} str - The string to be converted\n* @returns {string} The converted string\n*/\nexport const toXml = function (str) {\n // &apos; is ok in XML, but not HTML\n // &gt; does not normally need escaping, though it can if within a CDATA expression (and preceded by \"]]\")\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#x27;'); // Note: `&apos;` is XML only\n};\n\n/**\n* Converts XML entities in a string to single characters.\n* @function module:utilities.fromXml\n* @example `&amp;` becomes `&`\n* @param {string} str - The string to be converted\n* @returns {string} The converted string\n*/\nexport function fromXml (str) {\n return $('<p/>').html(str).text();\n}\n\n// This code was written by Tyler Akins and has been placed in the\n// public domain. It would be nice if you left this header intact.\n// Base64 code from Tyler Akins -- http://rumkin.com\n\n// schiller: Removed string concatenation in favour of Array.join() optimization,\n// also precalculate the size of the array needed.\n\n/**\n* Converts a string to base64.\n* @function module:utilities.encode64\n* @param {string} input\n* @returns {string} Base64 output\n*/\nexport function encode64 (input) {\n // base64 strings are 4/3 larger than the original string\n input = encodeUTF8(input); // convert non-ASCII characters\n // input = convertToXMLReferences(input);\n if (window.btoa) {\n return window.btoa(input); // Use native if available\n }\n const output = new Array(Math.floor((input.length + 2) / 3) * 4);\n\n let i = 0,\n p = 0;\n do {\n const chr1 = input.charCodeAt(i++);\n const chr2 = input.charCodeAt(i++);\n const chr3 = input.charCodeAt(i++);\n\n /* eslint-disable no-bitwise */\n const enc1 = chr1 >> 2;\n const enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n\n let enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n let enc4 = chr3 & 63;\n /* eslint-enable no-bitwise */\n\n if (isNaN(chr2)) {\n enc3 = 64;\n enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output[p++] = KEYSTR.charAt(enc1);\n output[p++] = KEYSTR.charAt(enc2);\n output[p++] = KEYSTR.charAt(enc3);\n output[p++] = KEYSTR.charAt(enc4);\n } while (i < input.length);\n\n return output.join('');\n}\n\n/**\n* Converts a string from base64.\n* @function module:utilities.decode64\n* @param {string} input Base64-encoded input\n* @returns {string} Decoded output\n*/\nexport function decode64 (input) {\n if (window.atob) {\n return decodeUTF8(window.atob(input));\n }\n\n // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n input = input.replace(/[^A-Za-z\\d+/=]/g, '');\n\n let output = '';\n let i = 0;\n\n do {\n const enc1 = KEYSTR.indexOf(input.charAt(i++));\n const enc2 = KEYSTR.indexOf(input.charAt(i++));\n const enc3 = KEYSTR.indexOf(input.charAt(i++));\n const enc4 = KEYSTR.indexOf(input.charAt(i++));\n\n /* eslint-disable no-bitwise */\n const chr1 = (enc1 << 2) | (enc2 >> 4);\n const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n const chr3 = ((enc3 & 3) << 6) | enc4;\n /* eslint-enable no-bitwise */\n\n output += String.fromCharCode(chr1);\n\n if (enc3 !== 64) {\n output += String.fromCharCode(chr2);\n }\n if (enc4 !== 64) {\n output += String.fromCharCode(chr3);\n }\n } while (i < input.length);\n return decodeUTF8(output);\n}\n\n/**\n* @function module:utilities.decodeUTF8\n* @param {string} argString\n* @returns {string}\n*/\nexport function decodeUTF8 (argString) {\n return decodeURIComponent(escape(argString));\n}\n\n// codedread:does not seem to work with webkit-based browsers on OSX // Brettz9: please test again as function upgraded\n/**\n* @function module:utilities.encodeUTF8\n* @param {string} argString\n* @returns {string}\n*/\nexport const encodeUTF8 = function (argString) {\n return unescape(encodeURIComponent(argString));\n};\n\n/**\n * Convert dataURL to object URL.\n * @function module:utilities.dataURLToObjectURL\n * @param {string} dataurl\n * @returns {string} object URL or empty string\n */\nexport const dataURLToObjectURL = function (dataurl) {\n if (typeof Uint8Array === 'undefined' || typeof Blob === 'undefined' || typeof URL === 'undefined' || !URL.createObjectURL) {\n return '';\n }\n const arr = dataurl.split(','),\n mime = arr[0].match(/:(.*?);/)[1],\n bstr = atob(arr[1]);\n /*\n const [prefix, suffix] = dataurl.split(','),\n {groups: {mime}} = prefix.match(/:(?<mime>.*?);/),\n bstr = atob(suffix);\n */\n let n = bstr.length;\n const u8arr = new Uint8Array(n);\n while (n--) {\n u8arr[n] = bstr.charCodeAt(n);\n }\n const blob = new Blob([u8arr], {type: mime});\n return URL.createObjectURL(blob);\n};\n\n/**\n * Get object URL for a blob object.\n * @function module:utilities.createObjectURL\n * @param {Blob} blob A Blob object or File object\n * @returns {string} object URL or empty string\n */\nexport const createObjectURL = function (blob) {\n if (!blob || typeof URL === 'undefined' || !URL.createObjectURL) {\n return '';\n }\n return URL.createObjectURL(blob);\n};\n\n/**\n * @property {string} blankPageObjectURL\n */\nexport const blankPageObjectURL = (function () {\n if (typeof Blob === 'undefined') {\n return '';\n }\n const blob = new Blob(['<html><head><title>SVG-edit</title></head><body>&nbsp;</body></html>'], {type: 'text/html'});\n return createObjectURL(blob);\n})();\n\n/**\n* Converts a string to use XML references (for non-ASCII).\n* @function module:utilities.convertToXMLReferences\n* @param {string} input\n* @returns {string} Decimal numeric character references\n*/\nexport const convertToXMLReferences = function (input) {\n let output = '';\n [...input].forEach((ch) => {\n const c = ch.charCodeAt();\n if (c <= 127) {\n output += ch;\n } else {\n output += `&#${c};`;\n }\n });\n return output;\n};\n\n/**\n* Cross-browser compatible method of converting a string to an XML tree.\n* Found this function [here]{@link http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f}.\n* @function module:utilities.text2xml\n* @param {string} sXML\n* @throws {Error}\n* @returns {XMLDocument}\n*/\nexport const text2xml = function (sXML) {\n if (sXML.includes('<svg:svg')) {\n sXML = sXML.replace(/<(\\/?)svg:/g, '<$1').replace('xmlns:svg', 'xmlns');\n }\n\n let out, dXML;\n try {\n dXML = (window.DOMParser) ? new DOMParser() : new window.ActiveXObject('Microsoft.XMLDOM');\n dXML.async = false;\n } catch (e) {\n throw new Error('XML Parser could not be instantiated');\n }\n try {\n if (dXML.loadXML) {\n out = (dXML.loadXML(sXML)) ? dXML : false;\n } else {\n out = dXML.parseFromString(sXML, 'text/xml');\n }\n } catch (e2) { throw new Error('Error parsing XML string'); }\n return out;\n};\n\n/**\n* @typedef {PlainObject} module:utilities.BBoxObject (like `DOMRect`)\n* @property {Float} x\n* @property {Float} y\n* @property {Float} width\n* @property {Float} height\n*/\n\n/**\n* Converts a `SVGRect` into an object.\n* @function module:utilities.bboxToObj\n* @param {SVGRect} bbox - a SVGRect\n* @returns {module:utilities.BBoxObject} An object with properties names x, y, width, height.\n*/\nexport const bboxToObj = function ({x, y, width, height}) {\n return {x, y, width, height};\n};\n\n/**\n* @callback module:utilities.TreeWalker\n* @param {Element} elem - DOM element being traversed\n* @returns {void}\n*/\n\n/**\n* Walks the tree and executes the callback on each element in a top-down fashion.\n* @function module:utilities.walkTree\n* @param {Element} elem - DOM element to traverse\n* @param {module:utilities.TreeWalker} cbFn - Callback function to run on each element\n* @returns {void}\n*/\nexport const walkTree = function (elem, cbFn) {\n if (elem && elem.nodeType === 1) {\n cbFn(elem);\n let i = elem.childNodes.length;\n while (i--) {\n walkTree(elem.childNodes.item(i), cbFn);\n }\n }\n};\n\n/**\n* Walks the tree and executes the callback on each element in a depth-first fashion.\n* @function module:utilities.walkTreePost\n* @todo Shouldn't this be calling walkTreePost?\n* @param {Element} elem - DOM element to traverse\n* @param {module:utilities.TreeWalker} cbFn - Callback function to run on each element\n* @returns {void}\n*/\nexport const walkTreePost = function (elem, cbFn) {\n if (elem && elem.nodeType === 1) {\n let i = elem.childNodes.length;\n while (i--) {\n walkTree(elem.childNodes.item(i), cbFn);\n }\n cbFn(elem);\n }\n};\n\n/**\n* Extracts the URL from the `url(...)` syntax of some attributes.\n* Three variants:\n* - `<circle fill=\"url(someFile.svg#foo)\" />`\n* - `<circle fill=\"url('someFile.svg#foo')\" />`\n* - `<circle fill='url(\"someFile.svg#foo\")' />`\n* @function module:utilities.getUrlFromAttr\n* @param {string} attrVal The attribute value as a string\n* @returns {string} String with just the URL, like \"someFile.svg#foo\"\n*/\nexport const getUrlFromAttr = function (attrVal) {\n if (attrVal) {\n // url('#somegrad')\n if (attrVal.startsWith('url(\"')) {\n return attrVal.substring(5, attrVal.indexOf('\"', 6));\n }\n // url('#somegrad')\n if (attrVal.startsWith(\"url('\")) {\n return attrVal.substring(5, attrVal.indexOf(\"'\", 6));\n }\n if (attrVal.startsWith('url(')) {\n return attrVal.substring(4, attrVal.indexOf(')'));\n }\n }\n return null;\n};\n\n/**\n* @function module:utilities.getHref\n* @param {Element} elem\n* @returns {string} The given element's `xlink:href` value\n*/\nexport let getHref = function (elem) { // eslint-disable-line import/no-mutable-exports\n return elem.getAttributeNS(NS.XLINK, 'href');\n};\n\n/**\n* Sets the given element's `xlink:href` value.\n* @function module:utilities.setHref\n* @param {Element} elem\n* @param {string} val\n* @returns {void}\n*/\nexport let setHref = function (elem, val) { // eslint-disable-line import/no-mutable-exports\n elem.setAttributeNS(NS.XLINK, 'xlink:href', val);\n};\n\n/**\n* @function module:utilities.findDefs\n* @returns {SVGDefsElement} The document's `<defs>` element, creating it first if necessary\n*/\nexport const findDefs = function () {\n const svgElement = editorContext_.getSVGContent();\n let defs = svgElement.getElementsByTagNameNS(NS.SVG, 'defs');\n if (defs.length > 0) {\n defs = defs[0];\n } else {\n defs = svgElement.ownerDocument.createElementNS(NS.SVG, 'defs');\n if (svgElement.firstChild) {\n // first child is a comment, so call nextSibling\n svgElement.insertBefore(defs, svgElement.firstChild.nextSibling);\n // svgElement.firstChild.nextSibling.before(defs); // Not safe\n } else {\n svgElement.append(defs);\n }\n }\n return defs;\n};\n\n// TODO(codedread): Consider moving the next to functions to bbox.js\n\n/**\n* Get correct BBox for a path in Webkit.\n* Converted from code found [here]{@link http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html}.\n* @function module:utilities.getPathBBox\n* @param {SVGPathElement} path - The path DOM element to get the BBox for\n* @returns {module:utilities.BBoxObject} A BBox-like object\n*/\nexport const getPathBBox = function (path) {\n const seglist = path.pathSegList;\n const tot = seglist.numberOfItems;\n\n const bounds = [[], []];\n const start = seglist.getItem(0);\n let P0 = [start.x, start.y];\n\n const getCalc = function (j, P1, P2, P3) {\n return function (t) {\n return 1 - (t ** 3) * P0[j] +\n 3 * 1 - (t ** 2) * t * P1[j] +\n 3 * (1 - t) * (t ** 2) * P2[j] +\n (t ** 3) * P3[j];\n };\n };\n\n for (let i = 0; i < tot; i++) {\n const seg = seglist.getItem(i);\n\n if (seg.x === undefined) { continue; }\n\n // Add actual points to limits\n bounds[0].push(P0[0]);\n bounds[1].push(P0[1]);\n\n if (seg.x1) {\n const P1 = [seg.x1, seg.y1],\n P2 = [seg.x2, seg.y2],\n P3 = [seg.x, seg.y];\n\n for (let j = 0; j < 2; j++) {\n const calc = getCalc(j, P1, P2, P3);\n\n const b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j];\n const a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j];\n const c = 3 * P1[j] - 3 * P0[j];\n\n if (a === 0) {\n if (b === 0) { continue; }\n const t = -c / b;\n if (t > 0 && t < 1) {\n bounds[j].push(calc(t));\n }\n continue;\n }\n const b2ac = (b ** 2) - 4 * c * a;\n if (b2ac < 0) { continue; }\n const t1 = (-b + Math.sqrt(b2ac)) / (2 * a);\n if (t1 > 0 && t1 < 1) { bounds[j].push(calc(t1)); }\n const t2 = (-b - Math.sqrt(b2ac)) / (2 * a);\n if (t2 > 0 && t2 < 1) { bounds[j].push(calc(t2)); }\n }\n P0 = P3;\n } else {\n bounds[0].push(seg.x);\n bounds[1].push(seg.y);\n }\n }\n\n const x = Math.min.apply(null, bounds[0]);\n const w = Math.max.apply(null, bounds[0]) - x;\n const y = Math.min.apply(null, bounds[1]);\n const h = Math.max.apply(null, bounds[1]) - y;\n return {\n x,\n y,\n width: w,\n height: h\n };\n};\n\n/**\n* Get the given/selected element's bounding box object, checking for\n* horizontal/vertical lines (see issue 717)\n* Note that performance is currently terrible, so some way to improve would\n* be great.\n* @param {Element} selected - Container or `<use>` DOM element\n* @returns {DOMRect} Bounding box object\n*/\nfunction groupBBFix (selected) {\n if (supportsHVLineContainerBBox()) {\n try { return selected.getBBox(); } catch (e) {}\n }\n const ref = $.data(selected, 'ref');\n let matched = null;\n let ret, copy;\n\n if (ref) {\n copy = $(ref).children().clone().attr('visibility', 'hidden');\n $(svgroot_).append(copy);\n matched = copy.filter('line, path');\n } else {\n matched = $(selected).find('line, path');\n }\n\n let issue = false;\n if (matched.length) {\n matched.each(function () {\n const bb = this.getBBox();\n if (!bb.width || !bb.height) {\n issue = true;\n }\n });\n if (issue) {\n const elems = ref ? copy : $(selected).children();\n ret = getStrokedBBox(elems);\n } else {\n ret = selected.getBBox();\n }\n } else {\n ret = selected.getBBox();\n }\n if (ref) {\n copy.remove();\n }\n return ret;\n}\n\n/**\n* Get the given/selected element's bounding box object, convert it to be more\n* usable when necessary.\n* @function module:utilities.getBBox\n* @param {Element} elem - Optional DOM element to get the BBox for\n* @returns {module:utilities.BBoxObject} Bounding box object\n*/\nexport const getBBox = function (elem) {\n const selected = elem || editorContext_.geSelectedElements()[0];\n if (elem.nodeType !== 1) { return null; }\n const elname = selected.nodeName;\n\n let ret = null;\n switch (elname) {\n case 'text':\n if (selected.textContent === '') {\n selected.textContent = 'a'; // Some character needed for the selector to use.\n ret = selected.getBBox();\n selected.textContent = '';\n } else if (selected.getBBox) {\n ret = selected.getBBox();\n }\n break;\n case 'path':\n if (!supportsPathBBox()) {\n ret = getPathBBox(selected);\n } else if (selected.getBBox) {\n ret = selected.getBBox();\n }\n break;\n case 'g':\n case 'a':\n ret = groupBBFix(selected);\n break;\n default:\n\n if (elname === 'use') {\n ret = groupBBFix(selected); // , true);\n }\n if (elname === 'use' || (elname === 'foreignObject' && isWebkit())) {\n if (!ret) { ret = selected.getBBox(); }\n // This is resolved in later versions of webkit, perhaps we should\n // have a featured detection for correct 'use' behavior?\n // ——————————\n if (!isWebkit()) {\n const {x, y, width, height} = ret;\n const bb = {\n width,\n height,\n x: x + parseFloat(selected.getAttribute('x') || 0),\n y: y + parseFloat(selected.getAttribute('y') || 0)\n };\n ret = bb;\n }\n } else if (visElemsArr.includes(elname)) {\n if (selected) {\n try {\n ret = selected.getBBox();\n } catch (err) {\n // tspan (and textPath apparently) have no `getBBox` in Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=937268\n // Re: Chrome returning bbox for containing text element, see: https://bugs.chromium.org/p/chromium/issues/detail?id=349835\n const extent = selected.getExtentOfChar(0); // pos+dimensions of the first glyph\n const width = selected.getComputedTextLength(); // width of the tspan\n ret = {\n x: extent.x,\n y: extent.y,\n width,\n height: extent.height\n };\n }\n } else {\n // Check if element is child of a foreignObject\n const fo = $(selected).closest('foreignObject');\n if (fo.length) {\n if (fo[0].getBBox) {\n ret = fo[0].getBBox();\n }\n }\n }\n }\n }\n if (ret) {\n ret = bboxToObj(ret);\n }\n\n // get the bounding box from the DOM (which is in that element's coordinate system)\n return ret;\n};\n\n/**\n* @typedef {GenericArray} module:utilities.PathSegmentArray\n* @property {Integer} length 2\n* @property {\"M\"|\"L\"|\"C\"|\"Z\"} 0\n* @property {Float[]} 1\n*/\n\n/**\n* Create a path 'd' attribute from path segments.\n* Each segment is an array of the form: `[singleChar, [x,y, x,y, ...]]`\n* @function module:utilities.getPathDFromSegments\n* @param {module:utilities.PathSegmentArray[]} pathSegments - An array of path segments to be converted\n* @returns {string} The converted path d attribute.\n*/\nexport const getPathDFromSegments = function (pathSegments) {\n let d = '';\n\n $.each(pathSegments, function (j, [singleChar, pts]) {\n d += singleChar;\n for (let i = 0; i < pts.length; i += 2) {\n d += (pts[i] + ',' + pts[i + 1]) + ' ';\n }\n });\n\n return d;\n};\n\n/**\n* Make a path 'd' attribute from a simple SVG element shape.\n* @function module:utilities.getPathDFromElement\n* @param {Element} elem - The element to be converted\n* @returns {string} The path d attribute or `undefined` if the element type is unknown.\n*/\nexport const getPathDFromElement = function (elem) {\n // Possibly the cubed root of 6, but 1.81 works best\n let num = 1.81;\n let d, a, rx, ry;\n switch (elem.tagName) {\n case 'ellipse':\n case 'circle': {\n a = $(elem).attr(['rx', 'ry', 'cx', 'cy']);\n const {cx, cy} = a;\n ({rx, ry} = a);\n if (elem.tagName === 'circle') {\n ry = $(elem).attr('r');\n rx = ry;\n }\n\n d = getPathDFromSegments([\n ['M', [(cx - rx), (cy)]],\n ['C', [(cx - rx), (cy - ry / num), (cx - rx / num), (cy - ry), (cx), (cy - ry)]],\n ['C', [(cx + rx / num), (cy - ry), (cx + rx), (cy - ry / num), (cx + rx), (cy)]],\n ['C', [(cx + rx), (cy + ry / num), (cx + rx / num), (cy + ry), (cx), (cy + ry)]],\n ['C', [(cx - rx / num), (cy + ry), (cx - rx), (cy + ry / num), (cx - rx), (cy)]],\n ['Z', []]\n ]);\n break;\n } case 'path':\n d = elem.getAttribute('d');\n break;\n case 'line':\n a = $(elem).attr(['x1', 'y1', 'x2', 'y2']);\n d = 'M' + a.x1 + ',' + a.y1 + 'L' + a.x2 + ',' + a.y2;\n break;\n case 'polyline':\n d = 'M' + elem.getAttribute('points');\n break;\n case 'polygon':\n d = 'M' + elem.getAttribute('points') + ' Z';\n break;\n case 'rect': {\n const r = $(elem).attr(['rx', 'ry']);\n ({rx, ry} = r);\n const b = elem.getBBox();\n const {x, y} = b,\n w = b.width,\n h = b.height;\n num = 4 - num; // Why? Because!\n\n if (!rx && !ry) {\n // Regular rect\n d = getPathDFromSegments([\n ['M', [x, y]],\n ['L', [x + w, y]],\n ['L', [x + w, y + h]],\n ['L', [x, y + h]],\n ['L', [x, y]],\n ['Z', []]\n ]);\n } else {\n d = getPathDFromSegments([\n ['M', [x, y + ry]],\n ['C', [x, y + ry / num, x + rx / num, y, x + rx, y]],\n ['L', [x + w - rx, y]],\n ['C', [x + w - rx / num, y, x + w, y + ry / num, x + w, y + ry]],\n ['L', [x + w, y + h - ry]],\n ['C', [x + w, y + h - ry / num, x + w - rx / num, y + h, x + w - rx, y + h]],\n ['L', [x + rx, y + h]],\n ['C', [x + rx / num, y + h, x, y + h - ry / num, x, y + h - ry]],\n ['L', [x, y + ry]],\n ['Z', []]\n ]);\n }\n break;\n } default:\n break;\n }\n\n return d;\n};\n\n/**\n* Get a set of attributes from an element that is useful for convertToPath.\n* @function module:utilities.getExtraAttributesForConvertToPath\n* @param {Element} elem - The element to be probed\n* @returns {PlainObject<\"marker-start\"|\"marker-end\"|\"marker-mid\"|\"filter\"|\"clip-path\", string>} An object with attributes.\n*/\nexport const getExtraAttributesForConvertToPath = function (elem) {\n const attrs = {};\n // TODO: make this list global so that we can properly maintain it\n // TODO: what about @transform, @clip-rule, @fill-rule, etc?\n $.each(['marker-start', 'marker-end', 'marker-mid', 'filter', 'clip-path'], function () {\n const a = elem.getAttribute(this);\n if (a) {\n attrs[this] = a;\n }\n });\n return attrs;\n};\n\n/**\n* Get the BBox of an element-as-path.\n* @function module:utilities.getBBoxOfElementAsPath\n* @param {Element} elem - The DOM element to be probed\n* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson\n* @param {module:path.pathActions} pathActions - If a transform exists, `pathActions.resetOrientation()` is used. See: canvas.pathActions.\n* @returns {DOMRect|false} The resulting path's bounding box object.\n*/\nexport const getBBoxOfElementAsPath = function (elem, addSVGElementFromJson, pathActions) {\n const path = addSVGElementFromJson({\n element: 'path',\n attr: getExtraAttributesForConvertToPath(elem)\n });\n\n const eltrans = elem.getAttribute('transform');\n if (eltrans) {\n path.setAttribute('transform', eltrans);\n }\n\n const {parentNode} = elem;\n if (elem.nextSibling) {\n elem.before(path);\n } else {\n parentNode.append(path);\n }\n\n const d = getPathDFromElement(elem);\n if (d) {\n path.setAttribute('d', d);\n } else {\n path.remove();\n }\n\n // Get the correct BBox of the new path, then discard it\n pathActions.resetOrientation(path);\n let bb = false;\n try {\n bb = path.getBBox();\n } catch (e) {\n // Firefox fails\n }\n path.remove();\n return bb;\n};\n\n/**\n* Convert selected element to a path.\n* @function module:utilities.convertToPath\n* @param {Element} elem - The DOM element to be converted\n* @param {module:utilities.SVGElementJSON} attrs - Apply attributes to new path. see canvas.convertToPath\n* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson\n* @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions.\n* @param {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection} clearSelection - see [canvas.clearSelection]{@link module:svgcanvas.SvgCanvas#clearSelection}\n* @param {module:path.EditorContext#addToSelection} addToSelection - see [canvas.addToSelection]{@link module:svgcanvas.SvgCanvas#addToSelection}\n* @param {module:history} hstry - see history module\n* @param {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory} addCommandToHistory - see [canvas.addCommandToHistory]{@link module:svgcanvas~addCommandToHistory}\n* @returns {SVGPathElement|null} The converted path element or null if the DOM element was not recognized.\n*/\nexport const convertToPath = function (elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, hstry, addCommandToHistory) {\n const batchCmd = new hstry.BatchCommand('Convert element to Path');\n\n // Any attribute on the element not covered by the passed-in attributes\n attrs = $.extend({}, attrs, getExtraAttributesForConvertToPath(elem));\n\n const path = addSVGElementFromJson({\n element: 'path',\n attr: attrs\n });\n\n const eltrans = elem.getAttribute('transform');\n if (eltrans) {\n path.setAttribute('transform', eltrans);\n }\n\n const {id} = elem;\n const {parentNode} = elem;\n if (elem.nextSibling) {\n elem.before(path);\n } else {\n parentNode.append(path);\n }\n\n const d = getPathDFromElement(elem);\n if (d) {\n path.setAttribute('d', d);\n\n // Replace the current element with the converted one\n\n // Reorient if it has a matrix\n if (eltrans) {\n const tlist = getTransformList(path);\n if (hasMatrixTransform(tlist)) {\n pathActions.resetOrientation(path);\n }\n }\n\n const {nextSibling} = elem;\n batchCmd.addSubCommand(new hstry.RemoveElementCommand(elem, nextSibling, parent));\n batchCmd.addSubCommand(new hstry.InsertElementCommand(path));\n\n clearSelection();\n elem.remove();\n path.setAttribute('id', id);\n path.removeAttribute('visibility');\n addToSelection([path], true);\n\n addCommandToHistory(batchCmd);\n\n return path;\n }\n // the elem.tagName was not recognized, so no \"d\" attribute. Remove it, so we've haven't changed anything.\n path.remove();\n return null;\n};\n\n/**\n* Can the bbox be optimized over the native getBBox? The optimized bbox is the same as the native getBBox when\n* the rotation angle is a multiple of 90 degrees and there are no complex transforms.\n* Getting an optimized bbox can be dramatically slower, so we want to make sure it's worth it.\n*\n* The best example for this is a circle rotate 45 degrees. The circle doesn't get wider or taller when rotated\n* about it's center.\n*\n* The standard, unoptimized technique gets the native bbox of the circle, rotates the box 45 degrees, uses\n* that width and height, and applies any transforms to get the final bbox. This means the calculated bbox\n* is much wider than the original circle. If the angle had been 0, 90, 180, etc. both techniques render the\n* same bbox.\n*\n* The optimization is not needed if the rotation is a multiple 90 degrees. The default technique is to call\n* getBBox then apply the angle and any transforms.\n*\n* @param {Float} angle - The rotation angle in degrees\n* @param {boolean} hasAMatrixTransform - True if there is a matrix transform\n* @returns {boolean} True if the bbox can be optimized.\n*/\nfunction bBoxCanBeOptimizedOverNativeGetBBox (angle, hasAMatrixTransform) {\n const angleModulo90 = angle % 90;\n const closeTo90 = angleModulo90 < -89.99 || angleModulo90 > 89.99;\n const closeTo0 = angleModulo90 > -0.001 && angleModulo90 < 0.001;\n return hasAMatrixTransform || !(closeTo0 || closeTo90);\n}\n\n/**\n* Get bounding box that includes any transforms.\n* @function module:utilities.getBBoxWithTransform\n* @param {Element} elem - The DOM element to be converted\n* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson\n* @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions.\n* @returns {module:utilities.BBoxObject|module:math.TransformedBox|DOMRect} A single bounding box object\n*/\nexport const getBBoxWithTransform = function (elem, addSVGElementFromJson, pathActions) {\n // TODO: Fix issue with rotated groups. Currently they work\n // fine in FF, but not in other browsers (same problem mentioned\n // in Issue 339 comment #2).\n\n let bb = getBBox(elem);\n\n if (!bb) {\n return null;\n }\n\n const tlist = getTransformList(elem);\n const angle = getRotationAngleFromTransformList(tlist);\n const hasMatrixXForm = hasMatrixTransform(tlist);\n\n if (angle || hasMatrixXForm) {\n let goodBb = false;\n if (bBoxCanBeOptimizedOverNativeGetBBox(angle, hasMatrixXForm)) {\n // Get the BBox from the raw path for these elements\n // TODO: why ellipse and not circle\n const elemNames = ['ellipse', 'path', 'line', 'polyline', 'polygon'];\n if (elemNames.includes(elem.tagName)) {\n goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions);\n bb = goodBb;\n } else if (elem.tagName === 'rect') {\n // Look for radius\n const rx = elem.getAttribute('rx');\n const ry = elem.getAttribute('ry');\n if (rx || ry) {\n goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions);\n bb = goodBb;\n }\n }\n }\n\n if (!goodBb) {\n const {matrix} = transformListToTransform(tlist);\n bb = transformBox(bb.x, bb.y, bb.width, bb.height, matrix).aabox;\n\n // Old technique that was exceedingly slow with large documents.\n //\n // Accurate way to get BBox of rotated element in Firefox:\n // Put element in group and get its BBox\n //\n // Must use clone else FF freaks out\n // const clone = elem.cloneNode(true);\n // const g = document.createElementNS(NS.SVG, 'g');\n // const parent = elem.parentNode;\n // parent.append(g);\n // g.append(clone);\n // const bb2 = bboxToObj(g.getBBox());\n // g.remove();\n }\n }\n return bb;\n};\n\n/**\n * @param {Element} elem\n * @returns {Float}\n * @todo This is problematic with large stroke-width and, for example, a single\n * horizontal line. The calculated BBox extends way beyond left and right sides.\n */\nfunction getStrokeOffsetForBBox (elem) {\n const sw = elem.getAttribute('stroke-width');\n return (!isNaN(sw) && elem.getAttribute('stroke') !== 'none') ? sw / 2 : 0;\n}\n\n/**\n * @typedef {PlainObject} BBox\n * @property {Integer} x The x value\n * @property {Integer} y The y value\n * @property {Float} width\n * @property {Float} height\n */\n\n/**\n* Get the bounding box for one or more stroked and/or transformed elements.\n* @function module:utilities.getStrokedBBox\n* @param {Element[]} elems - Array with DOM elements to check\n* @param {module:utilities.EditorContext#addSVGElementFromJson} addSVGElementFromJson - Function to add the path element to the current layer. See canvas.addSVGElementFromJson\n* @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions.\n* @returns {module:utilities.BBoxObject|module:math.TransformedBox|DOMRect} A single bounding box object\n*/\nexport const getStrokedBBox = function (elems, addSVGElementFromJson, pathActions) {\n if (!elems || !elems.length) { return false; }\n\n let fullBb;\n $.each(elems, function () {\n if (fullBb) { return; }\n if (!this.parentNode) { return; }\n fullBb = getBBoxWithTransform(this, addSVGElementFromJson, pathActions);\n });\n\n // This shouldn't ever happen...\n if (fullBb === undefined) { return null; }\n\n // fullBb doesn't include the stoke, so this does no good!\n // if (elems.length == 1) return fullBb;\n\n let maxX = fullBb.x + fullBb.width;\n let maxY = fullBb.y + fullBb.height;\n let minX = fullBb.x;\n let minY = fullBb.y;\n\n // If only one elem, don't call the potentially slow getBBoxWithTransform method again.\n if (elems.length === 1) {\n const offset = getStrokeOffsetForBBox(elems[0]);\n minX -= offset;\n minY -= offset;\n maxX += offset;\n maxY += offset;\n } else {\n $.each(elems, function (i, elem) {\n const curBb = getBBoxWithTransform(elem, addSVGElementFromJson, pathActions);\n if (curBb) {\n const offset = getStrokeOffsetForBBox(elem);\n minX = Math.min(minX, curBb.x - offset);\n minY = Math.min(minY, curBb.y - offset);\n // TODO: The old code had this test for max, but not min. I suspect this test should be for both min and max\n if (elem.nodeType === 1) {\n maxX = Math.max(maxX, curBb.x + curBb.width + offset);\n maxY = Math.max(maxY, curBb.y + curBb.height + offset);\n }\n }\n });\n }\n\n fullBb.x = minX;\n fullBb.y = minY;\n fullBb.width = maxX - minX;\n fullBb.height = maxY - minY;\n return fullBb;\n};\n\n/**\n* Get all elements that have a BBox (excludes `<defs>`, `<title>`, etc).\n* Note that 0-opacity, off-screen etc elements are still considered \"visible\"\n* for this function.\n* @function module:utilities.getVisibleElements\n* @param {Element} parentElement - The parent DOM element to search within\n* @returns {Element[]} All \"visible\" elements.\n*/\nexport const getVisibleElements = function (parentElement) {\n if (!parentElement) {\n parentElement = $(editorContext_.getSVGContent()).children(); // Prevent layers from being included\n }\n\n const contentElems = [];\n $(parentElement).children().each(function (i, elem) {\n if (elem.getBBox) {\n contentElems.push(elem);\n }\n });\n return contentElems.reverse();\n};\n\n/**\n* Get the bounding box for one or more stroked and/or transformed elements.\n* @function module:utilities.getStrokedBBoxDefaultVisible\n* @param {Element[]} elems - Array with DOM elements to check\n* @returns {module:utilities.BBoxObject} A single bounding box object\n*/\nexport const getStrokedBBoxDefaultVisible = function (elems) {\n if (!elems) { elems = getVisibleElements(); }\n return getStrokedBBox(\n elems,\n editorContext_.addSVGElementFromJson,\n editorContext_.pathActions\n );\n};\n\n/**\n* Get the rotation angle of the given transform list.\n* @function module:utilities.getRotationAngleFromTransformList\n* @param {SVGTransformList} tlist - List of transforms\n* @param {boolean} toRad - When true returns the value in radians rather than degrees\n* @returns {Float} The angle in degrees or radians\n*/\nexport const getRotationAngleFromTransformList = function (tlist, toRad) {\n if (!tlist) { return 0; } // <svg> elements have no tlist\n const N = tlist.numberOfItems;\n for (let i = 0; i < N; ++i) {\n const xform = tlist.getItem(i);\n if (xform.type === 4) {\n return toRad ? xform.angle * Math.PI / 180.0 : xform.angle;\n }\n }\n return 0.0;\n};\n\n/**\n* Get the rotation angle of the given/selected DOM element.\n* @function module:utilities.getRotationAngle\n* @param {Element} [elem] - DOM element to get the angle for. Default to first of selected elements.\n* @param {boolean} [toRad=false] - When true returns the value in radians rather than degrees\n* @returns {Float} The angle in degrees or radians\n*/\nexport let getRotationAngle = function (elem, toRad) { // eslint-disable-line import/no-mutable-exports\n const selected = elem || editorContext_.getSelectedElements()[0];\n // find the rotation transform (if any) and set it\n const tlist = getTransformList(selected);\n return getRotationAngleFromTransformList(tlist, toRad);\n};\n\n/**\n* Get the reference element associated with the given attribute value.\n* @function module:utilities.getRefElem\n* @param {string} attrVal - The attribute value as a string\n* @returns {Element} Reference element\n*/\nexport const getRefElem = function (attrVal) {\n return getElem(getUrlFromAttr(attrVal).substr(1));\n};\n\n/**\n* Get a DOM element by ID within the SVG root element.\n* @function module:utilities.getElem\n* @param {string} id - String with the element's new ID\n* @returns {?Element}\n*/\nexport const getElem = (supportsSelectors())\n ? function (id) {\n // querySelector lookup\n return svgroot_.querySelector('#' + id);\n }\n : supportsXpath()\n ? function (id) {\n // xpath lookup\n return domdoc_.evaluate(\n 'svg:svg[@id=\"svgroot\"]//svg:*[@id=\"' + id + '\"]',\n domcontainer_,\n function () { return NS.SVG; },\n 9,\n null\n ).singleNodeValue;\n }\n : function (id) {\n // jQuery lookup: twice as slow as xpath in FF\n return $(svgroot_).find('[id=' + id + ']')[0];\n };\n\n/**\n* Assigns multiple attributes to an element.\n* @function module:utilities.assignAttributes\n* @param {Element} elem - DOM element to apply new attribute values to\n* @param {PlainObject<string, string>} attrs - Object with attribute keys/values\n* @param {Integer} [suspendLength] - Milliseconds to suspend redraw\n* @param {boolean} [unitCheck=false] - Boolean to indicate the need to use units.setUnitAttr\n* @returns {void}\n*/\nexport const assignAttributes = function (elem, attrs, suspendLength, unitCheck) {\n for (const [key, value] of Object.entries(attrs)) {\n const ns = (key.substr(0, 4) === 'xml:'\n ? NS.XML\n : key.substr(0, 6) === 'xlink:' ? NS.XLINK : null);\n if (isNullish(value)) {\n if (ns) {\n elem.removeAttributeNS(ns, key);\n } else {\n elem.removeAttribute(key);\n }\n continue;\n }\n if (ns) {\n elem.setAttributeNS(ns, key, value);\n } else if (!unitCheck) {\n elem.setAttribute(key, value);\n } else {\n setUnitAttr(elem, key, value);\n }\n }\n};\n\n/**\n* Remove unneeded (default) attributes, making resulting SVG smaller.\n* @function module:utilities.cleanupElement\n* @param {Element} element - DOM element to clean up\n* @returns {void}\n*/\nexport const cleanupElement = function (element) {\n const defaults = {\n 'fill-opacity': 1,\n 'stop-opacity': 1,\n opacity: 1,\n stroke: 'none',\n 'stroke-dasharray': 'none',\n 'stroke-linejoin': 'miter',\n 'stroke-linecap': 'butt',\n 'stroke-opacity': 1,\n 'stroke-width': 1,\n rx: 0,\n ry: 0\n };\n\n if (element.nodeName === 'ellipse') {\n // Ellipse elements require rx and ry attributes\n delete defaults.rx;\n delete defaults.ry;\n }\n\n Object.entries(defaults).forEach(([attr, val]) => {\n if (element.getAttribute(attr) === String(val)) {\n element.removeAttribute(attr);\n }\n });\n};\n\n/**\n* Round value to for snapping.\n* @function module:utilities.snapToGrid\n* @param {Float} value\n* @returns {Integer}\n*/\nexport const snapToGrid = function (value) {\n const unit = editorContext_.getBaseUnit();\n let stepSize = editorContext_.getSnappingStep();\n if (unit !== 'px') {\n stepSize *= getTypeMap()[unit];\n }\n value = Math.round(value / stepSize) * stepSize;\n return value;\n};\n\n/**\n* Escapes special characters in a regular expression.\n* @function module:utilities.regexEscape\n* @param {string} str\n* @returns {string}\n*/\nexport const regexEscape = function (str) {\n // Originally from: http://phpjs.org/functions\n return String(str).replace(/[.\\\\+*?[^\\]$(){}=!<>|:-]/g, '\\\\$&');\n};\n\n/**\n * Prevents default browser click behaviour on the given element.\n * @function module:utilities.preventClickDefault\n * @param {Element} img - The DOM element to prevent the click on\n * @returns {void}\n */\nexport const preventClickDefault = function (img) {\n $(img).click(function (e) { e.preventDefault(); });\n};\n\n/**\n * @callback module:utilities.GetNextID\n * @returns {string} The ID\n */\n/**\n * Create a clone of an element, updating its ID and its children's IDs when needed.\n * @function module:utilities.copyElem\n * @param {Element} el - DOM element to clone\n * @param {module:utilities.GetNextID} getNextId - The getter of the next unique ID.\n * @returns {Element} The cloned element\n */\nexport const copyElem = function (el, getNextId) {\n // manually create a copy of the element\n const newEl = document.createElementNS(el.namespaceURI, el.nodeName);\n $.each(el.attributes, function (i, attr) {\n if (attr.localName !== '-moz-math-font-style') {\n newEl.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value);\n }\n });\n // set the copied element's new id\n newEl.removeAttribute('id');\n newEl.id = getNextId();\n\n // Opera's \"d\" value needs to be reset for Opera/Win/non-EN\n // Also needed for webkit (else does not keep curved segments on clone)\n if (isWebkit() && el.nodeName === 'path') {\n const fixedD = convertPath(el);\n newEl.setAttribute('d', fixedD);\n }\n\n // now create copies of all children\n $.each(el.childNodes, function (i, child) {\n switch (child.nodeType) {\n case 1: // element node\n newEl.append(copyElem(child, getNextId));\n break;\n case 3: // text node\n newEl.textContent = child.nodeValue;\n break;\n default:\n break;\n }\n });\n\n if ($(el).data('gsvg')) {\n $(newEl).data('gsvg', newEl.firstChild);\n } else if ($(el).data('symbol')) {\n const ref = $(el).data('symbol');\n $(newEl).data('ref', ref).data('symbol', ref);\n } else if (newEl.tagName === 'image') {\n preventClickDefault(newEl);\n }\n\n return newEl;\n};\n\n/**\n * Whether a value is `null` or `undefined`.\n * @param {any} val\n * @returns {boolean}\n */\nexport const isNullish = (val) => {\n return val === null || val === undefined;\n};\n\n/**\n* Overwrite methods for unit testing.\n* @function module:utilities.mock\n* @param {PlainObject} mockMethods\n* @returns {void}\n*/\nexport const mock = ({\n getHref: getHrefUser, setHref: setHrefUser, getRotationAngle: getRotationAngleUser\n}) => {\n getHref = getHrefUser;\n setHref = setHrefUser;\n getRotationAngle = getRotationAngleUser;\n};\n","/* globals jQuery */\n/**\n * Adds context menu functionality.\n * @module contextmenu\n * @license Apache-2.0\n * @author Adam Bender\n */\n// Dependencies:\n// 1) jQuery (for dom injection of context menus)\n\nconst $ = jQuery;\n\nlet contextMenuExtensions = {};\n\n/**\n * Signature depends on what the user adds; in the case of our uses with\n * SVGEditor, no parameters are passed nor anything expected for a return.\n * @callback module:contextmenu.MenuItemAction\n * @param {...args} args\n * @returns {any}\n*/\n\n/**\n* @typedef {PlainObject} module:contextmenu.MenuItem\n* @property {string} id\n* @property {string} label\n* @property {module:contextmenu.MenuItemAction} action\n*/\n\n/**\n* @param {module:contextmenu.MenuItem} menuItem\n* @returns {boolean}\n*/\nconst menuItemIsValid = function (menuItem) {\n return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action === 'function';\n};\n\n/**\n* @function module:contextmenu.add\n* @param {module:contextmenu.MenuItem} menuItem\n* @throws {Error|TypeError}\n* @returns {void}\n*/\nexport const add = function (menuItem) {\n // menuItem: {id, label, shortcut, action}\n if (!menuItemIsValid(menuItem)) {\n throw new TypeError('Menu items must be defined and have at least properties: id, label, action, where action must be a function');\n }\n if (menuItem.id in contextMenuExtensions) {\n throw new Error('Cannot add extension \"' + menuItem.id + '\", an extension by that name already exists\"');\n }\n // Register menuItem action, see below for deferred menu dom injection\n console.log('Registered contextmenu item: {id:' + menuItem.id + ', label:' + menuItem.label + '}'); // eslint-disable-line no-console\n contextMenuExtensions[menuItem.id] = menuItem;\n // TODO: Need to consider how to handle custom enable/disable behavior\n};\n\n/**\n* @function module:contextmenu.hasCustomHandler\n* @param {string} handlerKey\n* @returns {boolean}\n*/\nexport const hasCustomHandler = function (handlerKey) {\n return Boolean(contextMenuExtensions[handlerKey]);\n};\n\n/**\n* @function module:contextmenu.getCustomHandler\n* @param {string} handlerKey\n* @returns {module:contextmenu.MenuItemAction}\n*/\nexport const getCustomHandler = function (handlerKey) {\n return contextMenuExtensions[handlerKey].action;\n};\n\n/**\n* @param {module:contextmenu.MenuItem} menuItem\n* @returns {void}\n*/\nconst injectExtendedContextMenuItemIntoDom = function (menuItem) {\n if (!Object.keys(contextMenuExtensions).length) {\n // all menuItems appear at the bottom of the menu in their own container.\n // if this is the first extension menu we need to add the separator.\n $('#cmenu_canvas').append(\"<li class='separator'>\");\n }\n const shortcut = menuItem.shortcut || '';\n $('#cmenu_canvas').append(\"<li class='disabled'><a href='#\" + menuItem.id + \"'>\" +\n menuItem.label + \"<span class='shortcut'>\" +\n shortcut + '</span></a></li>');\n};\n\n/**\n* @function module:contextmenu.injectExtendedContextMenuItemsIntoDom\n* @returns {void}\n*/\nexport const injectExtendedContextMenuItemsIntoDom = function () {\n Object.values(contextMenuExtensions).forEach((menuItem) => {\n injectExtendedContextMenuItemIntoDom(menuItem);\n });\n};\n/**\n* @function module:contextmenu.resetCustomMenus\n* @returns {void}\n*/\nexport const resetCustomMenus = function () { contextMenuExtensions = {}; };\n","/* eslint-disable jsdoc/require-file-overview */\n/**\n * Adapted from {@link https://github.com/uupaa/dynamic-import-polyfill/blob/master/importModule.js}.\n * @module importModule\n * @license MIT\n */\n\n/**\n * Converts a possible relative URL into an absolute one.\n * @param {string} url\n * @returns {string}\n */\nfunction toAbsoluteURL (url) {\n const a = document.createElement('a');\n a.setAttribute('href', url); // <a href=\"hoge.html\">\n return a.cloneNode(false).href; // -> \"http://example.com/hoge.html\"\n}\n\n/**\n * Add any of the whitelisted attributes to the script tag.\n * @param {HTMLScriptElement} script\n * @param {PlainObject<string, string>} atts\n * @returns {void}\n */\nfunction addScriptAtts (script, atts) {\n ['id', 'class', 'type'].forEach((prop) => {\n if (prop in atts) {\n script[prop] = atts[prop];\n }\n });\n}\n\n// Additions by Brett\n/**\n* @typedef {PlainObject} module:importModule.ImportConfig\n* @property {string} global The variable name to set on `window` (when not using the modular version)\n* @property {boolean} [returnDefault=false]\n*/\n\n/**\n* @function module:importModule.importSetGlobalDefault\n* @param {string|GenericArray<any>} url\n* @param {module:importModule.ImportConfig} config\n* @returns {Promise<any>} The value to which it resolves depends on the export of the targeted module.\n*/\nexport function importSetGlobalDefault (url, config) {\n return importSetGlobal(url, {...config, returnDefault: true});\n}\n/**\n* @function module:importModule.importSetGlobal\n* @param {string|string[]} url\n* @param {module:importModule.ImportConfig} config\n* @returns {Promise<ArbitraryModule>} The promise resolves to either an `ArbitraryModule` or\n* any other value depends on the export of the targeted module.\n*/\nexport async function importSetGlobal (url, {global: glob, returnDefault}) {\n // Todo: Replace calls to this function with `import()` when supported\n const modularVersion = !('svgEditor' in window) ||\n !window.svgEditor ||\n window.svgEditor.modules !== false;\n if (modularVersion) {\n return importModule(url, undefined, {returnDefault});\n }\n await importScript(url);\n return window[glob];\n}\n\n/**\n *\n * @author Brett Zamir (other items are from `dynamic-import-polyfill`)\n * @param {string|string[]} url\n * @param {PlainObject} [atts={}]\n * @returns {Promise<void|Error>} Resolves to `undefined` or rejects with an `Error` upon a\n * script loading error\n */\nexport function importScript (url, atts = {}) {\n if (Array.isArray(url)) {\n return Promise.all(url.map((u) => {\n return importScript(u, atts);\n }));\n }\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n const script = document.createElement('script');\n /**\n *\n * @returns {void}\n */\n function scriptOnError () {\n reject(new Error(`Failed to import: ${url}`));\n destructor();\n }\n /**\n *\n * @returns {void}\n */\n function scriptOnLoad () {\n resolve();\n destructor();\n }\n const destructor = () => {\n script.removeEventListener('error', scriptOnError);\n script.removeEventListener('load', scriptOnLoad);\n script.remove();\n script.src = '';\n };\n script.defer = 'defer';\n addScriptAtts(script, atts);\n script.addEventListener('error', scriptOnError);\n script.addEventListener('load', scriptOnLoad);\n script.src = url;\n\n document.head.append(script);\n });\n}\n\n/**\n*\n* @param {string|string[]} url\n* @param {PlainObject} [atts={}]\n* @param {PlainObject} opts\n* @param {boolean} [opts.returnDefault=false} = {}]\n* @returns {Promise<any>} Resolves to value of loading module or rejects with\n* `Error` upon a script loading error.\n*/\nexport function importModule (url, atts = {}, {returnDefault = false} = {}) {\n if (Array.isArray(url)) {\n return Promise.all(url.map((u) => {\n return importModule(u, atts);\n }));\n }\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n const vector = '$importModule$' + Math.random().toString(32).slice(2);\n const script = document.createElement('script');\n /**\n *\n * @returns {void}\n */\n function scriptOnError () {\n reject(new Error(`Failed to import: ${url}`));\n destructor();\n }\n /**\n *\n * @returns {void}\n */\n function scriptOnLoad () {\n resolve(window[vector]);\n destructor();\n }\n const destructor = () => {\n delete window[vector];\n script.removeEventListener('error', scriptOnError);\n script.removeEventListener('load', scriptOnLoad);\n script.remove();\n URL.revokeObjectURL(script.src);\n script.src = '';\n };\n addScriptAtts(script, atts);\n script.defer = 'defer';\n script.type = 'module';\n script.addEventListener('error', scriptOnError);\n script.addEventListener('load', scriptOnLoad);\n const absURL = toAbsoluteURL(url);\n const loader = `import * as m from '${absURL.replace(/'/g, \"\\\\'\")}'; window.${vector} = ${returnDefault ? 'm.default || ' : ''}m;`; // export Module\n const blob = new Blob([loader], {type: 'text/javascript'});\n script.src = URL.createObjectURL(blob);\n\n document.head.append(script);\n });\n}\n\nexport default importModule;\n","/**\n * Created by alexey2baranov on 28.01.17.\n */\n/*\n An extraction of the deparam method from Ben Alman's jQuery BBQ\n http://benalman.com/projects/jquery-bbq-plugin/\n */\n\nconst coerce_types = {'true': !0, 'false': !1, 'null': null};\n\nfunction deparam (params, coerce) {\n // console.log(params)\n const obj = {};\n\n // Iterate over all name=value pairs.\n params.replace(/\\+/g, ' ').split('&').forEach(function (v) {\n const param = v.split('=');\n\n let\n key = decodeURIComponent(param[0]),\n // If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it\n // into its component parts.\n keys = key.split(']['),\n keys_last = keys.length - 1;\n\n // If the first keys part contains [ and the last ends with ], then []\n // are correctly balanced.\n if (/\\[/.test(keys[0]) && /\\]$/.test(keys[keys_last])) {\n // Remove the trailing ] from the last keys part.\n keys[keys_last] = keys[keys_last].replace(/\\]$/, '');\n\n // Split first keys part into two parts on the [ and add them back onto\n // the beginning of the keys array.\n keys = keys.shift().split('[').concat(keys);\n\n keys_last = keys.length - 1;\n } else {\n // Basic 'foo' style key.\n keys_last = 0;\n }\n\n // Are we dealing with a name=value pair, or just a name?\n if (param.length >= 2) {\n let val = decodeURIComponent(param.slice(1).join('='));\n\n // Coerce values.\n if (coerce) {\n val = val && !isNaN(val) ? +val // number\n : val === 'undefined' ? undefined // undefined\n : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null\n : val; // string\n }\n\n if (keys_last) {\n let cur = obj;\n // Complex key, build deep object structure based on a few rules:\n // * The 'cur' pointer starts at the object top-level.\n // * [] = array push (n is set to array length), [n] = array if n is\n // numeric, otherwise object.\n // * If at the last keys part, set the value.\n // * For each keys part, if the current level is undefined create an\n // object or array based on the type of the next keys part.\n // * Move the 'cur' pointer to the next level.\n // * Rinse & repeat.\n for (let i = 0; i <= keys_last; i++) {\n key = keys[i] === '' ? cur.length : keys[i];\n cur = cur[key] = i < keys_last\n ? cur[key] || (keys[i + 1] && isNaN(keys[i + 1]) ? {} : [])\n : val;\n }\n\n } else {\n // Simple key, even simpler rules, since only scalars and shallow\n // arrays are allowed.\n\n if (Array.isArray(obj[key])) {\n // val is already an array, so push on the next value.\n obj[key].push(val);\n\n } else if (obj[key] !== undefined) {\n // val isn't an array, but since a second value has been specified,\n // convert val into an array.\n obj[key] = [obj[key], val];\n\n } else {\n // val is a scalar.\n obj[key] = val;\n }\n }\n\n } else if (key) {\n // No value was defined, so set something meaningful.\n obj[key] = coerce\n ? undefined\n : '';\n }\n });\n\n return obj;\n}\n\nexport default deparam;\n","/**\n * @module jQueryPluginDBox\n */\n/**\n* @param {external:jQuery} $\n* @param {PlainObject} [strings]\n* @param {PlainObject} [strings.ok]\n* @param {PlainObject} [strings.cancel]\n* @returns {external:jQuery}\n*/\nexport default function jQueryPluginDBox ($, strings = {ok: 'Ok', cancel: 'Cancel'}) {\n // This sets up alternative dialog boxes. They mostly work the same way as\n // their UI counterparts, expect instead of returning the result, a callback\n // needs to be included that returns the result as its first parameter.\n // In the future we may want to add additional types of dialog boxes, since\n // they should be easy to handle this way.\n $('#dialog_container').draggable({\n cancel: '#dialog_content, #dialog_buttons *',\n containment: 'window'\n }).css('position', 'absolute');\n\n const box = $('#dialog_box'),\n btnHolder = $('#dialog_buttons'),\n dialogContent = $('#dialog_content');\n\n /**\n * @typedef {PlainObject} module:jQueryPluginDBox.PromiseResultObject\n * @property {string|true} response\n * @property {boolean} checked\n */\n\n /**\n * Resolves to `false` (if cancelled), for prompts and selects\n * without checkboxes, it resolves to the value of the form control. For other\n * types without checkboxes, it resolves to `true`. For checkboxes, it resolves\n * to an object with the `response` key containing the same value as the previous\n * mentioned (string or `true`) and a `checked` (boolean) property.\n * @typedef {Promise<boolean|string|module:jQueryPluginDBox.PromiseResultObject>} module:jQueryPluginDBox.ResultPromise\n */\n /**\n * @typedef {PlainObject} module:jQueryPluginDBox.SelectOption\n * @property {string} text\n * @property {string} value\n */\n /**\n * @typedef {PlainObject} module:jQueryPluginDBox.CheckboxInfo\n * @property {string} label Label for the checkbox\n * @property {string} value Value of the checkbox\n * @property {string} tooltip Tooltip on the checkbox label\n * @property {boolean} checked Whether the checkbox is checked by default\n */\n /**\n * Triggered upon a change of value for the select pull-down.\n * @callback module:jQueryPluginDBox.SelectChangeListener\n * @returns {void}\n */\n /**\n * Creates a dialog of the specified type with a given message\n * and any defaults and type-specific metadata. Returns a `Promise`\n * which resolves differently depending on whether the dialog\n * was cancelled or okayed (with the response and any checked state).\n * @param {\"alert\"|\"prompt\"|\"select\"|\"process\"} type\n * @param {string} msg\n * @param {string} [defaultVal]\n * @param {module:jQueryPluginDBox.SelectOption[]} [opts]\n * @param {module:jQueryPluginDBox.SelectChangeListener} [changeListener]\n * @param {module:jQueryPluginDBox.CheckboxInfo} [checkbox]\n * @returns {jQueryPluginDBox.ResultPromise}\n */\n function dbox (type, msg, defaultVal, opts, changeListener, checkbox) {\n dialogContent.html('<p>' + msg.replace(/\\n/g, '</p><p>') + '</p>')\n .toggleClass('prompt', (type === 'prompt'));\n btnHolder.empty();\n\n const ok = $('<input type=\"button\" data-ok=\"\" value=\"' + strings.ok + '\">').appendTo(btnHolder);\n\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n if (type !== 'alert') {\n $('<input type=\"button\" value=\"' + strings.cancel + '\">')\n .appendTo(btnHolder)\n .click(function () {\n box.hide();\n resolve(false);\n });\n }\n\n let ctrl, chkbx;\n if (type === 'prompt') {\n ctrl = $('<input type=\"text\">').prependTo(btnHolder);\n ctrl.val(defaultVal || '');\n ctrl.bind('keydown', 'return', function () { ok.click(); });\n } else if (type === 'select') {\n const div = $('<div style=\"text-align:center;\">');\n ctrl = $(`<select aria-label=\"${msg}\">`).appendTo(div);\n if (checkbox) {\n const label = $('<label>').text(checkbox.label);\n chkbx = $('<input type=\"checkbox\">').appendTo(label);\n chkbx.val(checkbox.value);\n if (checkbox.tooltip) {\n label.attr('title', checkbox.tooltip);\n }\n chkbx.prop('checked', Boolean(checkbox.checked));\n div.append($('<div>').append(label));\n }\n $.each(opts || [], function (opt, val) {\n if (typeof val === 'object') {\n ctrl.append($('<option>').val(val.value).html(val.text));\n } else {\n ctrl.append($('<option>').html(val));\n }\n });\n dialogContent.append(div);\n if (defaultVal) {\n ctrl.val(defaultVal);\n }\n if (changeListener) {\n ctrl.bind('change', 'return', changeListener);\n }\n ctrl.bind('keydown', 'return', function () { ok.click(); });\n } else if (type === 'process') {\n ok.hide();\n }\n\n box.show();\n\n ok.click(function () {\n box.hide();\n const response = (type === 'prompt' || type === 'select') ? ctrl.val() : true;\n if (chkbx) {\n resolve({response, checked: chkbx.prop('checked')});\n return;\n }\n resolve(response);\n }).focus();\n\n if (type === 'prompt' || type === 'select') {\n ctrl.focus();\n }\n });\n }\n\n /**\n * @param {string} msg Message to alert\n * @returns {jQueryPluginDBox.ResultPromise}\n */\n $.alert = function (msg) {\n return dbox('alert', msg);\n };\n /**\n * @param {string} msg Message for which to ask confirmation\n * @returns {jQueryPluginDBox.ResultPromise}\n */\n $.confirm = function (msg) {\n return dbox('confirm', msg);\n };\n /**\n * @param {string} msg Message to indicate upon cancelable indicator\n * @returns {jQueryPluginDBox.ResultPromise}\n */\n $.process_cancel = function (msg) {\n return dbox('process', msg);\n };\n /**\n * @param {string} msg Message to accompany the prompt\n * @param {string} [defaultText=''] The default text to show for the prompt\n * @returns {jQueryPluginDBox.ResultPromise}\n */\n $.prompt = function (msg, defaultText = '') {\n return dbox('prompt', msg, defaultText);\n };\n $.select = function (msg, opts, changeListener, txt, checkbox) {\n return dbox('select', msg, txt, opts, changeListener, checkbox);\n };\n return $;\n}\n","/* globals jQuery */\n/**\n * Provides tools for the layer concept.\n * @module layer\n * @license MIT\n *\n * @copyright 2011 Jeff Schiller, 2016 Flint O'Brien\n */\n\nimport {NS} from './namespaces.js';\nimport {toXml, walkTree, isNullish} from './utilities.js';\n\nconst $ = jQuery;\n\n/**\n * This class encapsulates the concept of a layer in the drawing. It can be constructed with\n * an existing group element or, with three parameters, will create a new layer group element.\n *\n * @example\n * const l1 = new Layer('name', group); // Use the existing group for this layer.\n * const l2 = new Layer('name', group, svgElem); // Create a new group and add it to the DOM after group.\n * const l3 = new Layer('name', null, svgElem); // Create a new group and add it to the DOM as the last layer.\n * @memberof module:layer\n */\nclass Layer {\n /**\n * @param {string} name - Layer name\n * @param {SVGGElement|null} group - An existing SVG group element or null.\n * If group and no svgElem, use group for this layer.\n * If group and svgElem, create a new group element and insert it in the DOM after group.\n * If no group and svgElem, create a new group element and insert it in the DOM as the last layer.\n * @param {SVGGElement} [svgElem] - The SVG DOM element. If defined, use this to add\n * a new layer to the document.\n */\n constructor (name, group, svgElem) {\n this.name_ = name;\n this.group_ = svgElem ? null : group;\n\n if (svgElem) {\n // Create a group element with title and add it to the DOM.\n const svgdoc = svgElem.ownerDocument;\n this.group_ = svgdoc.createElementNS(NS.SVG, 'g');\n const layerTitle = svgdoc.createElementNS(NS.SVG, 'title');\n layerTitle.textContent = name;\n this.group_.append(layerTitle);\n if (group) {\n $(group).after(this.group_);\n } else {\n svgElem.append(this.group_);\n }\n }\n\n addLayerClass(this.group_);\n walkTree(this.group_, function (e) {\n e.setAttribute('style', 'pointer-events:inherit');\n });\n\n this.group_.setAttribute('style', svgElem ? 'pointer-events:all' : 'pointer-events:none');\n }\n\n /**\n * Get the layer's name.\n * @returns {string} The layer name\n */\n getName () {\n return this.name_;\n }\n\n /**\n * Get the group element for this layer.\n * @returns {SVGGElement} The layer SVG group\n */\n getGroup () {\n return this.group_;\n }\n\n /**\n * Active this layer so it takes pointer events.\n * @returns {void}\n */\n activate () {\n this.group_.setAttribute('style', 'pointer-events:all');\n }\n\n /**\n * Deactive this layer so it does NOT take pointer events.\n * @returns {void}\n */\n deactivate () {\n this.group_.setAttribute('style', 'pointer-events:none');\n }\n\n /**\n * Set this layer visible or hidden based on 'visible' parameter.\n * @param {boolean} visible - If true, make visible; otherwise, hide it.\n * @returns {void}\n */\n setVisible (visible) {\n const expected = visible === undefined || visible ? 'inline' : 'none';\n const oldDisplay = this.group_.getAttribute('display');\n if (oldDisplay !== expected) {\n this.group_.setAttribute('display', expected);\n }\n }\n\n /**\n * Is this layer visible?\n * @returns {boolean} True if visible.\n */\n isVisible () {\n return this.group_.getAttribute('display') !== 'none';\n }\n\n /**\n * Get layer opacity.\n * @returns {Float} Opacity value.\n */\n getOpacity () {\n const opacity = this.group_.getAttribute('opacity');\n if (isNullish(opacity)) {\n return 1;\n }\n return parseFloat(opacity);\n }\n\n /**\n * Sets the opacity of this layer. If opacity is not a value between 0.0 and 1.0,\n * nothing happens.\n * @param {Float} opacity - A float value in the range 0.0-1.0\n * @returns {void}\n */\n setOpacity (opacity) {\n if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) {\n this.group_.setAttribute('opacity', opacity);\n }\n }\n\n /**\n * Append children to this layer.\n * @param {SVGGElement} children - The children to append to this layer.\n * @returns {void}\n */\n appendChildren (children) {\n for (const child of children) {\n this.group_.append(child);\n }\n }\n\n /**\n * @returns {SVGTitleElement|null}\n */\n getTitleElement () {\n const len = this.group_.childNodes.length;\n for (let i = 0; i < len; ++i) {\n const child = this.group_.childNodes.item(i);\n if (child && child.tagName === 'title') {\n return child;\n }\n }\n return null;\n }\n\n /**\n * Set the name of this layer.\n * @param {string} name - The new name.\n * @param {module:history.HistoryRecordingService} hrService - History recording service\n * @returns {string|null} The new name if changed; otherwise, null.\n */\n setName (name, hrService) {\n const previousName = this.name_;\n name = toXml(name);\n // now change the underlying title element contents\n const title = this.getTitleElement();\n if (title) {\n $(title).empty();\n title.textContent = name;\n this.name_ = name;\n if (hrService) {\n hrService.changeElement(title, {'#text': previousName});\n }\n return this.name_;\n }\n return null;\n }\n\n /**\n * Remove this layer's group from the DOM. No more functions on group can be called after this.\n * @returns {SVGGElement} The layer SVG group that was just removed.\n */\n removeGroup () {\n const parent = this.group_.parentNode;\n const group = parent.removeChild(this.group_);\n this.group_ = undefined;\n return group;\n }\n}\n/**\n * @property {string} CLASS_NAME - class attribute assigned to all layer groups.\n */\nLayer.CLASS_NAME = 'layer';\n\n/**\n * @property {RegExp} CLASS_REGEX - Used to test presence of class Layer.CLASS_NAME\n */\nLayer.CLASS_REGEX = new RegExp('(\\\\s|^)' + Layer.CLASS_NAME + '(\\\\s|$)');\n\n/**\n * Add class `Layer.CLASS_NAME` to the element (usually `class='layer'`).\n *\n * @param {SVGGElement} elem - The SVG element to update\n * @returns {void}\n */\nfunction addLayerClass (elem) {\n const classes = elem.getAttribute('class');\n if (isNullish(classes) || !classes.length) {\n elem.setAttribute('class', Layer.CLASS_NAME);\n } else if (!Layer.CLASS_REGEX.test(classes)) {\n elem.setAttribute('class', classes + ' ' + Layer.CLASS_NAME);\n }\n}\n\nexport default Layer;\n","/**\n * HistoryRecordingService component of history.\n * @module history\n * @license MIT\n * @copyright 2016 Flint O'Brien\n */\n\nimport {\n BatchCommand, MoveElementCommand, InsertElementCommand, RemoveElementCommand,\n ChangeElementCommand\n} from './history.js';\n\n/**\n * History recording service.\n *\n * A self-contained service interface for recording history. Once injected, no other dependencies\n * or globals are required (example: UndoManager, command types, etc.). Easy to mock for unit tests.\n * Built on top of history classes in history.js.\n *\n * There is a simple start/end interface for batch commands.\n *\n * HistoryRecordingService.NO_HISTORY is a singleton that can be passed in to functions\n * that record history. This helps when the caller requires that no history be recorded.\n *\n * The following will record history: insert, batch, insert.\n * @example\n * hrService = new history.HistoryRecordingService(this.undoMgr);\n * hrService.insertElement(elem, text); // add simple command to history.\n * hrService.startBatchCommand('create two elements');\n * hrService.changeElement(elem, attrs, text); // add to batchCommand\n * hrService.changeElement(elem, attrs2, text); // add to batchCommand\n * hrService.endBatchCommand(); // add batch command with two change commands to history.\n * hrService.insertElement(elem, text); // add simple command to history.\n *\n * @example\n * // Note that all functions return this, so commands can be chained, like so:\n * hrService\n * .startBatchCommand('create two elements')\n * .insertElement(elem, text)\n * .changeElement(elem, attrs, text)\n * .endBatchCommand();\n *\n * @memberof module:history\n */\nclass HistoryRecordingService {\n /**\n * @param {history.UndoManager|null} undoManager - The undo manager.\n * A value of `null` is valid for cases where no history recording is required.\n * See singleton: {@link module:history.HistoryRecordingService.HistoryRecordingService.NO_HISTORY}\n */\n constructor (undoManager) {\n this.undoManager_ = undoManager;\n this.currentBatchCommand_ = null;\n this.batchCommandStack_ = [];\n }\n\n /**\n * Start a batch command so multiple commands can recorded as a single history command.\n * Requires a corresponding call to endBatchCommand. Start and end commands can be nested.\n *\n * @param {string} text - Optional string describing the batch command.\n * @returns {module:history.HistoryRecordingService}\n */\n startBatchCommand (text) {\n if (!this.undoManager_) { return this; }\n this.currentBatchCommand_ = new BatchCommand(text);\n this.batchCommandStack_.push(this.currentBatchCommand_);\n return this;\n }\n\n /**\n * End a batch command and add it to the history or a parent batch command.\n * @returns {module:history.HistoryRecordingService}\n */\n endBatchCommand () {\n if (!this.undoManager_) { return this; }\n if (this.currentBatchCommand_) {\n const batchCommand = this.currentBatchCommand_;\n this.batchCommandStack_.pop();\n const {length: len} = this.batchCommandStack_;\n this.currentBatchCommand_ = len ? this.batchCommandStack_[len - 1] : null;\n this.addCommand_(batchCommand);\n }\n return this;\n }\n\n /**\n * Add a `MoveElementCommand` to the history or current batch command.\n * @param {Element} elem - The DOM element that was moved\n * @param {Element} oldNextSibling - The element's next sibling before it was moved\n * @param {Element} oldParent - The element's parent before it was moved\n * @param {string} [text] - An optional string visible to user related to this change\n * @returns {module:history.HistoryRecordingService}\n */\n moveElement (elem, oldNextSibling, oldParent, text) {\n if (!this.undoManager_) { return this; }\n this.addCommand_(new MoveElementCommand(elem, oldNextSibling, oldParent, text));\n return this;\n }\n\n /**\n * Add an `InsertElementCommand` to the history or current batch command.\n * @param {Element} elem - The DOM element that was added\n * @param {string} [text] - An optional string visible to user related to this change\n * @returns {module:history.HistoryRecordingService}\n */\n insertElement (elem, text) {\n if (!this.undoManager_) { return this; }\n this.addCommand_(new InsertElementCommand(elem, text));\n return this;\n }\n\n /**\n * Add a `RemoveElementCommand` to the history or current batch command.\n * @param {Element} elem - The DOM element that was removed\n * @param {Element} oldNextSibling - The element's next sibling before it was removed\n * @param {Element} oldParent - The element's parent before it was removed\n * @param {string} [text] - An optional string visible to user related to this change\n * @returns {module:history.HistoryRecordingService}\n */\n removeElement (elem, oldNextSibling, oldParent, text) {\n if (!this.undoManager_) { return this; }\n this.addCommand_(new RemoveElementCommand(elem, oldNextSibling, oldParent, text));\n return this;\n }\n\n /**\n * Add a `ChangeElementCommand` to the history or current batch command.\n * @param {Element} elem - The DOM element that was changed\n * @param {module:history.CommandAttributes} attrs - An object with the attributes to be changed and the values they had *before* the change\n * @param {string} [text] - An optional string visible to user related to this change\n * @returns {module:history.HistoryRecordingService}\n */\n changeElement (elem, attrs, text) {\n if (!this.undoManager_) { return this; }\n this.addCommand_(new ChangeElementCommand(elem, attrs, text));\n return this;\n }\n\n /**\n * Private function to add a command to the history or current batch command.\n * @private\n * @param {Command} cmd\n * @returns {module:history.HistoryRecordingService|void}\n */\n addCommand_ (cmd) {\n if (!this.undoManager_) { return this; }\n if (this.currentBatchCommand_) {\n this.currentBatchCommand_.addSubCommand(cmd);\n } else {\n this.undoManager_.addCommandToHistory(cmd);\n }\n return undefined;\n }\n}\n/**\n * @memberof module:history.HistoryRecordingService\n * @property {module:history.HistoryRecordingService} NO_HISTORY - Singleton that can be passed to functions that record history, but the caller requires that no history be recorded.\n */\nHistoryRecordingService.NO_HISTORY = new HistoryRecordingService();\nexport default HistoryRecordingService;\n","/* globals jQuery */\n/**\n * Tools for drawing.\n * @module draw\n * @license MIT\n * @copyright 2011 Jeff Schiller\n */\n\nimport Layer from './layer.js';\nimport HistoryRecordingService from './historyrecording.js';\n\nimport {NS} from './namespaces.js';\nimport {isOpera} from './browser.js';\nimport {\n toXml, getElem,\n copyElem as utilCopyElem\n} from './utilities.js';\nimport {\n BatchCommand, RemoveElementCommand, MoveElementCommand, ChangeElementCommand\n} from './history.js';\n\nconst $ = jQuery;\n\nconst visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'.split(',');\n\nconst RandomizeModes = {\n LET_DOCUMENT_DECIDE: 0,\n ALWAYS_RANDOMIZE: 1,\n NEVER_RANDOMIZE: 2\n};\nlet randIds = RandomizeModes.LET_DOCUMENT_DECIDE;\n// Array with current disabled elements (for in-group editing)\nlet disabledElems = [];\n\n/**\n * Get a HistoryRecordingService.\n * @param {module:history.HistoryRecordingService} [hrService] - if exists, return it instead of creating a new service.\n * @returns {module:history.HistoryRecordingService}\n */\nfunction historyRecordingService (hrService) {\n return hrService || new HistoryRecordingService(canvas_.undoMgr);\n}\n\n/**\n * Find the layer name in a group element.\n * @param {Element} group The group element to search in.\n * @returns {string} The layer name or empty string.\n */\nfunction findLayerNameInGroup (group) {\n return $('title', group).text() ||\n (isOpera() && group.querySelectorAll\n // Hack for Opera 10.60\n ? $(group.querySelectorAll('title')).text()\n : '');\n}\n\n/**\n * Given a set of names, return a new unique name.\n * @param {string[]} existingLayerNames - Existing layer names.\n * @returns {string} - The new name.\n */\nfunction getNewLayerName (existingLayerNames) {\n let i = 1;\n // TODO(codedread): What about internationalization of \"Layer\"?\n while (existingLayerNames.includes(('Layer ' + i))) { i++; }\n return 'Layer ' + i;\n}\n\n/**\n * This class encapsulates the concept of a SVG-edit drawing.\n */\nexport class Drawing {\n /**\n * @param {SVGSVGElement} svgElem - The SVG DOM Element that this JS object\n * encapsulates. If the svgElem has a se:nonce attribute on it, then\n * IDs will use the nonce as they are generated.\n * @param {string} [optIdPrefix=svg_] - The ID prefix to use.\n * @throws {Error} If not initialized with an SVG element\n */\n constructor (svgElem, optIdPrefix) {\n if (!svgElem || !svgElem.tagName || !svgElem.namespaceURI ||\n svgElem.tagName !== 'svg' || svgElem.namespaceURI !== NS.SVG) {\n throw new Error('Error: svgedit.draw.Drawing instance initialized without a <svg> element');\n }\n\n /**\n * The SVG DOM Element that represents this drawing.\n * @type {SVGSVGElement}\n */\n this.svgElem_ = svgElem;\n\n /**\n * The latest object number used in this drawing.\n * @type {Integer}\n */\n this.obj_num = 0;\n\n /**\n * The prefix to prepend to each element id in the drawing.\n * @type {string}\n */\n this.idPrefix = optIdPrefix || 'svg_';\n\n /**\n * An array of released element ids to immediately reuse.\n * @type {Integer[]}\n */\n this.releasedNums = [];\n\n /**\n * The z-ordered array of Layer objects. Each layer has a name\n * and group element.\n * The first layer is the one at the bottom of the rendering.\n * @type {Layer[]}\n */\n this.all_layers = [];\n\n /**\n * Map of all_layers by name.\n *\n * Note: Layers are ordered, but referenced externally by name; so, we need both container\n * types depending on which function is called (i.e. all_layers and layer_map).\n *\n * @type {PlainObject<string, Layer>}\n */\n this.layer_map = {};\n\n /**\n * The current layer being used.\n * @type {Layer}\n */\n this.current_layer = null;\n\n /**\n * The nonce to use to uniquely identify elements across drawings.\n * @type {!string}\n */\n this.nonce_ = '';\n const n = this.svgElem_.getAttributeNS(NS.SE, 'nonce');\n // If already set in the DOM, use the nonce throughout the document\n // else, if randomizeIds(true) has been called, create and set the nonce.\n if (n && randIds !== RandomizeModes.NEVER_RANDOMIZE) {\n this.nonce_ = n;\n } else if (randIds === RandomizeModes.ALWAYS_RANDOMIZE) {\n this.setNonce(Math.floor(Math.random() * 100001));\n }\n }\n\n /**\n * @param {string} id Element ID to retrieve\n * @returns {Element} SVG element within the root SVGSVGElement\n */\n getElem_ (id) {\n if (this.svgElem_.querySelector) {\n // querySelector lookup\n return this.svgElem_.querySelector('#' + id);\n }\n // jQuery lookup: twice as slow as xpath in FF\n return $(this.svgElem_).find('[id=' + id + ']')[0];\n }\n\n /**\n * @returns {SVGSVGElement}\n */\n getSvgElem () {\n return this.svgElem_;\n }\n\n /**\n * @returns {!(string|Integer)} The previously set nonce\n */\n getNonce () {\n return this.nonce_;\n }\n\n /**\n * @param {!(string|Integer)} n The nonce to set\n * @returns {void}\n */\n setNonce (n) {\n this.svgElem_.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE);\n this.svgElem_.setAttributeNS(NS.SE, 'se:nonce', n);\n this.nonce_ = n;\n }\n\n /**\n * Clears any previously set nonce.\n * @returns {void}\n */\n clearNonce () {\n // We deliberately leave any se:nonce attributes alone,\n // we just don't use it to randomize ids.\n this.nonce_ = '';\n }\n\n /**\n * Returns the latest object id as a string.\n * @returns {string} The latest object Id.\n */\n getId () {\n return this.nonce_\n ? this.idPrefix + this.nonce_ + '_' + this.obj_num\n : this.idPrefix + this.obj_num;\n }\n\n /**\n * Returns the next object Id as a string.\n * @returns {string} The next object Id to use.\n */\n getNextId () {\n const oldObjNum = this.obj_num;\n let restoreOldObjNum = false;\n\n // If there are any released numbers in the release stack,\n // use the last one instead of the next obj_num.\n // We need to temporarily use obj_num as that is what getId() depends on.\n if (this.releasedNums.length > 0) {\n this.obj_num = this.releasedNums.pop();\n restoreOldObjNum = true;\n } else {\n // If we are not using a released id, then increment the obj_num.\n this.obj_num++;\n }\n\n // Ensure the ID does not exist.\n let id = this.getId();\n while (this.getElem_(id)) {\n if (restoreOldObjNum) {\n this.obj_num = oldObjNum;\n restoreOldObjNum = false;\n }\n this.obj_num++;\n id = this.getId();\n }\n // Restore the old object number if required.\n if (restoreOldObjNum) {\n this.obj_num = oldObjNum;\n }\n return id;\n }\n\n /**\n * Releases the object Id, letting it be used as the next id in getNextId().\n * This method DOES NOT remove any elements from the DOM, it is expected\n * that client code will do this.\n * @param {string} id - The id to release.\n * @returns {boolean} True if the id was valid to be released, false otherwise.\n */\n releaseId (id) {\n // confirm if this is a valid id for this Document, else return false\n const front = this.idPrefix + (this.nonce_ ? this.nonce_ + '_' : '');\n if (typeof id !== 'string' || !id.startsWith(front)) {\n return false;\n }\n // extract the obj_num of this id\n const num = parseInt(id.substr(front.length));\n\n // if we didn't get a positive number or we already released this number\n // then return false.\n if (typeof num !== 'number' || num <= 0 || this.releasedNums.includes(num)) {\n return false;\n }\n\n // push the released number into the released queue\n this.releasedNums.push(num);\n\n return true;\n }\n\n /**\n * Returns the number of layers in the current drawing.\n * @returns {Integer} The number of layers in the current drawing.\n */\n getNumLayers () {\n return this.all_layers.length;\n }\n\n /**\n * Check if layer with given name already exists.\n * @param {string} name - The layer name to check\n * @returns {boolean}\n */\n hasLayer (name) {\n return this.layer_map[name] !== undefined;\n }\n\n /**\n * Returns the name of the ith layer. If the index is out of range, an empty string is returned.\n * @param {Integer} i - The zero-based index of the layer you are querying.\n * @returns {string} The name of the ith layer (or the empty string if none found)\n */\n getLayerName (i) {\n return i >= 0 && i < this.getNumLayers() ? this.all_layers[i].getName() : '';\n }\n\n /**\n * @returns {SVGGElement|null} The SVGGElement representing the current layer.\n */\n getCurrentLayer () {\n return this.current_layer ? this.current_layer.getGroup() : null;\n }\n\n /**\n * Get a layer by name.\n * @param {string} name\n * @returns {SVGGElement} The SVGGElement representing the named layer or null.\n */\n getLayerByName (name) {\n const layer = this.layer_map[name];\n return layer ? layer.getGroup() : null;\n }\n\n /**\n * Returns the name of the currently selected layer. If an error occurs, an empty string\n * is returned.\n * @returns {string} The name of the currently active layer (or the empty string if none found).\n */\n getCurrentLayerName () {\n return this.current_layer ? this.current_layer.getName() : '';\n }\n\n /**\n * Set the current layer's name.\n * @param {string} name - The new name.\n * @param {module:history.HistoryRecordingService} hrService - History recording service\n * @returns {string|null} The new name if changed; otherwise, null.\n */\n setCurrentLayerName (name, hrService) {\n let finalName = null;\n if (this.current_layer) {\n const oldName = this.current_layer.getName();\n finalName = this.current_layer.setName(name, hrService);\n if (finalName) {\n delete this.layer_map[oldName];\n this.layer_map[finalName] = this.current_layer;\n }\n }\n return finalName;\n }\n\n /**\n * Set the current layer's position.\n * @param {Integer} newpos - The zero-based index of the new position of the layer. Range should be 0 to layers-1\n * @returns {{title: SVGGElement, previousName: string}|null} If the name was changed, returns {title:SVGGElement, previousName:string}; otherwise null.\n */\n setCurrentLayerPosition (newpos) {\n const layerCount = this.getNumLayers();\n if (!this.current_layer || newpos < 0 || newpos >= layerCount) {\n return null;\n }\n\n let oldpos;\n for (oldpos = 0; oldpos < layerCount; ++oldpos) {\n if (this.all_layers[oldpos] === this.current_layer) { break; }\n }\n // some unknown error condition (current_layer not in all_layers)\n if (oldpos === layerCount) { return null; }\n\n if (oldpos !== newpos) {\n // if our new position is below us, we need to insert before the node after newpos\n const currentGroup = this.current_layer.getGroup();\n const oldNextSibling = currentGroup.nextSibling;\n\n let refGroup = null;\n if (newpos > oldpos) {\n if (newpos < layerCount - 1) {\n refGroup = this.all_layers[newpos + 1].getGroup();\n }\n // if our new position is above us, we need to insert before the node at newpos\n } else {\n refGroup = this.all_layers[newpos].getGroup();\n }\n this.svgElem_.insertBefore(currentGroup, refGroup); // Ok to replace with `refGroup.before(currentGroup);`?\n\n this.identifyLayers();\n this.setCurrentLayer(this.getLayerName(newpos));\n\n return {\n currentGroup,\n oldNextSibling\n };\n }\n return null;\n }\n\n /**\n * @param {module:history.HistoryRecordingService} hrService\n * @returns {void}\n */\n mergeLayer (hrService) {\n const currentGroup = this.current_layer.getGroup();\n const prevGroup = $(currentGroup).prev()[0];\n if (!prevGroup) { return; }\n\n hrService.startBatchCommand('Merge Layer');\n\n const layerNextSibling = currentGroup.nextSibling;\n hrService.removeElement(currentGroup, layerNextSibling, this.svgElem_);\n\n while (currentGroup.firstChild) {\n const child = currentGroup.firstChild;\n if (child.localName === 'title') {\n hrService.removeElement(child, child.nextSibling, currentGroup);\n child.remove();\n continue;\n }\n const oldNextSibling = child.nextSibling;\n prevGroup.append(child);\n hrService.moveElement(child, oldNextSibling, currentGroup);\n }\n\n // Remove current layer's group\n this.current_layer.removeGroup();\n // Remove the current layer and set the previous layer as the new current layer\n const index = this.all_layers.indexOf(this.current_layer);\n if (index > 0) {\n const name = this.current_layer.getName();\n this.current_layer = this.all_layers[index - 1];\n this.all_layers.splice(index, 1);\n delete this.layer_map[name];\n }\n\n hrService.endBatchCommand();\n }\n\n /**\n * @param {module:history.HistoryRecordingService} hrService\n * @returns {void}\n */\n mergeAllLayers (hrService) {\n // Set the current layer to the last layer.\n this.current_layer = this.all_layers[this.all_layers.length - 1];\n\n hrService.startBatchCommand('Merge all Layers');\n while (this.all_layers.length > 1) {\n this.mergeLayer(hrService);\n }\n hrService.endBatchCommand();\n }\n\n /**\n * Sets the current layer. If the name is not a valid layer name, then this\n * function returns `false`. Otherwise it returns `true`. This is not an\n * undo-able action.\n * @param {string} name - The name of the layer you want to switch to.\n * @returns {boolean} `true` if the current layer was switched, otherwise `false`\n */\n setCurrentLayer (name) {\n const layer = this.layer_map[name];\n if (layer) {\n if (this.current_layer) {\n this.current_layer.deactivate();\n }\n this.current_layer = layer;\n this.current_layer.activate();\n return true;\n }\n return false;\n }\n\n /**\n * Deletes the current layer from the drawing and then clears the selection.\n * This function then calls the 'changed' handler. This is an undoable action.\n * @todo Does this actually call the 'changed' handler?\n * @returns {SVGGElement} The SVGGElement of the layer removed or null.\n */\n deleteCurrentLayer () {\n if (this.current_layer && this.getNumLayers() > 1) {\n const oldLayerGroup = this.current_layer.removeGroup();\n this.identifyLayers();\n return oldLayerGroup;\n }\n return null;\n }\n\n /**\n * Updates layer system and sets the current layer to the\n * top-most layer (last `<g>` child of this drawing).\n * @returns {void}\n */\n identifyLayers () {\n this.all_layers = [];\n this.layer_map = {};\n const numchildren = this.svgElem_.childNodes.length;\n // loop through all children of SVG element\n const orphans = [], layernames = [];\n let layer = null;\n let childgroups = false;\n for (let i = 0; i < numchildren; ++i) {\n const child = this.svgElem_.childNodes.item(i);\n // for each g, find its layer name\n if (child && child.nodeType === 1) {\n if (child.tagName === 'g') {\n childgroups = true;\n const name = findLayerNameInGroup(child);\n if (name) {\n layernames.push(name);\n layer = new Layer(name, child);\n this.all_layers.push(layer);\n this.layer_map[name] = layer;\n } else {\n // if group did not have a name, it is an orphan\n orphans.push(child);\n }\n } else if (visElems.includes(child.nodeName)) {\n // Child is \"visible\" (i.e. not a <title> or <defs> element), so it is an orphan\n orphans.push(child);\n }\n }\n }\n\n // If orphans or no layers found, create a new layer and add all the orphans to it\n if (orphans.length > 0 || !childgroups) {\n layer = new Layer(getNewLayerName(layernames), null, this.svgElem_);\n layer.appendChildren(orphans);\n this.all_layers.push(layer);\n this.layer_map[name] = layer;\n } else {\n layer.activate();\n }\n this.current_layer = layer;\n }\n\n /**\n * Creates a new top-level layer in the drawing with the given name and\n * makes it the current layer.\n * @param {string} name - The given name. If the layer name exists, a new name will be generated.\n * @param {module:history.HistoryRecordingService} hrService - History recording service\n * @returns {SVGGElement} The SVGGElement of the new layer, which is\n * also the current layer of this drawing.\n */\n createLayer (name, hrService) {\n if (this.current_layer) {\n this.current_layer.deactivate();\n }\n // Check for duplicate name.\n if (name === undefined || name === null || name === '' || this.layer_map[name]) {\n name = getNewLayerName(Object.keys(this.layer_map));\n }\n\n // Crate new layer and add to DOM as last layer\n const layer = new Layer(name, null, this.svgElem_);\n // Like to assume hrService exists, but this is backwards compatible with old version of createLayer.\n if (hrService) {\n hrService.startBatchCommand('Create Layer');\n hrService.insertElement(layer.getGroup());\n hrService.endBatchCommand();\n }\n\n this.all_layers.push(layer);\n this.layer_map[name] = layer;\n this.current_layer = layer;\n return layer.getGroup();\n }\n\n /**\n * Creates a copy of the current layer with the given name and makes it the current layer.\n * @param {string} name - The given name. If the layer name exists, a new name will be generated.\n * @param {module:history.HistoryRecordingService} hrService - History recording service\n * @returns {SVGGElement} The SVGGElement of the new layer, which is\n * also the current layer of this drawing.\n */\n cloneLayer (name, hrService) {\n if (!this.current_layer) { return null; }\n this.current_layer.deactivate();\n // Check for duplicate name.\n if (name === undefined || name === null || name === '' || this.layer_map[name]) {\n name = getNewLayerName(Object.keys(this.layer_map));\n }\n\n // Create new group and add to DOM just after current_layer\n const currentGroup = this.current_layer.getGroup();\n const layer = new Layer(name, currentGroup, this.svgElem_);\n const group = layer.getGroup();\n\n // Clone children\n const children = [...currentGroup.childNodes];\n children.forEach((child) => {\n if (child.localName === 'title') { return; }\n group.append(this.copyElem(child));\n });\n\n if (hrService) {\n hrService.startBatchCommand('Duplicate Layer');\n hrService.insertElement(group);\n hrService.endBatchCommand();\n }\n\n // Update layer containers and current_layer.\n const index = this.all_layers.indexOf(this.current_layer);\n if (index >= 0) {\n this.all_layers.splice(index + 1, 0, layer);\n } else {\n this.all_layers.push(layer);\n }\n this.layer_map[name] = layer;\n this.current_layer = layer;\n return group;\n }\n\n /**\n * Returns whether the layer is visible. If the layer name is not valid,\n * then this function returns `false`.\n * @param {string} layerName - The name of the layer which you want to query.\n * @returns {boolean} The visibility state of the layer, or `false` if the layer name was invalid.\n */\n getLayerVisibility (layerName) {\n const layer = this.layer_map[layerName];\n return layer ? layer.isVisible() : false;\n }\n\n /**\n * Sets the visibility of the layer. If the layer name is not valid, this\n * function returns `null`, otherwise it returns the `SVGElement` representing\n * the layer. This is an undo-able action.\n * @param {string} layerName - The name of the layer to change the visibility\n * @param {boolean} bVisible - Whether the layer should be visible\n * @returns {?SVGGElement} The SVGGElement representing the layer if the\n * `layerName` was valid, otherwise `null`.\n */\n setLayerVisibility (layerName, bVisible) {\n if (typeof bVisible !== 'boolean') {\n return null;\n }\n const layer = this.layer_map[layerName];\n if (!layer) { return null; }\n layer.setVisible(bVisible);\n return layer.getGroup();\n }\n\n /**\n * Returns the opacity of the given layer. If the input name is not a layer, `null` is returned.\n * @param {string} layerName - name of the layer on which to get the opacity\n * @returns {?Float} The opacity value of the given layer. This will be a value between 0.0 and 1.0, or `null`\n * if `layerName` is not a valid layer\n */\n getLayerOpacity (layerName) {\n const layer = this.layer_map[layerName];\n if (!layer) { return null; }\n return layer.getOpacity();\n }\n\n /**\n * Sets the opacity of the given layer. If the input name is not a layer,\n * nothing happens. If opacity is not a value between 0.0 and 1.0, then\n * nothing happens.\n * NOTE: this function exists solely to apply a highlighting/de-emphasis\n * effect to a layer. When it is possible for a user to affect the opacity\n * of a layer, we will need to allow this function to produce an undo-able\n * action.\n * @param {string} layerName - Name of the layer on which to set the opacity\n * @param {Float} opacity - A float value in the range 0.0-1.0\n * @returns {void}\n */\n setLayerOpacity (layerName, opacity) {\n if (typeof opacity !== 'number' || opacity < 0.0 || opacity > 1.0) {\n return;\n }\n const layer = this.layer_map[layerName];\n if (layer) {\n layer.setOpacity(opacity);\n }\n }\n\n /**\n * Create a clone of an element, updating its ID and its children's IDs when needed.\n * @param {Element} el - DOM element to clone\n * @returns {Element}\n */\n copyElem (el) {\n const that = this;\n const getNextIdClosure = function () { return that.getNextId(); };\n return utilCopyElem(el, getNextIdClosure);\n }\n}\n\n/**\n * Called to ensure that drawings will or will not have randomized ids.\n * The currentDrawing will have its nonce set if it doesn't already.\n * @function module:draw.randomizeIds\n * @param {boolean} enableRandomization - flag indicating if documents should have randomized ids\n * @param {draw.Drawing} currentDrawing\n * @returns {void}\n */\nexport const randomizeIds = function (enableRandomization, currentDrawing) {\n randIds = enableRandomization === false\n ? RandomizeModes.NEVER_RANDOMIZE\n : RandomizeModes.ALWAYS_RANDOMIZE;\n\n if (randIds === RandomizeModes.ALWAYS_RANDOMIZE && !currentDrawing.getNonce()) {\n currentDrawing.setNonce(Math.floor(Math.random() * 100001));\n } else if (randIds === RandomizeModes.NEVER_RANDOMIZE && currentDrawing.getNonce()) {\n currentDrawing.clearNonce();\n }\n};\n\n// Layer API Functions\n\n/**\n* Group: Layers.\n*/\n\n/**\n * @see {@link https://api.jquery.com/jQuery.data/}\n * @name external:jQuery.data\n */\n\n/**\n * @interface module:draw.DrawCanvasInit\n * @property {module:path.pathActions} pathActions\n * @property {external:jQuery.data} elData\n * @property {module:history.UndoManager} undoMgr\n */\n/**\n * @function module:draw.DrawCanvasInit#getCurrentGroup\n * @returns {Element}\n */\n/**\n * @function module:draw.DrawCanvasInit#setCurrentGroup\n * @param {Element} cg\n * @returns {void}\n*/\n/**\n * @function module:draw.DrawCanvasInit#getSelectedElements\n * @returns {Element[]} the array with selected DOM elements\n*/\n/**\n * @function module:draw.DrawCanvasInit#getSVGContent\n * @returns {SVGSVGElement}\n */\n/**\n * @function module:draw.DrawCanvasInit#getCurrentDrawing\n * @returns {module:draw.Drawing}\n */\n/**\n * @function module:draw.DrawCanvasInit#clearSelection\n * @param {boolean} [noCall] - When `true`, does not call the \"selected\" handler\n * @returns {void}\n*/\n/**\n * Run the callback function associated with the given event.\n * @function module:draw.DrawCanvasInit#call\n * @param {\"changed\"|\"contextset\"} ev - String with the event name\n * @param {module:svgcanvas.SvgCanvas#event:changed|module:svgcanvas.SvgCanvas#event:contextset} arg - Argument to pass through to the callback\n * function. If the event is \"changed\", a (single-item) array of `Element`s is\n * passed. If the event is \"contextset\", the arg is `null` or `Element`.\n * @returns {void}\n */\n/**\n * @function module:draw.DrawCanvasInit#addCommandToHistory\n * @param {Command} cmd\n * @returns {void}\n*/\n/**\n * @function module:draw.DrawCanvasInit#changeSVGContent\n * @returns {void}\n */\n\nlet canvas_;\n/**\n* @function module:draw.init\n* @param {module:draw.DrawCanvasInit} canvas\n* @returns {void}\n*/\nexport const init = function (canvas) {\n canvas_ = canvas;\n};\n\n/**\n* Updates layer system.\n* @function module:draw.identifyLayers\n* @returns {void}\n*/\nexport const identifyLayers = function () {\n leaveContext();\n canvas_.getCurrentDrawing().identifyLayers();\n};\n\n/**\n* Creates a new top-level layer in the drawing with the given name, sets the current layer\n* to it, and then clears the selection. This function then calls the 'changed' handler.\n* This is an undoable action.\n* @function module:draw.createLayer\n* @param {string} name - The given name\n* @param {module:history.HistoryRecordingService} hrService\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nexport const createLayer = function (name, hrService) {\n const newLayer = canvas_.getCurrentDrawing().createLayer(\n name,\n historyRecordingService(hrService)\n );\n canvas_.clearSelection();\n canvas_.call('changed', [newLayer]);\n};\n\n/**\n * Creates a new top-level layer in the drawing with the given name, copies all the current layer's contents\n * to it, and then clears the selection. This function then calls the 'changed' handler.\n * This is an undoable action.\n * @function module:draw.cloneLayer\n * @param {string} name - The given name. If the layer name exists, a new name will be generated.\n * @param {module:history.HistoryRecordingService} hrService - History recording service\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @returns {void}\n */\nexport const cloneLayer = function (name, hrService) {\n // Clone the current layer and make the cloned layer the new current layer\n const newLayer = canvas_.getCurrentDrawing().cloneLayer(name, historyRecordingService(hrService));\n\n canvas_.clearSelection();\n leaveContext();\n canvas_.call('changed', [newLayer]);\n};\n\n/**\n* Deletes the current layer from the drawing and then clears the selection. This function\n* then calls the 'changed' handler. This is an undoable action.\n* @function module:draw.deleteCurrentLayer\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {boolean} `true` if an old layer group was found to delete\n*/\nexport const deleteCurrentLayer = function () {\n let currentLayer = canvas_.getCurrentDrawing().getCurrentLayer();\n const {nextSibling} = currentLayer;\n const parent = currentLayer.parentNode;\n currentLayer = canvas_.getCurrentDrawing().deleteCurrentLayer();\n if (currentLayer) {\n const batchCmd = new BatchCommand('Delete Layer');\n // store in our Undo History\n batchCmd.addSubCommand(new RemoveElementCommand(currentLayer, nextSibling, parent));\n canvas_.addCommandToHistory(batchCmd);\n canvas_.clearSelection();\n canvas_.call('changed', [parent]);\n return true;\n }\n return false;\n};\n\n/**\n* Sets the current layer. If the name is not a valid layer name, then this function returns\n* false. Otherwise it returns true. This is not an undo-able action.\n* @function module:draw.setCurrentLayer\n* @param {string} name - The name of the layer you want to switch to.\n* @returns {boolean} true if the current layer was switched, otherwise false\n*/\nexport const setCurrentLayer = function (name) {\n const result = canvas_.getCurrentDrawing().setCurrentLayer(toXml(name));\n if (result) {\n canvas_.clearSelection();\n }\n return result;\n};\n\n/**\n* Renames the current layer. If the layer name is not valid (i.e. unique), then this function\n* does nothing and returns `false`, otherwise it returns `true`. This is an undo-able action.\n* @function module:draw.renameCurrentLayer\n* @param {string} newName - the new name you want to give the current layer. This name must\n* be unique among all layer names.\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {boolean} Whether the rename succeeded\n*/\nexport const renameCurrentLayer = function (newName) {\n const drawing = canvas_.getCurrentDrawing();\n const layer = drawing.getCurrentLayer();\n if (layer) {\n const result = drawing.setCurrentLayerName(newName, historyRecordingService());\n if (result) {\n canvas_.call('changed', [layer]);\n return true;\n }\n }\n return false;\n};\n\n/**\n* Changes the position of the current layer to the new value. If the new index is not valid,\n* this function does nothing and returns false, otherwise it returns true. This is an\n* undo-able action.\n* @function module:draw.setCurrentLayerPosition\n* @param {Integer} newPos - The zero-based index of the new position of the layer. This should be between\n* 0 and (number of layers - 1)\n* @returns {boolean} `true` if the current layer position was changed, `false` otherwise.\n*/\nexport const setCurrentLayerPosition = function (newPos) {\n const drawing = canvas_.getCurrentDrawing();\n const result = drawing.setCurrentLayerPosition(newPos);\n if (result) {\n canvas_.addCommandToHistory(new MoveElementCommand(result.currentGroup, result.oldNextSibling, canvas_.getSVGContent()));\n return true;\n }\n return false;\n};\n\n/**\n* Sets the visibility of the layer. If the layer name is not valid, this function return\n* `false`, otherwise it returns `true`. This is an undo-able action.\n* @function module:draw.setLayerVisibility\n* @param {string} layerName - The name of the layer to change the visibility\n* @param {boolean} bVisible - Whether the layer should be visible\n* @returns {boolean} true if the layer's visibility was set, false otherwise\n*/\nexport const setLayerVisibility = function (layerName, bVisible) {\n const drawing = canvas_.getCurrentDrawing();\n const prevVisibility = drawing.getLayerVisibility(layerName);\n const layer = drawing.setLayerVisibility(layerName, bVisible);\n if (layer) {\n const oldDisplay = prevVisibility ? 'inline' : 'none';\n canvas_.addCommandToHistory(new ChangeElementCommand(layer, {display: oldDisplay}, 'Layer Visibility'));\n } else {\n return false;\n }\n\n if (layer === drawing.getCurrentLayer()) {\n canvas_.clearSelection();\n canvas_.pathActions.clear();\n }\n // call('changed', [selected]);\n return true;\n};\n\n/**\n* Moves the selected elements to layerName. If the name is not a valid layer name, then `false`\n* is returned. Otherwise it returns `true`. This is an undo-able action.\n* @function module:draw.moveSelectedToLayer\n* @param {string} layerName - The name of the layer you want to which you want to move the selected elements\n* @returns {boolean} Whether the selected elements were moved to the layer.\n*/\nexport const moveSelectedToLayer = function (layerName) {\n // find the layer\n const drawing = canvas_.getCurrentDrawing();\n const layer = drawing.getLayerByName(layerName);\n if (!layer) { return false; }\n\n const batchCmd = new BatchCommand('Move Elements to Layer');\n\n // loop for each selected element and move it\n const selElems = canvas_.getSelectedElements();\n let i = selElems.length;\n while (i--) {\n const elem = selElems[i];\n if (!elem) { continue; }\n const oldNextSibling = elem.nextSibling;\n // TODO: this is pretty brittle!\n const oldLayer = elem.parentNode;\n layer.append(elem);\n batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldLayer));\n }\n\n canvas_.addCommandToHistory(batchCmd);\n\n return true;\n};\n\n/**\n* @function module:draw.mergeLayer\n* @param {module:history.HistoryRecordingService} hrService\n* @returns {void}\n*/\nexport const mergeLayer = function (hrService) {\n canvas_.getCurrentDrawing().mergeLayer(historyRecordingService(hrService));\n canvas_.clearSelection();\n leaveContext();\n canvas_.changeSVGContent();\n};\n\n/**\n* @function module:draw.mergeAllLayers\n* @param {module:history.HistoryRecordingService} hrService\n* @returns {void}\n*/\nexport const mergeAllLayers = function (hrService) {\n canvas_.getCurrentDrawing().mergeAllLayers(historyRecordingService(hrService));\n canvas_.clearSelection();\n leaveContext();\n canvas_.changeSVGContent();\n};\n\n/**\n* Return from a group context to the regular kind, make any previously\n* disabled elements enabled again.\n* @function module:draw.leaveContext\n* @fires module:svgcanvas.SvgCanvas#event:contextset\n* @returns {void}\n*/\nexport const leaveContext = function () {\n const len = disabledElems.length;\n if (len) {\n for (let i = 0; i < len; i++) {\n const elem = disabledElems[i];\n const orig = canvas_.elData(elem, 'orig_opac');\n if (orig !== 1) {\n elem.setAttribute('opacity', orig);\n } else {\n elem.removeAttribute('opacity');\n }\n elem.setAttribute('style', 'pointer-events: inherit');\n }\n disabledElems = [];\n canvas_.clearSelection(true);\n canvas_.call('contextset', null);\n }\n canvas_.setCurrentGroup(null);\n};\n\n/**\n* Set the current context (for in-group editing).\n* @function module:draw.setContext\n* @param {Element} elem\n* @fires module:svgcanvas.SvgCanvas#event:contextset\n* @returns {void}\n*/\nexport const setContext = function (elem) {\n leaveContext();\n if (typeof elem === 'string') {\n elem = getElem(elem);\n }\n\n // Edit inside this group\n canvas_.setCurrentGroup(elem);\n\n // Disable other elements\n $(elem).parentsUntil('#svgcontent').andSelf().siblings().each(function () {\n const opac = this.getAttribute('opacity') || 1;\n // Store the original's opacity\n canvas_.elData(this, 'orig_opac', opac);\n this.setAttribute('opacity', opac * 0.33);\n this.setAttribute('style', 'pointer-events: none');\n disabledElems.push(this);\n });\n\n canvas_.clearSelection();\n canvas_.call('contextset', canvas_.getCurrentGroup());\n};\n\n/**\n* @memberof module:draw\n* @class Layer\n* @see {@link module:layer.Layer}\n*/\nexport {Layer};\n","/**\n * Tools for SVG sanitization.\n * @module sanitize\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\nimport {getReverseNS, NS} from './namespaces.js';\nimport {isGecko} from './browser.js';\nimport {getHref, setHref, getUrlFromAttr} from './utilities.js';\n\nconst REVERSE_NS = getReverseNS();\n\n// Todo: Split out into core attributes, presentation attributes, etc. so consistent\n/**\n * This defines which elements and attributes that we support (or at least\n * don't remove).\n * @type {PlainObject}\n */\nconst svgWhiteList_ = {\n // SVG Elements\n a: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'xlink:href', 'xlink:title'],\n circle: ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],\n clipPath: ['class', 'clipPathUnits', 'id'],\n defs: [],\n style: ['type'],\n desc: [],\n ellipse: ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],\n feGaussianBlur: ['class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation'],\n feMorphology: ['class', 'in', 'operator', 'radius'],\n filter: ['class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y'],\n foreignObject: ['class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y'],\n g: ['class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor'],\n image: ['class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y'],\n line: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2'],\n linearGradient: ['class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2'],\n marker: ['id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox'],\n mask: ['class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y'],\n metadata: ['class', 'id'],\n path: ['class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],\n pattern: ['class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y'],\n polygon: ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],\n polyline: ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],\n radialGradient: ['class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href'],\n rect: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y'],\n stop: ['class', 'id', 'offset', 'requiredFeatures', 'stop-color', 'stop-opacity', 'style', 'systemLanguage'],\n svg: ['class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'y'],\n switch: ['class', 'id', 'requiredFeatures', 'systemLanguage'],\n symbol: ['class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox'],\n text: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y'],\n textPath: ['class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href'],\n title: [],\n tspan: ['class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y'],\n use: ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y'],\n\n // MathML Elements\n annotation: ['encoding'],\n 'annotation-xml': ['encoding'],\n maction: ['actiontype', 'other', 'selection'],\n math: ['class', 'id', 'display', 'xmlns'],\n menclose: ['notation'],\n merror: [],\n mfrac: ['linethickness'],\n mi: ['mathvariant'],\n mmultiscripts: [],\n mn: [],\n mo: ['fence', 'lspace', 'maxsize', 'minsize', 'rspace', 'stretchy'],\n mover: [],\n mpadded: ['lspace', 'width', 'height', 'depth', 'voffset'],\n mphantom: [],\n mprescripts: [],\n mroot: [],\n mrow: ['xlink:href', 'xlink:type', 'xmlns:xlink'],\n mspace: ['depth', 'height', 'width'],\n msqrt: [],\n mstyle: ['displaystyle', 'mathbackground', 'mathcolor', 'mathvariant', 'scriptlevel'],\n msub: [],\n msubsup: [],\n msup: [],\n mtable: ['align', 'columnalign', 'columnlines', 'columnspacing', 'displaystyle', 'equalcolumns', 'equalrows', 'frame', 'rowalign', 'rowlines', 'rowspacing', 'width'],\n mtd: ['columnalign', 'columnspan', 'rowalign', 'rowspan'],\n mtext: [],\n mtr: ['columnalign', 'rowalign'],\n munder: [],\n munderover: [],\n none: [],\n semantics: []\n};\n\n// Produce a Namespace-aware version of svgWhitelist\nconst svgWhiteListNS_ = {};\nObject.entries(svgWhiteList_).forEach(function ([elt, atts]) {\n const attNS = {};\n Object.entries(atts).forEach(function ([i, att]) {\n if (att.includes(':')) {\n const v = att.split(':');\n attNS[v[1]] = NS[(v[0]).toUpperCase()];\n } else {\n attNS[att] = att === 'xmlns' ? NS.XMLNS : null;\n }\n });\n svgWhiteListNS_[elt] = attNS;\n});\n\n/**\n* Sanitizes the input node and its children.\n* It only keeps what is allowed from our whitelist defined above.\n* @function module:sanitize.sanitizeSvg\n* @param {Text|Element} node - The DOM element to be checked (we'll also check its children) or text node to be cleaned up\n* @returns {void}\n*/\nexport const sanitizeSvg = function (node) {\n // Cleanup text nodes\n if (node.nodeType === 3) { // 3 === TEXT_NODE\n // Trim whitespace\n node.nodeValue = node.nodeValue.replace(/^\\s+|\\s+$/g, '');\n // Remove if empty\n if (!node.nodeValue.length) {\n node.remove();\n }\n }\n\n // We only care about element nodes.\n // Automatically return for all non-element nodes, such as comments, etc.\n if (node.nodeType !== 1) { // 1 == ELEMENT_NODE\n return;\n }\n\n const doc = node.ownerDocument;\n const parent = node.parentNode;\n // can parent ever be null here? I think the root node's parent is the document...\n if (!doc || !parent) {\n return;\n }\n\n const allowedAttrs = svgWhiteList_[node.nodeName];\n const allowedAttrsNS = svgWhiteListNS_[node.nodeName];\n // if this element is supported, sanitize it\n if (typeof allowedAttrs !== 'undefined') {\n const seAttrs = [];\n let i = node.attributes.length;\n while (i--) {\n // if the attribute is not in our whitelist, then remove it\n // could use jQuery's inArray(), but I don't know if that's any better\n const attr = node.attributes.item(i);\n const attrName = attr.nodeName;\n const attrLocalName = attr.localName;\n const attrNsURI = attr.namespaceURI;\n // Check that an attribute with the correct localName in the correct namespace is on\n // our whitelist or is a namespace declaration for one of our allowed namespaces\n if (!({}.hasOwnProperty.call(allowedAttrsNS, attrLocalName) && attrNsURI === allowedAttrsNS[attrLocalName] && attrNsURI !== NS.XMLNS) &&\n !(attrNsURI === NS.XMLNS && REVERSE_NS[attr.value])) {\n // TODO(codedread): Programmatically add the se: attributes to the NS-aware whitelist.\n // Bypassing the whitelist to allow se: prefixes.\n // Is there a more appropriate way to do this?\n if (attrName.startsWith('se:') || attrName.startsWith('data-')) {\n seAttrs.push([attrName, attr.value]);\n }\n node.removeAttributeNS(attrNsURI, attrLocalName);\n }\n\n // Add spaces before negative signs where necessary\n if (isGecko()) {\n switch (attrName) {\n case 'transform':\n case 'gradientTransform':\n case 'patternTransform': {\n const val = attr.value.replace(/(\\d)-/g, '$1 -');\n // const val = attr.value.replace(/(?<digit>\\d)-/g, '$<digit> -');\n node.setAttribute(attrName, val);\n break;\n }\n }\n }\n\n // For the style attribute, rewrite it in terms of XML presentational attributes\n if (attrName === 'style') {\n const props = attr.value.split(';');\n let p = props.length;\n while (p--) {\n const [name, val] = props[p].split(':');\n const styleAttrName = (name || '').trim();\n const styleAttrVal = (val || '').trim();\n // Now check that this attribute is supported\n if (allowedAttrs.includes(styleAttrName)) {\n node.setAttribute(styleAttrName, styleAttrVal);\n }\n }\n node.removeAttribute('style');\n }\n }\n\n Object.values(seAttrs).forEach(([att, val]) => {\n node.setAttributeNS(NS.SE, att, val);\n });\n\n // for some elements that have a xlink:href, ensure the URI refers to a local element\n // (but not for links)\n const href = getHref(node);\n if (href &&\n ['filter', 'linearGradient', 'pattern',\n 'radialGradient', 'textPath', 'use'].includes(node.nodeName)) {\n // TODO: we simply check if the first character is a #, is this bullet-proof?\n if (href[0] !== '#') {\n // remove the attribute (but keep the element)\n setHref(node, '');\n node.removeAttributeNS(NS.XLINK, 'href');\n }\n }\n\n // Safari crashes on a <use> without a xlink:href, so we just remove the node here\n if (node.nodeName === 'use' && !getHref(node)) {\n node.remove();\n return;\n }\n // if the element has attributes pointing to a non-local reference,\n // need to remove the attribute\n Object.values(['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'], function (attr) {\n let val = node.getAttribute(attr);\n if (val) {\n val = getUrlFromAttr(val);\n // simply check for first character being a '#'\n if (val && val[0] !== '#') {\n node.setAttribute(attr, '');\n node.removeAttribute(attr);\n }\n }\n });\n\n // recurse to children\n i = node.childNodes.length;\n while (i--) { sanitizeSvg(node.childNodes.item(i)); }\n // else (element not supported), remove it\n } else {\n // remove all children from this node and insert them before this node\n // TODO: in the case of animation elements this will hardly ever be correct\n const children = [];\n while (node.hasChildNodes()) {\n children.push(parent.insertBefore(node.firstChild, node));\n }\n\n // remove this node from the document altogether\n node.remove();\n\n // call sanitizeSvg on each of those children\n let i = children.length;\n while (i--) { sanitizeSvg(children[i]); }\n }\n};\n","/* globals jQuery */\n/**\n * Recalculate.\n * @module recalculate\n * @license MIT\n */\n\nimport jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`\nimport {NS} from './namespaces.js';\nimport {convertToNum} from './units.js';\nimport {isWebkit} from './browser.js';\nimport {getTransformList} from './svgtransformlist.js';\nimport {getRotationAngle, getHref, getBBox, getRefElem, isNullish} from './utilities.js';\nimport {BatchCommand, ChangeElementCommand} from './history.js';\nimport {remapElement} from './coords.js';\nimport {\n isIdentity, matrixMultiply, transformPoint, transformListToTransform,\n hasMatrixTransform\n} from './math.js';\n\nconst $ = jQueryPluginSVG(jQuery);\n\nlet context_;\n\n/**\n* @interface module:recalculate.EditorContext\n*/\n/**\n * @function module:recalculate.EditorContext#getSVGRoot\n * @returns {SVGSVGElement} The root DOM element\n */\n/**\n * @function module:recalculate.EditorContext#getStartTransform\n * @returns {string}\n*/\n/**\n * @function module:recalculate.EditorContext#setStartTransform\n * @param {string} transform\n * @returns {void}\n */\n\n/**\n* @function module:recalculate.init\n* @param {module:recalculate.EditorContext} editorContext\n* @returns {void}\n*/\nexport const init = function (editorContext) {\n context_ = editorContext;\n};\n\n/**\n* Updates a `<clipPath>`s values based on the given translation of an element.\n* @function module:recalculate.updateClipPath\n* @param {string} attr - The clip-path attribute value with the clipPath's ID\n* @param {Float} tx - The translation's x value\n* @param {Float} ty - The translation's y value\n* @returns {void}\n*/\nexport const updateClipPath = function (attr, tx, ty) {\n const path = getRefElem(attr).firstChild;\n const cpXform = getTransformList(path);\n const newxlate = context_.getSVGRoot().createSVGTransform();\n newxlate.setTranslate(tx, ty);\n\n cpXform.appendItem(newxlate);\n\n // Update clipPath's dimensions\n recalculateDimensions(path);\n};\n\n/**\n* Decides the course of action based on the element's transform list.\n* @function module:recalculate.recalculateDimensions\n* @param {Element} selected - The DOM element to recalculate\n* @returns {Command} Undo command object with the resulting change\n*/\nexport const recalculateDimensions = function (selected) {\n if (isNullish(selected)) { return null; }\n\n // Firefox Issue - 1081\n if (selected.nodeName === 'svg' && navigator.userAgent.includes('Firefox/20')) {\n return null;\n }\n\n const svgroot = context_.getSVGRoot();\n const tlist = getTransformList(selected);\n\n // remove any unnecessary transforms\n if (tlist && tlist.numberOfItems > 0) {\n let k = tlist.numberOfItems;\n const noi = k;\n while (k--) {\n const xform = tlist.getItem(k);\n if (xform.type === 0) {\n tlist.removeItem(k);\n // remove identity matrices\n } else if (xform.type === 1) {\n if (isIdentity(xform.matrix)) {\n if (noi === 1) {\n // Overcome Chrome bug (though only when noi is 1) with\n // `removeItem` preventing `removeAttribute` from\n // subsequently working\n // See https://bugs.chromium.org/p/chromium/issues/detail?id=843901\n selected.removeAttribute('transform');\n return null;\n }\n tlist.removeItem(k);\n }\n // remove zero-degree rotations\n } else if (xform.type === 4) {\n if (xform.angle === 0) {\n tlist.removeItem(k);\n }\n }\n }\n // End here if all it has is a rotation\n if (tlist.numberOfItems === 1 &&\n getRotationAngle(selected)) { return null; }\n }\n\n // if this element had no transforms, we are done\n if (!tlist || tlist.numberOfItems === 0) {\n // Chrome apparently had a bug that requires clearing the attribute first.\n selected.setAttribute('transform', '');\n // However, this still next line currently doesn't work at all in Chrome\n selected.removeAttribute('transform');\n // selected.transform.baseVal.clear(); // Didn't help for Chrome bug\n return null;\n }\n\n // TODO: Make this work for more than 2\n if (tlist) {\n let mxs = [];\n let k = tlist.numberOfItems;\n while (k--) {\n const xform = tlist.getItem(k);\n if (xform.type === 1) {\n mxs.push([xform.matrix, k]);\n } else if (mxs.length) {\n mxs = [];\n }\n }\n if (mxs.length === 2) {\n const mNew = svgroot.createSVGTransformFromMatrix(matrixMultiply(mxs[1][0], mxs[0][0]));\n tlist.removeItem(mxs[0][1]);\n tlist.removeItem(mxs[1][1]);\n tlist.insertItemBefore(mNew, mxs[1][1]);\n }\n\n // combine matrix + translate\n k = tlist.numberOfItems;\n if (k >= 2 && tlist.getItem(k - 2).type === 1 && tlist.getItem(k - 1).type === 2) {\n const mt = svgroot.createSVGTransform();\n\n const m = matrixMultiply(\n tlist.getItem(k - 2).matrix,\n tlist.getItem(k - 1).matrix\n );\n mt.setMatrix(m);\n tlist.removeItem(k - 2);\n tlist.removeItem(k - 2);\n tlist.appendItem(mt);\n }\n }\n\n // If it still has a single [M] or [R][M], return null too (prevents BatchCommand from being returned).\n switch (selected.tagName) {\n // Ignore these elements, as they can absorb the [M]\n case 'line':\n case 'polyline':\n case 'polygon':\n case 'path':\n break;\n default:\n if ((tlist.numberOfItems === 1 && tlist.getItem(0).type === 1) ||\n (tlist.numberOfItems === 2 && tlist.getItem(0).type === 1 && tlist.getItem(0).type === 4)) {\n return null;\n }\n }\n\n // Grouped SVG element\n const gsvg = $(selected).data('gsvg');\n\n // we know we have some transforms, so set up return variable\n const batchCmd = new BatchCommand('Transform');\n\n // store initial values that will be affected by reducing the transform list\n let changes = {};\n let initial = null;\n let attrs = [];\n switch (selected.tagName) {\n case 'line':\n attrs = ['x1', 'y1', 'x2', 'y2'];\n break;\n case 'circle':\n attrs = ['cx', 'cy', 'r'];\n break;\n case 'ellipse':\n attrs = ['cx', 'cy', 'rx', 'ry'];\n break;\n case 'foreignObject':\n case 'rect':\n case 'image':\n attrs = ['width', 'height', 'x', 'y'];\n break;\n case 'use':\n case 'text':\n case 'tspan':\n attrs = ['x', 'y'];\n break;\n case 'polygon':\n case 'polyline': {\n initial = {};\n initial.points = selected.getAttribute('points');\n const list = selected.points;\n const len = list.numberOfItems;\n changes.points = new Array(len);\n for (let i = 0; i < len; ++i) {\n const pt = list.getItem(i);\n changes.points[i] = {x: pt.x, y: pt.y};\n }\n break;\n } case 'path':\n initial = {};\n initial.d = selected.getAttribute('d');\n changes.d = selected.getAttribute('d');\n break;\n } // switch on element type to get initial values\n\n if (attrs.length) {\n changes = $(selected).attr(attrs);\n $.each(changes, function (attr, val) {\n changes[attr] = convertToNum(attr, val);\n });\n } else if (gsvg) {\n // GSVG exception\n changes = {\n x: $(gsvg).attr('x') || 0,\n y: $(gsvg).attr('y') || 0\n };\n }\n\n // if we haven't created an initial array in polygon/polyline/path, then\n // make a copy of initial values and include the transform\n if (isNullish(initial)) {\n initial = $.extend(true, {}, changes);\n $.each(initial, function (attr, val) {\n initial[attr] = convertToNum(attr, val);\n });\n }\n // save the start transform value too\n initial.transform = context_.getStartTransform() || '';\n\n let oldcenter, newcenter;\n\n // if it's a regular group, we have special processing to flatten transforms\n if ((selected.tagName === 'g' && !gsvg) || selected.tagName === 'a') {\n const box = getBBox(selected);\n\n oldcenter = {x: box.x + box.width / 2, y: box.y + box.height / 2};\n newcenter = transformPoint(\n box.x + box.width / 2,\n box.y + box.height / 2,\n transformListToTransform(tlist).matrix\n );\n // let m = svgroot.createSVGMatrix();\n\n // temporarily strip off the rotate and save the old center\n const gangle = getRotationAngle(selected);\n if (gangle) {\n const a = gangle * Math.PI / 180;\n let s;\n if (Math.abs(a) > (1.0e-10)) {\n s = Math.sin(a) / (1 - Math.cos(a));\n } else {\n // TODO: This blows up if the angle is exactly 0!\n s = 2 / a;\n }\n for (let i = 0; i < tlist.numberOfItems; ++i) {\n const xform = tlist.getItem(i);\n if (xform.type === 4) {\n // extract old center through mystical arts\n const rm = xform.matrix;\n oldcenter.y = (s * rm.e + rm.f) / 2;\n oldcenter.x = (rm.e - s * rm.f) / 2;\n tlist.removeItem(i);\n break;\n }\n }\n }\n const N = tlist.numberOfItems;\n let tx = 0, ty = 0, operation = 0;\n\n let firstM;\n if (N) {\n firstM = tlist.getItem(0).matrix;\n }\n\n let oldStartTransform;\n // first, if it was a scale then the second-last transform will be it\n if (N >= 3 && tlist.getItem(N - 2).type === 3 &&\n tlist.getItem(N - 3).type === 2 && tlist.getItem(N - 1).type === 2) {\n operation = 3; // scale\n\n // if the children are unrotated, pass the scale down directly\n // otherwise pass the equivalent matrix() down directly\n const tm = tlist.getItem(N - 3).matrix,\n sm = tlist.getItem(N - 2).matrix,\n tmn = tlist.getItem(N - 1).matrix;\n\n const children = selected.childNodes;\n let c = children.length;\n while (c--) {\n const child = children.item(c);\n tx = 0;\n ty = 0;\n if (child.nodeType === 1) {\n const childTlist = getTransformList(child);\n\n // some children might not have a transform (<metadata>, <defs>, etc)\n if (!childTlist) { continue; }\n\n const m = transformListToTransform(childTlist).matrix;\n\n // Convert a matrix to a scale if applicable\n // if (hasMatrixTransform(childTlist) && childTlist.numberOfItems == 1) {\n // if (m.b==0 && m.c==0 && m.e==0 && m.f==0) {\n // childTlist.removeItem(0);\n // const translateOrigin = svgroot.createSVGTransform(),\n // scale = svgroot.createSVGTransform(),\n // translateBack = svgroot.createSVGTransform();\n // translateOrigin.setTranslate(0, 0);\n // scale.setScale(m.a, m.d);\n // translateBack.setTranslate(0, 0);\n // childTlist.appendItem(translateBack);\n // childTlist.appendItem(scale);\n // childTlist.appendItem(translateOrigin);\n // }\n // }\n\n const angle = getRotationAngle(child);\n oldStartTransform = context_.getStartTransform();\n // const childxforms = [];\n context_.setStartTransform(child.getAttribute('transform'));\n if (angle || hasMatrixTransform(childTlist)) {\n const e2t = svgroot.createSVGTransform();\n e2t.setMatrix(matrixMultiply(tm, sm, tmn, m));\n childTlist.clear();\n childTlist.appendItem(e2t);\n // childxforms.push(e2t);\n // if not rotated or skewed, push the [T][S][-T] down to the child\n } else {\n // update the transform list with translate,scale,translate\n\n // slide the [T][S][-T] from the front to the back\n // [T][S][-T][M] = [M][T2][S2][-T2]\n\n // (only bringing [-T] to the right of [M])\n // [T][S][-T][M] = [T][S][M][-T2]\n // [-T2] = [M_inv][-T][M]\n const t2n = matrixMultiply(m.inverse(), tmn, m);\n // [T2] is always negative translation of [-T2]\n const t2 = svgroot.createSVGMatrix();\n t2.e = -t2n.e;\n t2.f = -t2n.f;\n\n // [T][S][-T][M] = [M][T2][S2][-T2]\n // [S2] = [T2_inv][M_inv][T][S][-T][M][-T2_inv]\n const s2 = matrixMultiply(t2.inverse(), m.inverse(), tm, sm, tmn, m, t2n.inverse());\n\n const translateOrigin = svgroot.createSVGTransform(),\n scale = svgroot.createSVGTransform(),\n translateBack = svgroot.createSVGTransform();\n translateOrigin.setTranslate(t2n.e, t2n.f);\n scale.setScale(s2.a, s2.d);\n translateBack.setTranslate(t2.e, t2.f);\n childTlist.appendItem(translateBack);\n childTlist.appendItem(scale);\n childTlist.appendItem(translateOrigin);\n // childxforms.push(translateBack);\n // childxforms.push(scale);\n // childxforms.push(translateOrigin);\n // logMatrix(translateBack.matrix);\n // logMatrix(scale.matrix);\n } // not rotated\n batchCmd.addSubCommand(recalculateDimensions(child));\n // TODO: If any <use> have this group as a parent and are\n // referencing this child, then we need to impose a reverse\n // scale on it so that when it won't get double-translated\n // const uses = selected.getElementsByTagNameNS(NS.SVG, 'use');\n // const href = '#' + child.id;\n // let u = uses.length;\n // while (u--) {\n // const useElem = uses.item(u);\n // if (href == getHref(useElem)) {\n // const usexlate = svgroot.createSVGTransform();\n // usexlate.setTranslate(-tx,-ty);\n // getTransformList(useElem).insertItemBefore(usexlate,0);\n // batchCmd.addSubCommand( recalculateDimensions(useElem) );\n // }\n // }\n context_.setStartTransform(oldStartTransform);\n } // element\n } // for each child\n // Remove these transforms from group\n tlist.removeItem(N - 1);\n tlist.removeItem(N - 2);\n tlist.removeItem(N - 3);\n } else if (N >= 3 && tlist.getItem(N - 1).type === 1) {\n operation = 3; // scale\n const m = transformListToTransform(tlist).matrix;\n const e2t = svgroot.createSVGTransform();\n e2t.setMatrix(m);\n tlist.clear();\n tlist.appendItem(e2t);\n // next, check if the first transform was a translate\n // if we had [ T1 ] [ M ] we want to transform this into [ M ] [ T2 ]\n // therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ]\n } else if ((N === 1 || (N > 1 && tlist.getItem(1).type !== 3)) &&\n tlist.getItem(0).type === 2) {\n operation = 2; // translate\n const T_M = transformListToTransform(tlist).matrix;\n tlist.removeItem(0);\n const mInv = transformListToTransform(tlist).matrix.inverse();\n const M2 = matrixMultiply(mInv, T_M);\n\n tx = M2.e;\n ty = M2.f;\n\n if (tx !== 0 || ty !== 0) {\n // we pass the translates down to the individual children\n const children = selected.childNodes;\n let c = children.length;\n\n const clipPathsDone = [];\n while (c--) {\n const child = children.item(c);\n if (child.nodeType === 1) {\n // Check if child has clip-path\n if (child.getAttribute('clip-path')) {\n // tx, ty\n const attr = child.getAttribute('clip-path');\n if (!clipPathsDone.includes(attr)) {\n updateClipPath(attr, tx, ty);\n clipPathsDone.push(attr);\n }\n }\n\n oldStartTransform = context_.getStartTransform();\n context_.setStartTransform(child.getAttribute('transform'));\n\n const childTlist = getTransformList(child);\n // some children might not have a transform (<metadata>, <defs>, etc)\n if (childTlist) {\n const newxlate = svgroot.createSVGTransform();\n newxlate.setTranslate(tx, ty);\n if (childTlist.numberOfItems) {\n childTlist.insertItemBefore(newxlate, 0);\n } else {\n childTlist.appendItem(newxlate);\n }\n batchCmd.addSubCommand(recalculateDimensions(child));\n // If any <use> have this group as a parent and are\n // referencing this child, then impose a reverse translate on it\n // so that when it won't get double-translated\n const uses = selected.getElementsByTagNameNS(NS.SVG, 'use');\n const href = '#' + child.id;\n let u = uses.length;\n while (u--) {\n const useElem = uses.item(u);\n if (href === getHref(useElem)) {\n const usexlate = svgroot.createSVGTransform();\n usexlate.setTranslate(-tx, -ty);\n getTransformList(useElem).insertItemBefore(usexlate, 0);\n batchCmd.addSubCommand(recalculateDimensions(useElem));\n }\n }\n context_.setStartTransform(oldStartTransform);\n }\n }\n }\n context_.setStartTransform(oldStartTransform);\n }\n // else, a matrix imposition from a parent group\n // keep pushing it down to the children\n } else if (N === 1 && tlist.getItem(0).type === 1 && !gangle) {\n operation = 1;\n const m = tlist.getItem(0).matrix,\n children = selected.childNodes;\n let c = children.length;\n while (c--) {\n const child = children.item(c);\n if (child.nodeType === 1) {\n oldStartTransform = context_.getStartTransform();\n context_.setStartTransform(child.getAttribute('transform'));\n const childTlist = getTransformList(child);\n\n if (!childTlist) { continue; }\n\n const em = matrixMultiply(m, transformListToTransform(childTlist).matrix);\n const e2m = svgroot.createSVGTransform();\n e2m.setMatrix(em);\n childTlist.clear();\n childTlist.appendItem(e2m, 0);\n\n batchCmd.addSubCommand(recalculateDimensions(child));\n context_.setStartTransform(oldStartTransform);\n\n // Convert stroke\n // TODO: Find out if this should actually happen somewhere else\n const sw = child.getAttribute('stroke-width');\n if (child.getAttribute('stroke') !== 'none' && !isNaN(sw)) {\n const avg = (Math.abs(em.a) + Math.abs(em.d)) / 2;\n child.setAttribute('stroke-width', sw * avg);\n }\n }\n }\n tlist.clear();\n // else it was just a rotate\n } else {\n if (gangle) {\n const newRot = svgroot.createSVGTransform();\n newRot.setRotate(gangle, newcenter.x, newcenter.y);\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(newRot, 0);\n } else {\n tlist.appendItem(newRot);\n }\n }\n if (tlist.numberOfItems === 0) {\n selected.removeAttribute('transform');\n }\n return null;\n }\n\n // if it was a translate, put back the rotate at the new center\n if (operation === 2) {\n if (gangle) {\n newcenter = {\n x: oldcenter.x + firstM.e,\n y: oldcenter.y + firstM.f\n };\n\n const newRot = svgroot.createSVGTransform();\n newRot.setRotate(gangle, newcenter.x, newcenter.y);\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(newRot, 0);\n } else {\n tlist.appendItem(newRot);\n }\n }\n // if it was a resize\n } else if (operation === 3) {\n const m = transformListToTransform(tlist).matrix;\n const roldt = svgroot.createSVGTransform();\n roldt.setRotate(gangle, oldcenter.x, oldcenter.y);\n const rold = roldt.matrix;\n const rnew = svgroot.createSVGTransform();\n rnew.setRotate(gangle, newcenter.x, newcenter.y);\n const rnewInv = rnew.matrix.inverse(),\n mInv = m.inverse(),\n extrat = matrixMultiply(mInv, rnewInv, rold, m);\n\n tx = extrat.e;\n ty = extrat.f;\n\n if (tx !== 0 || ty !== 0) {\n // now push this transform down to the children\n // we pass the translates down to the individual children\n const children = selected.childNodes;\n let c = children.length;\n while (c--) {\n const child = children.item(c);\n if (child.nodeType === 1) {\n oldStartTransform = context_.getStartTransform();\n context_.setStartTransform(child.getAttribute('transform'));\n const childTlist = getTransformList(child);\n const newxlate = svgroot.createSVGTransform();\n newxlate.setTranslate(tx, ty);\n if (childTlist.numberOfItems) {\n childTlist.insertItemBefore(newxlate, 0);\n } else {\n childTlist.appendItem(newxlate);\n }\n\n batchCmd.addSubCommand(recalculateDimensions(child));\n context_.setStartTransform(oldStartTransform);\n }\n }\n }\n\n if (gangle) {\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(rnew, 0);\n } else {\n tlist.appendItem(rnew);\n }\n }\n }\n // else, it's a non-group\n } else {\n // TODO: box might be null for some elements (<metadata> etc), need to handle this\n const box = getBBox(selected);\n\n // Paths (and possbly other shapes) will have no BBox while still in <defs>,\n // but we still may need to recalculate them (see issue 595).\n // TODO: Figure out how to get BBox from these elements in case they\n // have a rotation transform\n\n if (!box && selected.tagName !== 'path') return null;\n\n let m; // = svgroot.createSVGMatrix();\n // temporarily strip off the rotate and save the old center\n const angle = getRotationAngle(selected);\n if (angle) {\n oldcenter = {x: box.x + box.width / 2, y: box.y + box.height / 2};\n newcenter = transformPoint(\n box.x + box.width / 2,\n box.y + box.height / 2,\n transformListToTransform(tlist).matrix\n );\n\n const a = angle * Math.PI / 180;\n const s = (Math.abs(a) > (1.0e-10))\n ? Math.sin(a) / (1 - Math.cos(a))\n // TODO: This blows up if the angle is exactly 0!\n : 2 / a;\n\n for (let i = 0; i < tlist.numberOfItems; ++i) {\n const xform = tlist.getItem(i);\n if (xform.type === 4) {\n // extract old center through mystical arts\n const rm = xform.matrix;\n oldcenter.y = (s * rm.e + rm.f) / 2;\n oldcenter.x = (rm.e - s * rm.f) / 2;\n tlist.removeItem(i);\n break;\n }\n }\n }\n\n // 2 = translate, 3 = scale, 4 = rotate, 1 = matrix imposition\n let operation = 0;\n const N = tlist.numberOfItems;\n\n // Check if it has a gradient with userSpaceOnUse, in which case\n // adjust it by recalculating the matrix transform.\n // TODO: Make this work in Webkit using transformlist.SVGTransformList\n if (!isWebkit()) {\n const fill = selected.getAttribute('fill');\n if (fill && fill.startsWith('url(')) {\n const paint = getRefElem(fill);\n let type = 'pattern';\n if (paint.tagName !== type) type = 'gradient';\n const attrVal = paint.getAttribute(type + 'Units');\n if (attrVal === 'userSpaceOnUse') {\n // Update the userSpaceOnUse element\n m = transformListToTransform(tlist).matrix;\n const gtlist = getTransformList(paint);\n const gmatrix = transformListToTransform(gtlist).matrix;\n m = matrixMultiply(m, gmatrix);\n const mStr = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')';\n paint.setAttribute(type + 'Transform', mStr);\n }\n }\n }\n\n // first, if it was a scale of a non-skewed element, then the second-last\n // transform will be the [S]\n // if we had [M][T][S][T] we want to extract the matrix equivalent of\n // [T][S][T] and push it down to the element\n if (N >= 3 && tlist.getItem(N - 2).type === 3 &&\n tlist.getItem(N - 3).type === 2 && tlist.getItem(N - 1).type === 2) {\n // Removed this so a <use> with a given [T][S][T] would convert to a matrix.\n // Is that bad?\n // && selected.nodeName != 'use'\n operation = 3; // scale\n m = transformListToTransform(tlist, N - 3, N - 1).matrix;\n tlist.removeItem(N - 1);\n tlist.removeItem(N - 2);\n tlist.removeItem(N - 3);\n // if we had [T][S][-T][M], then this was a skewed element being resized\n // Thus, we simply combine it all into one matrix\n } else if (N === 4 && tlist.getItem(N - 1).type === 1) {\n operation = 3; // scale\n m = transformListToTransform(tlist).matrix;\n const e2t = svgroot.createSVGTransform();\n e2t.setMatrix(m);\n tlist.clear();\n tlist.appendItem(e2t);\n // reset the matrix so that the element is not re-mapped\n m = svgroot.createSVGMatrix();\n // if we had [R][T][S][-T][M], then this was a rotated matrix-element\n // if we had [T1][M] we want to transform this into [M][T2]\n // therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ] and we can push [T2]\n // down to the element\n } else if ((N === 1 || (N > 1 && tlist.getItem(1).type !== 3)) &&\n tlist.getItem(0).type === 2) {\n operation = 2; // translate\n const oldxlate = tlist.getItem(0).matrix,\n meq = transformListToTransform(tlist, 1).matrix,\n meqInv = meq.inverse();\n m = matrixMultiply(meqInv, oldxlate, meq);\n tlist.removeItem(0);\n // else if this child now has a matrix imposition (from a parent group)\n // we might be able to simplify\n } else if (N === 1 && tlist.getItem(0).type === 1 && !angle) {\n // Remap all point-based elements\n m = transformListToTransform(tlist).matrix;\n switch (selected.tagName) {\n case 'line':\n changes = $(selected).attr(['x1', 'y1', 'x2', 'y2']);\n // Fallthrough\n case 'polyline':\n case 'polygon':\n changes.points = selected.getAttribute('points');\n if (changes.points) {\n const list = selected.points;\n const len = list.numberOfItems;\n changes.points = new Array(len);\n for (let i = 0; i < len; ++i) {\n const pt = list.getItem(i);\n changes.points[i] = {x: pt.x, y: pt.y};\n }\n }\n // Fallthrough\n case 'path':\n changes.d = selected.getAttribute('d');\n operation = 1;\n tlist.clear();\n break;\n default:\n break;\n }\n // if it was a rotation, put the rotate back and return without a command\n // (this function has zero work to do for a rotate())\n } else {\n // operation = 4; // rotation\n if (angle) {\n const newRot = svgroot.createSVGTransform();\n newRot.setRotate(angle, newcenter.x, newcenter.y);\n\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(newRot, 0);\n } else {\n tlist.appendItem(newRot);\n }\n }\n if (tlist.numberOfItems === 0) {\n selected.removeAttribute('transform');\n }\n return null;\n }\n\n // if it was a translate or resize, we need to remap the element and absorb the xform\n if (operation === 1 || operation === 2 || operation === 3) {\n remapElement(selected, changes, m);\n } // if we are remapping\n\n // if it was a translate, put back the rotate at the new center\n if (operation === 2) {\n if (angle) {\n if (!hasMatrixTransform(tlist)) {\n newcenter = {\n x: oldcenter.x + m.e,\n y: oldcenter.y + m.f\n };\n }\n const newRot = svgroot.createSVGTransform();\n newRot.setRotate(angle, newcenter.x, newcenter.y);\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(newRot, 0);\n } else {\n tlist.appendItem(newRot);\n }\n }\n // We have special processing for tspans: Tspans are not transformable\n // but they can have x,y coordinates (sigh). Thus, if this was a translate,\n // on a text element, also translate any tspan children.\n if (selected.tagName === 'text') {\n const children = selected.childNodes;\n let c = children.length;\n while (c--) {\n const child = children.item(c);\n if (child.tagName === 'tspan') {\n const tspanChanges = {\n x: $(child).attr('x') || 0,\n y: $(child).attr('y') || 0\n };\n remapElement(child, tspanChanges, m);\n }\n }\n }\n // [Rold][M][T][S][-T] became [Rold][M]\n // we want it to be [Rnew][M][Tr] where Tr is the\n // translation required to re-center it\n // Therefore, [Tr] = [M_inv][Rnew_inv][Rold][M]\n } else if (operation === 3 && angle) {\n const {matrix} = transformListToTransform(tlist);\n const roldt = svgroot.createSVGTransform();\n roldt.setRotate(angle, oldcenter.x, oldcenter.y);\n const rold = roldt.matrix;\n const rnew = svgroot.createSVGTransform();\n rnew.setRotate(angle, newcenter.x, newcenter.y);\n const rnewInv = rnew.matrix.inverse();\n const mInv = matrix.inverse();\n const extrat = matrixMultiply(mInv, rnewInv, rold, matrix);\n\n remapElement(selected, changes, extrat);\n if (angle) {\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(rnew, 0);\n } else {\n tlist.appendItem(rnew);\n }\n }\n }\n } // a non-group\n\n // if the transform list has been emptied, remove it\n if (tlist.numberOfItems === 0) {\n selected.removeAttribute('transform');\n }\n\n batchCmd.addSubCommand(new ChangeElementCommand(selected, initial));\n\n return batchCmd;\n};\n","/* globals jQuery */\n/**\n * DOM element selection box tools.\n * @module select\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller\n */\n\nimport {isTouch, isWebkit} from './browser.js'; // , isOpera\nimport {getRotationAngle, getBBox, getStrokedBBox, isNullish} from './utilities.js';\nimport {transformListToTransform, transformBox, transformPoint} from './math.js';\nimport {getTransformList} from './svgtransformlist.js';\n\nconst $ = jQuery;\n\nlet svgFactory_;\nlet config_;\nlet selectorManager_; // A Singleton\nconst gripRadius = isTouch() ? 10 : 4;\n\n/**\n* Private class for DOM element selection boxes.\n*/\nexport class Selector {\n /**\n * @param {Integer} id - Internally identify the selector\n * @param {Element} elem - DOM element associated with this selector\n * @param {module:utilities.BBoxObject} [bbox] - Optional bbox to use for initialization (prevents duplicate `getBBox` call).\n */\n constructor (id, elem, bbox) {\n // this is the selector's unique number\n this.id = id;\n\n // this holds a reference to the element for which this selector is being used\n this.selectedElement = elem;\n\n // this is a flag used internally to track whether the selector is being used or not\n this.locked = true;\n\n // this holds a reference to the <g> element that holds all visual elements of the selector\n this.selectorGroup = svgFactory_.createSVGElement({\n element: 'g',\n attr: {id: ('selectorGroup' + this.id)}\n });\n\n // this holds a reference to the path rect\n this.selectorRect = this.selectorGroup.appendChild(\n svgFactory_.createSVGElement({\n element: 'path',\n attr: {\n id: ('selectedBox' + this.id),\n fill: 'none',\n stroke: '#22C',\n 'stroke-width': '1',\n 'stroke-dasharray': '5,5',\n // need to specify this so that the rect is not selectable\n style: 'pointer-events:none'\n }\n })\n );\n\n // this holds a reference to the grip coordinates for this selector\n this.gripCoords = {\n nw: null,\n n: null,\n ne: null,\n e: null,\n se: null,\n s: null,\n sw: null,\n w: null\n };\n\n this.reset(this.selectedElement, bbox);\n }\n\n /**\n * Used to reset the id and element that the selector is attached to.\n * @param {Element} e - DOM element associated with this selector\n * @param {module:utilities.BBoxObject} bbox - Optional bbox to use for reset (prevents duplicate getBBox call).\n * @returns {void}\n */\n reset (e, bbox) {\n this.locked = true;\n this.selectedElement = e;\n this.resize(bbox);\n this.selectorGroup.setAttribute('display', 'inline');\n }\n\n /**\n * Show the resize grips of this selector.\n * @param {boolean} show - Indicates whether grips should be shown or not\n * @returns {void}\n */\n showGrips (show) {\n const bShow = show ? 'inline' : 'none';\n selectorManager_.selectorGripsGroup.setAttribute('display', bShow);\n const elem = this.selectedElement;\n this.hasGrips = show;\n if (elem && show) {\n this.selectorGroup.append(selectorManager_.selectorGripsGroup);\n Selector.updateGripCursors(getRotationAngle(elem));\n }\n }\n\n /**\n * Updates the selector to match the element's size.\n * @param {module:utilities.BBoxObject} [bbox] - BBox to use for resize (prevents duplicate getBBox call).\n * @returns {void}\n */\n resize (bbox) {\n const selectedBox = this.selectorRect,\n mgr = selectorManager_,\n selectedGrips = mgr.selectorGrips,\n selected = this.selectedElement,\n sw = selected.getAttribute('stroke-width'),\n currentZoom = svgFactory_.getCurrentZoom();\n let offset = 1 / currentZoom;\n if (selected.getAttribute('stroke') !== 'none' && !isNaN(sw)) {\n offset += (sw / 2);\n }\n\n const {tagName} = selected;\n if (tagName === 'text') {\n offset += 2 / currentZoom;\n }\n\n // loop and transform our bounding box until we reach our first rotation\n const tlist = getTransformList(selected);\n const m = transformListToTransform(tlist).matrix;\n\n // This should probably be handled somewhere else, but for now\n // it keeps the selection box correctly positioned when zoomed\n m.e *= currentZoom;\n m.f *= currentZoom;\n\n if (!bbox) {\n bbox = getBBox(selected);\n }\n // TODO: getBBox (previous line) already knows to call getStrokedBBox when tagName === 'g'. Remove this?\n // TODO: getBBox doesn't exclude 'gsvg' and calls getStrokedBBox for any 'g'. Should getBBox be updated?\n if (tagName === 'g' && !$.data(selected, 'gsvg')) {\n // The bbox for a group does not include stroke vals, so we\n // get the bbox based on its children.\n const strokedBbox = getStrokedBBox([selected.childNodes]);\n if (strokedBbox) {\n bbox = strokedBbox;\n }\n }\n\n // apply the transforms\n const l = bbox.x, t = bbox.y, w = bbox.width, h = bbox.height;\n // bbox = {x: l, y: t, width: w, height: h}; // Not in use\n\n // we need to handle temporary transforms too\n // if skewed, get its transformed box, then find its axis-aligned bbox\n\n // *\n offset *= currentZoom;\n\n const nbox = transformBox(l * currentZoom, t * currentZoom, w * currentZoom, h * currentZoom, m),\n {aabox} = nbox;\n let nbax = aabox.x - offset,\n nbay = aabox.y - offset,\n nbaw = aabox.width + (offset * 2),\n nbah = aabox.height + (offset * 2);\n\n // now if the shape is rotated, un-rotate it\n const cx = nbax + nbaw / 2,\n cy = nbay + nbah / 2;\n\n const angle = getRotationAngle(selected);\n if (angle) {\n const rot = svgFactory_.svgRoot().createSVGTransform();\n rot.setRotate(-angle, cx, cy);\n const rotm = rot.matrix;\n nbox.tl = transformPoint(nbox.tl.x, nbox.tl.y, rotm);\n nbox.tr = transformPoint(nbox.tr.x, nbox.tr.y, rotm);\n nbox.bl = transformPoint(nbox.bl.x, nbox.bl.y, rotm);\n nbox.br = transformPoint(nbox.br.x, nbox.br.y, rotm);\n\n // calculate the axis-aligned bbox\n const {tl} = nbox;\n let minx = tl.x,\n miny = tl.y,\n maxx = tl.x,\n maxy = tl.y;\n\n const {min, max} = Math;\n\n minx = min(minx, min(nbox.tr.x, min(nbox.bl.x, nbox.br.x))) - offset;\n miny = min(miny, min(nbox.tr.y, min(nbox.bl.y, nbox.br.y))) - offset;\n maxx = max(maxx, max(nbox.tr.x, max(nbox.bl.x, nbox.br.x))) + offset;\n maxy = max(maxy, max(nbox.tr.y, max(nbox.bl.y, nbox.br.y))) + offset;\n\n nbax = minx;\n nbay = miny;\n nbaw = (maxx - minx);\n nbah = (maxy - miny);\n }\n\n const dstr = 'M' + nbax + ',' + nbay +\n ' L' + (nbax + nbaw) + ',' + nbay +\n ' ' + (nbax + nbaw) + ',' + (nbay + nbah) +\n ' ' + nbax + ',' + (nbay + nbah) + 'z';\n selectedBox.setAttribute('d', dstr);\n\n const xform = angle ? 'rotate(' + [angle, cx, cy].join(',') + ')' : '';\n this.selectorGroup.setAttribute('transform', xform);\n\n // TODO(codedread): Is this needed?\n // if (selected === selectedElements[0]) {\n this.gripCoords = {\n nw: [nbax, nbay],\n ne: [nbax + nbaw, nbay],\n sw: [nbax, nbay + nbah],\n se: [nbax + nbaw, nbay + nbah],\n n: [nbax + (nbaw) / 2, nbay],\n w: [nbax, nbay + (nbah) / 2],\n e: [nbax + nbaw, nbay + (nbah) / 2],\n s: [nbax + (nbaw) / 2, nbay + nbah]\n };\n Object.entries(this.gripCoords).forEach(([dir, coords]) => {\n selectedGrips[dir].setAttribute('cx', coords[0]);\n selectedGrips[dir].setAttribute('cy', coords[1]);\n });\n\n // we want to go 20 pixels in the negative transformed y direction, ignoring scale\n mgr.rotateGripConnector.setAttribute('x1', nbax + (nbaw) / 2);\n mgr.rotateGripConnector.setAttribute('y1', nbay);\n mgr.rotateGripConnector.setAttribute('x2', nbax + (nbaw) / 2);\n mgr.rotateGripConnector.setAttribute('y2', nbay - (gripRadius * 5));\n\n mgr.rotateGrip.setAttribute('cx', nbax + (nbaw) / 2);\n mgr.rotateGrip.setAttribute('cy', nbay - (gripRadius * 5));\n // }\n }\n\n // STATIC methods\n /**\n * Updates cursors for corner grips on rotation so arrows point the right way.\n * @param {Float} angle - Current rotation angle in degrees\n * @returns {void}\n */\n static updateGripCursors (angle) {\n const dirArr = Object.keys(selectorManager_.selectorGrips);\n let steps = Math.round(angle / 45);\n if (steps < 0) { steps += 8; }\n while (steps > 0) {\n dirArr.push(dirArr.shift());\n steps--;\n }\n Object.values(selectorManager_.selectorGrips).forEach((gripElement, i) => {\n gripElement.setAttribute('style', ('cursor:' + dirArr[i] + '-resize'));\n });\n }\n}\n\n/**\n* Manage all selector objects (selection boxes).\n*/\nexport class SelectorManager {\n /**\n * Sets up properties and calls `initGroup`.\n */\n constructor () {\n // this will hold the <g> element that contains all selector rects/grips\n this.selectorParentGroup = null;\n\n // this is a special rect that is used for multi-select\n this.rubberBandBox = null;\n\n // this will hold objects of type Selector (see above)\n this.selectors = [];\n\n // this holds a map of SVG elements to their Selector object\n this.selectorMap = {};\n\n // this holds a reference to the grip elements\n this.selectorGrips = {\n nw: null,\n n: null,\n ne: null,\n e: null,\n se: null,\n s: null,\n sw: null,\n w: null\n };\n\n this.selectorGripsGroup = null;\n this.rotateGripConnector = null;\n this.rotateGrip = null;\n\n this.initGroup();\n }\n\n /**\n * Resets the parent selector group element.\n * @returns {void}\n */\n initGroup () {\n // remove old selector parent group if it existed\n if (this.selectorParentGroup && this.selectorParentGroup.parentNode) {\n this.selectorParentGroup.remove();\n }\n\n // create parent selector group and add it to svgroot\n this.selectorParentGroup = svgFactory_.createSVGElement({\n element: 'g',\n attr: {id: 'selectorParentGroup'}\n });\n this.selectorGripsGroup = svgFactory_.createSVGElement({\n element: 'g',\n attr: {display: 'none'}\n });\n this.selectorParentGroup.append(this.selectorGripsGroup);\n svgFactory_.svgRoot().append(this.selectorParentGroup);\n\n this.selectorMap = {};\n this.selectors = [];\n this.rubberBandBox = null;\n\n // add the corner grips\n Object.keys(this.selectorGrips).forEach((dir) => {\n const grip = svgFactory_.createSVGElement({\n element: 'circle',\n attr: {\n id: ('selectorGrip_resize_' + dir),\n fill: '#22C',\n r: gripRadius,\n style: ('cursor:' + dir + '-resize'),\n // This expands the mouse-able area of the grips making them\n // easier to grab with the mouse.\n // This works in Opera and WebKit, but does not work in Firefox\n // see https://bugzilla.mozilla.org/show_bug.cgi?id=500174\n 'stroke-width': 2,\n 'pointer-events': 'all'\n }\n });\n\n $.data(grip, 'dir', dir);\n $.data(grip, 'type', 'resize');\n this.selectorGrips[dir] = this.selectorGripsGroup.appendChild(grip);\n });\n\n // add rotator elems\n this.rotateGripConnector = this.selectorGripsGroup.appendChild(\n svgFactory_.createSVGElement({\n element: 'line',\n attr: {\n id: ('selectorGrip_rotateconnector'),\n stroke: '#22C',\n 'stroke-width': '1'\n }\n })\n );\n\n this.rotateGrip = this.selectorGripsGroup.appendChild(\n svgFactory_.createSVGElement({\n element: 'circle',\n attr: {\n id: 'selectorGrip_rotate',\n fill: 'lime',\n r: gripRadius,\n stroke: '#22C',\n 'stroke-width': 2,\n style: 'cursor:url(' + config_.imgPath + 'rotate.png) 12 12, auto;'\n }\n })\n );\n $.data(this.rotateGrip, 'type', 'rotate');\n\n if ($('#canvasBackground').length) { return; }\n\n const [width, height] = config_.dimensions;\n const canvasbg = svgFactory_.createSVGElement({\n element: 'svg',\n attr: {\n id: 'canvasBackground',\n width,\n height,\n x: 0,\n y: 0,\n overflow: (isWebkit() ? 'none' : 'visible'), // Chrome 7 has a problem with this when zooming out\n style: 'pointer-events:none'\n }\n });\n\n const rect = svgFactory_.createSVGElement({\n element: 'rect',\n attr: {\n width: '100%',\n height: '100%',\n x: 0,\n y: 0,\n 'stroke-width': 1,\n stroke: '#000',\n fill: '#FFF',\n style: 'pointer-events:none'\n }\n });\n\n // Both Firefox and WebKit are too slow with this filter region (especially at higher\n // zoom levels) and Opera has at least one bug\n // if (!isOpera()) rect.setAttribute('filter', 'url(#canvashadow)');\n canvasbg.append(rect);\n svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent());\n // Ok to replace above with `svgFactory_.svgContent().before(canvasbg);`?\n }\n\n /**\n *\n * @param {Element} elem - DOM element to get the selector for\n * @param {module:utilities.BBoxObject} [bbox] - Optional bbox to use for reset (prevents duplicate getBBox call).\n * @returns {Selector} The selector based on the given element\n */\n requestSelector (elem, bbox) {\n if (isNullish(elem)) { return null; }\n\n const N = this.selectors.length;\n // If we've already acquired one for this element, return it.\n if (typeof this.selectorMap[elem.id] === 'object') {\n this.selectorMap[elem.id].locked = true;\n return this.selectorMap[elem.id];\n }\n for (let i = 0; i < N; ++i) {\n if (this.selectors[i] && !this.selectors[i].locked) {\n this.selectors[i].locked = true;\n this.selectors[i].reset(elem, bbox);\n this.selectorMap[elem.id] = this.selectors[i];\n return this.selectors[i];\n }\n }\n // if we reached here, no available selectors were found, we create one\n this.selectors[N] = new Selector(N, elem, bbox);\n this.selectorParentGroup.append(this.selectors[N].selectorGroup);\n this.selectorMap[elem.id] = this.selectors[N];\n return this.selectors[N];\n }\n\n /**\n * Removes the selector of the given element (hides selection box).\n *\n * @param {Element} elem - DOM element to remove the selector for\n * @returns {void}\n */\n releaseSelector (elem) {\n if (isNullish(elem)) { return; }\n const N = this.selectors.length,\n sel = this.selectorMap[elem.id];\n if (!sel.locked) {\n // TODO(codedread): Ensure this exists in this module.\n console.log('WARNING! selector was released but was already unlocked'); // eslint-disable-line no-console\n }\n for (let i = 0; i < N; ++i) {\n if (this.selectors[i] && this.selectors[i] === sel) {\n delete this.selectorMap[elem.id];\n sel.locked = false;\n sel.selectedElement = null;\n sel.showGrips(false);\n\n // remove from DOM and store reference in JS but only if it exists in the DOM\n try {\n sel.selectorGroup.setAttribute('display', 'none');\n } catch (e) {}\n\n break;\n }\n }\n }\n\n /**\n * @returns {SVGRectElement} The rubberBandBox DOM element. This is the rectangle drawn by\n * the user for selecting/zooming\n */\n getRubberBandBox () {\n if (!this.rubberBandBox) {\n this.rubberBandBox = this.selectorParentGroup.appendChild(\n svgFactory_.createSVGElement({\n element: 'rect',\n attr: {\n id: 'selectorRubberBand',\n fill: '#22C',\n 'fill-opacity': 0.15,\n stroke: '#22C',\n 'stroke-width': 0.5,\n display: 'none',\n style: 'pointer-events:none'\n }\n })\n );\n }\n return this.rubberBandBox;\n }\n}\n\n/**\n * An object that creates SVG elements for the canvas.\n *\n * @interface module:select.SVGFactory\n */\n/**\n * @function module:select.SVGFactory#createSVGElement\n * @param {module:utilities.EditorContext#addSVGElementFromJson} jsonMap\n * @returns {SVGElement}\n */\n/**\n * @function module:select.SVGFactory#svgRoot\n * @returns {SVGSVGElement}\n */\n/**\n * @function module:select.SVGFactory#svgContent\n * @returns {SVGSVGElement}\n */\n/**\n * @function module:select.SVGFactory#getCurrentZoom\n * @returns {Float} The current zoom level\n */\n\n/**\n * @typedef {GenericArray} module:select.Dimensions\n * @property {Integer} length 2\n * @property {Float} 0 Width\n * @property {Float} 1 Height\n */\n/**\n * @typedef {PlainObject} module:select.Config\n * @property {string} imgPath\n * @property {module:select.Dimensions} dimensions\n */\n\n/**\n * Initializes this module.\n * @function module:select.init\n * @param {module:select.Config} config - An object containing configurable parameters (imgPath)\n * @param {module:select.SVGFactory} svgFactory - An object implementing the SVGFactory interface.\n * @returns {void}\n */\nexport const init = function (config, svgFactory) {\n config_ = config;\n svgFactory_ = svgFactory;\n selectorManager_ = new SelectorManager();\n};\n\n/**\n * @function module:select.getSelectorManager\n * @returns {module:select.SelectorManager} The SelectorManager instance.\n */\nexport const getSelectorManager = () => selectorManager_;\n","/* globals jQuery */\n/**\n * Manipulating coordinates.\n * @module coords\n * @license MIT\n */\n\nimport './svgpathseg.js';\nimport {\n snapToGrid, assignAttributes, getBBox, getRefElem, findDefs\n} from './utilities.js';\nimport {\n transformPoint, transformListToTransform, matrixMultiply, transformBox\n} from './math.js';\nimport {getTransformList} from './svgtransformlist.js';\n\nconst $ = jQuery;\n\n// this is how we map paths to our preferred relative segment types\nconst pathMap = [\n 0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',\n 'H', 'h', 'V', 'v', 'S', 's', 'T', 't'\n];\n\n/**\n * @interface module:coords.EditorContext\n */\n/**\n * @function module:coords.EditorContext#getGridSnapping\n * @returns {boolean}\n */\n/**\n * @function module:coords.EditorContext#getDrawing\n * @returns {module:draw.Drawing}\n*/\n/**\n * @function module:coords.EditorContext#getSVGRoot\n * @returns {SVGSVGElement}\n*/\n\nlet editorContext_ = null;\n\n/**\n* @function module:coords.init\n* @param {module:svgcanvas.SvgCanvas#event:pointsAdded} editorContext\n* @returns {void}\n*/\nexport const init = function (editorContext) {\n editorContext_ = editorContext;\n};\n\n/**\n * Applies coordinate changes to an element based on the given matrix.\n * @name module:coords.remapElement\n * @type {module:path.EditorContext#remapElement}\n*/\nexport const remapElement = function (selected, changes, m) {\n const remap = function (x, y) { return transformPoint(x, y, m); },\n scalew = function (w) { return m.a * w; },\n scaleh = function (h) { return m.d * h; },\n doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg',\n finishUp = function () {\n if (doSnapping) {\n Object.entries(changes).forEach(([o, value]) => {\n changes[o] = snapToGrid(value);\n });\n }\n assignAttributes(selected, changes, 1000, true);\n },\n box = getBBox(selected);\n\n for (let i = 0; i < 2; i++) {\n const type = i === 0 ? 'fill' : 'stroke';\n const attrVal = selected.getAttribute(type);\n if (attrVal && attrVal.startsWith('url(')) {\n if (m.a < 0 || m.d < 0) {\n const grad = getRefElem(attrVal);\n const newgrad = grad.cloneNode(true);\n if (m.a < 0) {\n // flip x\n const x1 = newgrad.getAttribute('x1');\n const x2 = newgrad.getAttribute('x2');\n newgrad.setAttribute('x1', -(x1 - 1));\n newgrad.setAttribute('x2', -(x2 - 1));\n }\n\n if (m.d < 0) {\n // flip y\n const y1 = newgrad.getAttribute('y1');\n const y2 = newgrad.getAttribute('y2');\n newgrad.setAttribute('y1', -(y1 - 1));\n newgrad.setAttribute('y2', -(y2 - 1));\n }\n newgrad.id = editorContext_.getDrawing().getNextId();\n findDefs().append(newgrad);\n selected.setAttribute(type, 'url(#' + newgrad.id + ')');\n }\n\n // Not really working :(\n // if (selected.tagName === 'path') {\n // reorientGrads(selected, m);\n // }\n }\n }\n\n const elName = selected.tagName;\n if (elName === 'g' || elName === 'text' || elName === 'tspan' || elName === 'use') {\n // if it was a translate, then just update x,y\n if (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && (m.e !== 0 || m.f !== 0)) {\n // [T][M] = [M][T']\n // therefore [T'] = [M_inv][T][M]\n const existing = transformListToTransform(selected).matrix,\n tNew = matrixMultiply(existing.inverse(), m, existing);\n changes.x = parseFloat(changes.x) + tNew.e;\n changes.y = parseFloat(changes.y) + tNew.f;\n } else {\n // we just absorb all matrices into the element and don't do any remapping\n const chlist = getTransformList(selected);\n const mt = editorContext_.getSVGRoot().createSVGTransform();\n mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m));\n chlist.clear();\n chlist.appendItem(mt);\n }\n }\n\n // now we have a set of changes and an applied reduced transform list\n // we apply the changes directly to the DOM\n switch (elName) {\n case 'foreignObject':\n case 'rect':\n case 'image': {\n // Allow images to be inverted (give them matrix when flipped)\n if (elName === 'image' && (m.a < 0 || m.d < 0)) {\n // Convert to matrix\n const chlist = getTransformList(selected);\n const mt = editorContext_.getSVGRoot().createSVGTransform();\n mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m));\n chlist.clear();\n chlist.appendItem(mt);\n } else {\n const pt1 = remap(changes.x, changes.y);\n changes.width = scalew(changes.width);\n changes.height = scaleh(changes.height);\n changes.x = pt1.x + Math.min(0, changes.width);\n changes.y = pt1.y + Math.min(0, changes.height);\n changes.width = Math.abs(changes.width);\n changes.height = Math.abs(changes.height);\n }\n finishUp();\n break;\n } case 'ellipse': {\n const c = remap(changes.cx, changes.cy);\n changes.cx = c.x;\n changes.cy = c.y;\n changes.rx = scalew(changes.rx);\n changes.ry = scaleh(changes.ry);\n changes.rx = Math.abs(changes.rx);\n changes.ry = Math.abs(changes.ry);\n finishUp();\n break;\n } case 'circle': {\n const c = remap(changes.cx, changes.cy);\n changes.cx = c.x;\n changes.cy = c.y;\n // take the minimum of the new selected box's dimensions for the new circle radius\n const tbox = transformBox(box.x, box.y, box.width, box.height, m);\n const w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y;\n changes.r = Math.min(w / 2, h / 2);\n\n if (changes.r) { changes.r = Math.abs(changes.r); }\n finishUp();\n break;\n } case 'line': {\n const pt1 = remap(changes.x1, changes.y1);\n const pt2 = remap(changes.x2, changes.y2);\n changes.x1 = pt1.x;\n changes.y1 = pt1.y;\n changes.x2 = pt2.x;\n changes.y2 = pt2.y;\n } // Fallthrough\n case 'text':\n case 'tspan':\n case 'use': {\n finishUp();\n break;\n } case 'g': {\n const gsvg = $(selected).data('gsvg');\n if (gsvg) {\n assignAttributes(gsvg, changes, 1000, true);\n }\n break;\n } case 'polyline':\n case 'polygon': {\n const len = changes.points.length;\n for (let i = 0; i < len; ++i) {\n const pt = changes.points[i];\n const {x, y} = remap(pt.x, pt.y);\n changes.points[i].x = x;\n changes.points[i].y = y;\n }\n\n // const len = changes.points.length;\n let pstr = '';\n for (let i = 0; i < len; ++i) {\n const pt = changes.points[i];\n pstr += pt.x + ',' + pt.y + ' ';\n }\n selected.setAttribute('points', pstr);\n break;\n } case 'path': {\n const segList = selected.pathSegList;\n let len = segList.numberOfItems;\n changes.d = [];\n for (let i = 0; i < len; ++i) {\n const seg = segList.getItem(i);\n changes.d[i] = {\n type: seg.pathSegType,\n x: seg.x,\n y: seg.y,\n x1: seg.x1,\n y1: seg.y1,\n x2: seg.x2,\n y2: seg.y2,\n r1: seg.r1,\n r2: seg.r2,\n angle: seg.angle,\n largeArcFlag: seg.largeArcFlag,\n sweepFlag: seg.sweepFlag\n };\n }\n\n len = changes.d.length;\n const firstseg = changes.d[0],\n currentpt = remap(firstseg.x, firstseg.y);\n changes.d[0].x = currentpt.x;\n changes.d[0].y = currentpt.y;\n for (let i = 1; i < len; ++i) {\n const seg = changes.d[i];\n const {type} = seg;\n // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2\n // if relative, we want to scalew, scaleh\n if (type % 2 === 0) { // absolute\n const thisx = (seg.x !== undefined) ? seg.x : currentpt.x, // for V commands\n thisy = (seg.y !== undefined) ? seg.y : currentpt.y; // for H commands\n const pt = remap(thisx, thisy);\n const pt1 = remap(seg.x1, seg.y1);\n const pt2 = remap(seg.x2, seg.y2);\n seg.x = pt.x;\n seg.y = pt.y;\n seg.x1 = pt1.x;\n seg.y1 = pt1.y;\n seg.x2 = pt2.x;\n seg.y2 = pt2.y;\n seg.r1 = scalew(seg.r1);\n seg.r2 = scaleh(seg.r2);\n } else { // relative\n seg.x = scalew(seg.x);\n seg.y = scaleh(seg.y);\n seg.x1 = scalew(seg.x1);\n seg.y1 = scaleh(seg.y1);\n seg.x2 = scalew(seg.x2);\n seg.y2 = scaleh(seg.y2);\n seg.r1 = scalew(seg.r1);\n seg.r2 = scaleh(seg.r2);\n }\n } // for each segment\n\n let dstr = '';\n len = changes.d.length;\n for (let i = 0; i < len; ++i) {\n const seg = changes.d[i];\n const {type} = seg;\n dstr += pathMap[type];\n switch (type) {\n case 13: // relative horizontal line (h)\n case 12: // absolute horizontal line (H)\n dstr += seg.x + ' ';\n break;\n case 15: // relative vertical line (v)\n case 14: // absolute vertical line (V)\n dstr += seg.y + ' ';\n break;\n case 3: // relative move (m)\n case 5: // relative line (l)\n case 19: // relative smooth quad (t)\n case 2: // absolute move (M)\n case 4: // absolute line (L)\n case 18: // absolute smooth quad (T)\n dstr += seg.x + ',' + seg.y + ' ';\n break;\n case 7: // relative cubic (c)\n case 6: // absolute cubic (C)\n dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' +\n seg.x + ',' + seg.y + ' ';\n break;\n case 9: // relative quad (q)\n case 8: // absolute quad (Q)\n dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' ';\n break;\n case 11: // relative elliptical arc (a)\n case 10: // absolute elliptical arc (A)\n dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + Number(seg.largeArcFlag) +\n ' ' + Number(seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' ';\n break;\n case 17: // relative smooth cubic (s)\n case 16: // absolute smooth cubic (S)\n dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';\n break;\n }\n }\n\n selected.setAttribute('d', dstr);\n break;\n }\n }\n};\n","/* eslint-disable indent, unicorn/no-fn-reference-in-iterator */\n/* globals jQuery, jsPDF */\n/**\n * Numerous tools for working with the editor's \"canvas\".\n * @module svgcanvas\n *\n * @license MIT\n *\n * @copyright 2010 Alexis Deveria, 2010 Pavol Rusnak, 2010 Jeff Schiller\n *\n */\n\n/* Dependencies:\n1. Also expects jQuery UI for `svgCanvasToString` and\n`convertToGroup` use of `:data()` selector\n*/\n\n// Todo: Obtain/adapt latest jsPDF to utilize ES Module for `jsPDF`/avoid global\n\nimport './svgpathseg.js';\nimport jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`\nimport jQueryPluginDBox from './dbox.js';\nimport * as draw from './draw.js';\n// eslint-disable-next-line no-duplicate-imports\nimport {\n identifyLayers, createLayer, cloneLayer, deleteCurrentLayer,\n setCurrentLayer, renameCurrentLayer, setCurrentLayerPosition,\n setLayerVisibility, moveSelectedToLayer, mergeLayer, mergeAllLayers,\n leaveContext, setContext\n} from './draw.js';\nimport * as pathModule from './path.js';\nimport {sanitizeSvg} from './sanitize.js';\nimport {getReverseNS, NS} from './namespaces.js';\nimport {importSetGlobal, importScript} from './external/dynamic-import-polyfill/importModule.js';\nimport {\n text2xml, assignAttributes, cleanupElement, getElem, getUrlFromAttr,\n findDefs, getHref, setHref, getRefElem, getRotationAngle, getPathBBox,\n preventClickDefault, snapToGrid, walkTree, walkTreePost,\n getBBoxOfElementAsPath, convertToPath, toXml, encode64, decode64,\n dataURLToObjectURL, createObjectURL,\n getVisibleElements, dropXMLInternalSubset,\n init as utilsInit, getBBox as utilsGetBBox, getStrokedBBoxDefaultVisible,\n isNullish\n} from './utilities.js';\nimport * as hstry from './history.js';\nimport {\n transformPoint, matrixMultiply, hasMatrixTransform, transformListToTransform,\n getMatrix, snapToAngle, isIdentity, rectsIntersect, transformBox\n} from './math.js';\nimport {\n convertToNum, convertAttrs, convertUnit, shortFloat, getTypeMap,\n init as unitsInit\n} from './units.js';\nimport {\n isGecko, isChrome, isIE, isWebkit, supportsNonScalingStroke, supportsGoodTextCharPos\n} from './browser.js'; // , supportsEditableText\nimport {\n getTransformList, resetListMap,\n SVGTransformList as SVGEditTransformList\n} from './svgtransformlist.js';\nimport {\n remapElement,\n init as coordsInit\n} from './coords.js';\nimport {\n recalculateDimensions,\n init as recalculateInit\n} from './recalculate.js';\nimport {\n getSelectorManager,\n Selector,\n init as selectInit\n} from './select.js';\n\nlet $ = jQueryPluginSVG(jQuery);\nconst {\n MoveElementCommand, InsertElementCommand, RemoveElementCommand,\n ChangeElementCommand, BatchCommand, UndoManager, HistoryEventTypes\n} = hstry;\n\nif (!window.console) {\n window.console = {};\n window.console.log = function (str) { /* */ };\n window.console.dir = function (str) { /* */ };\n}\n\nif (window.opera) {\n window.console.log = function (str) { window.opera.postError(str); };\n window.console.dir = function (str) { /* */ };\n}\n\n// Reenable after fixing eslint-plugin-jsdoc to handle\n/**\n* The main SvgCanvas class that manages all SVG-related functions.\n* @memberof module:svgcanvas\n*\n* @borrows module:coords.remapElement as #remapElement\n* @borrows module:recalculate.recalculateDimensions as #recalculateDimensions\n*\n* @borrows module:utilities.cleanupElement as #cleanupElement\n* @borrows module:utilities.getStrokedBBoxDefaultVisible as #getStrokedBBox\n* @borrows module:utilities.getVisibleElements as #getVisibleElements\n* @borrows module:utilities.findDefs as #findDefs\n* @borrows module:utilities.getUrlFromAttr as #getUrlFromAttr\n* @borrows module:utilities.getHref as #getHref\n* @borrows module:utilities.setHref as #setHref\n* @borrows module:utilities.getRotationAngle as #getRotationAngle\n* @borrows module:utilities.getBBox as #getBBox\n* @borrows module:utilities.getElem as #getElem\n* @borrows module:utilities.getRefElem as #getRefElem\n* @borrows module:utilities.assignAttributes as #assignAttributes\n*\n* @borrows module:SVGTransformList.getTransformList as #getTransformList\n* @borrows module:math.matrixMultiply as #matrixMultiply\n* @borrows module:math.hasMatrixTransform as #hasMatrixTransform\n* @borrows module:math.transformListToTransform as #transformListToTransform\n* @borrows module:units.convertToNum as #convertToNum\n* @borrows module:sanitize.sanitizeSvg as #sanitizeSvg\n* @borrows module:path.pathActions.linkControlPoints as #linkControlPoints\n*/\nclass SvgCanvas {\n /**\n * @param {HTMLElement} container - The container HTML element that should hold the SVG root element\n * @param {module:SVGEditor.curConfig} config - An object that contains configuration data\n */\n constructor (container, config) {\n// Alias Namespace constants\n\n// Default configuration options\nconst curConfig = {\n show_outside_canvas: true,\n selectNew: true,\n dimensions: [640, 480]\n};\n\n// Update config with new one if given\nif (config) {\n $.extend(curConfig, config);\n}\n\n// Array with width/height of canvas\nconst {dimensions} = curConfig;\n\nconst canvas = this; // eslint-disable-line consistent-this\n\n// \"document\" element associated with the container (same as window.document using default svg-editor.js)\n// NOTE: This is not actually a SVG document, but an HTML document.\nconst svgdoc = container.ownerDocument;\n\n// This is a container for the document being edited, not the document itself.\n/**\n * @name module:svgcanvas~svgroot\n * @type {SVGSVGElement}\n */\nconst svgroot = svgdoc.importNode(\n text2xml(\n '<svg id=\"svgroot\" xmlns=\"' + NS.SVG + '\" xlinkns=\"' + NS.XLINK + '\" ' +\n 'width=\"' + dimensions[0] + '\" height=\"' + dimensions[1] + '\" x=\"' + dimensions[0] + '\" y=\"' + dimensions[1] + '\" overflow=\"visible\">' +\n '<defs>' +\n '<filter id=\"canvashadow\" filterUnits=\"objectBoundingBox\">' +\n '<feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"4\" result=\"blur\"/>' +\n '<feOffset in=\"blur\" dx=\"5\" dy=\"5\" result=\"offsetBlur\"/>' +\n '<feMerge>' +\n '<feMergeNode in=\"offsetBlur\"/>' +\n '<feMergeNode in=\"SourceGraphic\"/>' +\n '</feMerge>' +\n '</filter>' +\n '</defs>' +\n '</svg>'\n ).documentElement,\n true\n);\ncontainer.append(svgroot);\n\n/**\n * The actual element that represents the final output SVG element.\n * @name module:svgcanvas~svgcontent\n * @type {SVGSVGElement}\n */\nlet svgcontent = svgdoc.createElementNS(NS.SVG, 'svg');\n\n/**\n* This function resets the svgcontent element while keeping it in the DOM.\n* @function module:svgcanvas.SvgCanvas#clearSvgContentElement\n* @returns {void}\n*/\nconst clearSvgContentElement = canvas.clearSvgContentElement = function () {\n $(svgcontent).empty();\n\n // TODO: Clear out all other attributes first?\n $(svgcontent).attr({\n id: 'svgcontent',\n width: dimensions[0],\n height: dimensions[1],\n x: dimensions[0],\n y: dimensions[1],\n overflow: curConfig.show_outside_canvas ? 'visible' : 'hidden',\n xmlns: NS.SVG,\n 'xmlns:se': NS.SE,\n 'xmlns:xlink': NS.XLINK\n }).appendTo(svgroot);\n\n // TODO: make this string optional and set by the client\n const comment = svgdoc.createComment(' Created with SVG-edit - https://github.com/SVG-Edit/svgedit');\n svgcontent.append(comment);\n};\nclearSvgContentElement();\n\n// Prefix string for element IDs\nlet idprefix = 'svg_';\n\n/**\n* Changes the ID prefix to the given value.\n* @function module:svgcanvas.SvgCanvas#setIdPrefix\n* @param {string} p - String with the new prefix\n* @returns {void}\n*/\ncanvas.setIdPrefix = function (p) {\n idprefix = p;\n};\n\n/**\n* Current `draw.Drawing` object.\n* @type {module:draw.Drawing}\n* @name module:svgcanvas.SvgCanvas#current_drawing_\n*/\ncanvas.current_drawing_ = new draw.Drawing(svgcontent, idprefix);\n\n/**\n* Returns the current Drawing.\n* @name module:svgcanvas.SvgCanvas#getCurrentDrawing\n* @type {module:draw.DrawCanvasInit#getCurrentDrawing}\n*/\nconst getCurrentDrawing = canvas.getCurrentDrawing = function () {\n return canvas.current_drawing_;\n};\n\n/**\n* Float displaying the current zoom level (1 = 100%, .5 = 50%, etc.).\n* @type {Float}\n*/\nlet currentZoom = 1;\n\n// pointer to current group (for in-group editing)\nlet currentGroup = null;\n\n// Object containing data for the currently selected styles\nconst allProperties = {\n shape: {\n fill: (curConfig.initFill.color === 'none' ? '' : '#') + curConfig.initFill.color,\n fill_paint: null,\n fill_opacity: curConfig.initFill.opacity,\n stroke: '#' + curConfig.initStroke.color,\n stroke_paint: null,\n stroke_opacity: curConfig.initStroke.opacity,\n stroke_width: curConfig.initStroke.width,\n stroke_dasharray: 'none',\n stroke_linejoin: 'miter',\n stroke_linecap: 'butt',\n opacity: curConfig.initOpacity\n }\n};\n\nallProperties.text = $.extend(true, {}, allProperties.shape);\n$.extend(allProperties.text, {\n fill: '#000000',\n stroke_width: curConfig.text && curConfig.text.stroke_width,\n font_size: curConfig.text && curConfig.text.font_size,\n font_family: curConfig.text && curConfig.text.font_family\n});\n\n// Current shape style properties\nconst curShape = allProperties.shape;\n\n// Array with all the currently selected elements\n// default size of 1 until it needs to grow bigger\nlet selectedElements = [];\n\n/**\n* @typedef {PlainObject} module:svgcanvas.SVGAsJSON\n* @property {string} element\n* @property {PlainObject<string, string>} attr\n* @property {module:svgcanvas.SVGAsJSON[]} children\n*/\n\n/**\n* @function module:svgcanvas.SvgCanvas#getContentElem\n* @param {Text|Element} data\n* @returns {module:svgcanvas.SVGAsJSON}\n*/\nconst getJsonFromSvgElement = this.getJsonFromSvgElement = function (data) {\n // Text node\n if (data.nodeType === 3) return data.nodeValue;\n\n const retval = {\n element: data.tagName,\n // namespace: nsMap[data.namespaceURI],\n attr: {},\n children: []\n };\n\n // Iterate attributes\n for (let i = 0, attr; (attr = data.attributes[i]); i++) {\n retval.attr[attr.name] = attr.value;\n }\n\n // Iterate children\n for (let i = 0, node; (node = data.childNodes[i]); i++) {\n retval.children[i] = getJsonFromSvgElement(node);\n }\n\n return retval;\n};\n\n/**\n* This should really be an intersection implementing all rather than a union.\n* @name module:svgcanvas.SvgCanvas#addSVGElementFromJson\n* @type {module:utilities.EditorContext#addSVGElementFromJson|module:path.EditorContext#addSVGElementFromJson}\n*/\nconst addSVGElementFromJson = this.addSVGElementFromJson = function (data) {\n if (typeof data === 'string') return svgdoc.createTextNode(data);\n\n let shape = getElem(data.attr.id);\n // if shape is a path but we need to create a rect/ellipse, then remove the path\n const currentLayer = getCurrentDrawing().getCurrentLayer();\n if (shape && data.element !== shape.tagName) {\n shape.remove();\n shape = null;\n }\n if (!shape) {\n const ns = data.namespace || NS.SVG;\n shape = svgdoc.createElementNS(ns, data.element);\n if (currentLayer) {\n (currentGroup || currentLayer).append(shape);\n }\n }\n if (data.curStyles) {\n assignAttributes(shape, {\n fill: curShape.fill,\n stroke: curShape.stroke,\n 'stroke-width': curShape.stroke_width,\n 'stroke-dasharray': curShape.stroke_dasharray,\n 'stroke-linejoin': curShape.stroke_linejoin,\n 'stroke-linecap': curShape.stroke_linecap,\n 'stroke-opacity': curShape.stroke_opacity,\n 'fill-opacity': curShape.fill_opacity,\n opacity: curShape.opacity / 2,\n style: 'pointer-events:inherit'\n }, 100);\n }\n assignAttributes(shape, data.attr, 100);\n cleanupElement(shape);\n\n // Children\n if (data.children) {\n data.children.forEach((child) => {\n shape.append(addSVGElementFromJson(child));\n });\n }\n\n return shape;\n};\n\ncanvas.getTransformList = getTransformList;\n\ncanvas.matrixMultiply = matrixMultiply;\ncanvas.hasMatrixTransform = hasMatrixTransform;\ncanvas.transformListToTransform = transformListToTransform;\n\n/**\n* @type {module:utilities.EditorContext#getBaseUnit}\n*/\nconst getBaseUnit = () => { return curConfig.baseUnit; };\n\n/**\n* Initialize from units.js.\n* Send in an object implementing the ElementContainer interface (see units.js).\n*/\nunitsInit(\n /**\n * @implements {module:units.ElementContainer}\n */\n {\n getBaseUnit,\n getElement: getElem,\n getHeight () { return svgcontent.getAttribute('height') / currentZoom; },\n getWidth () { return svgcontent.getAttribute('width') / currentZoom; },\n getRoundDigits () { return saveOptions.round_digits; }\n }\n);\n\ncanvas.convertToNum = convertToNum;\n\n/**\n* This should really be an intersection implementing all rather than a union.\n* @type {module:draw.DrawCanvasInit#getSVGContent|module:utilities.EditorContext#getSVGContent}\n*/\nconst getSVGContent = () => { return svgcontent; };\n\n/**\n* Should really be an intersection with all needing to apply rather than a union.\n* @name module:svgcanvas.SvgCanvas#getSelectedElements\n* @type {module:utilities.EditorContext#getSelectedElements|module:draw.DrawCanvasInit#getSelectedElements|module:path.EditorContext#getSelectedElements}\n*/\nconst getSelectedElements = this.getSelectedElems = function () {\n return selectedElements;\n};\n\nconst {pathActions} = pathModule;\n\n/**\n* This should actually be an intersection as all interfaces should be met.\n* @type {module:utilities.EditorContext#getSVGRoot|module:recalculate.EditorContext#getSVGRoot|module:coords.EditorContext#getSVGRoot|module:path.EditorContext#getSVGRoot}\n*/\nconst getSVGRoot = () => svgroot;\n\nutilsInit(\n /**\n * @implements {module:utilities.EditorContext}\n */\n {\n pathActions, // Ok since not modifying\n getSVGContent,\n addSVGElementFromJson,\n getSelectedElements,\n getDOMDocument () { return svgdoc; },\n getDOMContainer () { return container; },\n getSVGRoot,\n // TODO: replace this mostly with a way to get the current drawing.\n getBaseUnit,\n getSnappingStep () { return curConfig.snappingStep; }\n }\n);\n\ncanvas.findDefs = findDefs;\ncanvas.getUrlFromAttr = getUrlFromAttr;\ncanvas.getHref = getHref;\ncanvas.setHref = setHref;\n/* const getBBox = */ canvas.getBBox = utilsGetBBox;\ncanvas.getRotationAngle = getRotationAngle;\ncanvas.getElem = getElem;\ncanvas.getRefElem = getRefElem;\ncanvas.assignAttributes = assignAttributes;\n\nthis.cleanupElement = cleanupElement;\n\n/**\n* This should actually be an intersection not a union as all should apply.\n* @type {module:coords.EditorContext#getGridSnapping|module:path.EditorContext#getGridSnapping}\n*/\nconst getGridSnapping = () => { return curConfig.gridSnapping; };\n\ncoordsInit(\n /**\n * @implements {module:coords.EditorContext}\n */\n {\n getDrawing () { return getCurrentDrawing(); },\n getSVGRoot,\n getGridSnapping\n }\n);\nthis.remapElement = remapElement;\n\nrecalculateInit(\n /**\n * @implements {module:recalculate.EditorContext}\n */\n {\n getSVGRoot,\n getStartTransform () { return startTransform; },\n setStartTransform (transform) { startTransform = transform; }\n }\n);\nthis.recalculateDimensions = recalculateDimensions;\n\n// import from sanitize.js\nconst nsMap = getReverseNS();\ncanvas.sanitizeSvg = sanitizeSvg;\n\n/**\n* @name undoMgr\n* @memberof module:svgcanvas.SvgCanvas#\n* @type {module:history.HistoryEventHandler}\n*/\nconst undoMgr = canvas.undoMgr = new UndoManager({\n /**\n * @param {string} eventType One of the HistoryEvent types\n * @param {module:history.HistoryCommand} cmd Fulfills the HistoryCommand interface\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @returns {void}\n */\n handleHistoryEvent (eventType, cmd) {\n const EventTypes = HistoryEventTypes;\n // TODO: handle setBlurOffsets.\n if (eventType === EventTypes.BEFORE_UNAPPLY || eventType === EventTypes.BEFORE_APPLY) {\n canvas.clearSelection();\n } else if (eventType === EventTypes.AFTER_APPLY || eventType === EventTypes.AFTER_UNAPPLY) {\n const elems = cmd.elements();\n canvas.pathActions.clear();\n call('changed', elems);\n const cmdType = cmd.type();\n const isApply = (eventType === EventTypes.AFTER_APPLY);\n if (cmdType === MoveElementCommand.type()) {\n const parent = isApply ? cmd.newParent : cmd.oldParent;\n if (parent === svgcontent) {\n draw.identifyLayers();\n }\n } else if (cmdType === InsertElementCommand.type() ||\n cmdType === RemoveElementCommand.type()) {\n if (cmd.parent === svgcontent) {\n draw.identifyLayers();\n }\n if (cmdType === InsertElementCommand.type()) {\n if (isApply) { restoreRefElems(cmd.elem); }\n } else if (!isApply) {\n restoreRefElems(cmd.elem);\n }\n if (cmd.elem.tagName === 'use') {\n setUseData(cmd.elem);\n }\n } else if (cmdType === ChangeElementCommand.type()) {\n // if we are changing layer names, re-identify all layers\n if (cmd.elem.tagName === 'title' &&\n cmd.elem.parentNode.parentNode === svgcontent\n ) {\n draw.identifyLayers();\n }\n const values = isApply ? cmd.newValues : cmd.oldValues;\n // If stdDeviation was changed, update the blur.\n if (values.stdDeviation) {\n canvas.setBlurOffsets(cmd.elem.parentNode, values.stdDeviation);\n }\n // This is resolved in later versions of webkit, perhaps we should\n // have a featured detection for correct 'use' behavior?\n // ——————————\n // Remove & Re-add hack for Webkit (issue 775)\n // if (cmd.elem.tagName === 'use' && isWebkit()) {\n // const {elem} = cmd;\n // if (!elem.getAttribute('x') && !elem.getAttribute('y')) {\n // const parent = elem.parentNode;\n // const sib = elem.nextSibling;\n // elem.remove();\n // parent.insertBefore(elem, sib);\n // // Ok to replace above with this? `sib.before(elem);`\n // }\n // }\n }\n }\n }\n});\n\n/**\n* This should really be an intersection applying to all types rather than a union.\n* @name module:svgcanvas~addCommandToHistory\n* @type {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory}\n*/\nconst addCommandToHistory = function (cmd) {\n canvas.undoMgr.addCommandToHistory(cmd);\n};\n\n/**\n* This should really be an intersection applying to all types rather than a union.\n* @name module:svgcanvas.SvgCanvas#getZoom\n* @type {module:path.EditorContext#getCurrentZoom|module:select.SVGFactory#getCurrentZoom}\n*/\nconst getCurrentZoom = this.getZoom = function () { return currentZoom; };\n\n/**\n* This method rounds the incoming value to the nearest value based on the `currentZoom`\n* @name module:svgcanvas.SvgCanvas#round\n* @type {module:path.EditorContext#round}\n*/\nconst round = this.round = function (val) {\n return parseInt(val * currentZoom) / currentZoom;\n};\n\nselectInit(\n curConfig,\n /**\n * Export to select.js.\n * @implements {module:select.SVGFactory}\n */\n {\n createSVGElement (jsonMap) { return canvas.addSVGElementFromJson(jsonMap); },\n svgRoot () { return svgroot; },\n svgContent () { return svgcontent; },\n getCurrentZoom\n }\n);\n/**\n* This object manages selectors for us.\n* @name module:svgcanvas.SvgCanvas#selectorManager\n* @type {module:select.SelectorManager}\n*/\nconst selectorManager = this.selectorManager = getSelectorManager();\n\n/**\n* @name module:svgcanvas.SvgCanvas#getNextId\n* @type {module:path.EditorContext#getNextId}\n*/\nconst getNextId = canvas.getNextId = function () {\n return getCurrentDrawing().getNextId();\n};\n\n/**\n* @name module:svgcanvas.SvgCanvas#getId\n* @type {module:path.EditorContext#getId}\n*/\nconst getId = canvas.getId = function () {\n return getCurrentDrawing().getId();\n};\n\n/**\n* The \"implements\" should really be an intersection applying to all types rather than a union.\n* @name module:svgcanvas.SvgCanvas#call\n* @type {module:draw.DrawCanvasInit#call|module:path.EditorContext#call}\n*/\nconst call = function (ev, arg) {\n if (events[ev]) {\n return events[ev](window, arg);\n }\n return undefined;\n};\n\n/**\n* Clears the selection. The 'selected' handler is then optionally called.\n* This should really be an intersection applying to all types rather than a union.\n* @name module:svgcanvas.SvgCanvas#clearSelection\n* @type {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection}\n* @fires module:svgcanvas.SvgCanvas#event:selected\n*/\nconst clearSelection = this.clearSelection = function (noCall) {\n selectedElements.forEach((elem) => {\n if (isNullish(elem)) {\n return;\n }\n selectorManager.releaseSelector(elem);\n });\n selectedElements = [];\n\n if (!noCall) { call('selected', selectedElements); }\n};\n\n/**\n* Adds a list of elements to the selection. The 'selected' handler is then called.\n* @name module:svgcanvas.SvgCanvas#addToSelection\n* @type {module:path.EditorContext#addToSelection}\n* @fires module:svgcanvas.SvgCanvas#event:selected\n*/\nconst addToSelection = this.addToSelection = function (elemsToAdd, showGrips) {\n if (!elemsToAdd.length) { return; }\n // find the first null in our selectedElements array\n\n let j = 0;\n while (j < selectedElements.length) {\n if (isNullish(selectedElements[j])) {\n break;\n }\n ++j;\n }\n\n // now add each element consecutively\n let i = elemsToAdd.length;\n while (i--) {\n let elem = elemsToAdd[i];\n if (!elem) { continue; }\n const bbox = utilsGetBBox(elem);\n if (!bbox) { continue; }\n\n if (elem.tagName === 'a' && elem.childNodes.length === 1) {\n // Make \"a\" element's child be the selected element\n elem = elem.firstChild;\n }\n\n // if it's not already there, add it\n if (!selectedElements.includes(elem)) {\n selectedElements[j] = elem;\n\n // only the first selectedBBoxes element is ever used in the codebase these days\n // if (j === 0) selectedBBoxes[0] = utilsGetBBox(elem);\n j++;\n const sel = selectorManager.requestSelector(elem, bbox);\n\n if (selectedElements.length > 1) {\n sel.showGrips(false);\n }\n }\n }\n if (!selectedElements.length) {\n return;\n }\n call('selected', selectedElements);\n\n if (showGrips || selectedElements.length === 1) {\n selectorManager.requestSelector(selectedElements[0]).showGrips(true);\n } else {\n selectorManager.requestSelector(selectedElements[0]).showGrips(false);\n }\n\n // make sure the elements are in the correct order\n // See: https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-compareDocumentPosition\n\n selectedElements.sort(function (a, b) {\n if (a && b && a.compareDocumentPosition) {\n return 3 - (b.compareDocumentPosition(a) & 6); // eslint-disable-line no-bitwise\n }\n if (isNullish(a)) {\n return 1;\n }\n return 0;\n });\n\n // Make sure first elements are not null\n while (isNullish(selectedElements[0])) {\n selectedElements.shift(0);\n }\n};\n\n/**\n* @type {module:path.EditorContext#getOpacity}\n*/\nconst getOpacity = function () {\n return curShape.opacity;\n};\n\n/**\n* @name module:svgcanvas.SvgCanvas#getMouseTarget\n* @type {module:path.EditorContext#getMouseTarget}\n*/\nconst getMouseTarget = this.getMouseTarget = function (evt) {\n if (isNullish(evt)) {\n return null;\n }\n let mouseTarget = evt.target;\n\n // if it was a <use>, Opera and WebKit return the SVGElementInstance\n if (mouseTarget.correspondingUseElement) { mouseTarget = mouseTarget.correspondingUseElement; }\n\n // for foreign content, go up until we find the foreignObject\n // WebKit browsers set the mouse target to the svgcanvas div\n if ([NS.MATH, NS.HTML].includes(mouseTarget.namespaceURI) &&\n mouseTarget.id !== 'svgcanvas'\n ) {\n while (mouseTarget.nodeName !== 'foreignObject') {\n mouseTarget = mouseTarget.parentNode;\n if (!mouseTarget) { return svgroot; }\n }\n }\n\n // Get the desired mouseTarget with jQuery selector-fu\n // If it's root-like, select the root\n const currentLayer = getCurrentDrawing().getCurrentLayer();\n if ([svgroot, container, svgcontent, currentLayer].includes(mouseTarget)) {\n return svgroot;\n }\n\n const $target = $(mouseTarget);\n\n // If it's a selection grip, return the grip parent\n if ($target.closest('#selectorParentGroup').length) {\n // While we could instead have just returned mouseTarget,\n // this makes it easier to indentify as being a selector grip\n return selectorManager.selectorParentGroup;\n }\n\n while (mouseTarget.parentNode !== (currentGroup || currentLayer)) {\n mouseTarget = mouseTarget.parentNode;\n }\n\n //\n // // go up until we hit a child of a layer\n // while (mouseTarget.parentNode.parentNode.tagName == 'g') {\n // mouseTarget = mouseTarget.parentNode;\n // }\n // Webkit bubbles the mouse event all the way up to the div, so we\n // set the mouseTarget to the svgroot like the other browsers\n // if (mouseTarget.nodeName.toLowerCase() == 'div') {\n // mouseTarget = svgroot;\n // }\n\n return mouseTarget;\n};\n\n/**\n* @namespace {module:path.pathActions} pathActions\n* @memberof module:svgcanvas.SvgCanvas#\n* @see module:path.pathActions\n*/\ncanvas.pathActions = pathActions;\n/**\n* @type {module:path.EditorContext#resetD}\n*/\nfunction resetD (p) {\n p.setAttribute('d', pathActions.convertPath(p));\n}\npathModule.init(\n /**\n * @implements {module:path.EditorContext}\n */\n {\n selectorManager, // Ok since not changing\n canvas, // Ok since not changing\n call,\n resetD,\n round,\n clearSelection,\n addToSelection,\n addCommandToHistory,\n remapElement,\n addSVGElementFromJson,\n getGridSnapping,\n getOpacity,\n getSelectedElements,\n getContainer () {\n return container;\n },\n setStarted (s) {\n started = s;\n },\n getRubberBox () {\n return rubberBox;\n },\n setRubberBox (rb) {\n rubberBox = rb;\n return rubberBox;\n },\n /**\n * @param {PlainObject} ptsInfo\n * @param {boolean} ptsInfo.closedSubpath\n * @param {SVGCircleElement[]} ptsInfo.grips\n * @fires module:svgcanvas.SvgCanvas#event:pointsAdded\n * @fires module:svgcanvas.SvgCanvas#event:selected\n * @returns {void}\n */\n addPtsToSelection ({closedSubpath, grips}) {\n // TODO: Correct this:\n pathActions.canDeleteNodes = true;\n pathActions.closed_subpath = closedSubpath;\n call('pointsAdded', {closedSubpath, grips});\n call('selected', grips);\n },\n /**\n * @param {PlainObject} changes\n * @param {ChangeElementCommand} changes.cmd\n * @param {SVGPathElement} changes.elem\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @returns {void}\n */\n endChanges ({cmd, elem}) {\n addCommandToHistory(cmd);\n call('changed', [elem]);\n },\n getCurrentZoom,\n getId,\n getNextId,\n getMouseTarget,\n getCurrentMode () {\n return currentMode;\n },\n setCurrentMode (cm) {\n currentMode = cm;\n return currentMode;\n },\n getDrawnPath () {\n return drawnPath;\n },\n setDrawnPath (dp) {\n drawnPath = dp;\n return drawnPath;\n },\n getSVGRoot\n }\n);\n\n// Interface strings, usually for title elements\nconst uiStrings = {};\n\nconst visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use';\nconst refAttrs = ['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'];\n\nconst elData = $.data;\n\n// Animation element to change the opacity of any newly created element\nconst opacAni = document.createElementNS(NS.SVG, 'animate');\n$(opacAni).attr({\n attributeName: 'opacity',\n begin: 'indefinite',\n dur: 1,\n fill: 'freeze'\n}).appendTo(svgroot);\n\nconst restoreRefElems = function (elem) {\n // Look for missing reference elements, restore any found\n const attrs = $(elem).attr(refAttrs);\n Object.values(attrs).forEach((val) => {\n if (val && val.startsWith('url(')) {\n const id = getUrlFromAttr(val).substr(1);\n const ref = getElem(id);\n if (!ref) {\n findDefs().append(removedElements[id]);\n delete removedElements[id];\n }\n }\n });\n\n const childs = elem.getElementsByTagName('*');\n\n if (childs.length) {\n for (let i = 0, l = childs.length; i < l; i++) {\n restoreRefElems(childs[i]);\n }\n }\n};\n\n// (function () {\n// TODO For Issue 208: this is a start on a thumbnail\n// const svgthumb = svgdoc.createElementNS(NS.SVG, 'use');\n// svgthumb.setAttribute('width', '100');\n// svgthumb.setAttribute('height', '100');\n// setHref(svgthumb, '#svgcontent');\n// svgroot.append(svgthumb);\n// }());\n\n/**\n * @typedef {PlainObject} module:svgcanvas.SaveOptions\n * @property {boolean} apply\n * @property {\"embed\"} [image]\n * @property {Integer} round_digits\n */\n\n// Object to contain image data for raster images that were found encodable\nconst encodableImages = {},\n\n // Object with save options\n /**\n * @type {module:svgcanvas.SaveOptions}\n */\n saveOptions = {round_digits: 5},\n\n // Object with IDs for imported files, to see if one was already added\n importIds = {},\n\n // Current text style properties\n curText = allProperties.text,\n\n // Object to contain all included extensions\n extensions = {},\n\n // Map of deleted reference elements\n removedElements = {};\n\nlet\n // String with image URL of last loadable image\n lastGoodImgUrl = curConfig.imgPath + 'logo.png',\n\n // Boolean indicating whether or not a draw action has been started\n started = false,\n\n // String with an element's initial transform attribute value\n startTransform = null,\n\n // String indicating the current editor mode\n currentMode = 'select',\n\n // String with the current direction in which an element is being resized\n currentResizeMode = 'none',\n\n // Current general properties\n curProperties = curShape,\n\n // Array with selected elements' Bounding box object\n // selectedBBoxes = new Array(1),\n\n // The DOM element that was just selected\n justSelected = null,\n\n // DOM element for selection rectangle drawn by the user\n rubberBox = null,\n\n // Array of current BBoxes, used in getIntersectionList().\n curBBoxes = [],\n\n // Canvas point for the most recent right click\n lastClickPoint = null;\n\nthis.runExtension = function (name, action, vars) {\n return this.runExtensions(action, vars, false, (n) => n === name);\n};\n/**\n* @typedef {module:svgcanvas.ExtensionMouseDownStatus|module:svgcanvas.ExtensionMouseUpStatus|module:svgcanvas.ExtensionIDsUpdatedStatus|module:locale.ExtensionLocaleData[]|void} module:svgcanvas.ExtensionStatus\n* @tutorial ExtensionDocs\n*/\n/**\n* @callback module:svgcanvas.ExtensionVarBuilder\n* @param {string} name The name of the extension\n* @returns {module:svgcanvas.SvgCanvas#event:ext_addLangData}\n*/\n/**\n* @callback module:svgcanvas.ExtensionNameFilter\n* @param {string} name\n* @returns {boolean}\n*/\n/**\n* @todo Consider: Should this return an array by default, so extension results aren't overwritten?\n* @todo Would be easier to document if passing in object with key of action and vars as value; could then define an interface which tied both together\n* @function module:svgcanvas.SvgCanvas#runExtensions\n* @param {\"mouseDown\"|\"mouseMove\"|\"mouseUp\"|\"zoomChanged\"|\"IDsUpdated\"|\"canvasUpdated\"|\"toolButtonStateUpdate\"|\"selectedChanged\"|\"elementTransition\"|\"elementChanged\"|\"langReady\"|\"langChanged\"|\"addLangData\"|\"onNewDocument\"|\"workareaResized\"} action\n* @param {module:svgcanvas.SvgCanvas#event:ext_mouseDown|module:svgcanvas.SvgCanvas#event:ext_mouseMove|module:svgcanvas.SvgCanvas#event:ext_mouseUp|module:svgcanvas.SvgCanvas#event:ext_zoomChanged|module:svgcanvas.SvgCanvas#event:ext_IDsUpdated|module:svgcanvas.SvgCanvas#event:ext_canvasUpdated|module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate|module:svgcanvas.SvgCanvas#event:ext_selectedChanged|module:svgcanvas.SvgCanvas#event:ext_elementTransition|module:svgcanvas.SvgCanvas#event:ext_elementChanged|module:svgcanvas.SvgCanvas#event:ext_langReady|module:svgcanvas.SvgCanvas#event:ext_langChanged|module:svgcanvas.SvgCanvas#event:ext_addLangData|module:svgcanvas.SvgCanvas#event:ext_onNewDocument|module:svgcanvas.SvgCanvas#event:ext_workareaResized|module:svgcanvas.ExtensionVarBuilder} [vars]\n* @param {boolean} [returnArray]\n* @param {module:svgcanvas.ExtensionNameFilter} nameFilter\n* @returns {GenericArray<module:svgcanvas.ExtensionStatus>|module:svgcanvas.ExtensionStatus|false} See {@tutorial ExtensionDocs} on the ExtensionStatus.\n*/\nconst runExtensions = this.runExtensions = function (action, vars, returnArray, nameFilter) {\n let result = returnArray ? [] : false;\n $.each(extensions, function (name, ext) {\n if (nameFilter && !nameFilter(name)) {\n return;\n }\n if (ext && action in ext) {\n if (typeof vars === 'function') {\n vars = vars(name); // ext, action\n }\n if (returnArray) {\n result.push(ext[action](vars));\n } else {\n result = ext[action](vars);\n }\n }\n });\n return result;\n};\n\n/**\n* @typedef {PlainObject} module:svgcanvas.ExtensionMouseDownStatus\n* @property {boolean} started Indicates that creating/editing has started\n*/\n/**\n* @typedef {PlainObject} module:svgcanvas.ExtensionMouseUpStatus\n* @property {boolean} keep Indicates if the current element should be kept\n* @property {boolean} started Indicates if editing should still be considered as \"started\"\n* @property {Element} element The element being affected\n*/\n/**\n* @typedef {PlainObject} module:svgcanvas.ExtensionIDsUpdatedStatus\n* @property {string[]} remove Contains string IDs (used by `ext-connector.js`)\n*/\n\n/**\n * @interface module:svgcanvas.ExtensionInitResponse\n * @property {module:SVGEditor.ContextTool[]|PlainObject<string, module:SVGEditor.ContextTool>} [context_tools]\n * @property {module:SVGEditor.Button[]|PlainObject<Integer, module:SVGEditor.Button>} [buttons]\n * @property {string} [svgicons] The location of a local SVG or SVGz file\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#mouseDown\n * @param {module:svgcanvas.SvgCanvas#event:ext_mouseDown} arg\n * @returns {void|module:svgcanvas.ExtensionMouseDownStatus}\n */\n/**\n * @function module:svgcanvas.ExtensionInitResponse#mouseMove\n * @param {module:svgcanvas.SvgCanvas#event:ext_mouseMove} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#mouseUp\n * @param {module:svgcanvas.SvgCanvas#event:ext_mouseUp} arg\n * @returns {module:svgcanvas.ExtensionMouseUpStatus}\n */\n/**\n * @function module:svgcanvas.ExtensionInitResponse#zoomChanged\n * @param {module:svgcanvas.SvgCanvas#event:ext_zoomChanged} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#IDsUpdated\n * @param {module:svgcanvas.SvgCanvas#event:ext_IDsUpdated} arg\n * @returns {module:svgcanvas.ExtensionIDsUpdatedStatus}\n */\n/**\n * @function module:svgcanvas.ExtensionInitResponse#canvasUpdated\n * @param {module:svgcanvas.SvgCanvas#event:ext_canvasUpdated} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#toolButtonStateUpdate\n * @param {module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#selectedChanged\n * @param {module:svgcanvas.SvgCanvas#event:ext_selectedChanged} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#elementTransition\n * @param {module:svgcanvas.SvgCanvas#event:ext_elementTransition} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#elementChanged\n * @param {module:svgcanvas.SvgCanvas#event:ext_elementChanged} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#langReady\n * @param {module:svgcanvas.SvgCanvas#event:ext_langReady} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#langChanged\n * @param {module:svgcanvas.SvgCanvas#event:ext_langChanged} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#addLangData\n * @param {module:svgcanvas.SvgCanvas#event:ext_addLangData} arg\n * @returns {Promise<module:locale.ExtensionLocaleData>} Resolves to {@link module:locale.ExtensionLocaleData}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#onNewDocument\n * @param {module:svgcanvas.SvgCanvas#event:ext_onNewDocument} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#workareaResized\n * @param {module:svgcanvas.SvgCanvas#event:ext_workareaResized} arg\n * @returns {void}\n*/\n/**\n * @function module:svgcanvas.ExtensionInitResponse#callback\n * @this module:SVGEditor\n * @param {module:svgcanvas.SvgCanvas#event:ext_callback} arg\n * @returns {void}\n*/\n\n/**\n* @callback module:svgcanvas.ExtensionInitCallback\n* @this module:SVGEditor\n* @param {module:svgcanvas.ExtensionArgumentObject} arg\n* @returns {Promise<module:svgcanvas.ExtensionInitResponse|void>} Resolves to [ExtensionInitResponse]{@link module:svgcanvas.ExtensionInitResponse} or `undefined`\n*/\n/**\n* @typedef {PlainObject} module:svgcanvas.ExtensionInitArgs\n* @property {external:jQuery} $\n* @property {module:SVGEditor~ImportLocale} importLocale\n*/\n/**\n* Add an extension to the editor.\n* @function module:svgcanvas.SvgCanvas#addExtension\n* @param {string} name - String with the ID of the extension. Used internally; no need for i18n.\n* @param {module:svgcanvas.ExtensionInitCallback} [extInitFunc] - Function supplied by the extension with its data\n* @param {module:svgcanvas.ExtensionInitArgs} initArgs\n* @fires module:svgcanvas.SvgCanvas#event:extension_added\n* @throws {TypeError|Error} `TypeError` if `extInitFunc` is not a function, `Error`\n* if extension of supplied name already exists\n* @returns {Promise<void>} Resolves to `undefined`\n*/\nthis.addExtension = async function (name, extInitFunc, {$: jq, importLocale}) {\n if (typeof extInitFunc !== 'function') {\n throw new TypeError('Function argument expected for `svgcanvas.addExtension`');\n }\n if (name in extensions) {\n throw new Error('Cannot add extension \"' + name + '\", an extension by that name already exists.');\n }\n // Provide private vars/funcs here. Is there a better way to do this?\n /**\n * @typedef {module:svgcanvas.PrivateMethods} module:svgcanvas.ExtensionArgumentObject\n * @property {SVGSVGElement} svgroot See {@link module:svgcanvas~svgroot}\n * @property {SVGSVGElement} svgcontent See {@link module:svgcanvas~svgcontent}\n * @property {!(string|Integer)} nonce See {@link module:draw.Drawing#getNonce}\n * @property {module:select.SelectorManager} selectorManager\n * @property {module:SVGEditor~ImportLocale} importLocale\n */\n /**\n * @type {module:svgcanvas.ExtensionArgumentObject}\n * @see {@link module:svgcanvas.PrivateMethods} source for the other methods/properties\n */\n const argObj = $.extend(canvas.getPrivateMethods(), {\n $: jq,\n importLocale,\n svgroot,\n svgcontent,\n nonce: getCurrentDrawing().getNonce(),\n selectorManager\n });\n const extObj = await extInitFunc(argObj);\n if (extObj) {\n extObj.name = name;\n }\n\n extensions[name] = extObj;\n return call('extension_added', extObj);\n};\n\n/**\n* This method sends back an array or a NodeList full of elements that\n* intersect the multi-select rubber-band-box on the currentLayer only.\n*\n* We brute-force `getIntersectionList` for browsers that do not support it (Firefox).\n*\n* Reference:\n* Firefox does not implement `getIntersectionList()`, see {@link https://bugzilla.mozilla.org/show_bug.cgi?id=501421}.\n* @function module:svgcanvas.SvgCanvas#getIntersectionList\n* @param {SVGRect} rect\n* @returns {Element[]|NodeList} Bbox elements\n*/\nconst getIntersectionList = this.getIntersectionList = function (rect) {\n if (isNullish(rubberBox)) { return null; }\n\n const parent = currentGroup || getCurrentDrawing().getCurrentLayer();\n\n let rubberBBox;\n if (!rect) {\n rubberBBox = rubberBox.getBBox();\n const bb = svgcontent.createSVGRect();\n\n ['x', 'y', 'width', 'height', 'top', 'right', 'bottom', 'left'].forEach((o) => {\n bb[o] = rubberBBox[o] / currentZoom;\n });\n rubberBBox = bb;\n } else {\n rubberBBox = svgcontent.createSVGRect();\n rubberBBox.x = rect.x;\n rubberBBox.y = rect.y;\n rubberBBox.width = rect.width;\n rubberBBox.height = rect.height;\n }\n\n let resultList = null;\n if (!isIE()) {\n if (typeof svgroot.getIntersectionList === 'function') {\n // Offset the bbox of the rubber box by the offset of the svgcontent element.\n rubberBBox.x += parseInt(svgcontent.getAttribute('x'));\n rubberBBox.y += parseInt(svgcontent.getAttribute('y'));\n\n resultList = svgroot.getIntersectionList(rubberBBox, parent);\n }\n }\n\n if (isNullish(resultList) || typeof resultList.item !== 'function') {\n resultList = [];\n\n if (!curBBoxes.length) {\n // Cache all bboxes\n curBBoxes = getVisibleElementsAndBBoxes(parent);\n }\n let i = curBBoxes.length;\n while (i--) {\n if (!rubberBBox.width) { continue; }\n if (rectsIntersect(rubberBBox, curBBoxes[i].bbox)) {\n resultList.push(curBBoxes[i].elem);\n }\n }\n }\n\n // addToSelection expects an array, but it's ok to pass a NodeList\n // because using square-bracket notation is allowed:\n // https://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html\n return resultList;\n};\n\nthis.getStrokedBBox = getStrokedBBoxDefaultVisible;\n\nthis.getVisibleElements = getVisibleElements;\n\n/**\n* @typedef {PlainObject} ElementAndBBox\n* @property {Element} elem - The element\n* @property {module:utilities.BBoxObject} bbox - The element's BBox as retrieved from `getStrokedBBoxDefaultVisible`\n*/\n\n/**\n* Get all elements that have a BBox (excludes `<defs>`, `<title>`, etc).\n* Note that 0-opacity, off-screen etc elements are still considered \"visible\"\n* for this function.\n* @function module:svgcanvas.SvgCanvas#getVisibleElementsAndBBoxes\n* @param {Element} parent - The parent DOM element to search within\n* @returns {ElementAndBBox[]} An array with objects that include:\n*/\nconst getVisibleElementsAndBBoxes = this.getVisibleElementsAndBBoxes = function (parent) {\n if (!parent) {\n parent = $(svgcontent).children(); // Prevent layers from being included\n }\n const contentElems = [];\n $(parent).children().each(function (i, elem) {\n if (elem.getBBox) {\n contentElems.push({elem, bbox: getStrokedBBoxDefaultVisible([elem])});\n }\n });\n return contentElems.reverse();\n};\n\n/**\n* Wrap an SVG element into a group element, mark the group as 'gsvg'.\n* @function module:svgcanvas.SvgCanvas#groupSvgElem\n* @param {Element} elem - SVG element to wrap\n* @returns {void}\n*/\nconst groupSvgElem = this.groupSvgElem = function (elem) {\n const g = document.createElementNS(NS.SVG, 'g');\n elem.replaceWith(g);\n $(g).append(elem).data('gsvg', elem)[0].id = getNextId();\n};\n\n// Set scope for these functions\n\n// Object to contain editor event names and callback functions\nconst events = {};\n\ncanvas.call = call;\n/**\n * Array of what was changed (elements, layers).\n * @event module:svgcanvas.SvgCanvas#event:changed\n * @type {Element[]}\n */\n/**\n * Array of selected elements.\n * @event module:svgcanvas.SvgCanvas#event:selected\n * @type {Element[]}\n */\n/**\n * Array of selected elements.\n * @event module:svgcanvas.SvgCanvas#event:transition\n * @type {Element[]}\n */\n/**\n * The Element is always `SVGGElement`?\n * If not `null`, will be the set current group element.\n * @event module:svgcanvas.SvgCanvas#event:contextset\n * @type {null|Element}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:pointsAdded\n * @type {PlainObject}\n * @property {boolean} closedSubpath\n * @property {SVGCircleElement[]} grips Grips elements\n */\n\n/**\n * @event module:svgcanvas.SvgCanvas#event:zoomed\n * @type {PlainObject}\n * @property {Float} x\n * @property {Float} y\n * @property {Float} width\n * @property {Float} height\n * @property {0.5|2} factor\n * @see module:SVGEditor.BBoxObjectWithFactor\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:updateCanvas\n * @type {PlainObject}\n * @property {false} center\n * @property {module:math.XYObject} newCtr\n */\n/**\n * @typedef {PlainObject} module:svgcanvas.ExtensionInitResponsePlusName\n * @implements {module:svgcanvas.ExtensionInitResponse}\n * @property {string} name The extension's resolved ID (whether explicit or based on file name)\n */\n/**\n * Generalized extension object response of\n * [`init()`]{@link module:svgcanvas.ExtensionInitCallback}\n * along with the name of the extension.\n * @event module:svgcanvas.SvgCanvas#event:extension_added\n * @type {module:svgcanvas.ExtensionInitResponsePlusName|void}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:extensions_added\n * @type {void}\n*/\n/**\n * @typedef {PlainObject} module:svgcanvas.Message\n * @property {any} data The data\n * @property {string} origin The origin\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:message\n * @type {module:svgcanvas.Message}\n */\n/**\n * SVG canvas converted to string.\n * @event module:svgcanvas.SvgCanvas#event:saved\n * @type {string}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:setnonce\n * @type {!(string|Integer)}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:unsetnonce\n * @type {void}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:zoomDone\n * @type {void}\n*/\n/**\n * @event module:svgcanvas.SvgCanvas#event:cleared\n * @type {void}\n*/\n\n/**\n * @event module:svgcanvas.SvgCanvas#event:exported\n * @type {module:svgcanvas.ImageExportedResults}\n */\n/**\n * @event module:svgcanvas.SvgCanvas#event:exportedPDF\n * @type {module:svgcanvas.PDFExportedResults}\n */\n/**\n * Creating a cover-all class until {@link https://github.com/jsdoc3/jsdoc/issues/1545} may be supported.\n * `undefined` may be returned by {@link module:svgcanvas.SvgCanvas#event:extension_added} if the extension's `init` returns `undefined` It is also the type for the following events \"zoomDone\", \"unsetnonce\", \"cleared\", and \"extensions_added\".\n * @event module:svgcanvas.SvgCanvas#event:GenericCanvasEvent\n * @type {module:svgcanvas.SvgCanvas#event:selected|module:svgcanvas.SvgCanvas#event:changed|module:svgcanvas.SvgCanvas#event:contextset|module:svgcanvas.SvgCanvas#event:pointsAdded|module:svgcanvas.SvgCanvas#event:extension_added|module:svgcanvas.SvgCanvas#event:extensions_added|module:svgcanvas.SvgCanvas#event:message|module:svgcanvas.SvgCanvas#event:transition|module:svgcanvas.SvgCanvas#event:zoomed|module:svgcanvas.SvgCanvas#event:updateCanvas|module:svgcanvas.SvgCanvas#event:saved|module:svgcanvas.SvgCanvas#event:exported|module:svgcanvas.SvgCanvas#event:exportedPDF|module:svgcanvas.SvgCanvas#event:setnonce|module:svgcanvas.SvgCanvas#event:unsetnonce|void}\n */\n\n/**\n * The promise return, if present, resolves to `undefined`\n * (`extension_added`, `exported`, `saved`).\n * @typedef {Promise<void>|void} module:svgcanvas.EventHandlerReturn\n*/\n\n/**\n* @callback module:svgcanvas.EventHandler\n* @param {external:Window} win\n* @param {module:svgcanvas.SvgCanvas#event:GenericCanvasEvent} arg\n* @listens module:svgcanvas.SvgCanvas#event:GenericCanvasEvent\n* @returns {module:svgcanvas.EventHandlerReturn}\n*/\n\n/**\n* Attaches a callback function to an event.\n* @function module:svgcanvas.SvgCanvas#bind\n* @param {\"changed\"|\"contextset\"|\"selected\"|\"pointsAdded\"|\"extension_added\"|\"extensions_added\"|\"message\"|\"transition\"|\"zoomed\"|\"updateCanvas\"|\"zoomDone\"|\"saved\"|\"exported\"|\"exportedPDF\"|\"setnonce\"|\"unsetnonce\"|\"cleared\"} ev - String indicating the name of the event\n* @param {module:svgcanvas.EventHandler} f - The callback function to bind to the event\n* @returns {module:svgcanvas.EventHandler} The previous event\n*/\ncanvas.bind = function (ev, f) {\n const old = events[ev];\n events[ev] = f;\n return old;\n};\n\n/**\n* Runs the SVG Document through the sanitizer and then updates its paths.\n* @function module:svgcanvas.SvgCanvas#prepareSvg\n* @param {XMLDocument} newDoc - The SVG DOM document\n* @returns {void}\n*/\nthis.prepareSvg = function (newDoc) {\n this.sanitizeSvg(newDoc.documentElement);\n\n // convert paths into absolute commands\n const paths = [...newDoc.getElementsByTagNameNS(NS.SVG, 'path')];\n paths.forEach((path) => {\n path.setAttribute('d', pathActions.convertPath(path));\n pathActions.fixEnd(path);\n });\n};\n\n/**\n* Hack for Firefox bugs where text element features aren't updated or get\n* messed up. See issue 136 and issue 137.\n* This function clones the element and re-selects it.\n* @function module:svgcanvas~ffClone\n* @todo Test for this bug on load and add it to \"support\" object instead of\n* browser sniffing\n* @param {Element} elem - The (text) DOM element to clone\n* @returns {Element} Cloned element\n*/\nconst ffClone = function (elem) {\n if (!isGecko()) { return elem; }\n const clone = elem.cloneNode(true);\n elem.before(clone);\n elem.remove();\n selectorManager.releaseSelector(elem);\n selectedElements[0] = clone;\n selectorManager.requestSelector(clone).showGrips(true);\n return clone;\n};\n\n// `this.each` is deprecated, if any extension used this it can be recreated by doing this:\n// * @example $(canvas.getRootElem()).children().each(...)\n// * @function module:svgcanvas.SvgCanvas#each\n// this.each = function (cb) {\n// $(svgroot).children().each(cb);\n// };\n\n/**\n* Removes any old rotations if present, prepends a new rotation at the\n* transformed center.\n* @function module:svgcanvas.SvgCanvas#setRotationAngle\n* @param {string|Float} val - The new rotation angle in degrees\n* @param {boolean} preventUndo - Indicates whether the action should be undoable or not\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setRotationAngle = function (val, preventUndo) {\n // ensure val is the proper type\n val = parseFloat(val);\n const elem = selectedElements[0];\n const oldTransform = elem.getAttribute('transform');\n const bbox = utilsGetBBox(elem);\n const cx = bbox.x + bbox.width / 2, cy = bbox.y + bbox.height / 2;\n const tlist = getTransformList(elem);\n\n // only remove the real rotational transform if present (i.e. at index=0)\n if (tlist.numberOfItems > 0) {\n const xform = tlist.getItem(0);\n if (xform.type === 4) {\n tlist.removeItem(0);\n }\n }\n // find Rnc and insert it\n if (val !== 0) {\n const center = transformPoint(cx, cy, transformListToTransform(tlist).matrix);\n const Rnc = svgroot.createSVGTransform();\n Rnc.setRotate(val, center.x, center.y);\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(Rnc, 0);\n } else {\n tlist.appendItem(Rnc);\n }\n } else if (tlist.numberOfItems === 0) {\n elem.removeAttribute('transform');\n }\n\n if (!preventUndo) {\n // we need to undo it, then redo it so it can be undo-able! :)\n // TODO: figure out how to make changes to transform list undo-able cross-browser?\n const newTransform = elem.getAttribute('transform');\n elem.setAttribute('transform', oldTransform);\n changeSelectedAttribute('transform', newTransform, selectedElements);\n call('changed', selectedElements);\n }\n // const pointGripContainer = getElem('pathpointgrip_container');\n // if (elem.nodeName === 'path' && pointGripContainer) {\n // pathActions.setPointContainerTransform(elem.getAttribute('transform'));\n // }\n const selector = selectorManager.requestSelector(selectedElements[0]);\n selector.resize();\n Selector.updateGripCursors(val);\n};\n\n/**\n* Runs `recalculateDimensions` on the selected elements,\n* adding the changes to a single batch command.\n* @function module:svgcanvas.SvgCanvas#recalculateAllSelectedDimensions\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nconst recalculateAllSelectedDimensions = this.recalculateAllSelectedDimensions = function () {\n const text = (currentResizeMode === 'none' ? 'position' : 'size');\n const batchCmd = new BatchCommand(text);\n\n let i = selectedElements.length;\n while (i--) {\n const elem = selectedElements[i];\n // if (getRotationAngle(elem) && !hasMatrixTransform(getTransformList(elem))) { continue; }\n const cmd = recalculateDimensions(elem);\n if (cmd) {\n batchCmd.addSubCommand(cmd);\n }\n }\n\n if (!batchCmd.isEmpty()) {\n addCommandToHistory(batchCmd);\n call('changed', selectedElements);\n }\n};\n\n/**\n * Debug tool to easily see the current matrix in the browser's console.\n * @function module:svgcanvas~logMatrix\n * @param {SVGMatrix} m The matrix\n * @returns {void}\n */\nconst logMatrix = function (m) {\n console.log([m.a, m.b, m.c, m.d, m.e, m.f]); // eslint-disable-line no-console\n};\n\n// Root Current Transformation Matrix in user units\nlet rootSctm = null;\n\n/**\n* Group: Selection.\n*/\n\n// TODO: do we need to worry about selectedBBoxes here?\n\n/**\n* Selects only the given elements, shortcut for `clearSelection(); addToSelection()`.\n* @function module:svgcanvas.SvgCanvas#selectOnly\n* @param {Element[]} elems - an array of DOM elements to be selected\n* @param {boolean} showGrips - Indicates whether the resize grips should be shown\n* @returns {void}\n*/\nconst selectOnly = this.selectOnly = function (elems, showGrips) {\n clearSelection(true);\n addToSelection(elems, showGrips);\n};\n\n// TODO: could use slice here to make this faster?\n// TODO: should the 'selected' handler\n\n/**\n* Removes elements from the selection.\n* @function module:svgcanvas.SvgCanvas#removeFromSelection\n* @param {Element[]} elemsToRemove - An array of elements to remove from selection\n* @returns {void}\n*/\n/* const removeFromSelection = */ this.removeFromSelection = function (elemsToRemove) {\n if (isNullish(selectedElements[0])) { return; }\n if (!elemsToRemove.length) { return; }\n\n // find every element and remove it from our array copy\n const newSelectedItems = [],\n len = selectedElements.length;\n for (let i = 0; i < len; ++i) {\n const elem = selectedElements[i];\n if (elem) {\n // keep the item\n if (!elemsToRemove.includes(elem)) {\n newSelectedItems.push(elem);\n } else { // remove the item and its selector\n selectorManager.releaseSelector(elem);\n }\n }\n }\n // the copy becomes the master now\n selectedElements = newSelectedItems;\n};\n\n/**\n* Clears the selection, then adds all elements in the current layer to the selection.\n* @function module:svgcanvas.SvgCanvas#selectAllInCurrentLayer\n* @returns {void}\n*/\nthis.selectAllInCurrentLayer = function () {\n const currentLayer = getCurrentDrawing().getCurrentLayer();\n if (currentLayer) {\n currentMode = 'select';\n selectOnly($(currentGroup || currentLayer).children());\n }\n};\n\nlet drawnPath = null;\n\n// Mouse events\n(function () {\nconst freehand = {\n minx: null,\n miny: null,\n maxx: null,\n maxy: null\n};\nconst THRESHOLD_DIST = 0.8,\n STEP_COUNT = 10;\nlet dAttr = null,\n startX = null,\n startY = null,\n rStartX = null,\n rStartY = null,\n initBbox = {},\n sumDistance = 0,\n controllPoint2 = {x: 0, y: 0},\n controllPoint1 = {x: 0, y: 0},\n start = {x: 0, y: 0},\n end = {x: 0, y: 0},\n bSpline = {x: 0, y: 0},\n nextPos = {x: 0, y: 0},\n parameter,\n nextParameter;\n\nconst getBsplinePoint = function (t) {\n const spline = {x: 0, y: 0},\n p0 = controllPoint2,\n p1 = controllPoint1,\n p2 = start,\n p3 = end,\n S = 1.0 / 6.0,\n t2 = t * t,\n t3 = t2 * t;\n\n const m = [\n [-1, 3, -3, 1],\n [3, -6, 3, 0],\n [-3, 0, 3, 0],\n [1, 4, 1, 0]\n ];\n\n spline.x = S * (\n (p0.x * m[0][0] + p1.x * m[0][1] + p2.x * m[0][2] + p3.x * m[0][3]) * t3 +\n (p0.x * m[1][0] + p1.x * m[1][1] + p2.x * m[1][2] + p3.x * m[1][3]) * t2 +\n (p0.x * m[2][0] + p1.x * m[2][1] + p2.x * m[2][2] + p3.x * m[2][3]) * t +\n (p0.x * m[3][0] + p1.x * m[3][1] + p2.x * m[3][2] + p3.x * m[3][3])\n );\n spline.y = S * (\n (p0.y * m[0][0] + p1.y * m[0][1] + p2.y * m[0][2] + p3.y * m[0][3]) * t3 +\n (p0.y * m[1][0] + p1.y * m[1][1] + p2.y * m[1][2] + p3.y * m[1][3]) * t2 +\n (p0.y * m[2][0] + p1.y * m[2][1] + p2.y * m[2][2] + p3.y * m[2][3]) * t +\n (p0.y * m[3][0] + p1.y * m[3][1] + p2.y * m[3][2] + p3.y * m[3][3])\n );\n\n return {\n x: spline.x,\n y: spline.y\n };\n};\n/**\n * Follows these conditions:\n * - When we are in a create mode, the element is added to the canvas but the\n * action is not recorded until mousing up.\n * - When we are in select mode, select the element, remember the position\n * and do nothing else.\n * @param {MouseEvent} evt\n * @fires module:svgcanvas.SvgCanvas#event:ext_mouseDown\n * @returns {void}\n */\nconst mouseDown = function (evt) {\n if (canvas.spaceKey || evt.button === 1) { return; }\n\n const rightClick = evt.button === 2;\n\n if (evt.altKey) { // duplicate when dragging\n canvas.cloneSelectedElements(0, 0);\n }\n\n rootSctm = $('#svgcontent g')[0].getScreenCTM().inverse();\n\n const pt = transformPoint(evt.pageX, evt.pageY, rootSctm),\n mouseX = pt.x * currentZoom,\n mouseY = pt.y * currentZoom;\n\n evt.preventDefault();\n\n if (rightClick) {\n currentMode = 'select';\n lastClickPoint = pt;\n }\n\n // This would seem to be unnecessary...\n // if (!['select', 'resize'].includes(currentMode)) {\n // setGradient();\n // }\n\n let x = mouseX / currentZoom,\n y = mouseY / currentZoom;\n let mouseTarget = getMouseTarget(evt);\n\n if (mouseTarget.tagName === 'a' && mouseTarget.childNodes.length === 1) {\n mouseTarget = mouseTarget.firstChild;\n }\n\n // realX/y ignores grid-snap value\n const realX = x;\n rStartX = startX = x;\n const realY = y;\n rStartY = startY = y;\n\n if (curConfig.gridSnapping) {\n x = snapToGrid(x);\n y = snapToGrid(y);\n startX = snapToGrid(startX);\n startY = snapToGrid(startY);\n }\n\n // if it is a selector grip, then it must be a single element selected,\n // set the mouseTarget to that and update the mode to rotate/resize\n\n if (mouseTarget === selectorManager.selectorParentGroup && !isNullish(selectedElements[0])) {\n const grip = evt.target;\n const griptype = elData(grip, 'type');\n // rotating\n if (griptype === 'rotate') {\n currentMode = 'rotate';\n // resizing\n } else if (griptype === 'resize') {\n currentMode = 'resize';\n currentResizeMode = elData(grip, 'dir');\n }\n mouseTarget = selectedElements[0];\n }\n\n startTransform = mouseTarget.getAttribute('transform');\n\n const tlist = getTransformList(mouseTarget);\n switch (currentMode) {\n case 'select':\n started = true;\n currentResizeMode = 'none';\n if (rightClick) { started = false; }\n\n if (mouseTarget !== svgroot) {\n // if this element is not yet selected, clear selection and select it\n if (!selectedElements.includes(mouseTarget)) {\n // only clear selection if shift is not pressed (otherwise, add\n // element to selection)\n if (!evt.shiftKey) {\n // No need to do the call here as it will be done on addToSelection\n clearSelection(true);\n }\n addToSelection([mouseTarget]);\n justSelected = mouseTarget;\n pathActions.clear();\n }\n // else if it's a path, go into pathedit mode in mouseup\n\n if (!rightClick) {\n // insert a dummy transform so if the element(s) are moved it will have\n // a transform to use for its translate\n for (const selectedElement of selectedElements) {\n if (isNullish(selectedElement)) { continue; }\n const slist = getTransformList(selectedElement);\n if (slist.numberOfItems) {\n slist.insertItemBefore(svgroot.createSVGTransform(), 0);\n } else {\n slist.appendItem(svgroot.createSVGTransform());\n }\n }\n }\n } else if (!rightClick) {\n clearSelection();\n currentMode = 'multiselect';\n if (isNullish(rubberBox)) {\n rubberBox = selectorManager.getRubberBandBox();\n }\n rStartX *= currentZoom;\n rStartY *= currentZoom;\n // console.log('p',[evt.pageX, evt.pageY]);\n // console.log('c',[evt.clientX, evt.clientY]);\n // console.log('o',[evt.offsetX, evt.offsetY]);\n // console.log('s',[startX, startY]);\n\n assignAttributes(rubberBox, {\n x: rStartX,\n y: rStartY,\n width: 0,\n height: 0,\n display: 'inline'\n }, 100);\n }\n break;\n case 'zoom':\n started = true;\n if (isNullish(rubberBox)) {\n rubberBox = selectorManager.getRubberBandBox();\n }\n assignAttributes(rubberBox, {\n x: realX * currentZoom,\n y: realX * currentZoom,\n width: 0,\n height: 0,\n display: 'inline'\n }, 100);\n break;\n case 'resize': {\n started = true;\n startX = x;\n startY = y;\n\n // Getting the BBox from the selection box, since we know we\n // want to orient around it\n initBbox = utilsGetBBox($('#selectedBox0')[0]);\n const bb = {};\n $.each(initBbox, function (key, val) {\n bb[key] = val / currentZoom;\n });\n initBbox = bb;\n\n // append three dummy transforms to the tlist so that\n // we can translate,scale,translate in mousemove\n const pos = getRotationAngle(mouseTarget) ? 1 : 0;\n\n if (hasMatrixTransform(tlist)) {\n tlist.insertItemBefore(svgroot.createSVGTransform(), pos);\n tlist.insertItemBefore(svgroot.createSVGTransform(), pos);\n tlist.insertItemBefore(svgroot.createSVGTransform(), pos);\n } else {\n tlist.appendItem(svgroot.createSVGTransform());\n tlist.appendItem(svgroot.createSVGTransform());\n tlist.appendItem(svgroot.createSVGTransform());\n\n if (supportsNonScalingStroke()) {\n // Handle crash for newer Chrome and Safari 6 (Mobile and Desktop):\n // https://code.google.com/p/svg-edit/issues/detail?id=904\n // Chromium issue: https://code.google.com/p/chromium/issues/detail?id=114625\n // TODO: Remove this workaround once vendor fixes the issue\n const iswebkit = isWebkit();\n\n let delayedStroke;\n if (iswebkit) {\n delayedStroke = function (ele) {\n const stroke_ = ele.getAttribute('stroke');\n ele.removeAttribute('stroke');\n // Re-apply stroke after delay. Anything higher than 1 seems to cause flicker\n if (stroke_ !== null) setTimeout(function () { ele.setAttribute('stroke', stroke_); }, 0);\n };\n }\n mouseTarget.style.vectorEffect = 'non-scaling-stroke';\n if (iswebkit) { delayedStroke(mouseTarget); }\n\n const all = mouseTarget.getElementsByTagName('*'),\n len = all.length;\n for (let i = 0; i < len; i++) {\n if (!all[i].style) { // mathML\n continue;\n }\n all[i].style.vectorEffect = 'non-scaling-stroke';\n if (iswebkit) { delayedStroke(all[i]); }\n }\n }\n }\n break;\n }\n case 'fhellipse':\n case 'fhrect':\n case 'fhpath':\n start.x = realX;\n start.y = realY;\n controllPoint1 = {x: 0, y: 0};\n controllPoint2 = {x: 0, y: 0};\n started = true;\n dAttr = realX + ',' + realY + ' ';\n // Commented out as doing nothing now:\n // strokeW = parseFloat(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width;\n addSVGElementFromJson({\n element: 'polyline',\n curStyles: true,\n attr: {\n points: dAttr,\n id: getNextId(),\n fill: 'none',\n opacity: curShape.opacity / 2,\n 'stroke-linecap': 'round',\n style: 'pointer-events:none'\n }\n });\n freehand.minx = realX;\n freehand.maxx = realX;\n freehand.miny = realY;\n freehand.maxy = realY;\n break;\n case 'image': {\n started = true;\n const newImage = addSVGElementFromJson({\n element: 'image',\n attr: {\n x,\n y,\n width: 0,\n height: 0,\n id: getNextId(),\n opacity: curShape.opacity / 2,\n style: 'pointer-events:inherit'\n }\n });\n setHref(newImage, lastGoodImgUrl);\n preventClickDefault(newImage);\n break;\n } case 'square':\n // TODO: once we create the rect, we lose information that this was a square\n // (for resizing purposes this could be important)\n // Fallthrough\n case 'rect':\n started = true;\n startX = x;\n startY = y;\n addSVGElementFromJson({\n element: 'rect',\n curStyles: true,\n attr: {\n x,\n y,\n width: 0,\n height: 0,\n id: getNextId(),\n opacity: curShape.opacity / 2\n }\n });\n break;\n case 'line': {\n started = true;\n const strokeW = Number(curShape.stroke_width) === 0 ? 1 : curShape.stroke_width;\n addSVGElementFromJson({\n element: 'line',\n curStyles: true,\n attr: {\n x1: x,\n y1: y,\n x2: x,\n y2: y,\n id: getNextId(),\n stroke: curShape.stroke,\n 'stroke-width': strokeW,\n 'stroke-dasharray': curShape.stroke_dasharray,\n 'stroke-linejoin': curShape.stroke_linejoin,\n 'stroke-linecap': curShape.stroke_linecap,\n 'stroke-opacity': curShape.stroke_opacity,\n fill: 'none',\n opacity: curShape.opacity / 2,\n style: 'pointer-events:none'\n }\n });\n break;\n } case 'circle':\n started = true;\n addSVGElementFromJson({\n element: 'circle',\n curStyles: true,\n attr: {\n cx: x,\n cy: y,\n r: 0,\n id: getNextId(),\n opacity: curShape.opacity / 2\n }\n });\n break;\n case 'ellipse':\n started = true;\n addSVGElementFromJson({\n element: 'ellipse',\n curStyles: true,\n attr: {\n cx: x,\n cy: y,\n rx: 0,\n ry: 0,\n id: getNextId(),\n opacity: curShape.opacity / 2\n }\n });\n break;\n case 'text':\n started = true;\n /* const newText = */ addSVGElementFromJson({\n element: 'text',\n curStyles: true,\n attr: {\n x,\n y,\n id: getNextId(),\n fill: curText.fill,\n 'stroke-width': curText.stroke_width,\n 'font-size': curText.font_size,\n 'font-family': curText.font_family,\n 'text-anchor': 'middle',\n 'xml:space': 'preserve',\n opacity: curShape.opacity\n }\n });\n // newText.textContent = 'text';\n break;\n case 'path':\n // Fall through\n case 'pathedit':\n startX *= currentZoom;\n startY *= currentZoom;\n pathActions.mouseDown(evt, mouseTarget, startX, startY);\n started = true;\n break;\n case 'textedit':\n startX *= currentZoom;\n startY *= currentZoom;\n textActions.mouseDown(evt, mouseTarget, startX, startY);\n started = true;\n break;\n case 'rotate':\n started = true;\n // we are starting an undoable change (a drag-rotation)\n canvas.undoMgr.beginUndoableChange('transform', selectedElements);\n break;\n default:\n // This could occur in an extension\n break;\n }\n\n /**\n * The main (left) mouse button is held down on the canvas area.\n * @event module:svgcanvas.SvgCanvas#event:ext_mouseDown\n * @type {PlainObject}\n * @property {MouseEvent} event The event object\n * @property {Float} start_x x coordinate on canvas\n * @property {Float} start_y y coordinate on canvas\n * @property {Element[]} selectedElements An array of the selected Elements\n */\n const extResult = runExtensions('mouseDown', /** @type {module:svgcanvas.SvgCanvas#event:ext_mouseDown} */ {\n event: evt,\n start_x: startX,\n start_y: startY,\n selectedElements\n }, true);\n\n $.each(extResult, function (i, r) {\n if (r && r.started) {\n started = true;\n }\n });\n};\n\n// in this function we do not record any state changes yet (but we do update\n// any elements that are still being created, moved or resized on the canvas)\n/**\n *\n * @param {MouseEvent} evt\n * @fires module:svgcanvas.SvgCanvas#event:transition\n * @fires module:svgcanvas.SvgCanvas#event:ext_mouseMove\n * @returns {void}\n */\nconst mouseMove = function (evt) {\n if (!started) { return; }\n if (evt.button === 1 || canvas.spaceKey) { return; }\n\n let i, xya, c, cx, cy, dx, dy, len, angle, box,\n selected = selectedElements[0];\n const\n pt = transformPoint(evt.pageX, evt.pageY, rootSctm),\n mouseX = pt.x * currentZoom,\n mouseY = pt.y * currentZoom,\n shape = getElem(getId());\n\n let realX = mouseX / currentZoom;\n let x = realX;\n let realY = mouseY / currentZoom;\n let y = realY;\n\n if (curConfig.gridSnapping) {\n x = snapToGrid(x);\n y = snapToGrid(y);\n }\n\n evt.preventDefault();\n let tlist;\n switch (currentMode) {\n case 'select': {\n // we temporarily use a translate on the element(s) being dragged\n // this transform is removed upon mousing up and the element is\n // relocated to the new location\n if (selectedElements[0] !== null) {\n dx = x - startX;\n dy = y - startY;\n\n if (curConfig.gridSnapping) {\n dx = snapToGrid(dx);\n dy = snapToGrid(dy);\n }\n\n /*\n // Commenting out as currently has no effect\n if (evt.shiftKey) {\n xya = snapToAngle(startX, startY, x, y);\n ({x, y} = xya);\n }\n */\n\n if (dx !== 0 || dy !== 0) {\n len = selectedElements.length;\n for (i = 0; i < len; ++i) {\n selected = selectedElements[i];\n if (isNullish(selected)) { break; }\n // if (i === 0) {\n // const box = utilsGetBBox(selected);\n // selectedBBoxes[i].x = box.x + dx;\n // selectedBBoxes[i].y = box.y + dy;\n // }\n\n // update the dummy transform in our transform list\n // to be a translate\n const xform = svgroot.createSVGTransform();\n tlist = getTransformList(selected);\n // Note that if Webkit and there's no ID for this\n // element, the dummy transform may have gotten lost.\n // This results in unexpected behaviour\n\n xform.setTranslate(dx, dy);\n if (tlist.numberOfItems) {\n tlist.replaceItem(xform, 0);\n } else {\n tlist.appendItem(xform);\n }\n\n // update our internal bbox that we're tracking while dragging\n selectorManager.requestSelector(selected).resize();\n }\n\n call('transition', selectedElements);\n }\n }\n break;\n } case 'multiselect': {\n realX *= currentZoom;\n realY *= currentZoom;\n assignAttributes(rubberBox, {\n x: Math.min(rStartX, realX),\n y: Math.min(rStartY, realY),\n width: Math.abs(realX - rStartX),\n height: Math.abs(realY - rStartY)\n }, 100);\n\n // for each selected:\n // - if newList contains selected, do nothing\n // - if newList doesn't contain selected, remove it from selected\n // - for any newList that was not in selectedElements, add it to selected\n const elemsToRemove = selectedElements.slice(), elemsToAdd = [],\n newList = getIntersectionList();\n\n // For every element in the intersection, add if not present in selectedElements.\n len = newList.length;\n for (i = 0; i < len; ++i) {\n const intElem = newList[i];\n // Found an element that was not selected before, so we should add it.\n if (!selectedElements.includes(intElem)) {\n elemsToAdd.push(intElem);\n }\n // Found an element that was already selected, so we shouldn't remove it.\n const foundInd = elemsToRemove.indexOf(intElem);\n if (foundInd !== -1) {\n elemsToRemove.splice(foundInd, 1);\n }\n }\n\n if (elemsToRemove.length > 0) {\n canvas.removeFromSelection(elemsToRemove);\n }\n\n if (elemsToAdd.length > 0) {\n canvas.addToSelection(elemsToAdd);\n }\n\n break;\n } case 'resize': {\n // we track the resize bounding box and translate/scale the selected element\n // while the mouse is down, when mouse goes up, we use this to recalculate\n // the shape's coordinates\n tlist = getTransformList(selected);\n const hasMatrix = hasMatrixTransform(tlist);\n box = hasMatrix ? initBbox : utilsGetBBox(selected);\n let left = box.x,\n top = box.y,\n {width, height} = box;\n dx = (x - startX);\n dy = (y - startY);\n\n if (curConfig.gridSnapping) {\n dx = snapToGrid(dx);\n dy = snapToGrid(dy);\n height = snapToGrid(height);\n width = snapToGrid(width);\n }\n\n // if rotated, adjust the dx,dy values\n angle = getRotationAngle(selected);\n if (angle) {\n const r = Math.sqrt(dx * dx + dy * dy),\n theta = Math.atan2(dy, dx) - angle * Math.PI / 180.0;\n dx = r * Math.cos(theta);\n dy = r * Math.sin(theta);\n }\n\n // if not stretching in y direction, set dy to 0\n // if not stretching in x direction, set dx to 0\n if (!currentResizeMode.includes('n') && !currentResizeMode.includes('s')) {\n dy = 0;\n }\n if (!currentResizeMode.includes('e') && !currentResizeMode.includes('w')) {\n dx = 0;\n }\n\n let // ts = null,\n tx = 0, ty = 0,\n sy = height ? (height + dy) / height : 1,\n sx = width ? (width + dx) / width : 1;\n // if we are dragging on the north side, then adjust the scale factor and ty\n if (currentResizeMode.includes('n')) {\n sy = height ? (height - dy) / height : 1;\n ty = height;\n }\n\n // if we dragging on the east side, then adjust the scale factor and tx\n if (currentResizeMode.includes('w')) {\n sx = width ? (width - dx) / width : 1;\n tx = width;\n }\n\n // update the transform list with translate,scale,translate\n const translateOrigin = svgroot.createSVGTransform(),\n scale = svgroot.createSVGTransform(),\n translateBack = svgroot.createSVGTransform();\n\n if (curConfig.gridSnapping) {\n left = snapToGrid(left);\n tx = snapToGrid(tx);\n top = snapToGrid(top);\n ty = snapToGrid(ty);\n }\n\n translateOrigin.setTranslate(-(left + tx), -(top + ty));\n if (evt.shiftKey) {\n if (sx === 1) {\n sx = sy;\n } else { sy = sx; }\n }\n scale.setScale(sx, sy);\n\n translateBack.setTranslate(left + tx, top + ty);\n if (hasMatrix) {\n const diff = angle ? 1 : 0;\n tlist.replaceItem(translateOrigin, 2 + diff);\n tlist.replaceItem(scale, 1 + diff);\n tlist.replaceItem(translateBack, Number(diff));\n } else {\n const N = tlist.numberOfItems;\n tlist.replaceItem(translateBack, N - 3);\n tlist.replaceItem(scale, N - 2);\n tlist.replaceItem(translateOrigin, N - 1);\n }\n\n selectorManager.requestSelector(selected).resize();\n\n call('transition', selectedElements);\n\n break;\n } case 'zoom': {\n realX *= currentZoom;\n realY *= currentZoom;\n assignAttributes(rubberBox, {\n x: Math.min(rStartX * currentZoom, realX),\n y: Math.min(rStartY * currentZoom, realY),\n width: Math.abs(realX - rStartX * currentZoom),\n height: Math.abs(realY - rStartY * currentZoom)\n }, 100);\n break;\n } case 'text': {\n assignAttributes(shape, {\n x,\n y\n }, 1000);\n break;\n } case 'line': {\n if (curConfig.gridSnapping) {\n x = snapToGrid(x);\n y = snapToGrid(y);\n }\n\n let x2 = x;\n let y2 = y;\n\n if (evt.shiftKey) {\n xya = snapToAngle(startX, startY, x2, y2);\n x2 = xya.x;\n y2 = xya.y;\n }\n\n shape.setAttribute('x2', x2);\n shape.setAttribute('y2', y2);\n break;\n } case 'foreignObject':\n // fall through\n case 'square':\n // fall through\n case 'rect':\n // fall through\n case 'image': {\n const square = (currentMode === 'square') || evt.shiftKey;\n let\n w = Math.abs(x - startX),\n h = Math.abs(y - startY);\n let newX, newY;\n if (square) {\n w = h = Math.max(w, h);\n newX = startX < x ? startX : startX - w;\n newY = startY < y ? startY : startY - h;\n } else {\n newX = Math.min(startX, x);\n newY = Math.min(startY, y);\n }\n\n if (curConfig.gridSnapping) {\n w = snapToGrid(w);\n h = snapToGrid(h);\n newX = snapToGrid(newX);\n newY = snapToGrid(newY);\n }\n\n assignAttributes(shape, {\n width: w,\n height: h,\n x: newX,\n y: newY\n }, 1000);\n\n break;\n } case 'circle': {\n c = $(shape).attr(['cx', 'cy']);\n ({cx, cy} = c);\n let rad = Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));\n if (curConfig.gridSnapping) {\n rad = snapToGrid(rad);\n }\n shape.setAttribute('r', rad);\n break;\n } case 'ellipse': {\n c = $(shape).attr(['cx', 'cy']);\n ({cx, cy} = c);\n if (curConfig.gridSnapping) {\n x = snapToGrid(x);\n cx = snapToGrid(cx);\n y = snapToGrid(y);\n cy = snapToGrid(cy);\n }\n shape.setAttribute('rx', Math.abs(x - cx));\n const ry = Math.abs(evt.shiftKey ? (x - cx) : (y - cy));\n shape.setAttribute('ry', ry);\n break;\n }\n case 'fhellipse':\n case 'fhrect': {\n freehand.minx = Math.min(realX, freehand.minx);\n freehand.maxx = Math.max(realX, freehand.maxx);\n freehand.miny = Math.min(realY, freehand.miny);\n freehand.maxy = Math.max(realY, freehand.maxy);\n }\n // Fallthrough\n case 'fhpath': {\n // dAttr += + realX + ',' + realY + ' ';\n // shape.setAttribute('points', dAttr);\n end.x = realX; end.y = realY;\n if (controllPoint2.x && controllPoint2.y) {\n for (i = 0; i < STEP_COUNT - 1; i++) {\n parameter = i / STEP_COUNT;\n nextParameter = (i + 1) / STEP_COUNT;\n bSpline = getBsplinePoint(nextParameter);\n nextPos = bSpline;\n bSpline = getBsplinePoint(parameter);\n sumDistance += Math.sqrt((nextPos.x - bSpline.x) * (nextPos.x - bSpline.x) + (nextPos.y - bSpline.y) * (nextPos.y - bSpline.y));\n if (sumDistance > THRESHOLD_DIST) {\n sumDistance -= THRESHOLD_DIST;\n\n // Faster than completely re-writing the points attribute.\n const point = svgcontent.createSVGPoint();\n point.x = bSpline.x;\n point.y = bSpline.y;\n shape.points.appendItem(point);\n }\n }\n }\n controllPoint2 = {x: controllPoint1.x, y: controllPoint1.y};\n controllPoint1 = {x: start.x, y: start.y};\n start = {x: end.x, y: end.y};\n break;\n // update path stretch line coordinates\n} case 'path':\n // fall through\n case 'pathedit': {\n x *= currentZoom;\n y *= currentZoom;\n\n if (curConfig.gridSnapping) {\n x = snapToGrid(x);\n y = snapToGrid(y);\n startX = snapToGrid(startX);\n startY = snapToGrid(startY);\n }\n if (evt.shiftKey) {\n const {path} = pathModule;\n let x1, y1;\n if (path) {\n x1 = path.dragging ? path.dragging[0] : startX;\n y1 = path.dragging ? path.dragging[1] : startY;\n } else {\n x1 = startX;\n y1 = startY;\n }\n xya = snapToAngle(x1, y1, x, y);\n ({x, y} = xya);\n }\n\n if (rubberBox && rubberBox.getAttribute('display') !== 'none') {\n realX *= currentZoom;\n realY *= currentZoom;\n assignAttributes(rubberBox, {\n x: Math.min(rStartX * currentZoom, realX),\n y: Math.min(rStartY * currentZoom, realY),\n width: Math.abs(realX - rStartX * currentZoom),\n height: Math.abs(realY - rStartY * currentZoom)\n }, 100);\n }\n pathActions.mouseMove(x, y);\n\n break;\n } case 'textedit': {\n x *= currentZoom;\n y *= currentZoom;\n // if (rubberBox && rubberBox.getAttribute('display') !== 'none') {\n // assignAttributes(rubberBox, {\n // x: Math.min(startX, x),\n // y: Math.min(startY, y),\n // width: Math.abs(x - startX),\n // height: Math.abs(y - startY)\n // }, 100);\n // }\n\n textActions.mouseMove(mouseX, mouseY);\n\n break;\n } case 'rotate': {\n box = utilsGetBBox(selected);\n cx = box.x + box.width / 2;\n cy = box.y + box.height / 2;\n const m = getMatrix(selected),\n center = transformPoint(cx, cy, m);\n cx = center.x;\n cy = center.y;\n angle = ((Math.atan2(cy - y, cx - x) * (180 / Math.PI)) - 90) % 360;\n if (curConfig.gridSnapping) {\n angle = snapToGrid(angle);\n }\n if (evt.shiftKey) { // restrict rotations to nice angles (WRS)\n const snap = 45;\n angle = Math.round(angle / snap) * snap;\n }\n\n canvas.setRotationAngle(angle < -180 ? (360 + angle) : angle, true);\n call('transition', selectedElements);\n break;\n } default:\n break;\n }\n\n /**\n * The mouse has moved on the canvas area.\n * @event module:svgcanvas.SvgCanvas#event:ext_mouseMove\n * @type {PlainObject}\n * @property {MouseEvent} event The event object\n * @property {Float} mouse_x x coordinate on canvas\n * @property {Float} mouse_y y coordinate on canvas\n * @property {Element} selected Refers to the first selected element\n */\n runExtensions('mouseMove', /** @type {module:svgcanvas.SvgCanvas#event:ext_mouseMove} */ {\n event: evt,\n mouse_x: mouseX,\n mouse_y: mouseY,\n selected\n });\n}; // mouseMove()\n\n// - in create mode, the element's opacity is set properly, we create an InsertElementCommand\n// and store it on the Undo stack\n// - in move/resize mode, the element's attributes which were affected by the move/resize are\n// identified, a ChangeElementCommand is created and stored on the stack for those attrs\n// this is done in when we recalculate the selected dimensions()\n/**\n *\n * @param {MouseEvent} evt\n * @fires module:svgcanvas.SvgCanvas#event:zoomed\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @fires module:svgcanvas.SvgCanvas#event:ext_mouseUp\n * @returns {void}\n */\nconst mouseUp = function (evt) {\n if (evt.button === 2) { return; }\n const tempJustSelected = justSelected;\n justSelected = null;\n if (!started) { return; }\n const pt = transformPoint(evt.pageX, evt.pageY, rootSctm),\n mouseX = pt.x * currentZoom,\n mouseY = pt.y * currentZoom,\n x = mouseX / currentZoom,\n y = mouseY / currentZoom;\n\n let element = getElem(getId());\n let keep = false;\n\n const realX = x;\n const realY = y;\n\n // TODO: Make true when in multi-unit mode\n const useUnit = false; // (curConfig.baseUnit !== 'px');\n started = false;\n let attrs, t;\n switch (currentMode) {\n // intentionally fall-through to select here\n case 'resize':\n case 'multiselect':\n if (!isNullish(rubberBox)) {\n rubberBox.setAttribute('display', 'none');\n curBBoxes = [];\n }\n currentMode = 'select';\n // Fallthrough\n case 'select':\n if (!isNullish(selectedElements[0])) {\n // if we only have one selected element\n if (isNullish(selectedElements[1])) {\n // set our current stroke/fill properties to the element's\n const selected = selectedElements[0];\n switch (selected.tagName) {\n case 'g':\n case 'use':\n case 'image':\n case 'foreignObject':\n break;\n default:\n curProperties.fill = selected.getAttribute('fill');\n curProperties.fill_opacity = selected.getAttribute('fill-opacity');\n curProperties.stroke = selected.getAttribute('stroke');\n curProperties.stroke_opacity = selected.getAttribute('stroke-opacity');\n curProperties.stroke_width = selected.getAttribute('stroke-width');\n curProperties.stroke_dasharray = selected.getAttribute('stroke-dasharray');\n curProperties.stroke_linejoin = selected.getAttribute('stroke-linejoin');\n curProperties.stroke_linecap = selected.getAttribute('stroke-linecap');\n }\n\n if (selected.tagName === 'text') {\n curText.font_size = selected.getAttribute('font-size');\n curText.font_family = selected.getAttribute('font-family');\n }\n selectorManager.requestSelector(selected).showGrips(true);\n\n // This shouldn't be necessary as it was done on mouseDown...\n // call('selected', [selected]);\n }\n // always recalculate dimensions to strip off stray identity transforms\n recalculateAllSelectedDimensions();\n // if it was being dragged/resized\n if (realX !== rStartX || realY !== rStartY) {\n const len = selectedElements.length;\n for (let i = 0; i < len; ++i) {\n if (isNullish(selectedElements[i])) { break; }\n if (!selectedElements[i].firstChild) {\n // Not needed for groups (incorrectly resizes elems), possibly not needed at all?\n selectorManager.requestSelector(selectedElements[i]).resize();\n }\n }\n // no change in position/size, so maybe we should move to pathedit\n } else {\n t = evt.target;\n if (selectedElements[0].nodeName === 'path' && isNullish(selectedElements[1])) {\n pathActions.select(selectedElements[0]);\n // if it was a path\n // else, if it was selected and this is a shift-click, remove it from selection\n } else if (evt.shiftKey) {\n if (tempJustSelected !== t) {\n canvas.removeFromSelection([t]);\n }\n }\n } // no change in mouse position\n\n // Remove non-scaling stroke\n if (supportsNonScalingStroke()) {\n const elem = selectedElements[0];\n if (elem) {\n elem.removeAttribute('style');\n walkTree(elem, function (el) {\n el.removeAttribute('style');\n });\n }\n }\n }\n return;\n case 'zoom': {\n if (!isNullish(rubberBox)) {\n rubberBox.setAttribute('display', 'none');\n }\n const factor = evt.shiftKey ? 0.5 : 2;\n call('zoomed', {\n x: Math.min(rStartX, realX),\n y: Math.min(rStartY, realY),\n width: Math.abs(realX - rStartX),\n height: Math.abs(realY - rStartY),\n factor\n });\n return;\n } case 'fhpath': {\n // Check that the path contains at least 2 points; a degenerate one-point path\n // causes problems.\n // Webkit ignores how we set the points attribute with commas and uses space\n // to separate all coordinates, see https://bugs.webkit.org/show_bug.cgi?id=29870\n sumDistance = 0;\n controllPoint2 = {x: 0, y: 0};\n controllPoint1 = {x: 0, y: 0};\n start = {x: 0, y: 0};\n end = {x: 0, y: 0};\n const coords = element.getAttribute('points');\n const commaIndex = coords.indexOf(',');\n if (commaIndex >= 0) {\n keep = coords.includes(',', commaIndex + 1);\n } else {\n keep = coords.includes(' ', coords.indexOf(' ') + 1);\n }\n if (keep) {\n element = pathActions.smoothPolylineIntoPath(element);\n }\n break;\n } case 'line':\n attrs = $(element).attr(['x1', 'x2', 'y1', 'y2']);\n keep = (attrs.x1 !== attrs.x2 || attrs.y1 !== attrs.y2);\n break;\n case 'foreignObject':\n case 'square':\n case 'rect':\n case 'image':\n attrs = $(element).attr(['width', 'height']);\n // Image should be kept regardless of size (use inherit dimensions later)\n keep = (attrs.width || attrs.height) || currentMode === 'image';\n break;\n case 'circle':\n keep = (element.getAttribute('r') !== '0');\n break;\n case 'ellipse':\n attrs = $(element).attr(['rx', 'ry']);\n keep = (attrs.rx || attrs.ry);\n break;\n case 'fhellipse':\n if ((freehand.maxx - freehand.minx) > 0 &&\n (freehand.maxy - freehand.miny) > 0) {\n element = addSVGElementFromJson({\n element: 'ellipse',\n curStyles: true,\n attr: {\n cx: (freehand.minx + freehand.maxx) / 2,\n cy: (freehand.miny + freehand.maxy) / 2,\n rx: (freehand.maxx - freehand.minx) / 2,\n ry: (freehand.maxy - freehand.miny) / 2,\n id: getId()\n }\n });\n call('changed', [element]);\n keep = true;\n }\n break;\n case 'fhrect':\n if ((freehand.maxx - freehand.minx) > 0 &&\n (freehand.maxy - freehand.miny) > 0) {\n element = addSVGElementFromJson({\n element: 'rect',\n curStyles: true,\n attr: {\n x: freehand.minx,\n y: freehand.miny,\n width: (freehand.maxx - freehand.minx),\n height: (freehand.maxy - freehand.miny),\n id: getId()\n }\n });\n call('changed', [element]);\n keep = true;\n }\n break;\n case 'text':\n keep = true;\n selectOnly([element]);\n textActions.start(element);\n break;\n case 'path': {\n // set element to null here so that it is not removed nor finalized\n element = null;\n // continue to be set to true so that mouseMove happens\n started = true;\n\n const res = pathActions.mouseUp(evt, element, mouseX, mouseY);\n ({element} = res);\n ({keep} = res);\n break;\n } case 'pathedit':\n keep = true;\n element = null;\n pathActions.mouseUp(evt);\n break;\n case 'textedit':\n keep = false;\n element = null;\n textActions.mouseUp(evt, mouseX, mouseY);\n break;\n case 'rotate': {\n keep = true;\n element = null;\n currentMode = 'select';\n const batchCmd = canvas.undoMgr.finishUndoableChange();\n if (!batchCmd.isEmpty()) {\n addCommandToHistory(batchCmd);\n }\n // perform recalculation to weed out any stray identity transforms that might get stuck\n recalculateAllSelectedDimensions();\n call('changed', selectedElements);\n break;\n } default:\n // This could occur in an extension\n break;\n }\n\n /**\n * The main (left) mouse button is released (anywhere).\n * @event module:svgcanvas.SvgCanvas#event:ext_mouseUp\n * @type {PlainObject}\n * @property {MouseEvent} event The event object\n * @property {Float} mouse_x x coordinate on canvas\n * @property {Float} mouse_y y coordinate on canvas\n */\n const extResult = runExtensions('mouseUp', /** @type {module:svgcanvas.SvgCanvas#event:ext_mouseUp} */ {\n event: evt,\n mouse_x: mouseX,\n mouse_y: mouseY\n }, true);\n\n $.each(extResult, function (i, r) {\n if (r) {\n keep = r.keep || keep;\n ({element} = r);\n started = r.started || started;\n }\n });\n\n if (!keep && !isNullish(element)) {\n getCurrentDrawing().releaseId(getId());\n element.remove();\n element = null;\n\n t = evt.target;\n\n // if this element is in a group, go up until we reach the top-level group\n // just below the layer groups\n // TODO: once we implement links, we also would have to check for <a> elements\n while (t && t.parentNode && t.parentNode.parentNode && t.parentNode.parentNode.tagName === 'g') {\n t = t.parentNode;\n }\n // if we are not in the middle of creating a path, and we've clicked on some shape,\n // then go to Select mode.\n // WebKit returns <div> when the canvas is clicked, Firefox/Opera return <svg>\n if ((currentMode !== 'path' || !drawnPath) &&\n t && t.parentNode &&\n t.parentNode.id !== 'selectorParentGroup' &&\n t.id !== 'svgcanvas' && t.id !== 'svgroot'\n ) {\n // switch into \"select\" mode if we've clicked on an element\n canvas.setMode('select');\n selectOnly([t], true);\n }\n } else if (!isNullish(element)) {\n /**\n * @name module:svgcanvas.SvgCanvas#addedNew\n * @type {boolean}\n */\n canvas.addedNew = true;\n\n if (useUnit) { convertAttrs(element); }\n\n let aniDur = 0.2;\n let cAni;\n if (opacAni.beginElement && parseFloat(element.getAttribute('opacity')) !== curShape.opacity) {\n cAni = $(opacAni).clone().attr({\n to: curShape.opacity,\n dur: aniDur\n }).appendTo(element);\n try {\n // Fails in FF4 on foreignObject\n cAni[0].beginElement();\n } catch (e) {}\n } else {\n aniDur = 0;\n }\n\n // Ideally this would be done on the endEvent of the animation,\n // but that doesn't seem to be supported in Webkit\n setTimeout(function () {\n if (cAni) { cAni.remove(); }\n element.setAttribute('opacity', curShape.opacity);\n element.setAttribute('style', 'pointer-events:inherit');\n cleanupElement(element);\n if (currentMode === 'path') {\n pathActions.toEditMode(element);\n } else if (curConfig.selectNew) {\n selectOnly([element], true);\n }\n // we create the insert command that is stored on the stack\n // undo means to call cmd.unapply(), redo means to call cmd.apply()\n addCommandToHistory(new InsertElementCommand(element));\n\n call('changed', [element]);\n }, aniDur * 1000);\n }\n\n startTransform = null;\n};\n\nconst dblClick = function (evt) {\n const evtTarget = evt.target;\n const parent = evtTarget.parentNode;\n\n // Do nothing if already in current group\n if (parent === currentGroup) { return; }\n\n let mouseTarget = getMouseTarget(evt);\n const {tagName} = mouseTarget;\n\n if (tagName === 'text' && currentMode !== 'textedit') {\n const pt = transformPoint(evt.pageX, evt.pageY, rootSctm);\n textActions.select(mouseTarget, pt.x, pt.y);\n }\n\n if ((tagName === 'g' || tagName === 'a') &&\n getRotationAngle(mouseTarget)\n ) {\n // TODO: Allow method of in-group editing without having to do\n // this (similar to editing rotated paths)\n\n // Ungroup and regroup\n pushGroupProperties(mouseTarget);\n mouseTarget = selectedElements[0];\n clearSelection(true);\n }\n // Reset context\n if (currentGroup) {\n draw.leaveContext();\n }\n\n if ((parent.tagName !== 'g' && parent.tagName !== 'a') ||\n parent === getCurrentDrawing().getCurrentLayer() ||\n mouseTarget === selectorManager.selectorParentGroup\n ) {\n // Escape from in-group edit\n return;\n }\n draw.setContext(mouseTarget);\n};\n\n// prevent links from being followed in the canvas\nconst handleLinkInCanvas = function (e) {\n e.preventDefault();\n return false;\n};\n\n// Added mouseup to the container here.\n// TODO(codedread): Figure out why after the Closure compiler, the window mouseup is ignored.\n$(container).mousedown(mouseDown).mousemove(mouseMove).click(handleLinkInCanvas).dblclick(dblClick).mouseup(mouseUp);\n// $(window).mouseup(mouseUp);\n\n// TODO(rafaelcastrocouto): User preference for shift key and zoom factor\n$(container).bind(\n 'mousewheel DOMMouseScroll',\n /**\n * @param {Event} e\n * @fires module:svgcanvas.SvgCanvas#event:updateCanvas\n * @fires module:svgcanvas.SvgCanvas#event:zoomDone\n * @returns {void}\n */\n function (e) {\n if (!e.shiftKey) { return; }\n\n e.preventDefault();\n const evt = e.originalEvent;\n\n rootSctm = $('#svgcontent g')[0].getScreenCTM().inverse();\n\n const workarea = $('#workarea');\n const scrbar = 15;\n const rulerwidth = curConfig.showRulers ? 16 : 0;\n\n // mouse relative to content area in content pixels\n const pt = transformPoint(evt.pageX, evt.pageY, rootSctm);\n\n // full work area width in screen pixels\n const editorFullW = workarea.width();\n const editorFullH = workarea.height();\n\n // work area width minus scroll and ruler in screen pixels\n const editorW = editorFullW - scrbar - rulerwidth;\n const editorH = editorFullH - scrbar - rulerwidth;\n\n // work area width in content pixels\n const workareaViewW = editorW * rootSctm.a;\n const workareaViewH = editorH * rootSctm.d;\n\n // content offset from canvas in screen pixels\n const wOffset = workarea.offset();\n const wOffsetLeft = wOffset.left + rulerwidth;\n const wOffsetTop = wOffset.top + rulerwidth;\n\n const delta = (evt.wheelDelta) ? evt.wheelDelta : (evt.detail) ? -evt.detail : 0;\n if (!delta) { return; }\n\n let factor = Math.max(3 / 4, Math.min(4 / 3, (delta)));\n\n let wZoom, hZoom;\n if (factor > 1) {\n wZoom = Math.ceil(editorW / workareaViewW * factor * 100) / 100;\n hZoom = Math.ceil(editorH / workareaViewH * factor * 100) / 100;\n } else {\n wZoom = Math.floor(editorW / workareaViewW * factor * 100) / 100;\n hZoom = Math.floor(editorH / workareaViewH * factor * 100) / 100;\n }\n let zoomlevel = Math.min(wZoom, hZoom);\n zoomlevel = Math.min(10, Math.max(0.01, zoomlevel));\n if (zoomlevel === currentZoom) {\n return;\n }\n factor = zoomlevel / currentZoom;\n\n // top left of workarea in content pixels before zoom\n const topLeftOld = transformPoint(wOffsetLeft, wOffsetTop, rootSctm);\n\n // top left of workarea in content pixels after zoom\n const topLeftNew = {\n x: pt.x - (pt.x - topLeftOld.x) / factor,\n y: pt.y - (pt.y - topLeftOld.y) / factor\n };\n\n // top left of workarea in canvas pixels relative to content after zoom\n const topLeftNewCanvas = {\n x: topLeftNew.x * zoomlevel,\n y: topLeftNew.y * zoomlevel\n };\n\n // new center in canvas pixels\n const newCtr = {\n x: topLeftNewCanvas.x - rulerwidth + editorFullW / 2,\n y: topLeftNewCanvas.y - rulerwidth + editorFullH / 2\n };\n\n canvas.setZoom(zoomlevel);\n $('#zoom').val((zoomlevel * 100).toFixed(1));\n\n call('updateCanvas', {center: false, newCtr});\n call('zoomDone');\n }\n);\n}());\n\n/* eslint-disable jsdoc/require-property */\n/**\n* Group: Text edit functions\n* Functions relating to editing text elements.\n* @namespace {PlainObject} textActions\n* @memberof module:svgcanvas.SvgCanvas#\n*/\nconst textActions = canvas.textActions = (function () {\n/* eslint-enable jsdoc/require-property */\nlet curtext;\nlet textinput;\nlet cursor;\nlet selblock;\nlet blinker;\nlet chardata = [];\nlet textbb; // , transbb;\nlet matrix;\nlet lastX, lastY;\nlet allowDbl;\n\n/**\n *\n * @param {Integer} index\n * @returns {void}\n */\nfunction setCursor (index) {\n const empty = (textinput.value === '');\n $(textinput).focus();\n\n if (!arguments.length) {\n if (empty) {\n index = 0;\n } else {\n if (textinput.selectionEnd !== textinput.selectionStart) { return; }\n index = textinput.selectionEnd;\n }\n }\n\n const charbb = chardata[index];\n if (!empty) {\n textinput.setSelectionRange(index, index);\n }\n cursor = getElem('text_cursor');\n if (!cursor) {\n cursor = document.createElementNS(NS.SVG, 'line');\n assignAttributes(cursor, {\n id: 'text_cursor',\n stroke: '#333',\n 'stroke-width': 1\n });\n cursor = getElem('selectorParentGroup').appendChild(cursor);\n }\n\n if (!blinker) {\n blinker = setInterval(function () {\n const show = (cursor.getAttribute('display') === 'none');\n cursor.setAttribute('display', show ? 'inline' : 'none');\n }, 600);\n }\n\n const startPt = ptToScreen(charbb.x, textbb.y);\n const endPt = ptToScreen(charbb.x, (textbb.y + textbb.height));\n\n assignAttributes(cursor, {\n x1: startPt.x,\n y1: startPt.y,\n x2: endPt.x,\n y2: endPt.y,\n visibility: 'visible',\n display: 'inline'\n });\n\n if (selblock) { selblock.setAttribute('d', ''); }\n}\n\n/**\n *\n * @param {Integer} start\n * @param {Integer} end\n * @param {boolean} skipInput\n * @returns {void}\n */\nfunction setSelection (start, end, skipInput) {\n if (start === end) {\n setCursor(end);\n return;\n }\n\n if (!skipInput) {\n textinput.setSelectionRange(start, end);\n }\n\n selblock = getElem('text_selectblock');\n if (!selblock) {\n selblock = document.createElementNS(NS.SVG, 'path');\n assignAttributes(selblock, {\n id: 'text_selectblock',\n fill: 'green',\n opacity: 0.5,\n style: 'pointer-events:none'\n });\n getElem('selectorParentGroup').append(selblock);\n }\n\n const startbb = chardata[start];\n const endbb = chardata[end];\n\n cursor.setAttribute('visibility', 'hidden');\n\n const tl = ptToScreen(startbb.x, textbb.y),\n tr = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y),\n bl = ptToScreen(startbb.x, textbb.y + textbb.height),\n br = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y + textbb.height);\n\n const dstr = 'M' + tl.x + ',' + tl.y +\n ' L' + tr.x + ',' + tr.y +\n ' ' + br.x + ',' + br.y +\n ' ' + bl.x + ',' + bl.y + 'z';\n\n assignAttributes(selblock, {\n d: dstr,\n display: 'inline'\n });\n}\n\n/**\n *\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {Integer}\n */\nfunction getIndexFromPoint (mouseX, mouseY) {\n // Position cursor here\n const pt = svgroot.createSVGPoint();\n pt.x = mouseX;\n pt.y = mouseY;\n\n // No content, so return 0\n if (chardata.length === 1) { return 0; }\n // Determine if cursor should be on left or right of character\n let charpos = curtext.getCharNumAtPosition(pt);\n if (charpos < 0) {\n // Out of text range, look at mouse coords\n charpos = chardata.length - 2;\n if (mouseX <= chardata[0].x) {\n charpos = 0;\n }\n } else if (charpos >= chardata.length - 2) {\n charpos = chardata.length - 2;\n }\n const charbb = chardata[charpos];\n const mid = charbb.x + (charbb.width / 2);\n if (mouseX > mid) {\n charpos++;\n }\n return charpos;\n}\n\n/**\n *\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {void}\n */\nfunction setCursorFromPoint (mouseX, mouseY) {\n setCursor(getIndexFromPoint(mouseX, mouseY));\n}\n\n/**\n *\n * @param {Float} x\n * @param {Float} y\n * @param {boolean} apply\n * @returns {void}\n */\nfunction setEndSelectionFromPoint (x, y, apply) {\n const i1 = textinput.selectionStart;\n const i2 = getIndexFromPoint(x, y);\n\n const start = Math.min(i1, i2);\n const end = Math.max(i1, i2);\n setSelection(start, end, !apply);\n}\n\n/**\n *\n * @param {Float} xIn\n * @param {Float} yIn\n * @returns {module:math.XYObject}\n */\nfunction screenToPt (xIn, yIn) {\n const out = {\n x: xIn,\n y: yIn\n };\n\n out.x /= currentZoom;\n out.y /= currentZoom;\n\n if (matrix) {\n const pt = transformPoint(out.x, out.y, matrix.inverse());\n out.x = pt.x;\n out.y = pt.y;\n }\n\n return out;\n}\n\n/**\n *\n * @param {Float} xIn\n * @param {Float} yIn\n * @returns {module:math.XYObject}\n */\nfunction ptToScreen (xIn, yIn) {\n const out = {\n x: xIn,\n y: yIn\n };\n\n if (matrix) {\n const pt = transformPoint(out.x, out.y, matrix);\n out.x = pt.x;\n out.y = pt.y;\n }\n\n out.x *= currentZoom;\n out.y *= currentZoom;\n\n return out;\n}\n\n/*\n// Not currently in use\nfunction hideCursor () {\n if (cursor) {\n cursor.setAttribute('visibility', 'hidden');\n }\n}\n*/\n\n/**\n *\n * @param {Event} evt\n * @returns {void}\n */\nfunction selectAll (evt) {\n setSelection(0, curtext.textContent.length);\n $(this).unbind(evt);\n}\n\n/**\n *\n * @param {Event} evt\n * @returns {void}\n */\nfunction selectWord (evt) {\n if (!allowDbl || !curtext) { return; }\n\n const ept = transformPoint(evt.pageX, evt.pageY, rootSctm),\n mouseX = ept.x * currentZoom,\n mouseY = ept.y * currentZoom;\n const pt = screenToPt(mouseX, mouseY);\n\n const index = getIndexFromPoint(pt.x, pt.y);\n const str = curtext.textContent;\n const first = str.substr(0, index).replace(/[a-z\\d]+$/i, '').length;\n const m = str.substr(index).match(/^[a-z\\d]+/i);\n const last = (m ? m[0].length : 0) + index;\n setSelection(first, last);\n\n // Set tripleclick\n $(evt.target).click(selectAll);\n setTimeout(function () {\n $(evt.target).unbind('click', selectAll);\n }, 300);\n}\n\nreturn /** @lends module:svgcanvas.SvgCanvas#textActions */ {\n /**\n * @param {Element} target\n * @param {Float} x\n * @param {Float} y\n * @returns {void}\n */\n select (target, x, y) {\n curtext = target;\n textActions.toEditMode(x, y);\n },\n /**\n * @param {Element} elem\n * @returns {void}\n */\n start (elem) {\n curtext = elem;\n textActions.toEditMode();\n },\n /**\n * @param {external:MouseEvent} evt\n * @param {Element} mouseTarget\n * @param {Float} startX\n * @param {Float} startY\n * @returns {void}\n */\n mouseDown (evt, mouseTarget, startX, startY) {\n const pt = screenToPt(startX, startY);\n\n textinput.focus();\n setCursorFromPoint(pt.x, pt.y);\n lastX = startX;\n lastY = startY;\n\n // TODO: Find way to block native selection\n },\n /**\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {void}\n */\n mouseMove (mouseX, mouseY) {\n const pt = screenToPt(mouseX, mouseY);\n setEndSelectionFromPoint(pt.x, pt.y);\n },\n /**\n * @param {external:MouseEvent} evt\n * @param {Float} mouseX\n * @param {Float} mouseY\n * @returns {void}\n */\n mouseUp (evt, mouseX, mouseY) {\n const pt = screenToPt(mouseX, mouseY);\n\n setEndSelectionFromPoint(pt.x, pt.y, true);\n\n // TODO: Find a way to make this work: Use transformed BBox instead of evt.target\n // if (lastX === mouseX && lastY === mouseY\n // && !rectsIntersect(transbb, {x: pt.x, y: pt.y, width: 0, height: 0})) {\n // textActions.toSelectMode(true);\n // }\n\n if (\n evt.target !== curtext &&\n mouseX < lastX + 2 &&\n mouseX > lastX - 2 &&\n mouseY < lastY + 2 &&\n mouseY > lastY - 2\n ) {\n textActions.toSelectMode(true);\n }\n },\n /**\n * @function\n * @param {Integer} index\n * @returns {void}\n */\n setCursor,\n /**\n * @param {Float} x\n * @param {Float} y\n * @returns {void}\n */\n toEditMode (x, y) {\n allowDbl = false;\n currentMode = 'textedit';\n selectorManager.requestSelector(curtext).showGrips(false);\n // Make selector group accept clicks\n /* const selector = */ selectorManager.requestSelector(curtext); // Do we need this? Has side effect of setting lock, so keeping for now, but next line wasn't being used\n // const sel = selector.selectorRect;\n\n textActions.init();\n\n $(curtext).css('cursor', 'text');\n\n // if (supportsEditableText()) {\n // curtext.setAttribute('editable', 'simple');\n // return;\n // }\n\n if (!arguments.length) {\n setCursor();\n } else {\n const pt = screenToPt(x, y);\n setCursorFromPoint(pt.x, pt.y);\n }\n\n setTimeout(function () {\n allowDbl = true;\n }, 300);\n },\n /**\n * @param {boolean|Element} selectElem\n * @fires module:svgcanvas.SvgCanvas#event:selected\n * @returns {void}\n */\n toSelectMode (selectElem) {\n currentMode = 'select';\n clearInterval(blinker);\n blinker = null;\n if (selblock) { $(selblock).attr('display', 'none'); }\n if (cursor) { $(cursor).attr('visibility', 'hidden'); }\n $(curtext).css('cursor', 'move');\n\n if (selectElem) {\n clearSelection();\n $(curtext).css('cursor', 'move');\n\n call('selected', [curtext]);\n addToSelection([curtext], true);\n }\n if (curtext && !curtext.textContent.length) {\n // No content, so delete\n canvas.deleteSelectedElements();\n }\n\n $(textinput).blur();\n\n curtext = false;\n\n // if (supportsEditableText()) {\n // curtext.removeAttribute('editable');\n // }\n },\n /**\n * @param {Element} elem\n * @returns {void}\n */\n setInputElem (elem) {\n textinput = elem;\n // $(textinput).blur(hideCursor);\n },\n /**\n * @returns {void}\n */\n clear () {\n if (currentMode === 'textedit') {\n textActions.toSelectMode();\n }\n },\n /**\n * @param {Element} inputElem Not in use\n * @returns {void}\n */\n init (inputElem) {\n if (!curtext) { return; }\n let i, end;\n // if (supportsEditableText()) {\n // curtext.select();\n // return;\n // }\n\n if (!curtext.parentNode) {\n // Result of the ffClone, need to get correct element\n curtext = selectedElements[0];\n selectorManager.requestSelector(curtext).showGrips(false);\n }\n\n const str = curtext.textContent;\n const len = str.length;\n\n const xform = curtext.getAttribute('transform');\n\n textbb = utilsGetBBox(curtext);\n\n matrix = xform ? getMatrix(curtext) : null;\n\n chardata = [];\n chardata.length = len;\n textinput.focus();\n\n $(curtext).unbind('dblclick', selectWord).dblclick(selectWord);\n\n if (!len) {\n end = {x: textbb.x + (textbb.width / 2), width: 0};\n }\n\n for (i = 0; i < len; i++) {\n const start = curtext.getStartPositionOfChar(i);\n end = curtext.getEndPositionOfChar(i);\n\n if (!supportsGoodTextCharPos()) {\n const offset = canvas.contentW * currentZoom;\n start.x -= offset;\n end.x -= offset;\n\n start.x /= currentZoom;\n end.x /= currentZoom;\n }\n\n // Get a \"bbox\" equivalent for each character. Uses the\n // bbox data of the actual text for y, height purposes\n\n // TODO: Decide if y, width and height are actually necessary\n chardata[i] = {\n x: start.x,\n y: textbb.y, // start.y?\n width: end.x - start.x,\n height: textbb.height\n };\n }\n\n // Add a last bbox for cursor at end of text\n chardata.push({\n x: end.x,\n width: 0\n });\n setSelection(textinput.selectionStart, textinput.selectionEnd, true);\n }\n};\n}());\n\n/**\n* Group: Serialization.\n*/\n\n/**\n* Looks at DOM elements inside the `<defs>` to see if they are referred to,\n* removes them from the DOM if they are not.\n* @function module:svgcanvas.SvgCanvas#removeUnusedDefElems\n* @returns {Integer} The number of elements that were removed\n*/\nconst removeUnusedDefElems = this.removeUnusedDefElems = function () {\n const defs = svgcontent.getElementsByTagNameNS(NS.SVG, 'defs');\n if (!defs || !defs.length) { return 0; }\n\n // if (!defs.firstChild) { return; }\n\n const defelemUses = [];\n let numRemoved = 0;\n const attrs = ['fill', 'stroke', 'filter', 'marker-start', 'marker-mid', 'marker-end'];\n const alen = attrs.length;\n\n const allEls = svgcontent.getElementsByTagNameNS(NS.SVG, '*');\n const allLen = allEls.length;\n\n let i, j;\n for (i = 0; i < allLen; i++) {\n const el = allEls[i];\n for (j = 0; j < alen; j++) {\n const ref = getUrlFromAttr(el.getAttribute(attrs[j]));\n if (ref) {\n defelemUses.push(ref.substr(1));\n }\n }\n\n // gradients can refer to other gradients\n const href = getHref(el);\n if (href && href.startsWith('#')) {\n defelemUses.push(href.substr(1));\n }\n }\n\n const defelems = $(defs).find('linearGradient, radialGradient, filter, marker, svg, symbol');\n i = defelems.length;\n while (i--) {\n const defelem = defelems[i];\n const {id} = defelem;\n if (!defelemUses.includes(id)) {\n // Not found, so remove (but remember)\n removedElements[id] = defelem;\n defelem.remove();\n numRemoved++;\n }\n }\n\n return numRemoved;\n};\n\n/**\n* Main function to set up the SVG content for output.\n* @function module:svgcanvas.SvgCanvas#svgCanvasToString\n* @returns {string} The SVG image for output\n*/\nthis.svgCanvasToString = function () {\n // keep calling it until there are none to remove\n while (removeUnusedDefElems() > 0) {} // eslint-disable-line no-empty\n\n pathActions.clear(true);\n\n // Keep SVG-Edit comment on top\n $.each(svgcontent.childNodes, function (i, node) {\n if (i && node.nodeType === 8 && node.data.includes('Created with')) {\n svgcontent.firstChild.before(node);\n }\n });\n\n // Move out of in-group editing mode\n if (currentGroup) {\n draw.leaveContext();\n selectOnly([currentGroup]);\n }\n\n const nakedSvgs = [];\n\n // Unwrap gsvg if it has no special attributes (only id and style)\n $(svgcontent).find('g:data(gsvg)').each(function () {\n const attrs = this.attributes;\n let len = attrs.length;\n for (let i = 0; i < len; i++) {\n if (attrs[i].nodeName === 'id' || attrs[i].nodeName === 'style') {\n len--;\n }\n }\n // No significant attributes, so ungroup\n if (len <= 0) {\n const svg = this.firstChild;\n nakedSvgs.push(svg);\n $(this).replaceWith(svg);\n }\n });\n const output = this.svgToString(svgcontent, 0);\n\n // Rewrap gsvg\n if (nakedSvgs.length) {\n $(nakedSvgs).each(function () {\n groupSvgElem(this);\n });\n }\n\n return output;\n};\n\n/**\n* Sub function ran on each SVG element to convert it to a string as desired.\n* @function module:svgcanvas.SvgCanvas#svgToString\n* @param {Element} elem - The SVG element to convert\n* @param {Integer} indent - Number of spaces to indent this tag\n* @returns {string} The given element as an SVG tag\n*/\nthis.svgToString = function (elem, indent) {\n const out = [];\n const unit = curConfig.baseUnit;\n const unitRe = new RegExp('^-?[\\\\d\\\\.]+' + unit + '$');\n\n if (elem) {\n cleanupElement(elem);\n const attrs = [...elem.attributes];\n const childs = elem.childNodes;\n attrs.sort((a, b) => {\n return a.name > b.name ? -1 : 1;\n });\n\n for (let i = 0; i < indent; i++) { out.push(' '); }\n out.push('<'); out.push(elem.nodeName);\n if (elem.id === 'svgcontent') {\n // Process root element separately\n const res = getResolution();\n\n const vb = '';\n // TODO: Allow this by dividing all values by current baseVal\n // Note that this also means we should properly deal with this on import\n // if (curConfig.baseUnit !== 'px') {\n // const unit = curConfig.baseUnit;\n // const unitM = getTypeMap()[unit];\n // res.w = shortFloat(res.w / unitM);\n // res.h = shortFloat(res.h / unitM);\n // vb = ' viewBox=\"' + [0, 0, res.w, res.h].join(' ') + '\"';\n // res.w += unit;\n // res.h += unit;\n // }\n\n if (unit !== 'px') {\n res.w = convertUnit(res.w, unit) + unit;\n res.h = convertUnit(res.h, unit) + unit;\n }\n\n out.push(' width=\"' + res.w + '\" height=\"' + res.h + '\"' + vb + ' xmlns=\"' + NS.SVG + '\"');\n\n const nsuris = {};\n\n // Check elements for namespaces, add if found\n $(elem).find('*').andSelf().each(function () {\n // const el = this;\n // for some elements have no attribute\n const uri = this.namespaceURI;\n if (uri && !nsuris[uri] && nsMap[uri] && nsMap[uri] !== 'xmlns' && nsMap[uri] !== 'xml') {\n nsuris[uri] = true;\n out.push(' xmlns:' + nsMap[uri] + '=\"' + uri + '\"');\n }\n\n $.each(this.attributes, function (i, attr) {\n const u = attr.namespaceURI;\n if (u && !nsuris[u] && nsMap[u] !== 'xmlns' && nsMap[u] !== 'xml') {\n nsuris[u] = true;\n out.push(' xmlns:' + nsMap[u] + '=\"' + u + '\"');\n }\n });\n });\n\n let i = attrs.length;\n const attrNames = ['width', 'height', 'xmlns', 'x', 'y', 'viewBox', 'id', 'overflow'];\n while (i--) {\n const attr = attrs[i];\n const attrVal = toXml(attr.value);\n\n // Namespaces have already been dealt with, so skip\n if (attr.nodeName.startsWith('xmlns:')) { continue; }\n\n // only serialize attributes we don't use internally\n if (attrVal !== '' && !attrNames.includes(attr.localName)) {\n if (!attr.namespaceURI || nsMap[attr.namespaceURI]) {\n out.push(' ');\n out.push(attr.nodeName); out.push('=\"');\n out.push(attrVal); out.push('\"');\n }\n }\n }\n } else {\n // Skip empty defs\n if (elem.nodeName === 'defs' && !elem.firstChild) { return ''; }\n\n const mozAttrs = ['-moz-math-font-style', '_moz-math-font-style'];\n for (let i = attrs.length - 1; i >= 0; i--) {\n const attr = attrs[i];\n let attrVal = toXml(attr.value);\n // remove bogus attributes added by Gecko\n if (mozAttrs.includes(attr.localName)) { continue; }\n if (attrVal === 'null') {\n const styleName = attr.localName.replace(/-[a-z]/g, (s) => s[1].toUpperCase());\n if (Object.prototype.hasOwnProperty.call(elem.style, styleName)) { continue; }\n }\n if (attrVal !== '') {\n if (attrVal.startsWith('pointer-events')) { continue; }\n if (attr.localName === 'class' && attrVal.startsWith('se_')) { continue; }\n out.push(' ');\n if (attr.localName === 'd') { attrVal = pathActions.convertPath(elem, true); }\n if (!isNaN(attrVal)) {\n attrVal = shortFloat(attrVal);\n } else if (unitRe.test(attrVal)) {\n attrVal = shortFloat(attrVal) + unit;\n }\n\n // Embed images when saving\n if (saveOptions.apply &&\n elem.nodeName === 'image' &&\n attr.localName === 'href' &&\n saveOptions.images &&\n saveOptions.images === 'embed'\n ) {\n const img = encodableImages[attrVal];\n if (img) { attrVal = img; }\n }\n\n // map various namespaces to our fixed namespace prefixes\n // (the default xmlns attribute itself does not get a prefix)\n if (!attr.namespaceURI || attr.namespaceURI === NS.SVG || nsMap[attr.namespaceURI]) {\n out.push(attr.nodeName); out.push('=\"');\n out.push(attrVal); out.push('\"');\n }\n }\n }\n }\n\n if (elem.hasChildNodes()) {\n out.push('>');\n indent++;\n let bOneLine = false;\n\n for (let i = 0; i < childs.length; i++) {\n const child = childs.item(i);\n switch (child.nodeType) {\n case 1: // element node\n out.push('\\n');\n out.push(this.svgToString(child, indent));\n break;\n case 3: { // text node\n const str = child.nodeValue.replace(/^\\s+|\\s+$/g, '');\n if (str !== '') {\n bOneLine = true;\n out.push(String(toXml(str)));\n }\n break;\n } case 4: // cdata node\n out.push('\\n');\n out.push(new Array(indent + 1).join(' '));\n out.push('<![CDATA[');\n out.push(child.nodeValue);\n out.push(']]>');\n break;\n case 8: // comment\n out.push('\\n');\n out.push(new Array(indent + 1).join(' '));\n out.push('<!--');\n out.push(child.data);\n out.push('-->');\n break;\n } // switch on node type\n }\n indent--;\n if (!bOneLine) {\n out.push('\\n');\n for (let i = 0; i < indent; i++) { out.push(' '); }\n }\n out.push('</'); out.push(elem.nodeName); out.push('>');\n } else {\n out.push('/>');\n }\n }\n return out.join('');\n}; // end svgToString()\n\n/**\n * Function to run when image data is found.\n * @callback module:svgcanvas.ImageEmbeddedCallback\n * @param {string|false} result Data URL\n * @returns {void}\n */\n/**\n* Converts a given image file to a data URL when possible, then runs a given callback.\n* @function module:svgcanvas.SvgCanvas#embedImage\n* @param {string} src - The path/URL of the image\n* @returns {Promise<string|false>} Resolves to a Data URL (string|false)\n*/\nthis.embedImage = function (src) {\n // Todo: Remove this Promise in favor of making an async/await `Image.load` utility\n return new Promise(function (resolve, reject) { // eslint-disable-line promise/avoid-new\n // load in the image and once it's loaded, get the dimensions\n $(new Image()).load(function (response, status, xhr) {\n if (status === 'error') {\n reject(new Error('Error loading image: ' + xhr.status + ' ' + xhr.statusText));\n return;\n }\n // create a canvas the same size as the raster image\n const cvs = document.createElement('canvas');\n cvs.width = this.width;\n cvs.height = this.height;\n // load the raster image into the canvas\n cvs.getContext('2d').drawImage(this, 0, 0);\n // retrieve the data: URL\n try {\n let urldata = ';svgedit_url=' + encodeURIComponent(src);\n urldata = cvs.toDataURL().replace(';base64', urldata + ';base64');\n encodableImages[src] = urldata;\n } catch (e) {\n encodableImages[src] = false;\n }\n lastGoodImgUrl = src;\n resolve(encodableImages[src]);\n }).attr('src', src);\n });\n};\n\n/**\n* Sets a given URL to be a \"last good image\" URL.\n* @function module:svgcanvas.SvgCanvas#setGoodImage\n* @param {string} val\n* @returns {void}\n*/\nthis.setGoodImage = function (val) {\n lastGoodImgUrl = val;\n};\n\n/**\n* Does nothing by default, handled by optional widget/extension.\n* @function module:svgcanvas.SvgCanvas#open\n* @returns {void}\n*/\nthis.open = function () {\n /* */\n};\n\n/**\n* Serializes the current drawing into SVG XML text and passes it to the 'saved' handler.\n* This function also includes the XML prolog. Clients of the `SvgCanvas` bind their save\n* function to the 'saved' event.\n* @function module:svgcanvas.SvgCanvas#save\n* @param {module:svgcanvas.SaveOptions} opts\n* @fires module:svgcanvas.SvgCanvas#event:saved\n* @returns {void}\n*/\nthis.save = function (opts) {\n // remove the selected outline before serializing\n clearSelection();\n // Update save options if provided\n if (opts) { $.extend(saveOptions, opts); }\n saveOptions.apply = true;\n\n // no need for doctype, see https://jwatt.org/svg/authoring/#doctype-declaration\n const str = this.svgCanvasToString();\n call('saved', str);\n};\n\n/**\n* @typedef {PlainObject} module:svgcanvas.IssuesAndCodes\n* @property {string[]} issueCodes The locale-independent code names\n* @property {string[]} issues The localized descriptions\n*/\n\n/**\n* Codes only is useful for locale-independent detection.\n* @returns {module:svgcanvas.IssuesAndCodes}\n*/\nfunction getIssues () {\n // remove the selected outline before serializing\n clearSelection();\n\n // Check for known CanVG issues\n const issues = [];\n const issueCodes = [];\n\n // Selector and notice\n const issueList = {\n feGaussianBlur: uiStrings.exportNoBlur,\n foreignObject: uiStrings.exportNoforeignObject,\n '[stroke-dasharray]': uiStrings.exportNoDashArray\n };\n const content = $(svgcontent);\n\n // Add font/text check if Canvas Text API is not implemented\n if (!('font' in $('<canvas>')[0].getContext('2d'))) {\n issueList.text = uiStrings.exportNoText;\n }\n\n $.each(issueList, function (sel, descr) {\n if (content.find(sel).length) {\n issueCodes.push(sel);\n issues.push(descr);\n }\n });\n return {issues, issueCodes};\n}\n\nlet canvg;\n/**\n* @typedef {\"feGaussianBlur\"|\"foreignObject\"|\"[stroke-dasharray]\"|\"text\"} module:svgcanvas.IssueCode\n*/\n/**\n* @typedef {PlainObject} module:svgcanvas.ImageExportedResults\n* @property {string} datauri Contents as a Data URL\n* @property {string} bloburl May be the empty string\n* @property {string} svg The SVG contents as a string\n* @property {string[]} issues The localization messages of `issueCodes`\n* @property {module:svgcanvas.IssueCode[]} issueCodes CanVG issues found with the SVG\n* @property {\"PNG\"|\"JPEG\"|\"BMP\"|\"WEBP\"|\"ICO\"} type The chosen image type\n* @property {\"image/png\"|\"image/jpeg\"|\"image/bmp\"|\"image/webp\"} mimeType The image MIME type\n* @property {Float} quality A decimal between 0 and 1 (for use with JPEG or WEBP)\n* @property {string} exportWindowName A convenience for passing along a `window.name` to target a window on which the export could be added\n*/\n\n/**\n* Generates a PNG (or JPG, BMP, WEBP) Data URL based on the current image,\n* then calls \"exported\" with an object including the string, image\n* information, and any issues found.\n* @function module:svgcanvas.SvgCanvas#rasterExport\n* @param {\"PNG\"|\"JPEG\"|\"BMP\"|\"WEBP\"|\"ICO\"} [imgType=\"PNG\"]\n* @param {Float} [quality] Between 0 and 1\n* @param {string} [exportWindowName]\n* @param {PlainObject} [opts]\n* @param {boolean} [opts.avoidEvent]\n* @fires module:svgcanvas.SvgCanvas#event:exported\n* @todo Confirm/fix ICO type\n* @returns {Promise<module:svgcanvas.ImageExportedResults>} Resolves to {@link module:svgcanvas.ImageExportedResults}\n*/\nthis.rasterExport = async function (imgType, quality, exportWindowName, opts = {}) {\n const type = imgType === 'ICO' ? 'BMP' : (imgType || 'PNG');\n const mimeType = 'image/' + type.toLowerCase();\n const {issues, issueCodes} = getIssues();\n const svg = this.svgCanvasToString();\n\n if (!canvg) {\n ({canvg} = await importSetGlobal(curConfig.canvgPath + 'canvg.js', {\n global: 'canvg'\n }));\n }\n if (!$('#export_canvas').length) {\n $('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');\n }\n const c = $('#export_canvas')[0];\n c.width = canvas.contentW;\n c.height = canvas.contentH;\n\n await canvg(c, svg);\n // Todo: Make async/await utility in place of `toBlob`, so we can remove this constructor\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n const dataURLType = type.toLowerCase();\n const datauri = quality\n ? c.toDataURL('image/' + dataURLType, quality)\n : c.toDataURL('image/' + dataURLType);\n let bloburl;\n /**\n * Called when `bloburl` is available for export.\n * @returns {void}\n */\n function done () {\n const obj = {\n datauri, bloburl, svg, issues, issueCodes, type: imgType,\n mimeType, quality, exportWindowName\n };\n if (!opts.avoidEvent) {\n call('exported', obj);\n }\n resolve(obj);\n }\n if (c.toBlob) {\n c.toBlob((blob) => {\n bloburl = createObjectURL(blob);\n done();\n }, mimeType, quality);\n return;\n }\n bloburl = dataURLToObjectURL(datauri);\n done();\n });\n};\n/**\n * @external jsPDF\n */\n/**\n * @typedef {void|\"save\"|\"arraybuffer\"|\"blob\"|\"datauristring\"|\"dataurlstring\"|\"dataurlnewwindow\"|\"datauri\"|\"dataurl\"} external:jsPDF.OutputType\n * @todo Newer version to add also allows these `outputType` values \"bloburi\"|\"bloburl\" which return strings, so document here and for `outputType` of `module:svgcanvas.PDFExportedResults` below if added\n*/\n/**\n* @typedef {PlainObject} module:svgcanvas.PDFExportedResults\n* @property {string} svg The SVG PDF output\n* @property {string|ArrayBuffer|Blob|window} output The output based on the `outputType`;\n* if `undefined`, \"datauristring\", \"dataurlstring\", \"datauri\",\n* or \"dataurl\", will be a string (`undefined` gives a document, while the others\n* build as Data URLs; \"datauri\" and \"dataurl\" change the location of the current page); if\n* \"arraybuffer\", will return `ArrayBuffer`; if \"blob\", returns a `Blob`;\n* if \"dataurlnewwindow\", will change the current page's location and return a string\n* if in Safari and no window object is found; otherwise opens in, and returns, a new `window`\n* object; if \"save\", will have the same return as \"dataurlnewwindow\" if\n* `navigator.getUserMedia` support is found without `URL.createObjectURL` support; otherwise\n* returns `undefined` but attempts to save\n* @property {external:jsPDF.OutputType} outputType\n* @property {string[]} issues The human-readable localization messages of corresponding `issueCodes`\n* @property {module:svgcanvas.IssueCode[]} issueCodes\n* @property {string} exportWindowName\n*/\n\n/**\n* Generates a PDF based on the current image, then calls \"exportedPDF\" with\n* an object including the string, the data URL, and any issues found.\n* @function module:svgcanvas.SvgCanvas#exportPDF\n* @param {string} [exportWindowName] Will also be used for the download file name here\n* @param {external:jsPDF.OutputType} [outputType=\"dataurlstring\"]\n* @fires module:svgcanvas.SvgCanvas#event:exportedPDF\n* @returns {Promise<module:svgcanvas.PDFExportedResults>} Resolves to {@link module:svgcanvas.PDFExportedResults}\n*/\nthis.exportPDF = async function (\n exportWindowName,\n outputType = isChrome() ? 'save' : undefined\n) {\n if (!window.jsPDF) {\n // Todo: Switch to `import()` when widely supported and available (also allow customization of path)\n await importScript([\n // We do not currently have these paths configurable as they are\n // currently global-only, so not Rolled-up\n 'jspdf/underscore-min.js',\n // 'jspdf/jspdf.min.js',\n '../../svgedit-myfix/editor/jspdf/jspdf-1.0.150.debug.js'\n ]);\n\n const modularVersion = !('svgEditor' in window) ||\n !window.svgEditor ||\n window.svgEditor.modules !== false;\n // Todo: Switch to `import()` when widely supported and available (also allow customization of path)\n await importScript(curConfig.jspdfPath + 'jspdf.plugin.svgToPdf.js', {\n type: modularVersion\n ? 'module'\n : 'text/javascript'\n });\n // await importModule('jspdf/jspdf.plugin.svgToPdf.js');\n }\n\n const res = getResolution();\n const orientation = res.w > res.h ? 'landscape' : 'portrait';\n const unit = 'pt'; // curConfig.baseUnit; // We could use baseUnit, but that is presumably not intended for export purposes\n\n // Todo: Give options to use predefined jsPDF formats like \"a4\", etc. from pull-down (with option to keep customizable)\n const doc = jsPDF({\n orientation,\n unit,\n format: [res.w, res.h]\n // , compressPdf: true\n });\n const docTitle = getDocumentTitle();\n doc.setProperties({\n title: docTitle /* ,\n subject: '',\n author: '',\n keywords: '',\n creator: '' */\n });\n const {issues, issueCodes} = getIssues();\n const svg = this.svgCanvasToString();\n doc.addSVG(svg, 0, 0);\n\n // doc.output('save'); // Works to open in a new\n // window; todo: configure this and other export\n // options to optionally work in this manner as\n // opposed to opening a new tab\n outputType = outputType || 'dataurlstring';\n const obj = {svg, issues, issueCodes, exportWindowName, outputType};\n obj.output = doc.output(outputType, outputType === 'save' ? (exportWindowName || 'svg.pdf') : undefined);\n call('exportedPDF', obj);\n return obj;\n};\n\n/**\n* Returns the current drawing as raw SVG XML text.\n* @function module:svgcanvas.SvgCanvas#getSvgString\n* @returns {string} The current drawing as raw SVG XML text.\n*/\nthis.getSvgString = function () {\n saveOptions.apply = false;\n return this.svgCanvasToString();\n};\n\n/**\n* This function determines whether to use a nonce in the prefix, when\n* generating IDs for future documents in SVG-Edit.\n* If you're controlling SVG-Edit externally, and want randomized IDs, call\n* this BEFORE calling `svgCanvas.setSvgString`.\n* @function module:svgcanvas.SvgCanvas#randomizeIds\n* @param {boolean} [enableRandomization] If true, adds a nonce to the prefix. Thus\n* `svgCanvas.randomizeIds() <==> svgCanvas.randomizeIds(true)`\n* @returns {void}\n*/\nthis.randomizeIds = function (enableRandomization) {\n if (arguments.length > 0 && enableRandomization === false) {\n draw.randomizeIds(false, getCurrentDrawing());\n } else {\n draw.randomizeIds(true, getCurrentDrawing());\n }\n};\n\n/**\n* Ensure each element has a unique ID.\n* @function module:svgcanvas.SvgCanvas#uniquifyElems\n* @param {Element} g - The parent element of the tree to give unique IDs\n* @returns {void}\n*/\nconst uniquifyElems = this.uniquifyElems = function (g) {\n const ids = {};\n // TODO: Handle markers and connectors. These are not yet re-identified properly\n // as their referring elements do not get remapped.\n //\n // <marker id='se_marker_end_svg_7'/>\n // <polyline id='svg_7' se:connector='svg_1 svg_6' marker-end='url(#se_marker_end_svg_7)'/>\n //\n // Problem #1: if svg_1 gets renamed, we do not update the polyline's se:connector attribute\n // Problem #2: if the polyline svg_7 gets renamed, we do not update the marker id nor the polyline's marker-end attribute\n const refElems = ['filter', 'linearGradient', 'pattern', 'radialGradient', 'symbol', 'textPath', 'use'];\n\n walkTree(g, function (n) {\n // if it's an element node\n if (n.nodeType === 1) {\n // and the element has an ID\n if (n.id) {\n // and we haven't tracked this ID yet\n if (!(n.id in ids)) {\n // add this id to our map\n ids[n.id] = {elem: null, attrs: [], hrefs: []};\n }\n ids[n.id].elem = n;\n }\n\n // now search for all attributes on this element that might refer\n // to other elements\n $.each(refAttrs, function (i, attr) {\n const attrnode = n.getAttributeNode(attr);\n if (attrnode) {\n // the incoming file has been sanitized, so we should be able to safely just strip off the leading #\n const url = getUrlFromAttr(attrnode.value),\n refid = url ? url.substr(1) : null;\n if (refid) {\n if (!(refid in ids)) {\n // add this id to our map\n ids[refid] = {elem: null, attrs: [], hrefs: []};\n }\n ids[refid].attrs.push(attrnode);\n }\n }\n });\n\n // check xlink:href now\n const href = getHref(n);\n // TODO: what if an <image> or <a> element refers to an element internally?\n if (href && refElems.includes(n.nodeName)) {\n const refid = href.substr(1);\n if (refid) {\n if (!(refid in ids)) {\n // add this id to our map\n ids[refid] = {elem: null, attrs: [], hrefs: []};\n }\n ids[refid].hrefs.push(n);\n }\n }\n }\n });\n\n // in ids, we now have a map of ids, elements and attributes, let's re-identify\n for (const oldid in ids) {\n if (!oldid) { continue; }\n const {elem} = ids[oldid];\n if (elem) {\n const newid = getNextId();\n\n // assign element its new id\n elem.id = newid;\n\n // remap all url() attributes\n const {attrs} = ids[oldid];\n let j = attrs.length;\n while (j--) {\n const attr = attrs[j];\n attr.ownerElement.setAttribute(attr.name, 'url(#' + newid + ')');\n }\n\n // remap all href attributes\n const hreffers = ids[oldid].hrefs;\n let k = hreffers.length;\n while (k--) {\n const hreffer = hreffers[k];\n setHref(hreffer, '#' + newid);\n }\n }\n }\n};\n\n/**\n* Assigns reference data for each use element.\n* @function module:svgcanvas.SvgCanvas#setUseData\n* @param {Element} parent\n* @returns {void}\n*/\nconst setUseData = this.setUseData = function (parent) {\n let elems = $(parent);\n\n if (parent.tagName !== 'use') {\n elems = elems.find('use');\n }\n\n elems.each(function () {\n const id = getHref(this).substr(1);\n const refElem = getElem(id);\n if (!refElem) { return; }\n $(this).data('ref', refElem);\n if (refElem.tagName === 'symbol' || refElem.tagName === 'svg') {\n $(this).data('symbol', refElem).data('ref', refElem);\n }\n });\n};\n\n/**\n* Converts gradients from userSpaceOnUse to objectBoundingBox.\n* @function module:svgcanvas.SvgCanvas#convertGradients\n* @param {Element} elem\n* @returns {void}\n*/\nconst convertGradients = this.convertGradients = function (elem) {\n let elems = $(elem).find('linearGradient, radialGradient');\n if (!elems.length && isWebkit()) {\n // Bug in webkit prevents regular *Gradient selector search\n elems = $(elem).find('*').filter(function () {\n return (this.tagName.includes('Gradient'));\n });\n }\n\n elems.each(function () {\n const grad = this; // eslint-disable-line consistent-this\n if ($(grad).attr('gradientUnits') === 'userSpaceOnUse') {\n // TODO: Support more than one element with this ref by duplicating parent grad\n const fillStrokeElems = $(svgcontent).find('[fill=\"url(#' + grad.id + ')\"],[stroke=\"url(#' + grad.id + ')\"]');\n if (!fillStrokeElems.length) { return; }\n\n // get object's bounding box\n const bb = utilsGetBBox(fillStrokeElems[0]);\n\n // This will occur if the element is inside a <defs> or a <symbol>,\n // in which we shouldn't need to convert anyway.\n if (!bb) { return; }\n\n if (grad.tagName === 'linearGradient') {\n const gCoords = $(grad).attr(['x1', 'y1', 'x2', 'y2']);\n\n // If has transform, convert\n const tlist = grad.gradientTransform.baseVal;\n if (tlist && tlist.numberOfItems > 0) {\n const m = transformListToTransform(tlist).matrix;\n const pt1 = transformPoint(gCoords.x1, gCoords.y1, m);\n const pt2 = transformPoint(gCoords.x2, gCoords.y2, m);\n\n gCoords.x1 = pt1.x;\n gCoords.y1 = pt1.y;\n gCoords.x2 = pt2.x;\n gCoords.y2 = pt2.y;\n grad.removeAttribute('gradientTransform');\n }\n\n $(grad).attr({\n x1: (gCoords.x1 - bb.x) / bb.width,\n y1: (gCoords.y1 - bb.y) / bb.height,\n x2: (gCoords.x2 - bb.x) / bb.width,\n y2: (gCoords.y2 - bb.y) / bb.height\n });\n grad.removeAttribute('gradientUnits');\n }\n // else {\n // Note: radialGradient elements cannot be easily converted\n // because userSpaceOnUse will keep circular gradients, while\n // objectBoundingBox will x/y scale the gradient according to\n // its bbox.\n //\n // For now we'll do nothing, though we should probably have\n // the gradient be updated as the element is moved, as\n // inkscape/illustrator do.\n //\n // const gCoords = $(grad).attr(['cx', 'cy', 'r']);\n //\n // $(grad).attr({\n // cx: (gCoords.cx - bb.x) / bb.width,\n // cy: (gCoords.cy - bb.y) / bb.height,\n // r: gCoords.r\n // });\n //\n // grad.removeAttribute('gradientUnits');\n // }\n }\n });\n};\n\n/**\n* Converts selected/given `<use>` or child SVG element to a group.\n* @function module:svgcanvas.SvgCanvas#convertToGroup\n* @param {Element} elem\n* @fires module:svgcanvas.SvgCanvas#event:selected\n* @returns {void}\n*/\nconst convertToGroup = this.convertToGroup = function (elem) {\n if (!elem) {\n elem = selectedElements[0];\n }\n const $elem = $(elem);\n const batchCmd = new BatchCommand();\n let ts;\n\n if ($elem.data('gsvg')) {\n // Use the gsvg as the new group\n const svg = elem.firstChild;\n const pt = $(svg).attr(['x', 'y']);\n\n $(elem.firstChild.firstChild).unwrap();\n $(elem).removeData('gsvg');\n\n const tlist = getTransformList(elem);\n const xform = svgroot.createSVGTransform();\n xform.setTranslate(pt.x, pt.y);\n tlist.appendItem(xform);\n recalculateDimensions(elem);\n call('selected', [elem]);\n } else if ($elem.data('symbol')) {\n elem = $elem.data('symbol');\n\n ts = $elem.attr('transform');\n const pos = $elem.attr(['x', 'y']);\n\n const vb = elem.getAttribute('viewBox');\n\n if (vb) {\n const nums = vb.split(' ');\n pos.x -= Number(nums[0]);\n pos.y -= Number(nums[1]);\n }\n\n // Not ideal, but works\n ts += ' translate(' + (pos.x || 0) + ',' + (pos.y || 0) + ')';\n\n const prev = $elem.prev();\n\n // Remove <use> element\n batchCmd.addSubCommand(new RemoveElementCommand($elem[0], $elem[0].nextSibling, $elem[0].parentNode));\n $elem.remove();\n\n // See if other elements reference this symbol\n const hasMore = $(svgcontent).find('use:data(symbol)').length;\n\n const g = svgdoc.createElementNS(NS.SVG, 'g');\n const childs = elem.childNodes;\n\n let i;\n for (i = 0; i < childs.length; i++) {\n g.append(childs[i].cloneNode(true));\n }\n\n // Duplicate the gradients for Gecko, since they weren't included in the <symbol>\n if (isGecko()) {\n const dupeGrads = $(findDefs()).children('linearGradient,radialGradient,pattern').clone();\n $(g).append(dupeGrads);\n }\n\n if (ts) {\n g.setAttribute('transform', ts);\n }\n\n const parent = elem.parentNode;\n\n uniquifyElems(g);\n\n // Put the dupe gradients back into <defs> (after uniquifying them)\n if (isGecko()) {\n $(findDefs()).append($(g).find('linearGradient,radialGradient,pattern'));\n }\n\n // now give the g itself a new id\n g.id = getNextId();\n\n prev.after(g);\n\n if (parent) {\n if (!hasMore) {\n // remove symbol/svg element\n const {nextSibling} = elem;\n elem.remove();\n batchCmd.addSubCommand(new RemoveElementCommand(elem, nextSibling, parent));\n }\n batchCmd.addSubCommand(new InsertElementCommand(g));\n }\n\n setUseData(g);\n\n if (isGecko()) {\n convertGradients(findDefs());\n } else {\n convertGradients(g);\n }\n\n // recalculate dimensions on the top-level children so that unnecessary transforms\n // are removed\n walkTreePost(g, function (n) {\n try {\n recalculateDimensions(n);\n } catch (e) {\n console.log(e); // eslint-disable-line no-console\n }\n });\n\n // Give ID for any visible element missing one\n $(g).find(visElems).each(function () {\n if (!this.id) { this.id = getNextId(); }\n });\n\n selectOnly([g]);\n\n const cm = pushGroupProperties(g, true);\n if (cm) {\n batchCmd.addSubCommand(cm);\n }\n\n addCommandToHistory(batchCmd);\n } else {\n console.log('Unexpected element to ungroup:', elem); // eslint-disable-line no-console\n }\n};\n\n/**\n* This function sets the current drawing as the input SVG XML.\n* @function module:svgcanvas.SvgCanvas#setSvgString\n* @param {string} xmlString - The SVG as XML text.\n* @param {boolean} [preventUndo=false] - Indicates if we want to do the\n* changes without adding them to the undo stack - e.g. for initializing a\n* drawing on page load.\n* @fires module:svgcanvas.SvgCanvas#event:setnonce\n* @fires module:svgcanvas.SvgCanvas#event:unsetnonce\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {boolean} This function returns `false` if the set was\n* unsuccessful, `true` otherwise.\n*/\nthis.setSvgString = function (xmlString, preventUndo) {\n try {\n // convert string into XML document\n const newDoc = text2xml(xmlString);\n if (newDoc.firstElementChild &&\n newDoc.firstElementChild.namespaceURI !== NS.SVG) {\n return false;\n }\n\n this.prepareSvg(newDoc);\n\n const batchCmd = new BatchCommand('Change Source');\n\n // remove old svg document\n const {nextSibling} = svgcontent;\n const oldzoom = svgroot.removeChild(svgcontent);\n batchCmd.addSubCommand(new RemoveElementCommand(oldzoom, nextSibling, svgroot));\n\n // set new svg document\n // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode()\n if (svgdoc.adoptNode) {\n svgcontent = svgdoc.adoptNode(newDoc.documentElement);\n } else {\n svgcontent = svgdoc.importNode(newDoc.documentElement, true);\n }\n\n svgroot.append(svgcontent);\n const content = $(svgcontent);\n\n canvas.current_drawing_ = new draw.Drawing(svgcontent, idprefix);\n\n // retrieve or set the nonce\n const nonce = getCurrentDrawing().getNonce();\n if (nonce) {\n call('setnonce', nonce);\n } else {\n call('unsetnonce');\n }\n\n // change image href vals if possible\n content.find('image').each(function () {\n const image = this; // eslint-disable-line consistent-this\n preventClickDefault(image);\n const val = getHref(this);\n if (val) {\n if (val.startsWith('data:')) {\n // Check if an SVG-edit data URI\n const m = val.match(/svgedit_url=(.*?);/);\n // const m = val.match(/svgedit_url=(?<url>.*?);/);\n if (m) {\n const url = decodeURIComponent(m[1]);\n // const url = decodeURIComponent(m.groups.url);\n $(new Image()).load(function () {\n image.setAttributeNS(NS.XLINK, 'xlink:href', url);\n }).attr('src', url);\n }\n }\n // Add to encodableImages if it loads\n canvas.embedImage(val);\n }\n });\n\n // Wrap child SVGs in group elements\n content.find('svg').each(function () {\n // Skip if it's in a <defs>\n if ($(this).closest('defs').length) { return; }\n\n uniquifyElems(this);\n\n // Check if it already has a gsvg group\n const pa = this.parentNode;\n if (pa.childNodes.length === 1 && pa.nodeName === 'g') {\n $(pa).data('gsvg', this);\n pa.id = pa.id || getNextId();\n } else {\n groupSvgElem(this);\n }\n });\n\n // For Firefox: Put all paint elems in defs\n if (isGecko()) {\n content.find('linearGradient, radialGradient, pattern').appendTo(findDefs());\n }\n\n // Set ref element for <use> elements\n\n // TODO: This should also be done if the object is re-added through \"redo\"\n setUseData(content);\n\n convertGradients(content[0]);\n\n const attrs = {\n id: 'svgcontent',\n overflow: curConfig.show_outside_canvas ? 'visible' : 'hidden'\n };\n\n let percs = false;\n\n // determine proper size\n if (content.attr('viewBox')) {\n const vb = content.attr('viewBox').split(' ');\n attrs.width = vb[2];\n attrs.height = vb[3];\n // handle content that doesn't have a viewBox\n } else {\n $.each(['width', 'height'], function (i, dim) {\n // Set to 100 if not given\n const val = content.attr(dim) || '100%';\n\n if (String(val).substr(-1) === '%') {\n // Use user units if percentage given\n percs = true;\n } else {\n attrs[dim] = convertToNum(dim, val);\n }\n });\n }\n\n // identify layers\n draw.identifyLayers();\n\n // Give ID for any visible layer children missing one\n content.children().find(visElems).each(function () {\n if (!this.id) { this.id = getNextId(); }\n });\n\n // Percentage width/height, so let's base it on visible elements\n if (percs) {\n const bb = getStrokedBBoxDefaultVisible();\n attrs.width = bb.width + bb.x;\n attrs.height = bb.height + bb.y;\n }\n\n // Just in case negative numbers are given or\n // result from the percs calculation\n if (attrs.width <= 0) { attrs.width = 100; }\n if (attrs.height <= 0) { attrs.height = 100; }\n\n content.attr(attrs);\n this.contentW = attrs.width;\n this.contentH = attrs.height;\n\n batchCmd.addSubCommand(new InsertElementCommand(svgcontent));\n // update root to the correct size\n const changes = content.attr(['width', 'height']);\n batchCmd.addSubCommand(new ChangeElementCommand(svgroot, changes));\n\n // reset zoom\n currentZoom = 1;\n\n // reset transform lists\n resetListMap();\n clearSelection();\n pathModule.clearData();\n svgroot.append(selectorManager.selectorParentGroup);\n\n if (!preventUndo) addCommandToHistory(batchCmd);\n call('changed', [svgcontent]);\n } catch (e) {\n console.log(e); // eslint-disable-line no-console\n return false;\n }\n\n return true;\n};\n\n/**\n* This function imports the input SVG XML as a `<symbol>` in the `<defs>`, then adds a\n* `<use>` to the current layer.\n* @function module:svgcanvas.SvgCanvas#importSvgString\n* @param {string} xmlString - The SVG as XML text.\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {null|Element} This function returns null if the import was unsuccessful, or the element otherwise.\n* @todo\n* - properly handle if namespace is introduced by imported content (must add to svgcontent\n* and update all prefixes in the imported node)\n* - properly handle recalculating dimensions, `recalculateDimensions()` doesn't handle\n* arbitrary transform lists, but makes some assumptions about how the transform list\n* was obtained\n*/\nthis.importSvgString = function (xmlString) {\n let j, ts, useEl;\n try {\n // Get unique ID\n const uid = encode64(xmlString.length + xmlString).substr(0, 32);\n\n let useExisting = false;\n // Look for symbol and make sure symbol exists in image\n if (importIds[uid]) {\n if ($(importIds[uid].symbol).parents('#svgroot').length) {\n useExisting = true;\n }\n }\n\n const batchCmd = new BatchCommand('Import Image');\n let symbol;\n if (useExisting) {\n ({symbol} = importIds[uid]);\n ts = importIds[uid].xform;\n } else {\n // convert string into XML document\n const newDoc = text2xml(xmlString);\n\n this.prepareSvg(newDoc);\n\n // import new svg document into our document\n let svg;\n // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode()\n if (svgdoc.adoptNode) {\n svg = svgdoc.adoptNode(newDoc.documentElement);\n } else {\n svg = svgdoc.importNode(newDoc.documentElement, true);\n }\n\n uniquifyElems(svg);\n\n const innerw = convertToNum('width', svg.getAttribute('width')),\n innerh = convertToNum('height', svg.getAttribute('height')),\n innervb = svg.getAttribute('viewBox'),\n // if no explicit viewbox, create one out of the width and height\n vb = innervb ? innervb.split(' ') : [0, 0, innerw, innerh];\n for (j = 0; j < 4; ++j) {\n vb[j] = Number(vb[j]);\n }\n\n // TODO: properly handle preserveAspectRatio\n const // canvasw = +svgcontent.getAttribute('width'),\n canvash = Number(svgcontent.getAttribute('height'));\n // imported content should be 1/3 of the canvas on its largest dimension\n\n if (innerh > innerw) {\n ts = 'scale(' + (canvash / 3) / vb[3] + ')';\n } else {\n ts = 'scale(' + (canvash / 3) / vb[2] + ')';\n }\n\n // Hack to make recalculateDimensions understand how to scale\n ts = 'translate(0) ' + ts + ' translate(0)';\n\n symbol = svgdoc.createElementNS(NS.SVG, 'symbol');\n const defs = findDefs();\n\n if (isGecko()) {\n // Move all gradients into root for Firefox, workaround for this bug:\n // https://bugzilla.mozilla.org/show_bug.cgi?id=353575\n // TODO: Make this properly undo-able.\n $(svg).find('linearGradient, radialGradient, pattern').appendTo(defs);\n }\n\n while (svg.firstChild) {\n const first = svg.firstChild;\n symbol.append(first);\n }\n const attrs = svg.attributes;\n for (const attr of attrs) { // Ok for `NamedNodeMap`\n symbol.setAttribute(attr.nodeName, attr.value);\n }\n symbol.id = getNextId();\n\n // Store data\n importIds[uid] = {\n symbol,\n xform: ts\n };\n\n findDefs().append(symbol);\n batchCmd.addSubCommand(new InsertElementCommand(symbol));\n }\n\n useEl = svgdoc.createElementNS(NS.SVG, 'use');\n useEl.id = getNextId();\n setHref(useEl, '#' + symbol.id);\n\n (currentGroup || getCurrentDrawing().getCurrentLayer()).append(useEl);\n batchCmd.addSubCommand(new InsertElementCommand(useEl));\n clearSelection();\n\n useEl.setAttribute('transform', ts);\n recalculateDimensions(useEl);\n $(useEl).data('symbol', symbol).data('ref', symbol);\n addToSelection([useEl]);\n\n // TODO: Find way to add this in a recalculateDimensions-parsable way\n // if (vb[0] !== 0 || vb[1] !== 0) {\n // ts = 'translate(' + (-vb[0]) + ',' + (-vb[1]) + ') ' + ts;\n // }\n addCommandToHistory(batchCmd);\n call('changed', [svgcontent]);\n } catch (e) {\n console.log(e); // eslint-disable-line no-console\n return null;\n }\n\n // we want to return the element so we can automatically select it\n return useEl;\n};\n\n// Could deprecate, but besides external uses, their usage makes clear that\n// canvas is a dependency for all of these\nconst dr = {\n identifyLayers, createLayer, cloneLayer, deleteCurrentLayer,\n setCurrentLayer, renameCurrentLayer, setCurrentLayerPosition,\n setLayerVisibility, moveSelectedToLayer, mergeLayer, mergeAllLayers,\n leaveContext, setContext\n};\nObject.entries(dr).forEach(([prop, propVal]) => {\n canvas[prop] = propVal;\n});\ndraw.init(\n /**\n * @implements {module:draw.DrawCanvasInit}\n */\n {\n pathActions,\n getCurrentGroup () {\n return currentGroup;\n },\n setCurrentGroup (cg) {\n currentGroup = cg;\n },\n getSelectedElements,\n getSVGContent,\n undoMgr,\n elData,\n getCurrentDrawing,\n clearSelection,\n call,\n addCommandToHistory,\n /**\n * @fires module:svgcanvas.SvgCanvas#event:changed\n * @returns {void}\n */\n changeSVGContent () {\n call('changed', [svgcontent]);\n }\n }\n);\n\n/**\n* Group: Document functions.\n*/\n\n/**\n* Clears the current document. This is not an undoable action.\n* @function module:svgcanvas.SvgCanvas#clear\n* @fires module:svgcanvas.SvgCanvas#event:cleared\n* @returns {void}\n*/\nthis.clear = function () {\n pathActions.clear();\n\n clearSelection();\n\n // clear the svgcontent node\n canvas.clearSvgContentElement();\n\n // create new document\n canvas.current_drawing_ = new draw.Drawing(svgcontent);\n\n // create empty first layer\n canvas.createLayer('Layer 1');\n\n // clear the undo stack\n canvas.undoMgr.resetUndoStack();\n\n // reset the selector manager\n selectorManager.initGroup();\n\n // reset the rubber band box\n rubberBox = selectorManager.getRubberBandBox();\n\n call('cleared');\n};\n\n// Alias function\nthis.linkControlPoints = pathActions.linkControlPoints;\n\n/**\n* @function module:svgcanvas.SvgCanvas#getContentElem\n* @returns {Element} The content DOM element\n*/\nthis.getContentElem = function () { return svgcontent; };\n\n/**\n* @function module:svgcanvas.SvgCanvas#getRootElem\n* @returns {SVGSVGElement} The root DOM element\n*/\nthis.getRootElem = function () { return svgroot; };\n\n/**\n* @typedef {PlainObject} DimensionsAndZoom\n* @property {Float} w Width\n* @property {Float} h Height\n* @property {Float} zoom Zoom\n*/\n\n/**\n* @function module:svgcanvas.SvgCanvas#getResolution\n* @returns {DimensionsAndZoom} The current dimensions and zoom level in an object\n*/\nconst getResolution = this.getResolution = function () {\n// const vb = svgcontent.getAttribute('viewBox').split(' ');\n// return {w:vb[2], h:vb[3], zoom: currentZoom};\n\n const w = svgcontent.getAttribute('width') / currentZoom;\n const h = svgcontent.getAttribute('height') / currentZoom;\n\n return {\n w,\n h,\n zoom: currentZoom\n };\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getSnapToGrid\n* @returns {boolean} The current snap to grid setting\n*/\nthis.getSnapToGrid = function () { return curConfig.gridSnapping; };\n\n/**\n* @function module:svgcanvas.SvgCanvas#getVersion\n* @returns {string} A string which describes the revision number of SvgCanvas.\n*/\nthis.getVersion = function () {\n return 'svgcanvas.js ($Rev$)';\n};\n\n/**\n* Update interface strings with given values.\n* @function module:svgcanvas.SvgCanvas#setUiStrings\n* @param {module:path.uiStrings} strs - Object with strings (see the [locales API]{@link module:locale.LocaleStrings} and the [tutorial]{@tutorial LocaleDocs})\n* @returns {void}\n*/\nthis.setUiStrings = function (strs) {\n Object.assign(uiStrings, strs.notification);\n $ = jQueryPluginDBox($, strs.common);\n pathModule.setUiStrings(strs);\n};\n\n/**\n* Update configuration options with given values.\n* @function module:svgcanvas.SvgCanvas#setConfig\n* @param {module:SVGEditor.Config} opts - Object with options\n* @returns {void}\n*/\nthis.setConfig = function (opts) {\n Object.assign(curConfig, opts);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getTitle\n* @param {Element} [elem]\n* @returns {string|void} the current group/SVG's title contents or\n* `undefined` if no element is passed nd there are no selected elements.\n*/\nthis.getTitle = function (elem) {\n elem = elem || selectedElements[0];\n if (!elem) { return undefined; }\n elem = $(elem).data('gsvg') || $(elem).data('symbol') || elem;\n const childs = elem.childNodes;\n for (const child of childs) {\n if (child.nodeName === 'title') {\n return child.textContent;\n }\n }\n return '';\n};\n\n/**\n* Sets the group/SVG's title content.\n* @function module:svgcanvas.SvgCanvas#setGroupTitle\n* @param {string} val\n* @todo Combine this with `setDocumentTitle`\n* @returns {void}\n*/\nthis.setGroupTitle = function (val) {\n let elem = selectedElements[0];\n elem = $(elem).data('gsvg') || elem;\n\n const ts = $(elem).children('title');\n\n const batchCmd = new BatchCommand('Set Label');\n\n let title;\n if (!val.length) {\n // Remove title element\n const tsNextSibling = ts.nextSibling;\n batchCmd.addSubCommand(new RemoveElementCommand(ts[0], tsNextSibling, elem));\n ts.remove();\n } else if (ts.length) {\n // Change title contents\n title = ts[0];\n batchCmd.addSubCommand(new ChangeElementCommand(title, {'#text': title.textContent}));\n title.textContent = val;\n } else {\n // Add title element\n title = svgdoc.createElementNS(NS.SVG, 'title');\n title.textContent = val;\n $(elem).prepend(title);\n batchCmd.addSubCommand(new InsertElementCommand(title));\n }\n\n addCommandToHistory(batchCmd);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getDocumentTitle\n* @returns {string|void} The current document title or an empty string if not found\n*/\nconst getDocumentTitle = this.getDocumentTitle = function () {\n return canvas.getTitle(svgcontent);\n};\n\n/**\n* Adds/updates a title element for the document with the given name.\n* This is an undoable action.\n* @function module:svgcanvas.SvgCanvas#setDocumentTitle\n* @param {string} newTitle - String with the new title\n* @returns {void}\n*/\nthis.setDocumentTitle = function (newTitle) {\n const childs = svgcontent.childNodes;\n let docTitle = false, oldTitle = '';\n\n const batchCmd = new BatchCommand('Change Image Title');\n\n for (const child of childs) {\n if (child.nodeName === 'title') {\n docTitle = child;\n oldTitle = docTitle.textContent;\n break;\n }\n }\n if (!docTitle) {\n docTitle = svgdoc.createElementNS(NS.SVG, 'title');\n svgcontent.insertBefore(docTitle, svgcontent.firstChild);\n // svgcontent.firstChild.before(docTitle); // Ok to replace above with this?\n }\n\n if (newTitle.length) {\n docTitle.textContent = newTitle;\n } else {\n // No title given, so element is not necessary\n docTitle.remove();\n }\n batchCmd.addSubCommand(new ChangeElementCommand(docTitle, {'#text': oldTitle}));\n addCommandToHistory(batchCmd);\n};\n\n/**\n* Returns the editor's namespace URL, optionally adding it to the root element.\n* @function module:svgcanvas.SvgCanvas#getEditorNS\n* @param {boolean} [add] - Indicates whether or not to add the namespace value\n* @returns {string} The editor's namespace URL\n*/\nthis.getEditorNS = function (add) {\n if (add) {\n svgcontent.setAttribute('xmlns:se', NS.SE);\n }\n return NS.SE;\n};\n\n/**\n* Changes the document's dimensions to the given size.\n* @function module:svgcanvas.SvgCanvas#setResolution\n* @param {Float|\"fit\"} x - Number with the width of the new dimensions in user units.\n* Can also be the string \"fit\" to indicate \"fit to content\".\n* @param {Float} y - Number with the height of the new dimensions in user units.\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {boolean} Indicates if resolution change was successful.\n* It will fail on \"fit to content\" option with no content to fit to.\n*/\nthis.setResolution = function (x, y) {\n const res = getResolution();\n const {w, h} = res;\n let batchCmd;\n\n if (x === 'fit') {\n // Get bounding box\n const bbox = getStrokedBBoxDefaultVisible();\n\n if (bbox) {\n batchCmd = new BatchCommand('Fit Canvas to Content');\n const visEls = getVisibleElements();\n addToSelection(visEls);\n const dx = [], dy = [];\n $.each(visEls, function (i, item) {\n dx.push(bbox.x * -1);\n dy.push(bbox.y * -1);\n });\n\n const cmd = canvas.moveSelectedElements(dx, dy, true);\n batchCmd.addSubCommand(cmd);\n clearSelection();\n\n x = Math.round(bbox.width);\n y = Math.round(bbox.height);\n } else {\n return false;\n }\n }\n if (x !== w || y !== h) {\n if (!batchCmd) {\n batchCmd = new BatchCommand('Change Image Dimensions');\n }\n\n x = convertToNum('width', x);\n y = convertToNum('height', y);\n\n svgcontent.setAttribute('width', x);\n svgcontent.setAttribute('height', y);\n\n this.contentW = x;\n this.contentH = y;\n batchCmd.addSubCommand(new ChangeElementCommand(svgcontent, {width: w, height: h}));\n\n svgcontent.setAttribute('viewBox', [0, 0, x / currentZoom, y / currentZoom].join(' '));\n batchCmd.addSubCommand(new ChangeElementCommand(svgcontent, {viewBox: ['0 0', w, h].join(' ')}));\n\n addCommandToHistory(batchCmd);\n call('changed', [svgcontent]);\n }\n return true;\n};\n\n/**\n* @typedef {module:jQueryAttr.Attributes} module:svgcanvas.ElementPositionInCanvas\n* @property {Float} x\n* @property {Float} y\n*/\n\n/**\n* @function module:svgcanvas.SvgCanvas#getOffset\n* @returns {module:svgcanvas.ElementPositionInCanvas} An object with `x`, `y` values indicating the svgcontent element's\n* position in the editor's canvas.\n*/\nthis.getOffset = function () {\n return $(svgcontent).attr(['x', 'y']);\n};\n\n/**\n * @typedef {PlainObject} module:svgcanvas.ZoomAndBBox\n * @property {Float} zoom\n * @property {module:utilities.BBoxObject} bbox\n */\n/**\n* Sets the zoom level on the canvas-side based on the given value.\n* @function module:svgcanvas.SvgCanvas#setBBoxZoom\n* @param {\"selection\"|\"canvas\"|\"content\"|\"layer\"|module:SVGEditor.BBoxObjectWithFactor} val - Bounding box object to zoom to or string indicating zoom option. Note: the object value type is defined in `svg-editor.js`\n* @param {Integer} editorW - The editor's workarea box's width\n* @param {Integer} editorH - The editor's workarea box's height\n* @returns {module:svgcanvas.ZoomAndBBox|void}\n*/\nthis.setBBoxZoom = function (val, editorW, editorH) {\n let spacer = 0.85;\n let bb;\n const calcZoom = function (bb) { // eslint-disable-line no-shadow\n if (!bb) { return false; }\n const wZoom = Math.round((editorW / bb.width) * 100 * spacer) / 100;\n const hZoom = Math.round((editorH / bb.height) * 100 * spacer) / 100;\n const zoom = Math.min(wZoom, hZoom);\n canvas.setZoom(zoom);\n return {zoom, bbox: bb};\n };\n\n if (typeof val === 'object') {\n bb = val;\n if (bb.width === 0 || bb.height === 0) {\n const newzoom = bb.zoom ? bb.zoom : currentZoom * bb.factor;\n canvas.setZoom(newzoom);\n return {zoom: currentZoom, bbox: bb};\n }\n return calcZoom(bb);\n }\n\n switch (val) {\n case 'selection': {\n if (!selectedElements[0]) { return undefined; }\n const selectedElems = $.map(selectedElements, function (n) {\n if (n) {\n return n;\n }\n return undefined;\n });\n bb = getStrokedBBoxDefaultVisible(selectedElems);\n break;\n } case 'canvas': {\n const res = getResolution();\n spacer = 0.95;\n bb = {width: res.w, height: res.h, x: 0, y: 0};\n break;\n } case 'content':\n bb = getStrokedBBoxDefaultVisible();\n break;\n case 'layer':\n bb = getStrokedBBoxDefaultVisible(getVisibleElements(getCurrentDrawing().getCurrentLayer()));\n break;\n default:\n return undefined;\n }\n return calcZoom(bb);\n};\n\n/**\n* The zoom level has changed. Supplies the new zoom level as a number (not percentage).\n* @event module:svgcanvas.SvgCanvas#event:ext_zoomChanged\n* @type {Float}\n*/\n/**\n* The bottom panel was updated.\n* @event module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate\n* @type {PlainObject}\n* @property {boolean} nofill Indicates fill is disabled\n* @property {boolean} nostroke Indicates stroke is disabled\n*/\n/**\n* The element selection has changed (elements were added/removed from selection).\n* @event module:svgcanvas.SvgCanvas#event:ext_selectedChanged\n* @type {PlainObject}\n* @property {Element[]} elems Array of the newly selected elements\n* @property {Element|null} selectedElement The single selected element\n* @property {boolean} multiselected Indicates whether one or more elements were selected\n*/\n/**\n* Called when part of element is in process of changing, generally on\n* mousemove actions like rotate, move, etc.\n* @event module:svgcanvas.SvgCanvas#event:ext_elementTransition\n* @type {PlainObject}\n* @property {Element[]} elems Array of transitioning elements\n*/\n/**\n* One or more elements were changed.\n* @event module:svgcanvas.SvgCanvas#event:ext_elementChanged\n* @type {PlainObject}\n* @property {Element[]} elems Array of the affected elements\n*/\n/**\n* Invoked as soon as the locale is ready.\n* @event module:svgcanvas.SvgCanvas#event:ext_langReady\n* @type {PlainObject}\n* @property {string} lang The two-letter language code\n* @property {module:SVGEditor.uiStrings} uiStrings\n* @property {module:SVGEditor~ImportLocale} importLocale\n*/\n/**\n* The language was changed. Two-letter code of the new language.\n* @event module:svgcanvas.SvgCanvas#event:ext_langChanged\n* @type {string}\n*/\n/**\n* Means for an extension to add locale data. The two-letter language code.\n* @event module:svgcanvas.SvgCanvas#event:ext_addLangData\n* @type {PlainObject}\n* @property {string} lang\n* @property {module:SVGEditor~ImportLocale} importLocale\n*/\n/**\n * Called when new image is created.\n * @event module:svgcanvas.SvgCanvas#event:ext_onNewDocument\n * @type {void}\n */\n/**\n * Called when sidepanel is resized or toggled.\n * @event module:svgcanvas.SvgCanvas#event:ext_workareaResized\n * @type {void}\n*/\n/**\n * Called upon addition of the extension, or, if svgicons are set,\n * after the icons are ready when extension SVG icons have loaded.\n * @event module:svgcanvas.SvgCanvas#event:ext_callback\n * @type {void}\n*/\n\n/**\n* Sets the zoom to the given level.\n* @function module:svgcanvas.SvgCanvas#setZoom\n* @param {Float} zoomLevel - Float indicating the zoom level to change to\n* @fires module:svgcanvas.SvgCanvas#event:ext_zoomChanged\n* @returns {void}\n*/\nthis.setZoom = function (zoomLevel) {\n const res = getResolution();\n svgcontent.setAttribute('viewBox', '0 0 ' + res.w / zoomLevel + ' ' + res.h / zoomLevel);\n currentZoom = zoomLevel;\n $.each(selectedElements, function (i, elem) {\n if (!elem) { return; }\n selectorManager.requestSelector(elem).resize();\n });\n pathActions.zoomChange();\n runExtensions('zoomChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext_zoomChanged} */ zoomLevel);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getMode\n* @returns {string} The current editor mode string\n*/\nthis.getMode = function () {\n return currentMode;\n};\n\n/**\n* Sets the editor's mode to the given string.\n* @function module:svgcanvas.SvgCanvas#setMode\n* @param {string} name - String with the new mode to change to\n* @returns {void}\n*/\nthis.setMode = function (name) {\n pathActions.clear(true);\n textActions.clear();\n curProperties = (selectedElements[0] && selectedElements[0].nodeName === 'text') ? curText : curShape;\n currentMode = name;\n};\n\n/**\n* Group: Element Styling.\n*/\n\n/**\n* @typedef {PlainObject} module:svgcanvas.PaintOptions\n* @property {\"solidColor\"} type\n*/\n\n/**\n* @function module:svgcanvas.SvgCanvas#getColor\n* @param {string} type\n* @returns {string|module:svgcanvas.PaintOptions|Float|module:jGraduate~Paint} The current fill/stroke option\n*/\nthis.getColor = function (type) {\n return curProperties[type];\n};\n\n/**\n* Change the current stroke/fill color/gradient value.\n* @function module:svgcanvas.SvgCanvas#setColor\n* @param {string} type - String indicating fill or stroke\n* @param {string} val - The value to set the stroke attribute to\n* @param {boolean} preventUndo - Boolean indicating whether or not this should be an undoable option\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setColor = function (type, val, preventUndo) {\n curShape[type] = val;\n curProperties[type + '_paint'] = {type: 'solidColor'};\n const elems = [];\n /**\n *\n * @param {Element} e\n * @returns {void}\n */\n function addNonG (e) {\n if (e.nodeName !== 'g') {\n elems.push(e);\n }\n }\n let i = selectedElements.length;\n while (i--) {\n const elem = selectedElements[i];\n if (elem) {\n if (elem.tagName === 'g') {\n walkTree(elem, addNonG);\n } else if (type === 'fill') {\n if (elem.tagName !== 'polyline' && elem.tagName !== 'line') {\n elems.push(elem);\n }\n } else {\n elems.push(elem);\n }\n }\n }\n if (elems.length > 0) {\n if (!preventUndo) {\n changeSelectedAttribute(type, val, elems);\n call('changed', elems);\n } else {\n changeSelectedAttributeNoUndo(type, val, elems);\n }\n }\n};\n\n/**\n* Apply the current gradient to selected element's fill or stroke.\n* @function module:svgcanvas.SvgCanvas#setGradient\n* @param {\"fill\"|\"stroke\"} type - String indicating \"fill\" or \"stroke\" to apply to an element\n* @returns {void}\n*/\nconst setGradient = this.setGradient = function (type) {\n if (!curProperties[type + '_paint'] || curProperties[type + '_paint'].type === 'solidColor') { return; }\n let grad = canvas[type + 'Grad'];\n // find out if there is a duplicate gradient already in the defs\n const duplicateGrad = findDuplicateGradient(grad);\n const defs = findDefs();\n // no duplicate found, so import gradient into defs\n if (!duplicateGrad) {\n // const origGrad = grad;\n grad = defs.appendChild(svgdoc.importNode(grad, true));\n // get next id and set it on the grad\n grad.id = getNextId();\n } else { // use existing gradient\n grad = duplicateGrad;\n }\n canvas.setColor(type, 'url(#' + grad.id + ')');\n};\n\n/**\n* Check if exact gradient already exists.\n* @function module:svgcanvas~findDuplicateGradient\n* @param {SVGGradientElement} grad - The gradient DOM element to compare to others\n* @returns {SVGGradientElement} The existing gradient if found, `null` if not\n*/\nconst findDuplicateGradient = function (grad) {\n const defs = findDefs();\n const existingGrads = $(defs).find('linearGradient, radialGradient');\n let i = existingGrads.length;\n const radAttrs = ['r', 'cx', 'cy', 'fx', 'fy'];\n while (i--) {\n const og = existingGrads[i];\n if (grad.tagName === 'linearGradient') {\n if (grad.getAttribute('x1') !== og.getAttribute('x1') ||\n grad.getAttribute('y1') !== og.getAttribute('y1') ||\n grad.getAttribute('x2') !== og.getAttribute('x2') ||\n grad.getAttribute('y2') !== og.getAttribute('y2')\n ) {\n continue;\n }\n } else {\n const gradAttrs = $(grad).attr(radAttrs);\n const ogAttrs = $(og).attr(radAttrs);\n\n let diff = false;\n $.each(radAttrs, function (j, attr) {\n if (gradAttrs[attr] !== ogAttrs[attr]) { diff = true; }\n });\n\n if (diff) { continue; }\n }\n\n // else could be a duplicate, iterate through stops\n const stops = grad.getElementsByTagNameNS(NS.SVG, 'stop');\n const ostops = og.getElementsByTagNameNS(NS.SVG, 'stop');\n\n if (stops.length !== ostops.length) {\n continue;\n }\n\n let j = stops.length;\n while (j--) {\n const stop = stops[j];\n const ostop = ostops[j];\n\n if (stop.getAttribute('offset') !== ostop.getAttribute('offset') ||\n stop.getAttribute('stop-opacity') !== ostop.getAttribute('stop-opacity') ||\n stop.getAttribute('stop-color') !== ostop.getAttribute('stop-color')) {\n break;\n }\n }\n\n if (j === -1) {\n return og;\n }\n } // for each gradient in defs\n\n return null;\n};\n\n/**\n* Set a color/gradient to a fill/stroke.\n* @function module:svgcanvas.SvgCanvas#setPaint\n* @param {\"fill\"|\"stroke\"} type - String with \"fill\" or \"stroke\"\n* @param {module:jGraduate.jGraduatePaintOptions} paint - The jGraduate paint object to apply\n* @returns {void}\n*/\nthis.setPaint = function (type, paint) {\n // make a copy\n const p = new $.jGraduate.Paint(paint);\n this.setPaintOpacity(type, p.alpha / 100, true);\n\n // now set the current paint object\n curProperties[type + '_paint'] = p;\n switch (p.type) {\n case 'solidColor':\n this.setColor(type, p.solidColor !== 'none' ? '#' + p.solidColor : 'none');\n break;\n case 'linearGradient':\n case 'radialGradient':\n canvas[type + 'Grad'] = p[p.type];\n setGradient(type);\n break;\n }\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#setStrokePaint\n* @param {module:jGraduate~Paint} paint\n* @returns {void}\n*/\nthis.setStrokePaint = function (paint) {\n this.setPaint('stroke', paint);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#setFillPaint\n* @param {module:jGraduate~Paint} paint\n* @returns {void}\n*/\nthis.setFillPaint = function (paint) {\n this.setPaint('fill', paint);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getStrokeWidth\n* @returns {Float|string} The current stroke-width value\n*/\nthis.getStrokeWidth = function () {\n return curProperties.stroke_width;\n};\n\n/**\n* Sets the stroke width for the current selected elements.\n* When attempting to set a line's width to 0, this changes it to 1 instead.\n* @function module:svgcanvas.SvgCanvas#setStrokeWidth\n* @param {Float} val - A Float indicating the new stroke width value\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setStrokeWidth = function (val) {\n if (val === 0 && ['line', 'path'].includes(currentMode)) {\n canvas.setStrokeWidth(1);\n return;\n }\n curProperties.stroke_width = val;\n\n const elems = [];\n /**\n *\n * @param {Element} e\n * @returns {void}\n */\n function addNonG (e) {\n if (e.nodeName !== 'g') {\n elems.push(e);\n }\n }\n let i = selectedElements.length;\n while (i--) {\n const elem = selectedElements[i];\n if (elem) {\n if (elem.tagName === 'g') {\n walkTree(elem, addNonG);\n } else {\n elems.push(elem);\n }\n }\n }\n if (elems.length > 0) {\n changeSelectedAttribute('stroke-width', val, elems);\n call('changed', selectedElements);\n }\n};\n\n/**\n* Set the given stroke-related attribute the given value for selected elements.\n* @function module:svgcanvas.SvgCanvas#setStrokeAttr\n* @param {string} attr - String with the attribute name\n* @param {string|Float} val - String or number with the attribute value\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setStrokeAttr = function (attr, val) {\n curShape[attr.replace('-', '_')] = val;\n const elems = [];\n\n let i = selectedElements.length;\n while (i--) {\n const elem = selectedElements[i];\n if (elem) {\n if (elem.tagName === 'g') {\n walkTree(elem, function (e) { if (e.nodeName !== 'g') { elems.push(e); } });\n } else {\n elems.push(elem);\n }\n }\n }\n if (elems.length > 0) {\n changeSelectedAttribute(attr, val, elems);\n call('changed', selectedElements);\n }\n};\n\n/**\n* @typedef {PlainObject} module:svgcanvas.StyleOptions\n* @property {string} fill\n* @property {Float} fill_opacity\n* @property {string} stroke\n* @property {Float} stroke_width\n* @property {string} stroke_dasharray\n* @property {string} stroke_linejoin\n* @property {string} stroke_linecap\n* @property {Float} stroke_opacity\n* @property {Float} opacity\n*/\n\n/**\n* @function module:svgcanvas.SvgCanvas#getStyle\n* @returns {module:svgcanvas.StyleOptions} current style options\n*/\nthis.getStyle = function () {\n return curShape;\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getOpacity\n* @returns {Float} the current opacity\n*/\nthis.getOpacity = getOpacity;\n\n/**\n* Sets the given opacity on the current selected elements.\n* @function module:svgcanvas.SvgCanvas#setOpacity\n* @param {string} val\n* @returns {void}\n*/\nthis.setOpacity = function (val) {\n curShape.opacity = val;\n changeSelectedAttribute('opacity', val);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getFillOpacity\n* @returns {Float} the current fill opacity\n*/\nthis.getFillOpacity = function () {\n return curShape.fill_opacity;\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getStrokeOpacity\n* @returns {string} the current stroke opacity\n*/\nthis.getStrokeOpacity = function () {\n return curShape.stroke_opacity;\n};\n\n/**\n* Sets the current fill/stroke opacity.\n* @function module:svgcanvas.SvgCanvas#setPaintOpacity\n* @param {string} type - String with \"fill\" or \"stroke\"\n* @param {Float} val - Float with the new opacity value\n* @param {boolean} preventUndo - Indicates whether or not this should be an undoable action\n* @returns {void}\n*/\nthis.setPaintOpacity = function (type, val, preventUndo) {\n curShape[type + '_opacity'] = val;\n if (!preventUndo) {\n changeSelectedAttribute(type + '-opacity', val);\n } else {\n changeSelectedAttributeNoUndo(type + '-opacity', val);\n }\n};\n\n/**\n* Gets the current fill/stroke opacity.\n* @function module:svgcanvas.SvgCanvas#getPaintOpacity\n* @param {\"fill\"|\"stroke\"} type - String with \"fill\" or \"stroke\"\n* @returns {Float} Fill/stroke opacity\n*/\nthis.getPaintOpacity = function (type) {\n return type === 'fill' ? this.getFillOpacity() : this.getStrokeOpacity();\n};\n\n/**\n* Gets the `stdDeviation` blur value of the given element.\n* @function module:svgcanvas.SvgCanvas#getBlur\n* @param {Element} elem - The element to check the blur value for\n* @returns {string} stdDeviation blur attribute value\n*/\nthis.getBlur = function (elem) {\n let val = 0;\n // const elem = selectedElements[0];\n\n if (elem) {\n const filterUrl = elem.getAttribute('filter');\n if (filterUrl) {\n const blur = getElem(elem.id + '_blur');\n if (blur) {\n val = blur.firstChild.getAttribute('stdDeviation');\n }\n }\n }\n return val;\n};\n\n(function () {\nlet curCommand = null;\nlet filter = null;\nlet filterHidden = false;\n\n/**\n* Sets the `stdDeviation` blur value on the selected element without being undoable.\n* @function module:svgcanvas.SvgCanvas#setBlurNoUndo\n* @param {Float} val - The new `stdDeviation` value\n* @returns {void}\n*/\ncanvas.setBlurNoUndo = function (val) {\n if (!filter) {\n canvas.setBlur(val);\n return;\n }\n if (val === 0) {\n // Don't change the StdDev, as that will hide the element.\n // Instead, just remove the value for \"filter\"\n changeSelectedAttributeNoUndo('filter', '');\n filterHidden = true;\n } else {\n const elem = selectedElements[0];\n if (filterHidden) {\n changeSelectedAttributeNoUndo('filter', 'url(#' + elem.id + '_blur)');\n }\n if (isWebkit()) {\n // console.log('e', elem); // eslint-disable-line no-console\n elem.removeAttribute('filter');\n elem.setAttribute('filter', 'url(#' + elem.id + '_blur)');\n }\n changeSelectedAttributeNoUndo('stdDeviation', val, [filter.firstChild]);\n canvas.setBlurOffsets(filter, val);\n }\n};\n\n/**\n *\n * @returns {void}\n */\nfunction finishChange () {\n const bCmd = canvas.undoMgr.finishUndoableChange();\n curCommand.addSubCommand(bCmd);\n addCommandToHistory(curCommand);\n curCommand = null;\n filter = null;\n}\n\n/**\n* Sets the `x`, `y`, `width`, `height` values of the filter element in order to\n* make the blur not be clipped. Removes them if not neeeded.\n* @function module:svgcanvas.SvgCanvas#setBlurOffsets\n* @param {Element} filterElem - The filter DOM element to update\n* @param {Float} stdDev - The standard deviation value on which to base the offset size\n* @returns {void}\n*/\ncanvas.setBlurOffsets = function (filterElem, stdDev) {\n if (stdDev > 3) {\n // TODO: Create algorithm here where size is based on expected blur\n assignAttributes(filterElem, {\n x: '-50%',\n y: '-50%',\n width: '200%',\n height: '200%'\n }, 100);\n // Removing these attributes hides text in Chrome (see Issue 579)\n } else if (!isWebkit()) {\n filterElem.removeAttribute('x');\n filterElem.removeAttribute('y');\n filterElem.removeAttribute('width');\n filterElem.removeAttribute('height');\n }\n};\n\n/**\n* Adds/updates the blur filter to the selected element.\n* @function module:svgcanvas.SvgCanvas#setBlur\n* @param {Float} val - Float with the new `stdDeviation` blur value\n* @param {boolean} complete - Whether or not the action should be completed (to add to the undo manager)\n* @returns {void}\n*/\ncanvas.setBlur = function (val, complete) {\n if (curCommand) {\n finishChange();\n return;\n }\n\n // Looks for associated blur, creates one if not found\n const elem = selectedElements[0];\n const elemId = elem.id;\n filter = getElem(elemId + '_blur');\n\n val -= 0;\n\n const batchCmd = new BatchCommand();\n\n // Blur found!\n if (filter) {\n if (val === 0) {\n filter = null;\n }\n } else {\n // Not found, so create\n const newblur = addSVGElementFromJson({element: 'feGaussianBlur',\n attr: {\n in: 'SourceGraphic',\n stdDeviation: val\n }\n });\n\n filter = addSVGElementFromJson({element: 'filter',\n attr: {\n id: elemId + '_blur'\n }\n });\n\n filter.append(newblur);\n findDefs().append(filter);\n\n batchCmd.addSubCommand(new InsertElementCommand(filter));\n }\n\n const changes = {filter: elem.getAttribute('filter')};\n\n if (val === 0) {\n elem.removeAttribute('filter');\n batchCmd.addSubCommand(new ChangeElementCommand(elem, changes));\n return;\n }\n\n changeSelectedAttribute('filter', 'url(#' + elemId + '_blur)');\n batchCmd.addSubCommand(new ChangeElementCommand(elem, changes));\n canvas.setBlurOffsets(filter, val);\n\n curCommand = batchCmd;\n canvas.undoMgr.beginUndoableChange('stdDeviation', [filter ? filter.firstChild : null]);\n if (complete) {\n canvas.setBlurNoUndo(val);\n finishChange();\n }\n};\n}());\n\n/**\n* Check whether selected element is bold or not.\n* @function module:svgcanvas.SvgCanvas#getBold\n* @returns {boolean} Indicates whether or not element is bold\n*/\nthis.getBold = function () {\n // should only have one element selected\n const selected = selectedElements[0];\n if (!isNullish(selected) && selected.tagName === 'text' &&\n isNullish(selectedElements[1])) {\n return (selected.getAttribute('font-weight') === 'bold');\n }\n return false;\n};\n\n/**\n* Make the selected element bold or normal.\n* @function module:svgcanvas.SvgCanvas#setBold\n* @param {boolean} b - Indicates bold (`true`) or normal (`false`)\n* @returns {void}\n*/\nthis.setBold = function (b) {\n const selected = selectedElements[0];\n if (!isNullish(selected) && selected.tagName === 'text' &&\n isNullish(selectedElements[1])) {\n changeSelectedAttribute('font-weight', b ? 'bold' : 'normal');\n }\n if (!selectedElements[0].textContent) {\n textActions.setCursor();\n }\n};\n\n/**\n* Check whether selected element is in italics or not.\n* @function module:svgcanvas.SvgCanvas#getItalic\n* @returns {boolean} Indicates whether or not element is italic\n*/\nthis.getItalic = function () {\n const selected = selectedElements[0];\n if (!isNullish(selected) && selected.tagName === 'text' &&\n isNullish(selectedElements[1])) {\n return (selected.getAttribute('font-style') === 'italic');\n }\n return false;\n};\n\n/**\n* Make the selected element italic or normal.\n* @function module:svgcanvas.SvgCanvas#setItalic\n* @param {boolean} i - Indicates italic (`true`) or normal (`false`)\n* @returns {void}\n*/\nthis.setItalic = function (i) {\n const selected = selectedElements[0];\n if (!isNullish(selected) && selected.tagName === 'text' &&\n isNullish(selectedElements[1])) {\n changeSelectedAttribute('font-style', i ? 'italic' : 'normal');\n }\n if (!selectedElements[0].textContent) {\n textActions.setCursor();\n }\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getFontFamily\n* @returns {string} The current font family\n*/\nthis.getFontFamily = function () {\n return curText.font_family;\n};\n\n/**\n* Set the new font family.\n* @function module:svgcanvas.SvgCanvas#setFontFamily\n* @param {string} val - String with the new font family\n* @returns {void}\n*/\nthis.setFontFamily = function (val) {\n curText.font_family = val;\n changeSelectedAttribute('font-family', val);\n if (selectedElements[0] && !selectedElements[0].textContent) {\n textActions.setCursor();\n }\n};\n\n/**\n* Set the new font color.\n* @function module:svgcanvas.SvgCanvas#setFontColor\n* @param {string} val - String with the new font color\n* @returns {void}\n*/\nthis.setFontColor = function (val) {\n curText.fill = val;\n changeSelectedAttribute('fill', val);\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getFontColor\n* @returns {string} The current font color\n*/\nthis.getFontColor = function () {\n return curText.fill;\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getFontSize\n* @returns {Float} The current font size\n*/\nthis.getFontSize = function () {\n return curText.font_size;\n};\n\n/**\n* Applies the given font size to the selected element.\n* @function module:svgcanvas.SvgCanvas#setFontSize\n* @param {Float} val - Float with the new font size\n* @returns {void}\n*/\nthis.setFontSize = function (val) {\n curText.font_size = val;\n changeSelectedAttribute('font-size', val);\n if (!selectedElements[0].textContent) {\n textActions.setCursor();\n }\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#getText\n* @returns {string} The current text (`textContent`) of the selected element\n*/\nthis.getText = function () {\n const selected = selectedElements[0];\n if (isNullish(selected)) { return ''; }\n return selected.textContent;\n};\n\n/**\n* Updates the text element with the given string.\n* @function module:svgcanvas.SvgCanvas#setTextContent\n* @param {string} val - String with the new text\n* @returns {void}\n*/\nthis.setTextContent = function (val) {\n changeSelectedAttribute('#text', val);\n textActions.init(val);\n textActions.setCursor();\n};\n\n/**\n* Sets the new image URL for the selected image element. Updates its size if\n* a new URL is given.\n* @function module:svgcanvas.SvgCanvas#setImageURL\n* @param {string} val - String with the image URL/path\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setImageURL = function (val) {\n const elem = selectedElements[0];\n if (!elem) { return; }\n\n const attrs = $(elem).attr(['width', 'height']);\n const setsize = (!attrs.width || !attrs.height);\n\n const curHref = getHref(elem);\n\n // Do nothing if no URL change or size change\n if (curHref === val && !setsize) {\n return;\n }\n\n const batchCmd = new BatchCommand('Change Image URL');\n\n setHref(elem, val);\n batchCmd.addSubCommand(new ChangeElementCommand(elem, {\n '#href': curHref\n }));\n\n $(new Image()).load(function () {\n const changes = $(elem).attr(['width', 'height']);\n\n $(elem).attr({\n width: this.width,\n height: this.height\n });\n\n selectorManager.requestSelector(elem).resize();\n\n batchCmd.addSubCommand(new ChangeElementCommand(elem, changes));\n addCommandToHistory(batchCmd);\n call('changed', [elem]);\n }).attr('src', val);\n};\n\n/**\n* Sets the new link URL for the selected anchor element.\n* @function module:svgcanvas.SvgCanvas#setLinkURL\n* @param {string} val - String with the link URL/path\n* @returns {void}\n*/\nthis.setLinkURL = function (val) {\n let elem = selectedElements[0];\n if (!elem) { return; }\n if (elem.tagName !== 'a') {\n // See if parent is an anchor\n const parentsA = $(elem).parents('a');\n if (parentsA.length) {\n elem = parentsA[0];\n } else {\n return;\n }\n }\n\n const curHref = getHref(elem);\n\n if (curHref === val) { return; }\n\n const batchCmd = new BatchCommand('Change Link URL');\n\n setHref(elem, val);\n batchCmd.addSubCommand(new ChangeElementCommand(elem, {\n '#href': curHref\n }));\n\n addCommandToHistory(batchCmd);\n};\n\n/**\n* Sets the `rx` and `ry` values to the selected `rect` element\n* to change its corner radius.\n* @function module:svgcanvas.SvgCanvas#setRectRadius\n* @param {string|Float} val - The new radius\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.setRectRadius = function (val) {\n const selected = selectedElements[0];\n if (!isNullish(selected) && selected.tagName === 'rect') {\n const r = selected.getAttribute('rx');\n if (r !== String(val)) {\n selected.setAttribute('rx', val);\n selected.setAttribute('ry', val);\n addCommandToHistory(new ChangeElementCommand(selected, {rx: r, ry: r}, 'Radius'));\n call('changed', [selected]);\n }\n }\n};\n\n/**\n* Wraps the selected element(s) in an anchor element or converts group to one.\n* @function module:svgcanvas.SvgCanvas#makeHyperlink\n* @param {string} url\n* @returns {void}\n*/\nthis.makeHyperlink = function (url) {\n canvas.groupSelectedElements('a', url);\n\n // TODO: If element is a single \"g\", convert to \"a\"\n // if (selectedElements.length > 1 && selectedElements[1]) {\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#removeHyperlink\n* @returns {void}\n*/\nthis.removeHyperlink = function () {\n canvas.ungroupSelectedElement();\n};\n\n/**\n* Group: Element manipulation.\n*/\n\n/**\n* Sets the new segment type to the selected segment(s).\n* @function module:svgcanvas.SvgCanvas#setSegType\n* @param {Integer} newType - New segment type. See {@link https://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSeg} for list\n* @returns {void}\n*/\nthis.setSegType = function (newType) {\n pathActions.setSegType(newType);\n};\n\n/**\n* Convert selected element to a path, or get the BBox of an element-as-path.\n* @function module:svgcanvas.SvgCanvas#convertToPath\n* @todo (codedread): Remove the getBBox argument and split this function into two.\n* @param {Element} elem - The DOM element to be converted\n* @param {boolean} getBBox - Boolean on whether or not to only return the path's BBox\n* @returns {void|DOMRect|false|SVGPathElement|null} If the getBBox flag is true, the resulting path's bounding box object.\n* Otherwise the resulting path element is returned.\n*/\nthis.convertToPath = function (elem, getBBox) {\n if (isNullish(elem)) {\n const elems = selectedElements;\n $.each(elems, function (i, el) {\n if (el) { canvas.convertToPath(el); }\n });\n return undefined;\n }\n if (getBBox) {\n return getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions);\n }\n // TODO: Why is this applying attributes from curShape, then inside utilities.convertToPath it's pulling addition attributes from elem?\n // TODO: If convertToPath is called with one elem, curShape and elem are probably the same; but calling with multiple is a bug or cool feature.\n const attrs = {\n fill: curShape.fill,\n 'fill-opacity': curShape.fill_opacity,\n stroke: curShape.stroke,\n 'stroke-width': curShape.stroke_width,\n 'stroke-dasharray': curShape.stroke_dasharray,\n 'stroke-linejoin': curShape.stroke_linejoin,\n 'stroke-linecap': curShape.stroke_linecap,\n 'stroke-opacity': curShape.stroke_opacity,\n opacity: curShape.opacity,\n visibility: 'hidden'\n };\n return convertToPath(elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, hstry, addCommandToHistory);\n};\n\n/**\n* This function makes the changes to the elements. It does not add the change\n* to the history stack.\n* @param {string} attr - Attribute name\n* @param {string|Float} newValue - String or number with the new attribute value\n* @param {Element[]} elems - The DOM elements to apply the change to\n* @returns {void}\n*/\nconst changeSelectedAttributeNoUndo = function (attr, newValue, elems) {\n if (currentMode === 'pathedit') {\n // Editing node\n pathActions.moveNode(attr, newValue);\n }\n elems = elems || selectedElements;\n let i = elems.length;\n const noXYElems = ['g', 'polyline', 'path'];\n // const goodGAttrs = ['transform', 'opacity', 'filter'];\n\n while (i--) {\n let elem = elems[i];\n if (isNullish(elem)) { continue; }\n\n // Set x,y vals on elements that don't have them\n if ((attr === 'x' || attr === 'y') && noXYElems.includes(elem.tagName)) {\n const bbox = getStrokedBBoxDefaultVisible([elem]);\n const diffX = attr === 'x' ? newValue - bbox.x : 0;\n const diffY = attr === 'y' ? newValue - bbox.y : 0;\n canvas.moveSelectedElements(diffX * currentZoom, diffY * currentZoom, true);\n continue;\n }\n\n // only allow the transform/opacity/filter attribute to change on <g> elements, slightly hacky\n // TODO: Missing statement body\n // if (elem.tagName === 'g' && goodGAttrs.includes(attr)) {}\n let oldval = attr === '#text' ? elem.textContent : elem.getAttribute(attr);\n if (isNullish(oldval)) { oldval = ''; }\n if (oldval !== String(newValue)) {\n if (attr === '#text') {\n // const oldW = utilsGetBBox(elem).width;\n elem.textContent = newValue;\n\n // FF bug occurs on on rotated elements\n if ((/rotate/).test(elem.getAttribute('transform'))) {\n elem = ffClone(elem);\n }\n // Hoped to solve the issue of moving text with text-anchor=\"start\",\n // but this doesn't actually fix it. Hopefully on the right track, though. -Fyrd\n // const box = getBBox(elem), left = box.x, top = box.y, {width, height} = box,\n // dx = width - oldW, dy = 0;\n // const angle = getRotationAngle(elem, true);\n // if (angle) {\n // const r = Math.sqrt(dx * dx + dy * dy);\n // const theta = Math.atan2(dy, dx) - angle;\n // dx = r * Math.cos(theta);\n // dy = r * Math.sin(theta);\n //\n // elem.setAttribute('x', elem.getAttribute('x') - dx);\n // elem.setAttribute('y', elem.getAttribute('y') - dy);\n // }\n } else if (attr === '#href') {\n setHref(elem, newValue);\n } else { elem.setAttribute(attr, newValue); }\n\n // Go into \"select\" mode for text changes\n // NOTE: Important that this happens AFTER elem.setAttribute() or else attributes like\n // font-size can get reset to their old value, ultimately by svgEditor.updateContextPanel(),\n // after calling textActions.toSelectMode() below\n if (currentMode === 'textedit' && attr !== '#text' && elem.textContent.length) {\n textActions.toSelectMode(elem);\n }\n\n // if (i === 0) {\n // selectedBBoxes[0] = utilsGetBBox(elem);\n // }\n\n // Use the Firefox ffClone hack for text elements with gradients or\n // where other text attributes are changed.\n if (isGecko() && elem.nodeName === 'text' && (/rotate/).test(elem.getAttribute('transform'))) {\n if (String(newValue).startsWith('url') || (['font-size', 'font-family', 'x', 'y'].includes(attr) && elem.textContent)) {\n elem = ffClone(elem);\n }\n }\n // Timeout needed for Opera & Firefox\n // codedread: it is now possible for this function to be called with elements\n // that are not in the selectedElements array, we need to only request a\n // selector if the element is in that array\n if (selectedElements.includes(elem)) {\n setTimeout(function () {\n // Due to element replacement, this element may no longer\n // be part of the DOM\n if (!elem.parentNode) { return; }\n selectorManager.requestSelector(elem).resize();\n }, 0);\n }\n // if this element was rotated, and we changed the position of this element\n // we need to update the rotational transform attribute\n const angle = getRotationAngle(elem);\n if (angle !== 0 && attr !== 'transform') {\n const tlist = getTransformList(elem);\n let n = tlist.numberOfItems;\n while (n--) {\n const xform = tlist.getItem(n);\n if (xform.type === 4) {\n // remove old rotate\n tlist.removeItem(n);\n\n const box = utilsGetBBox(elem);\n const center = transformPoint(box.x + box.width / 2, box.y + box.height / 2, transformListToTransform(tlist).matrix);\n const cx = center.x,\n cy = center.y;\n const newrot = svgroot.createSVGTransform();\n newrot.setRotate(angle, cx, cy);\n tlist.insertItemBefore(newrot, n);\n break;\n }\n }\n }\n } // if oldValue != newValue\n } // for each elem\n};\n\n/**\n* Change the given/selected element and add the original value to the history stack.\n* If you want to change all `selectedElements`, ignore the `elems` argument.\n* If you want to change only a subset of `selectedElements`, then send the\n* subset to this function in the `elems` argument.\n* @function module:svgcanvas.SvgCanvas#changeSelectedAttribute\n* @param {string} attr - String with the attribute name\n* @param {string|Float} val - String or number with the new attribute value\n* @param {Element[]} elems - The DOM elements to apply the change to\n* @returns {void}\n*/\nconst changeSelectedAttribute = this.changeSelectedAttribute = function (attr, val, elems) {\n elems = elems || selectedElements;\n canvas.undoMgr.beginUndoableChange(attr, elems);\n // const i = elems.length;\n\n changeSelectedAttributeNoUndo(attr, val, elems);\n\n const batchCmd = canvas.undoMgr.finishUndoableChange();\n if (!batchCmd.isEmpty()) {\n addCommandToHistory(batchCmd);\n }\n};\n\n/**\n* Removes all selected elements from the DOM and adds the change to the\n* history stack.\n* @function module:svgcanvas.SvgCanvas#deleteSelectedElements\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.deleteSelectedElements = function () {\n const batchCmd = new BatchCommand('Delete Elements');\n const len = selectedElements.length;\n const selectedCopy = []; // selectedElements is being deleted\n\n for (let i = 0; i < len; ++i) {\n const selected = selectedElements[i];\n if (isNullish(selected)) { break; }\n\n let parent = selected.parentNode;\n let t = selected;\n\n // this will unselect the element and remove the selectedOutline\n selectorManager.releaseSelector(t);\n\n // Remove the path if present.\n pathModule.removePath_(t.id);\n\n // Get the parent if it's a single-child anchor\n if (parent.tagName === 'a' && parent.childNodes.length === 1) {\n t = parent;\n parent = parent.parentNode;\n }\n\n const {nextSibling} = t;\n const elem = parent.removeChild(t);\n selectedCopy.push(selected); // for the copy\n batchCmd.addSubCommand(new RemoveElementCommand(elem, nextSibling, parent));\n }\n selectedElements = [];\n\n if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); }\n call('changed', selectedCopy);\n clearSelection();\n};\n\n/**\n* Removes all selected elements from the DOM and adds the change to the\n* history stack. Remembers removed elements on the clipboard.\n* @function module:svgcanvas.SvgCanvas#cutSelectedElements\n* @returns {void}\n*/\nthis.cutSelectedElements = function () {\n canvas.copySelectedElements();\n canvas.deleteSelectedElements();\n};\n\nconst CLIPBOARD_ID = 'svgedit_clipboard';\n\n/**\n* Flash the clipboard data momentarily on localStorage so all tabs can see.\n* @returns {void}\n*/\nfunction flashStorage () {\n const data = sessionStorage.getItem(CLIPBOARD_ID);\n localStorage.setItem(CLIPBOARD_ID, data);\n setTimeout(function () {\n localStorage.removeItem(CLIPBOARD_ID);\n }, 1);\n}\n\n/**\n* Transfers sessionStorage from one tab to another.\n* @param {!Event} ev Storage event.\n* @returns {void}\n*/\nfunction storageChange (ev) {\n if (!ev.newValue) return; // This is a call from removeItem.\n if (ev.key === CLIPBOARD_ID + '_startup') {\n // Another tab asked for our sessionStorage.\n localStorage.removeItem(CLIPBOARD_ID + '_startup');\n flashStorage();\n } else if (ev.key === CLIPBOARD_ID) {\n // Another tab sent data.\n sessionStorage.setItem(CLIPBOARD_ID, ev.newValue);\n }\n}\n\n// Listen for changes to localStorage.\nwindow.addEventListener('storage', storageChange, false);\n// Ask other tabs for sessionStorage (this is ONLY to trigger event).\nlocalStorage.setItem(CLIPBOARD_ID + '_startup', Math.random());\n\n/**\n* Remembers the current selected elements on the clipboard.\n* @function module:svgcanvas.SvgCanvas#copySelectedElements\n* @returns {void}\n*/\nthis.copySelectedElements = function () {\n const data =\n JSON.stringify(selectedElements.map((x) => getJsonFromSvgElement(x)));\n // Use sessionStorage for the clipboard data.\n sessionStorage.setItem(CLIPBOARD_ID, data);\n flashStorage();\n\n const menu = $('#cmenu_canvas');\n // Context menu might not exist (it is provided by editor.js).\n if (menu.enableContextMenuItems) {\n menu.enableContextMenuItems('#paste,#paste_in_place');\n }\n};\n\n/**\n* @function module:svgcanvas.SvgCanvas#pasteElements\n* @param {\"in_place\"|\"point\"|void} type\n* @param {Integer|void} x Expected if type is \"point\"\n* @param {Integer|void} y Expected if type is \"point\"\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @fires module:svgcanvas.SvgCanvas#event:ext_IDsUpdated\n* @returns {void}\n*/\nthis.pasteElements = function (type, x, y) {\n let clipb = JSON.parse(sessionStorage.getItem(CLIPBOARD_ID));\n if (!clipb) return;\n let len = clipb.length;\n if (!len) return;\n\n const pasted = [];\n const batchCmd = new BatchCommand('Paste elements');\n // const drawing = getCurrentDrawing();\n /**\n * @typedef {PlainObject<string, string>} module:svgcanvas.ChangedIDs\n */\n /**\n * @type {module:svgcanvas.ChangedIDs}\n */\n const changedIDs = {};\n\n // Recursively replace IDs and record the changes\n /**\n *\n * @param {module:svgcanvas.SVGAsJSON} elem\n * @returns {void}\n */\n function checkIDs (elem) {\n if (elem.attr && elem.attr.id) {\n changedIDs[elem.attr.id] = getNextId();\n elem.attr.id = changedIDs[elem.attr.id];\n }\n if (elem.children) elem.children.forEach(checkIDs);\n }\n clipb.forEach(checkIDs);\n\n // Give extensions like the connector extension a chance to reflect new IDs and remove invalid elements\n /**\n * Triggered when `pasteElements` is called from a paste action (context menu or key).\n * @event module:svgcanvas.SvgCanvas#event:ext_IDsUpdated\n * @type {PlainObject}\n * @property {module:svgcanvas.SVGAsJSON[]} elems\n * @property {module:svgcanvas.ChangedIDs} changes Maps past ID (on attribute) to current ID\n */\n runExtensions(\n 'IDsUpdated',\n /** @type {module:svgcanvas.SvgCanvas#event:ext_IDsUpdated} */\n {elems: clipb, changes: changedIDs},\n true\n ).forEach(function (extChanges) {\n if (!extChanges || !('remove' in extChanges)) return;\n\n extChanges.remove.forEach(function (removeID) {\n clipb = clipb.filter(function (clipBoardItem) {\n return clipBoardItem.attr.id !== removeID;\n });\n });\n });\n\n // Move elements to lastClickPoint\n while (len--) {\n const elem = clipb[len];\n if (!elem) { continue; }\n\n const copy = addSVGElementFromJson(elem);\n pasted.push(copy);\n batchCmd.addSubCommand(new InsertElementCommand(copy));\n\n restoreRefElems(copy);\n }\n\n selectOnly(pasted);\n\n if (type !== 'in_place') {\n let ctrX, ctrY;\n\n if (!type) {\n ctrX = lastClickPoint.x;\n ctrY = lastClickPoint.y;\n } else if (type === 'point') {\n ctrX = x;\n ctrY = y;\n }\n\n const bbox = getStrokedBBoxDefaultVisible(pasted);\n const cx = ctrX - (bbox.x + bbox.width / 2),\n cy = ctrY - (bbox.y + bbox.height / 2),\n dx = [],\n dy = [];\n\n $.each(pasted, function (i, item) {\n dx.push(cx);\n dy.push(cy);\n });\n\n const cmd = canvas.moveSelectedElements(dx, dy, false);\n if (cmd) batchCmd.addSubCommand(cmd);\n }\n\n addCommandToHistory(batchCmd);\n call('changed', pasted);\n};\n\n/**\n* Wraps all the selected elements in a group (`g`) element.\n* @function module:svgcanvas.SvgCanvas#groupSelectedElements\n* @param {\"a\"|\"g\"} [type=\"g\"] - type of element to group into, defaults to `<g>`\n* @param {string} [urlArg]\n* @returns {void}\n*/\nthis.groupSelectedElements = function (type, urlArg) {\n if (!type) { type = 'g'; }\n let cmdStr = '';\n let url;\n\n switch (type) {\n case 'a': {\n cmdStr = 'Make hyperlink';\n url = urlArg || '';\n break;\n } default: {\n type = 'g';\n cmdStr = 'Group Elements';\n break;\n }\n }\n\n const batchCmd = new BatchCommand(cmdStr);\n\n // create and insert the group element\n const g = addSVGElementFromJson({\n element: type,\n attr: {\n id: getNextId()\n }\n });\n if (type === 'a') {\n setHref(g, url);\n }\n batchCmd.addSubCommand(new InsertElementCommand(g));\n\n // now move all children into the group\n let i = selectedElements.length;\n while (i--) {\n let elem = selectedElements[i];\n if (isNullish(elem)) { continue; }\n\n if (elem.parentNode.tagName === 'a' && elem.parentNode.childNodes.length === 1) {\n elem = elem.parentNode;\n }\n\n const oldNextSibling = elem.nextSibling;\n const oldParent = elem.parentNode;\n g.append(elem);\n batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent));\n }\n if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); }\n\n // update selection\n selectOnly([g], true);\n};\n\n/**\n* Pushes all appropriate parent group properties down to its children, then\n* removes them from the group.\n* @function module:svgcanvas.SvgCanvas#pushGroupProperties\n* @param {SVGAElement|SVGGElement} g\n* @param {boolean} undoable\n* @returns {BatchCommand|void}\n*/\nconst pushGroupProperties = this.pushGroupProperties = function (g, undoable) {\n const children = g.childNodes;\n const len = children.length;\n const xform = g.getAttribute('transform');\n\n const glist = getTransformList(g);\n const m = transformListToTransform(glist).matrix;\n\n const batchCmd = new BatchCommand('Push group properties');\n\n // TODO: get all fill/stroke properties from the group that we are about to destroy\n // \"fill\", \"fill-opacity\", \"fill-rule\", \"stroke\", \"stroke-dasharray\", \"stroke-dashoffset\",\n // \"stroke-linecap\", \"stroke-linejoin\", \"stroke-miterlimit\", \"stroke-opacity\",\n // \"stroke-width\"\n // and then for each child, if they do not have the attribute (or the value is 'inherit')\n // then set the child's attribute\n\n const gangle = getRotationAngle(g);\n\n const gattrs = $(g).attr(['filter', 'opacity']);\n let gfilter, gblur, changes;\n const drawing = getCurrentDrawing();\n\n for (let i = 0; i < len; i++) {\n const elem = children[i];\n\n if (elem.nodeType !== 1) { continue; }\n\n if (gattrs.opacity !== null && gattrs.opacity !== 1) {\n // const c_opac = elem.getAttribute('opacity') || 1;\n const newOpac = Math.round((elem.getAttribute('opacity') || 1) * gattrs.opacity * 100) / 100;\n changeSelectedAttribute('opacity', newOpac, [elem]);\n }\n\n if (gattrs.filter) {\n let cblur = this.getBlur(elem);\n const origCblur = cblur;\n if (!gblur) { gblur = this.getBlur(g); }\n if (cblur) {\n // Is this formula correct?\n cblur = Number(gblur) + Number(cblur);\n } else if (cblur === 0) {\n cblur = gblur;\n }\n\n // If child has no current filter, get group's filter or clone it.\n if (!origCblur) {\n // Set group's filter to use first child's ID\n if (!gfilter) {\n gfilter = getRefElem(gattrs.filter);\n } else {\n // Clone the group's filter\n gfilter = drawing.copyElem(gfilter);\n findDefs().append(gfilter);\n }\n } else {\n gfilter = getRefElem(elem.getAttribute('filter'));\n }\n\n // Change this in future for different filters\n const suffix = (gfilter.firstChild.tagName === 'feGaussianBlur') ? 'blur' : 'filter';\n gfilter.id = elem.id + '_' + suffix;\n changeSelectedAttribute('filter', 'url(#' + gfilter.id + ')', [elem]);\n\n // Update blur value\n if (cblur) {\n changeSelectedAttribute('stdDeviation', cblur, [gfilter.firstChild]);\n canvas.setBlurOffsets(gfilter, cblur);\n }\n }\n\n let chtlist = getTransformList(elem);\n\n // Don't process gradient transforms\n if (elem.tagName.includes('Gradient')) { chtlist = null; }\n\n // Hopefully not a problem to add this. Necessary for elements like <desc/>\n if (!chtlist) { continue; }\n\n // Apparently <defs> can get get a transformlist, but we don't want it to have one!\n if (elem.tagName === 'defs') { continue; }\n\n if (glist.numberOfItems) {\n // TODO: if the group's transform is just a rotate, we can always transfer the\n // rotate() down to the children (collapsing consecutive rotates and factoring\n // out any translates)\n if (gangle && glist.numberOfItems === 1) {\n // [Rg] [Rc] [Mc]\n // we want [Tr] [Rc2] [Mc] where:\n // - [Rc2] is at the child's current center but has the\n // sum of the group and child's rotation angles\n // - [Tr] is the equivalent translation that this child\n // undergoes if the group wasn't there\n\n // [Tr] = [Rg] [Rc] [Rc2_inv]\n\n // get group's rotation matrix (Rg)\n const rgm = glist.getItem(0).matrix;\n\n // get child's rotation matrix (Rc)\n let rcm = svgroot.createSVGMatrix();\n const cangle = getRotationAngle(elem);\n if (cangle) {\n rcm = chtlist.getItem(0).matrix;\n }\n\n // get child's old center of rotation\n const cbox = utilsGetBBox(elem);\n const ceqm = transformListToTransform(chtlist).matrix;\n const coldc = transformPoint(cbox.x + cbox.width / 2, cbox.y + cbox.height / 2, ceqm);\n\n // sum group and child's angles\n const sangle = gangle + cangle;\n\n // get child's rotation at the old center (Rc2_inv)\n const r2 = svgroot.createSVGTransform();\n r2.setRotate(sangle, coldc.x, coldc.y);\n\n // calculate equivalent translate\n const trm = matrixMultiply(rgm, rcm, r2.matrix.inverse());\n\n // set up tlist\n if (cangle) {\n chtlist.removeItem(0);\n }\n\n if (sangle) {\n if (chtlist.numberOfItems) {\n chtlist.insertItemBefore(r2, 0);\n } else {\n chtlist.appendItem(r2);\n }\n }\n\n if (trm.e || trm.f) {\n const tr = svgroot.createSVGTransform();\n tr.setTranslate(trm.e, trm.f);\n if (chtlist.numberOfItems) {\n chtlist.insertItemBefore(tr, 0);\n } else {\n chtlist.appendItem(tr);\n }\n }\n } else { // more complicated than just a rotate\n // transfer the group's transform down to each child and then\n // call recalculateDimensions()\n const oldxform = elem.getAttribute('transform');\n changes = {};\n changes.transform = oldxform || '';\n\n const newxform = svgroot.createSVGTransform();\n\n // [ gm ] [ chm ] = [ chm ] [ gm' ]\n // [ gm' ] = [ chmInv ] [ gm ] [ chm ]\n const chm = transformListToTransform(chtlist).matrix,\n chmInv = chm.inverse();\n const gm = matrixMultiply(chmInv, m, chm);\n newxform.setMatrix(gm);\n chtlist.appendItem(newxform);\n }\n const cmd = recalculateDimensions(elem);\n if (cmd) { batchCmd.addSubCommand(cmd); }\n }\n }\n\n // remove transform and make it undo-able\n if (xform) {\n changes = {};\n changes.transform = xform;\n g.setAttribute('transform', '');\n g.removeAttribute('transform');\n batchCmd.addSubCommand(new ChangeElementCommand(g, changes));\n }\n\n if (undoable && !batchCmd.isEmpty()) {\n return batchCmd;\n }\n return undefined;\n};\n\n/**\n* Unwraps all the elements in a selected group (`g`) element. This requires\n* significant recalculations to apply group's transforms, etc. to its children.\n* @function module:svgcanvas.SvgCanvas#ungroupSelectedElement\n* @returns {void}\n*/\nthis.ungroupSelectedElement = function () {\n let g = selectedElements[0];\n if (!g) {\n return;\n }\n if ($(g).data('gsvg') || $(g).data('symbol')) {\n // Is svg, so actually convert to group\n convertToGroup(g);\n return;\n }\n if (g.tagName === 'use') {\n // Somehow doesn't have data set, so retrieve\n const symbol = getElem(getHref(g).substr(1));\n $(g).data('symbol', symbol).data('ref', symbol);\n convertToGroup(g);\n return;\n }\n const parentsA = $(g).parents('a');\n if (parentsA.length) {\n g = parentsA[0];\n }\n\n // Look for parent \"a\"\n if (g.tagName === 'g' || g.tagName === 'a') {\n const batchCmd = new BatchCommand('Ungroup Elements');\n const cmd = pushGroupProperties(g, true);\n if (cmd) { batchCmd.addSubCommand(cmd); }\n\n const parent = g.parentNode;\n const anchor = g.nextSibling;\n const children = new Array(g.childNodes.length);\n\n let i = 0;\n while (g.firstChild) {\n let elem = g.firstChild;\n const oldNextSibling = elem.nextSibling;\n const oldParent = elem.parentNode;\n\n // Remove child title elements\n if (elem.tagName === 'title') {\n const {nextSibling} = elem;\n batchCmd.addSubCommand(new RemoveElementCommand(elem, nextSibling, oldParent));\n elem.remove();\n continue;\n }\n\n children[i++] = elem = anchor.before(elem);\n batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent));\n }\n\n // remove the group from the selection\n clearSelection();\n\n // delete the group element (but make undo-able)\n const gNextSibling = g.nextSibling;\n g = parent.removeChild(g);\n batchCmd.addSubCommand(new RemoveElementCommand(g, gNextSibling, parent));\n\n if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); }\n\n // update selection\n addToSelection(children);\n }\n};\n\n/**\n* Repositions the selected element to the bottom in the DOM to appear on top of\n* other elements.\n* @function module:svgcanvas.SvgCanvas#moveToTopSelectedElement\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.moveToTopSelectedElement = function () {\n const [selected] = selectedElements;\n if (!isNullish(selected)) {\n let t = selected;\n const oldParent = t.parentNode;\n const oldNextSibling = t.nextSibling;\n t = t.parentNode.appendChild(t);\n // If the element actually moved position, add the command and fire the changed\n // event handler.\n if (oldNextSibling !== t.nextSibling) {\n addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'top'));\n call('changed', [t]);\n }\n }\n};\n\n/**\n* Repositions the selected element to the top in the DOM to appear under\n* other elements.\n* @function module:svgcanvas.SvgCanvas#moveToBottomSelectedElement\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.moveToBottomSelectedElement = function () {\n const [selected] = selectedElements;\n if (!isNullish(selected)) {\n let t = selected;\n const oldParent = t.parentNode;\n const oldNextSibling = t.nextSibling;\n let {firstChild} = t.parentNode;\n if (firstChild.tagName === 'title') {\n firstChild = firstChild.nextSibling;\n }\n // This can probably be removed, as the defs should not ever apppear\n // inside a layer group\n if (firstChild.tagName === 'defs') {\n firstChild = firstChild.nextSibling;\n }\n t = t.parentNode.insertBefore(t, firstChild);\n // If the element actually moved position, add the command and fire the changed\n // event handler.\n if (oldNextSibling !== t.nextSibling) {\n addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'bottom'));\n call('changed', [t]);\n }\n }\n};\n\n/**\n* Moves the select element up or down the stack, based on the visibly\n* intersecting elements.\n* @function module:svgcanvas.SvgCanvas#moveUpDownSelected\n* @param {\"Up\"|\"Down\"} dir - String that's either 'Up' or 'Down'\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {void}\n*/\nthis.moveUpDownSelected = function (dir) {\n const selected = selectedElements[0];\n if (!selected) { return; }\n\n curBBoxes = [];\n let closest, foundCur;\n // jQuery sorts this list\n const list = $(getIntersectionList(getStrokedBBoxDefaultVisible([selected]))).toArray();\n if (dir === 'Down') { list.reverse(); }\n\n $.each(list, function () {\n if (!foundCur) {\n if (this === selected) {\n foundCur = true;\n }\n return true;\n }\n closest = this; // eslint-disable-line consistent-this\n return false;\n });\n if (!closest) { return; }\n\n const t = selected;\n const oldParent = t.parentNode;\n const oldNextSibling = t.nextSibling;\n $(closest)[dir === 'Down' ? 'before' : 'after'](t);\n // If the element actually moved position, add the command and fire the changed\n // event handler.\n if (oldNextSibling !== t.nextSibling) {\n addCommandToHistory(new MoveElementCommand(t, oldNextSibling, oldParent, 'Move ' + dir));\n call('changed', [t]);\n }\n};\n\n/**\n* Moves selected elements on the X/Y axis.\n* @function module:svgcanvas.SvgCanvas#moveSelectedElements\n* @param {Float} dx - Float with the distance to move on the x-axis\n* @param {Float} dy - Float with the distance to move on the y-axis\n* @param {boolean} undoable - Boolean indicating whether or not the action should be undoable\n* @fires module:svgcanvas.SvgCanvas#event:changed\n* @returns {BatchCommand|void} Batch command for the move\n*/\nthis.moveSelectedElements = function (dx, dy, undoable) {\n // if undoable is not sent, default to true\n // if single values, scale them to the zoom\n if (dx.constructor !== Array) {\n dx /= currentZoom;\n dy /= currentZoom;\n }\n undoable = undoable || true;\n const batchCmd = new BatchCommand('position');\n let i = selectedElements.length;\n while (i--) {\n const selected = selectedElements[i];\n if (!isNullish(selected)) {\n // if (i === 0) {\n // selectedBBoxes[0] = utilsGetBBox(selected);\n // }\n // const b = {};\n // for (const j in selectedBBoxes[i]) b[j] = selectedBBoxes[i][j];\n // selectedBBoxes[i] = b;\n\n const xform = svgroot.createSVGTransform();\n const tlist = getTransformList(selected);\n\n // dx and dy could be arrays\n if (dx.constructor === Array) {\n // if (i === 0) {\n // selectedBBoxes[0].x += dx[0];\n // selectedBBoxes[0].y += dy[0];\n // }\n xform.setTranslate(dx[i], dy[i]);\n } else {\n // if (i === 0) {\n // selectedBBoxes[0].x += dx;\n // selectedBBoxes[0].y += dy;\n // }\n xform.setTranslate(dx, dy);\n }\n\n if (tlist.numberOfItems) {\n tlist.insertItemBefore(xform, 0);\n } else {\n tlist.appendItem(xform);\n }\n\n const cmd = recalculateDimensions(selected);\n if (cmd) {\n batchCmd.addSubCommand(cmd);\n }\n\n selectorManager.requestSelector(selected).resize();\n }\n }\n if (!batchCmd.isEmpty()) {\n if (undoable) {\n addCommandToHistory(batchCmd);\n }\n call('changed', selectedElements);\n return batchCmd;\n }\n return undefined;\n};\n\n/**\n* Create deep DOM copies (clones) of all selected elements and move them slightly\n* from their originals.\n* @function module:svgcanvas.SvgCanvas#cloneSelectedElements\n* @param {Float} x Float with the distance to move on the x-axis\n* @param {Float} y Float with the distance to move on the y-axis\n* @returns {void}\n*/\nthis.cloneSelectedElements = function (x, y) {\n let i, elem;\n const batchCmd = new BatchCommand('Clone Elements');\n // find all the elements selected (stop at first null)\n const len = selectedElements.length;\n /**\n * Sorts an array numerically and ascending.\n * @param {Element} a\n * @param {Element} b\n * @returns {Integer}\n */\n function sortfunction (a, b) {\n return ($(b).index() - $(a).index());\n }\n selectedElements.sort(sortfunction);\n for (i = 0; i < len; ++i) {\n elem = selectedElements[i];\n if (isNullish(elem)) { break; }\n }\n // use slice to quickly get the subset of elements we need\n const copiedElements = selectedElements.slice(0, i);\n this.clearSelection(true);\n // note that we loop in the reverse way because of the way elements are added\n // to the selectedElements array (top-first)\n const drawing = getCurrentDrawing();\n i = copiedElements.length;\n while (i--) {\n // clone each element and replace it within copiedElements\n elem = copiedElements[i] = drawing.copyElem(copiedElements[i]);\n (currentGroup || drawing.getCurrentLayer()).append(elem);\n batchCmd.addSubCommand(new InsertElementCommand(elem));\n }\n\n if (!batchCmd.isEmpty()) {\n addToSelection(copiedElements.reverse()); // Need to reverse for correct selection-adding\n this.moveSelectedElements(x, y, false);\n addCommandToHistory(batchCmd);\n }\n};\n\n/**\n* Aligns selected elements.\n* @function module:svgcanvas.SvgCanvas#alignSelectedElements\n* @param {string} type - String with single character indicating the alignment type\n* @param {\"selected\"|\"largest\"|\"smallest\"|\"page\"} relativeTo\n* @returns {void}\n*/\nthis.alignSelectedElements = function (type, relativeTo) {\n const bboxes = []; // angles = [];\n const len = selectedElements.length;\n if (!len) { return; }\n let minx = Number.MAX_VALUE, maxx = Number.MIN_VALUE,\n miny = Number.MAX_VALUE, maxy = Number.MIN_VALUE;\n let curwidth = Number.MIN_VALUE, curheight = Number.MIN_VALUE;\n for (let i = 0; i < len; ++i) {\n if (isNullish(selectedElements[i])) { break; }\n const elem = selectedElements[i];\n bboxes[i] = getStrokedBBoxDefaultVisible([elem]);\n\n // now bbox is axis-aligned and handles rotation\n switch (relativeTo) {\n case 'smallest':\n if (((type === 'l' || type === 'c' || type === 'r') &&\n (curwidth === Number.MIN_VALUE || curwidth > bboxes[i].width)) ||\n ((type === 't' || type === 'm' || type === 'b') &&\n (curheight === Number.MIN_VALUE || curheight > bboxes[i].height))\n ) {\n minx = bboxes[i].x;\n miny = bboxes[i].y;\n maxx = bboxes[i].x + bboxes[i].width;\n maxy = bboxes[i].y + bboxes[i].height;\n curwidth = bboxes[i].width;\n curheight = bboxes[i].height;\n }\n break;\n case 'largest':\n if (((type === 'l' || type === 'c' || type === 'r') &&\n (curwidth === Number.MIN_VALUE || curwidth < bboxes[i].width)) ||\n ((type === 't' || type === 'm' || type === 'b') &&\n (curheight === Number.MIN_VALUE || curheight < bboxes[i].height))\n ) {\n minx = bboxes[i].x;\n miny = bboxes[i].y;\n maxx = bboxes[i].x + bboxes[i].width;\n maxy = bboxes[i].y + bboxes[i].height;\n curwidth = bboxes[i].width;\n curheight = bboxes[i].height;\n }\n break;\n default: // 'selected'\n if (bboxes[i].x < minx) { minx = bboxes[i].x; }\n if (bboxes[i].y < miny) { miny = bboxes[i].y; }\n if (bboxes[i].x + bboxes[i].width > maxx) { maxx = bboxes[i].x + bboxes[i].width; }\n if (bboxes[i].y + bboxes[i].height > maxy) { maxy = bboxes[i].y + bboxes[i].height; }\n break;\n }\n } // loop for each element to find the bbox and adjust min/max\n\n if (relativeTo === 'page') {\n minx = 0;\n miny = 0;\n maxx = canvas.contentW;\n maxy = canvas.contentH;\n }\n\n const dx = new Array(len);\n const dy = new Array(len);\n for (let i = 0; i < len; ++i) {\n if (isNullish(selectedElements[i])) { break; }\n // const elem = selectedElements[i];\n const bbox = bboxes[i];\n dx[i] = 0;\n dy[i] = 0;\n switch (type) {\n case 'l': // left (horizontal)\n dx[i] = minx - bbox.x;\n break;\n case 'c': // center (horizontal)\n dx[i] = (minx + maxx) / 2 - (bbox.x + bbox.width / 2);\n break;\n case 'r': // right (horizontal)\n dx[i] = maxx - (bbox.x + bbox.width);\n break;\n case 't': // top (vertical)\n dy[i] = miny - bbox.y;\n break;\n case 'm': // middle (vertical)\n dy[i] = (miny + maxy) / 2 - (bbox.y + bbox.height / 2);\n break;\n case 'b': // bottom (vertical)\n dy[i] = maxy - (bbox.y + bbox.height);\n break;\n }\n }\n this.moveSelectedElements(dx, dy);\n};\n\n/**\n* Group: Additional editor tools.\n*/\n\n/**\n* @name module:svgcanvas.SvgCanvas#contentW\n* @type {Float}\n*/\nthis.contentW = getResolution().w;\n/**\n* @name module:svgcanvas.SvgCanvas#contentH\n* @type {Float}\n*/\nthis.contentH = getResolution().h;\n\n/**\n* @typedef {PlainObject} module:svgcanvas.CanvasInfo\n* @property {Float} x - The canvas' new x coordinate\n* @property {Float} y - The canvas' new y coordinate\n* @property {string} oldX - The canvas' old x coordinate\n* @property {string} oldY - The canvas' old y coordinate\n* @property {Float} d_x - The x position difference\n* @property {Float} d_y - The y position difference\n*/\n\n/**\n* Updates the editor canvas width/height/position after a zoom has occurred.\n* @function module:svgcanvas.SvgCanvas#updateCanvas\n* @param {Float} w - Float with the new width\n* @param {Float} h - Float with the new height\n* @fires module:svgcanvas.SvgCanvas#event:ext_canvasUpdated\n* @returns {module:svgcanvas.CanvasInfo}\n*/\nthis.updateCanvas = function (w, h) {\n svgroot.setAttribute('width', w);\n svgroot.setAttribute('height', h);\n const bg = $('#canvasBackground')[0];\n const oldX = svgcontent.getAttribute('x');\n const oldY = svgcontent.getAttribute('y');\n const x = ((w - this.contentW * currentZoom) / 2);\n const y = ((h - this.contentH * currentZoom) / 2);\n\n assignAttributes(svgcontent, {\n width: this.contentW * currentZoom,\n height: this.contentH * currentZoom,\n x,\n y,\n viewBox: '0 0 ' + this.contentW + ' ' + this.contentH\n });\n\n assignAttributes(bg, {\n width: svgcontent.getAttribute('width'),\n height: svgcontent.getAttribute('height'),\n x,\n y\n });\n\n const bgImg = getElem('background_image');\n if (bgImg) {\n assignAttributes(bgImg, {\n width: '100%',\n height: '100%'\n });\n }\n\n selectorManager.selectorParentGroup.setAttribute('transform', 'translate(' + x + ',' + y + ')');\n\n /**\n * Invoked upon updates to the canvas.\n * @event module:svgcanvas.SvgCanvas#event:ext_canvasUpdated\n * @type {PlainObject}\n * @property {Integer} new_x\n * @property {Integer} new_y\n * @property {string} old_x (Of Integer)\n * @property {string} old_y (Of Integer)\n * @property {Integer} d_x\n * @property {Integer} d_y\n */\n runExtensions(\n 'canvasUpdated',\n /**\n * @type {module:svgcanvas.SvgCanvas#event:ext_canvasUpdated}\n */\n {new_x: x, new_y: y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY}\n );\n return {x, y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY};\n};\n\n/**\n* Set the background of the editor (NOT the actual document).\n* @function module:svgcanvas.SvgCanvas#setBackground\n* @param {string} color - String with fill color to apply\n* @param {string} url - URL or path to image to use\n* @returns {void}\n*/\nthis.setBackground = function (color, url) {\n const bg = getElem('canvasBackground');\n const border = $(bg).find('rect')[0];\n let bgImg = getElem('background_image');\n let bgPattern = getElem('background_pattern');\n border.setAttribute('fill', color === 'chessboard' ? '#fff' : color);\n if (color === 'chessboard') {\n if (!bgPattern) {\n bgPattern = svgdoc.createElementNS(NS.SVG, 'foreignObject');\n assignAttributes(bgPattern, {\n id: 'background_pattern',\n width: '100%',\n height: '100%',\n preserveAspectRatio: 'xMinYMin',\n style: 'pointer-events:none'\n });\n const div = document.createElement('div');\n assignAttributes(div, {\n style: 'pointer-events:none;width:100%;height:100%;background-image:url(data:image/gif;base64,R0lGODlhEAAQAIAAAP///9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG+gq4jM3IFLJgpswNly/XkcBpIiVaInlLJr9FZWAQA7);'\n });\n bgPattern.appendChild(div);\n bg.append(bgPattern);\n }\n } else if (bgPattern) {\n bgPattern.remove();\n }\n if (url) {\n if (!bgImg) {\n bgImg = svgdoc.createElementNS(NS.SVG, 'image');\n assignAttributes(bgImg, {\n id: 'background_image',\n width: '100%',\n height: '100%',\n preserveAspectRatio: 'xMinYMin',\n style: 'pointer-events:none'\n });\n }\n setHref(bgImg, url);\n bg.append(bgImg);\n } else if (bgImg) {\n bgImg.remove();\n }\n};\n\n/**\n* Select the next/previous element within the current layer.\n* @function module:svgcanvas.SvgCanvas#cycleElement\n* @param {boolean} next - true = next and false = previous element\n* @fires module:svgcanvas.SvgCanvas#event:selected\n* @returns {void}\n*/\nthis.cycleElement = function (next) {\n let num;\n const curElem = selectedElements[0];\n let elem = false;\n const allElems = getVisibleElements(currentGroup || getCurrentDrawing().getCurrentLayer());\n if (!allElems.length) { return; }\n if (isNullish(curElem)) {\n num = next ? allElems.length - 1 : 0;\n elem = allElems[num];\n } else {\n let i = allElems.length;\n while (i--) {\n if (allElems[i] === curElem) {\n num = next ? i - 1 : i + 1;\n if (num >= allElems.length) {\n num = 0;\n } else if (num < 0) {\n num = allElems.length - 1;\n }\n elem = allElems[num];\n break;\n }\n }\n }\n selectOnly([elem], true);\n call('selected', selectedElements);\n};\n\nthis.clear();\n\n/**\n* @interface module:svgcanvas.PrivateMethods\n* @type {PlainObject}\n* @property {module:svgcanvas~addCommandToHistory} addCommandToHistory\n* @property {module:history.HistoryCommand} BatchCommand\n* @property {module:history.HistoryCommand} ChangeElementCommand\n* @property {module:utilities.decode64} decode64\n* @property {module:utilities.dropXMLInternalSubset} dropXMLInternalSubset\n* @property {module:utilities.encode64} encode64\n* @property {module:svgcanvas~ffClone} ffClone\n* @property {module:svgcanvas~findDuplicateGradient} findDuplicateGradient\n* @property {module:utilities.getPathBBox} getPathBBox\n* @property {module:units.getTypeMap} getTypeMap\n* @property {module:draw.identifyLayers} identifyLayers\n* @property {module:history.HistoryCommand} InsertElementCommand\n* @property {module:browser.isChrome} isChrome\n* @property {module:math.isIdentity} isIdentity\n* @property {module:browser.isIE} isIE\n* @property {module:svgcanvas~logMatrix} logMatrix\n* @property {module:history.HistoryCommand} MoveElementCommand\n* @property {module:namespaces.NS} NS\n* @property {module:utilities.preventClickDefault} preventClickDefault\n* @property {module:history.HistoryCommand} RemoveElementCommand\n* @property {module:SVGTransformList.SVGEditTransformList} SVGEditTransformList\n* @property {module:utilities.text2xml} text2xml\n* @property {module:math.transformBox} transformBox\n* @property {module:math.transformPoint} transformPoint\n* @property {module:utilities.walkTree} walkTree\n*/\n/**\n* @deprecated getPrivateMethods\n* Since all methods are/should be public somehow, this function should be removed;\n* we might require `import` in place of this in the future once ES6 Modules\n* widespread\n\n* Being able to access private methods publicly seems wrong somehow,\n* but currently appears to be the best way to allow testing and provide\n* access to them to plugins.\n* @function module:svgcanvas.SvgCanvas#getPrivateMethods\n* @returns {module:svgcanvas.PrivateMethods}\n*/\nthis.getPrivateMethods = function () {\n const obj = {\n addCommandToHistory,\n BatchCommand,\n ChangeElementCommand,\n decode64,\n dropXMLInternalSubset,\n encode64,\n ffClone,\n findDefs,\n findDuplicateGradient,\n getElem,\n getPathBBox,\n getTypeMap,\n getUrlFromAttr,\n identifyLayers: draw.identifyLayers,\n InsertElementCommand,\n isChrome,\n isIdentity,\n isIE,\n logMatrix,\n MoveElementCommand,\n NS,\n preventClickDefault,\n RemoveElementCommand,\n SVGEditTransformList,\n text2xml,\n transformBox,\n transformPoint,\n walkTree\n };\n return obj;\n};\n } // End constructor\n} // End class\n\nexport default SvgCanvas;\n","/**\n * @file SVG Icon Loader 2.0\n *\n * jQuery Plugin for loading SVG icons from a single file\n *\n * Adds {@link external:jQuery.svgIcons}, {@link external:jQuery.getSvgIcon}, {@link external:jQuery.resizeSvgIcons}\n *\n * How to use:\n\n1. Create the SVG master file that includes all icons:\n\nThe master SVG icon-containing file is an SVG file that contains\n`<g>` elements. Each `<g>` element should contain the markup of an SVG\nicon. The `<g>` element has an ID that should\ncorrespond with the ID of the HTML element used on the page that should contain\nor optionally be replaced by the icon. Additionally, one empty element should be\nadded at the end with id \"svg_eof\".\n\n2. Optionally create fallback raster images for each SVG icon.\n\n3. Include the jQuery and the SVG Icon Loader scripts on your page.\n\n4. Run `$.svgIcons()` when the document is ready. See its signature\n\n5. To access an icon at a later point without using the callback, use this:\n `$.getSvgIcon(id (string), uniqueClone (boolean))`;\n\nThis will return the icon (as jQuery object) with a given ID.\n\n6. To resize icons at a later point without using the callback, use this:\n `$.resizeSvgIcons(resizeOptions)` (use the same way as the \"resize\" parameter)\n *\n * @module jQuerySVGIcons\n * @license MIT\n * @copyright (c) 2009 Alexis Deveria\n * {@link http://a.deveria.com}\n * @example\n$(function () {\n $.svgIcons('my_icon_set.svg'); // The SVG file that contains all icons\n // No options have been set, so all icons will automatically be inserted\n // into HTML elements that match the same IDs.\n});\n\n* @example\n$(function () {\n // The SVG file that contains all icons\n $.svgIcons('my_icon_set.svg', {\n callback (icons) { // Custom callback function that sets click\n // events for each icon\n $.each(icons, function (id, icon) {\n icon.click(function () {\n alert('You clicked on the icon with id ' + id);\n });\n });\n }\n });\n});\n\n* @example\n$(function () {\n // The SVGZ file that contains all icons\n $.svgIcons('my_icon_set.svgz', {\n w: 32, // All icons will be 32px wide\n h: 32, // All icons will be 32px high\n fallback_path: 'icons/', // All fallback files can be found here\n fallback: {\n '#open_icon': 'open.png', // The \"open.png\" will be appended to the\n // HTML element with ID \"open_icon\"\n '#close_icon': 'close.png',\n '#save_icon': 'save.png'\n },\n placement: {'.open_icon': 'open'}, // The \"open\" icon will be added\n // to all elements with class \"open_icon\"\n resize: {\n '#save_icon .svg_icon': 64 // The \"save\" icon will be resized to 64 x 64px\n },\n\n callback (icons) { // Sets background color for \"close\" icon\n icons.close.css('background', 'red');\n },\n\n svgz: true // Indicates that an SVGZ file is being used\n });\n});\n*/\n\n// Todo: Move to own module (and have it import a modular base64 encoder)\nimport {encode64} from '../utilities.js';\n\nconst isOpera = Boolean(window.opera);\n\nconst fixIDs = function (svgEl, svgNum, force) {\n const defs = svgEl.find('defs');\n if (!defs.length) return svgEl;\n\n let idElems;\n if (isOpera) {\n idElems = defs.find('*').filter(function () {\n return Boolean(this.id);\n });\n } else {\n idElems = defs.find('[id]');\n }\n\n const allElems = svgEl[0].getElementsByTagName('*'),\n len = allElems.length;\n\n idElems.each(function (i) {\n const {id} = this;\n /*\n const noDupes = ($(svgdoc).find('#' + id).length <= 1);\n if (isOpera) noDupes = false; // Opera didn't clone svgEl, so not reliable\n if(!force && noDupes) return;\n */\n const newId = 'x' + id + svgNum + i;\n this.id = newId;\n\n const oldVal = 'url(#' + id + ')';\n const newVal = 'url(#' + newId + ')';\n\n // Selector method, possibly faster but fails in Opera / jQuery 1.4.3\n // svgEl.find('[fill=\"url(#' + id + ')\"]').each(function() {\n // this.setAttribute('fill', 'url(#' + newId + ')');\n // }).end().find('[stroke=\"url(#' + id + ')\"]').each(function() {\n // this.setAttribute('stroke', 'url(#' + newId + ')');\n // }).end().find('use').each(function() {\n // if(this.getAttribute('xlink:href') == '#' + id) {\n // this.setAttributeNS(xlinkns,'href','#' + newId);\n // }\n // }).end().find('[filter=\"url(#' + id + ')\"]').each(function() {\n // this.setAttribute('filter', 'url(#' + newId + ')');\n // });\n\n for (i = 0; i < len; i++) {\n const elem = allElems[i];\n if (elem.getAttribute('fill') === oldVal) {\n elem.setAttribute('fill', newVal);\n }\n if (elem.getAttribute('stroke') === oldVal) {\n elem.setAttribute('stroke', newVal);\n }\n if (elem.getAttribute('filter') === oldVal) {\n elem.setAttribute('filter', newVal);\n }\n }\n });\n return svgEl;\n};\n\n/**\n* @callback module:jQuerySVGIcons.SVGIconsLoadedCallback\n* @param {PlainObject<string, external:jQuery>} svgIcons IDs keyed to jQuery objects of images\n* @returns {void}\n*/\n\n/**\n * @function module:jQuerySVGIcons.jQuerySVGIcons\n * @param {external:jQuery} $ Its keys include all icon IDs and the values, the icon as a jQuery object\n * @returns {external:jQuery} The enhanced jQuery object\n*/\nexport default function jQueryPluginSVGIcons ($) {\n const svgIcons = {};\n\n /**\n * Map of raster images with each key being the SVG icon ID\n * to replace, and the value the image file name.\n * @typedef {PlainObject<string, string>} external:jQuery.svgIcons.Fallback\n */\n /**\n * Map of raster images with each key being the SVG icon ID\n * whose `alt` will be set, and the value being the `alt` text.\n * @typedef {PlainObject<string, string>} external:jQuery.svgIcons.Alts\n */\n /**\n * @function external:jQuery.svgIcons\n * @param {string} file The location of a local SVG or SVGz file\n * @param {PlainObject} [opts]\n * @param {Float} [opts.w] The icon widths\n * @param {Float} [opts.h] The icon heights\n * @param {external:jQuery.svgIcons.Fallback} [opts.fallback]\n * @param {string} [opts.fallback_path] The path to use for all images\n * listed under \"fallback\"\n * @param {boolean} [opts.replace] If set to `true`, HTML elements will\n * be replaced by, rather than include the SVG icon.\n * @param {PlainObject<string, string>} [opts.placement] Map with selectors\n * for keys and SVG icon ids as values. This provides a custom method of\n * adding icons.\n * @param {PlainObject<string, module:jQuerySVGIcons.Size>} [opts.resize] Map\n * with selectors for keys and numbers as values. This allows an easy way to\n * resize specific icons.\n * @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A\n * function to call when all icons have been loaded.\n * @param {boolean} [opts.id_match=true] Automatically attempt to match\n * SVG icon ids with corresponding HTML id\n * @param {boolean} [opts.no_img] Prevent attempting to convert the icon\n * into an `<img>` element (may be faster, help for browser consistency)\n * @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and\n * thus not to parse as XML. SVGZ files add compression benefits, but\n * getting data from them fails in Firefox 2 and older.\n * @param {jQuery.svgIcons.Alts} [opts.alts] Map of images with each key\n * being the SVG icon ID whose `alt` will be set, and the value being\n * the `alt` text\n * @param {string} [opts.testIconAlt=\"icon\"] Alt text for the injected test image.\n * In case wish to ensure have one for accessibility\n * @returns {void}\n */\n $.svgIcons = function (file, opts = {}) {\n const svgns = 'http://www.w3.org/2000/svg',\n xlinkns = 'http://www.w3.org/1999/xlink',\n iconW = opts.w || 24,\n iconH = opts.h || 24;\n let elems, svgdoc, testImg,\n iconsMade = false,\n dataLoaded = false,\n loadAttempts = 0;\n const // ua = navigator.userAgent,\n // isSafari = (ua.includes('Safari/') && !ua.includes('Chrome/')),\n dataPre = 'data:image/svg+xml;charset=utf-8;base64,';\n\n let dataEl;\n if (opts.svgz) {\n dataEl = $('<object data=\"' + file + '\" type=image/svg+xml>').appendTo('body').hide();\n try {\n svgdoc = dataEl[0].contentDocument;\n dataEl.load(getIcons);\n getIcons(0, true); // Opera will not run \"load\" event if file is already cached\n } catch (err1) {\n useFallback();\n }\n } else {\n const parser = new DOMParser();\n $.ajax({\n url: file,\n dataType: 'string',\n success (data) {\n if (!data) {\n $(useFallback);\n return;\n }\n svgdoc = parser.parseFromString(data, 'text/xml');\n $(function () {\n getIcons('ajax');\n });\n },\n error (err) {\n // TODO: Fix Opera widget icon bug\n if (window.opera) {\n $(function () {\n useFallback();\n });\n } else if (err.responseText) {\n svgdoc = parser.parseFromString(err.responseText, 'text/xml');\n\n if (!svgdoc.childNodes.length) {\n $(useFallback);\n }\n $(function () {\n getIcons('ajax');\n });\n } else {\n $(useFallback);\n }\n }\n });\n }\n\n /**\n *\n * @param {\"ajax\"|0|void} evt\n * @param {boolean} [noWait]\n * @returns {void}\n */\n function getIcons (evt, noWait) {\n if (evt !== 'ajax') {\n if (dataLoaded) return;\n // Webkit sometimes says svgdoc is undefined, other times\n // it fails to load all nodes. Thus we must make sure the \"eof\"\n // element is loaded.\n svgdoc = dataEl[0].contentDocument; // Needed again for Webkit\n const isReady = (svgdoc && svgdoc.getElementById('svg_eof'));\n if (!isReady && !(noWait && isReady)) {\n loadAttempts++;\n if (loadAttempts < 50) {\n setTimeout(getIcons, 20);\n } else {\n useFallback();\n dataLoaded = true;\n }\n return;\n }\n dataLoaded = true;\n }\n\n elems = $(svgdoc.firstChild).children(); // .getElementsByTagName('foreignContent');\n\n if (!opts.no_img) {\n const testSrc = dataPre + 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNzUiIGhlaWdodD0iMjc1Ij48L3N2Zz4%3D';\n\n testImg = $(new Image()).attr({\n src: testSrc,\n width: 0,\n height: 0,\n alt: opts.testIconAlt || 'icon'\n }).appendTo('body')\n .load(function () {\n // Safari 4 crashes, Opera and Chrome don't\n makeIcons(true);\n }).error(function () {\n makeIcons();\n });\n } else {\n setTimeout(function () {\n if (!iconsMade) makeIcons();\n }, 500);\n }\n }\n\n /**\n *\n * @param {external:jQuery} target\n * @param {external:jQuery} icon A wrapped `defs` or Image\n * @param {string} id SVG icon ID\n * @param {boolean} setID Whether to set the ID attribute (with `id`)\n * @returns {void}\n */\n function setIcon (target, icon, id, setID) {\n if (isOpera) icon.css('visibility', 'hidden');\n if (opts.replace) {\n if (setID) icon.attr('id', id);\n const cl = target.attr('class');\n if (cl) icon.attr('class', 'svg_icon ' + cl);\n if (!target.alt) {\n let alt = 'icon';\n if (opts.alts) {\n alt = opts.alts[id] || alt;\n }\n icon.attr('alt', alt);\n }\n target.replaceWith(icon);\n } else {\n target.append(icon);\n }\n if (isOpera) {\n setTimeout(function () {\n icon.removeAttr('style');\n }, 1);\n }\n }\n\n let holder;\n /**\n * @param {external:jQuery} icon A wrapped `defs` or Image\n * @param {string} id SVG icon ID\n * @returns {void}\n */\n function addIcon (icon, id) {\n if (opts.id_match === undefined || opts.id_match !== false) {\n setIcon(holder, icon, id, true);\n }\n svgIcons[id] = icon;\n }\n\n /**\n *\n * @param {boolean} [toImage]\n * @param {external:jQuery.svgIcons.Fallback} [fallback=false]\n * @returns {void}\n */\n function makeIcons (toImage = false, fallback = false) {\n if (iconsMade) return;\n if (opts.no_img) toImage = false;\n\n let tempHolder;\n if (toImage) {\n tempHolder = $(document.createElement('div'));\n tempHolder.hide().appendTo('body');\n }\n if (fallback) {\n const path = opts.fallback_path || '';\n $.each(fallback, function (id, imgsrc) {\n holder = $('#' + id);\n let alt = 'icon';\n if (opts.alts) {\n alt = opts.alts[id] || alt;\n }\n const icon = $(new Image())\n .attr({\n class: 'svg_icon',\n src: path + imgsrc,\n width: iconW,\n height: iconH,\n alt\n });\n\n addIcon(icon, id);\n });\n } else {\n const len = elems.length;\n for (let i = 0; i < len; i++) {\n const elem = elems[i];\n const {id} = elem;\n if (id === 'svg_eof') break;\n holder = $('#' + id);\n const svgroot = document.createElementNS(svgns, 'svg');\n // Per https://www.w3.org/TR/xml-names11/#defaulting, the namespace for\n // attributes should have no value.\n svgroot.setAttribute('viewBox', [0, 0, iconW, iconH].join(' '));\n\n let svg = elem.getElementsByTagNameNS(svgns, 'svg')[0];\n\n // Make flexible by converting width/height to viewBox\n const w = svg.getAttribute('width');\n const h = svg.getAttribute('height');\n svg.removeAttribute('width');\n svg.removeAttribute('height');\n\n const vb = svg.getAttribute('viewBox');\n if (!vb) {\n svg.setAttribute('viewBox', [0, 0, w, h].join(' '));\n }\n\n // Not using jQuery to be a bit faster\n svgroot.setAttribute('xmlns', svgns);\n svgroot.setAttribute('width', iconW);\n svgroot.setAttribute('height', iconH);\n svgroot.setAttribute('xmlns:xlink', xlinkns);\n svgroot.setAttribute('class', 'svg_icon');\n\n // Without cloning, Firefox will make another GET request.\n // With cloning, causes issue in Opera/Win/Non-EN\n if (!isOpera) svg = svg.cloneNode(true);\n\n svgroot.append(svg);\n\n let icon;\n if (toImage) {\n tempHolder.empty().append(svgroot);\n const str = dataPre + encode64(unescape(encodeURIComponent(\n new XMLSerializer().serializeToString(svgroot)\n )));\n let alt = 'icon';\n if (opts.alts) {\n alt = opts.alts[id] || alt;\n }\n icon = $(new Image())\n .attr({class: 'svg_icon', src: str, alt});\n } else {\n icon = fixIDs($(svgroot), i);\n }\n addIcon(icon, id);\n }\n }\n\n if (opts.placement) {\n $.each(opts.placement, function (sel, id) {\n if (!svgIcons[id]) return;\n $(sel).each(function (i) {\n let copy = svgIcons[id].clone();\n if (i > 0 && !toImage) copy = fixIDs(copy, i, true);\n setIcon($(this), copy, id);\n });\n });\n }\n if (!fallback) {\n if (toImage) tempHolder.remove();\n if (dataEl) dataEl.remove();\n if (testImg) testImg.remove();\n }\n if (opts.resize) $.resizeSvgIcons(opts.resize);\n iconsMade = true;\n\n if (opts.callback) opts.callback(svgIcons);\n }\n\n /**\n * @returns {void}\n */\n function useFallback () {\n if (file.includes('.svgz')) {\n const regFile = file.replace('.svgz', '.svg');\n if (window.console) {\n console.log('.svgz failed, trying with .svg'); // eslint-disable-line no-console\n }\n $.svgIcons(regFile, opts);\n } else if (opts.fallback) {\n makeIcons(false, opts.fallback);\n }\n }\n };\n\n /**\n * @function external:jQuery.getSvgIcon\n * @param {string} id\n * @param {boolean} uniqueClone Whether to clone\n * @returns {external:jQuery} The icon (optionally cloned)\n */\n $.getSvgIcon = function (id, uniqueClone) {\n let icon = svgIcons[id];\n if (uniqueClone && icon) {\n icon = fixIDs(icon, 0, true).clone(true);\n }\n return icon;\n };\n\n /**\n * @typedef {GenericArray} module:jQuerySVGIcons.Dimensions\n * @property {Integer} length 2\n * @property {Float} 0 Width\n * @property {Float} 1 Height\n */\n\n /**\n * If a Float is used, it will represent width and height. Arrays contain\n * the width and height.\n * @typedef {module:jQuerySVGIcons.Dimensions|Float} module:jQuerySVGIcons.Size\n */\n\n /**\n * @function external:jQuery.resizeSvgIcons\n * @param {PlainObject<string, module:jQuerySVGIcons.Size>} obj Object with\n * selectors as keys. The values are sizes.\n * @returns {void}\n */\n $.resizeSvgIcons = function (obj) {\n // FF2 and older don't detect .svg_icon, so we change it detect svg elems instead\n const changeSel = !$('.svg_icon:first').length;\n $.each(obj, function (sel, size) {\n const arr = Array.isArray(size);\n const w = arr ? size[0] : size,\n h = arr ? size[1] : size;\n if (changeSel) {\n sel = sel.replace(/\\.svg_icon/g, 'svg');\n }\n $(sel).each(function () {\n this.setAttribute('width', w);\n this.setAttribute('height', h);\n if (window.opera && window.widget) {\n this.parentNode.style.width = w + 'px';\n this.parentNode.style.height = h + 'px';\n }\n });\n });\n };\n return $;\n}\n","/**\n * @file jGraduate 0.4\n *\n * jQuery Plugin for a gradient picker\n *\n * @module jGraduate\n * @copyright 2010 Jeff Schiller {@link http://blog.codedread.com/}, 2010 Alexis Deveria {@link http://a.deveria.com/}\n *\n * @license Apache-2.0\n * @example\n * // The Paint object is described below.\n * $.jGraduate.Paint(); // constructs a 'none' color\n * @example $.jGraduate.Paint({copy: o}); // creates a copy of the paint o\n * @example $.jGraduate.Paint({hex: '#rrggbb'}); // creates a solid color paint with hex = \"#rrggbb\"\n * @example $.jGraduate.Paint({linearGradient: o, a: 50}); // creates a linear gradient paint with opacity=0.5\n * @example $.jGraduate.Paint({radialGradient: o, a: 7}); // creates a radial gradient paint with opacity=0.07\n * @example $.jGraduate.Paint({hex: '#rrggbb', linearGradient: o}); // throws an exception?\n*/\n\n/* eslint-disable jsdoc/require-property */\n/**\n * The jQuery namespace.\n * @external jQuery\n*/\n/**\n * The jQuery plugin namespace.\n * @namespace {PlainObject} fn\n * @memberof external:jQuery\n * @see {@link http://learn.jquery.com/plugins/|jQuery Plugins}\n */\n/* eslint-enable jsdoc/require-property */\n\nconst ns = {\n svg: 'http://www.w3.org/2000/svg',\n xlink: 'http://www.w3.org/1999/xlink'\n};\n\nif (!window.console) {\n window.console = {\n log (str) { /* */ },\n dir (str) { /* */ }\n };\n}\n\n/**\n* Adds {@link external:jQuery.jGraduate.Paint},\n* {@link external:jQuery.fn.jGraduateDefaults},\n* {@link external:jQuery.fn.jGraduate}.\n* @function module:jGraduate.jGraduate\n* @param {external:jQuery} $ The jQuery instance to wrap\n* @returns {external:jQuery}\n*/\nexport default function jQueryPluginJGraduate ($) {\n if (!$.loadingStylesheets) {\n $.loadingStylesheets = [];\n }\n const stylesheet = 'jgraduate/css/jGraduate.css';\n if (!$.loadingStylesheets.includes(stylesheet)) {\n $.loadingStylesheets.push(stylesheet);\n }\n\n /**\n * @typedef {PlainObject} module:jGraduate.jGraduatePaintOptions\n * @property {Float} [alpha]\n * @property {module:jGraduate~Paint} [copy] Copy paint object\n * @property {SVGLinearGradientElement} [linearGradient]\n * @property {SVGRadialGradientElement} [radialGradient]\n * @property {string} [solidColor]\n */\n\n /**\n * @memberof module:jGraduate~\n */\n class Paint {\n /**\n * @param {module:jGraduate.jGraduatePaintOptions} [opt]\n */\n constructor (opt) {\n const options = opt || {};\n this.alpha = isNaN(options.alpha) ? 100 : options.alpha;\n // copy paint object\n if (options.copy) {\n /**\n * @name module:jGraduate~Paint#type\n * @type {\"none\"|\"solidColor\"|\"linearGradient\"|\"radialGradient\"}\n */\n this.type = options.copy.type;\n /**\n * Represents opacity (0-100).\n * @name module:jGraduate~Paint#alpha\n * @type {Float}\n */\n this.alpha = options.copy.alpha;\n /**\n * Represents #RRGGBB hex of color.\n * @name module:jGraduate~Paint#solidColor\n * @type {string}\n */\n this.solidColor = null;\n /**\n * @name module:jGraduate~Paint#linearGradient\n * @type {SVGLinearGradientElement}\n */\n this.linearGradient = null;\n /**\n * @name module:jGraduate~Paint#radialGradient\n * @type {SVGRadialGradientElement}\n */\n this.radialGradient = null;\n\n switch (this.type) {\n case 'none':\n break;\n case 'solidColor':\n this.solidColor = options.copy.solidColor;\n break;\n case 'linearGradient':\n this.linearGradient = options.copy.linearGradient.cloneNode(true);\n break;\n case 'radialGradient':\n this.radialGradient = options.copy.radialGradient.cloneNode(true);\n break;\n }\n // create linear gradient paint\n } else if (options.linearGradient) {\n this.type = 'linearGradient';\n this.solidColor = null;\n this.radialGradient = null;\n this.linearGradient = options.linearGradient.cloneNode(true);\n // create linear gradient paint\n } else if (options.radialGradient) {\n this.type = 'radialGradient';\n this.solidColor = null;\n this.linearGradient = null;\n this.radialGradient = options.radialGradient.cloneNode(true);\n // create solid color paint\n } else if (options.solidColor) {\n this.type = 'solidColor';\n this.solidColor = options.solidColor;\n // create empty paint\n } else {\n this.type = 'none';\n this.solidColor = null;\n this.linearGradient = null;\n this.radialGradient = null;\n }\n }\n }\n\n /* eslint-disable jsdoc/require-property */\n /**\n * @namespace {PlainObject} jGraduate\n * @memberof external:jQuery\n */\n $.jGraduate = /** @lends external:jQuery.jGraduate */ {\n /* eslint-enable jsdoc/require-property */\n /**\n * @class external:jQuery.jGraduate.Paint\n * @see module:jGraduate~Paint\n */\n Paint\n };\n\n // JSDoc doesn't show this as belonging to our `module:jGraduate.Options` type,\n // so we use `@see`\n /**\n * @namespace {module:jGraduate.Options} jGraduateDefaults\n * @memberof external:jQuery.fn\n */\n $.fn.jGraduateDefaults = /** @lends external:jQuery.fn.jGraduateDefaults */ {\n /**\n * Creates an object with a 'none' color.\n * @type {external:jQuery.jGraduate.Paint}\n * @see module:jGraduate.Options\n */\n paint: new $.jGraduate.Paint(),\n /**\n * @namespace\n */\n window: {\n /**\n * @type {string}\n * @see module:jGraduate.Options\n */\n pickerTitle: 'Drag markers to pick a paint'\n },\n /**\n * @namespace\n */\n images: {\n /**\n * @type {string}\n * @see module:jGraduate.Options\n */\n clientPath: 'images/'\n },\n /**\n * @type {string}\n * @see module:jGraduate.Options\n */\n newstop: 'inverse' // same, inverse, black, white\n };\n\n const isGecko = navigator.userAgent.includes('Gecko/');\n\n /**\n * @typedef {PlainObject<string, string>} module:jGraduate.Attrs\n */\n /**\n * @param {SVGElement} elem\n * @param {module:jGraduate.Attrs} attrs\n * @returns {void}\n */\n function setAttrs (elem, attrs) {\n if (isGecko) {\n Object.entries(attrs).forEach(([aname, val]) => {\n elem.setAttribute(aname, val);\n });\n } else {\n Object.entries(attrs).forEach(([aname, val]) => {\n const prop = elem[aname];\n if (prop && prop.constructor === 'SVGLength') {\n prop.baseVal.value = val;\n } else {\n elem.setAttribute(aname, val);\n }\n });\n }\n }\n\n /**\n * @param {string} name\n * @param {module:jGraduate.Attrs} attrs\n * @param {Element} newparent\n * @returns {SVGElement}\n */\n function mkElem (name, attrs, newparent) {\n const elem = document.createElementNS(ns.svg, name);\n setAttrs(elem, attrs);\n if (newparent) {\n newparent.append(elem);\n }\n return elem;\n }\n\n /**\n * @typedef {PlainObject} module:jGraduate.ColorOpac Object may have one or both values\n * @property {string} [color] #Hex color\n * @property {Float} [opac] 0-1\n */\n /**\n * @typedef {PlainObject} module:jGraduate.Options\n * @property {module:jGraduate~Paint} [paint] A Paint object object describing the paint to display initially; defaults to a new instance without options (defaults to opaque white)\n * @property {external:Window} [window]\n * @property {string} [window.pickerTitle='Drag markers to pick a paint']\n * @property {PlainObject} [images]\n * @property {string} [images.clientPath='images/']\n * @property {\"same\"|\"inverse\"|\"black\"|\"white\"|module:jGraduate.ColorOpac} [newstop=\"inverse\"]\n */\n\n /**\n * @callback external:jQuery.fn.jGraduate.OkCallback\n * @param {external:jQuery.jGraduate.Paint} paint\n * @returns {void}\n */\n /**\n * @callback external:jQuery.fn.jGraduate.CancelCallback\n * @returns {void}\n */\n\n /**\n * @function external:jQuery.fn.jGraduate\n * @param {module:jGraduate.Options} [options]\n * @param {external:jQuery.fn.jGraduate.OkCallback} [okCallback] Called with a Paint object when Ok is pressed\n * @param {external:jQuery.fn.jGraduate.CancelCallback} [cancelCallback] Called with no arguments when Cancel is pressed\n * @returns {external:jQuery}\n */\n $.fn.jGraduate = function (options, okCallback, cancelCallback) {\n return this.each(function () {\n const $this = $(this),\n $settings = $.extend(true, {}, $.fn.jGraduateDefaults, options || {}),\n id = $this.attr('id'),\n idref = '#' + $this.attr('id') + ' ';\n\n if (!idref) {\n /* await */ $.alert('Container element must have an id attribute to maintain unique id strings for sub-elements.');\n return;\n }\n\n const okClicked = function () {\n switch ($this.paint.type) {\n case 'radialGradient':\n $this.paint.linearGradient = null;\n break;\n case 'linearGradient':\n $this.paint.radialGradient = null;\n break;\n case 'solidColor':\n $this.paint.radialGradient = $this.paint.linearGradient = null;\n break;\n }\n typeof $this.okCallback === 'function' && $this.okCallback($this.paint);\n $this.hide();\n };\n const cancelClicked = function () {\n typeof $this.cancelCallback === 'function' && $this.cancelCallback();\n $this.hide();\n };\n\n $.extend(\n true,\n $this,\n // public properties, methods, and callbacks\n {\n // make a copy of the incoming paint\n paint: new $.jGraduate.Paint({copy: $settings.paint}),\n okCallback: typeof okCallback === 'function' ? okCallback : null,\n cancelCallback: typeof cancelCallback === 'function' ? cancelCallback : null\n }\n );\n\n let // pos = $this.position(),\n color = null;\n const $win = $(window);\n\n if ($this.paint.type === 'none') {\n $this.paint = new $.jGraduate.Paint({solidColor: 'ffffff'});\n }\n\n $this.addClass('jGraduate_Picker');\n $this.html(\n '<ul class=\"jGraduate_tabs\">' +\n '<li class=\"jGraduate_tab_color jGraduate_tab_current\" data-type=\"col\">Solid Color</li>' +\n '<li class=\"jGraduate_tab_lingrad\" data-type=\"lg\">Linear Gradient</li>' +\n '<li class=\"jGraduate_tab_radgrad\" data-type=\"rg\">Radial Gradient</li>' +\n '</ul>' +\n '<div class=\"jGraduate_colPick\"></div>' +\n '<div class=\"jGraduate_gradPick\"></div>' +\n '<div class=\"jGraduate_LightBox\"></div>' +\n '<div id=\"' + id + '_jGraduate_stopPicker\" class=\"jGraduate_stopPicker\"></div>'\n );\n const colPicker = $(idref + '> .jGraduate_colPick');\n const gradPicker = $(idref + '> .jGraduate_gradPick');\n\n gradPicker.html(\n '<div id=\"' + id + '_jGraduate_Swatch\" class=\"jGraduate_Swatch\">' +\n '<h2 class=\"jGraduate_Title\">' + $settings.window.pickerTitle + '</h2>' +\n '<div id=\"' + id + '_jGraduate_GradContainer\" class=\"jGraduate_GradContainer\"></div>' +\n '<div id=\"' + id + '_jGraduate_StopSlider\" class=\"jGraduate_StopSlider\"></div>' +\n '</div>' +\n '<div class=\"jGraduate_Form jGraduate_Points jGraduate_lg_field\">' +\n '<div class=\"jGraduate_StopSection\">' +\n '<label class=\"jGraduate_Form_Heading\">Begin Point</label>' +\n '<div class=\"jGraduate_Form_Section\">' +\n '<label>x:</label>' +\n '<input type=\"text\" id=\"' + id + '_jGraduate_x1\" size=\"3\" title=\"Enter starting x value between 0.0 and 1.0\"/>' +\n '<label>y:</label>' +\n '<input type=\"text\" id=\"' + id + '_jGraduate_y1\" size=\"3\" title=\"Enter starting y value between 0.0 and 1.0\"/>' +\n '</div>' +\n '</div>' +\n '<div class=\"jGraduate_StopSection\">' +\n '<label class=\"jGraduate_Form_Heading\">End Point</label>' +\n '<div class=\"jGraduate_Form_Section\">' +\n '<label>x:</label>' +\n '<input type=\"text\" id=\"' + id + '_jGraduate_x2\" size=\"3\" title=\"Enter ending x value between 0.0 and 1.0\"/>' +\n '<label>y:</label>' +\n '<input type=\"text\" id=\"' + id + '_jGraduate_y2\" size=\"3\" title=\"Enter ending y value between 0.0 and 1.0\"/>' +\n '</div>' +\n '</div>' +\n '</div>' +\n '<div class=\"jGraduate_Form jGraduate_Points jGraduate_rg_field\">' +\n '<div class=\"jGraduate_StopSection\">' +\n '<label class=\"jGraduate_Form_Heading\">Center Point</label>' +\n '<div class=\"jGraduate_Form_Section\">' +\n '<label>x:</label>' +\n '<input type=\"text\" id=\"' + id + '_jGraduate_cx\" size=\"3\" title=\"Enter x value between 0.0 and 1.0\"/>' +\n '<label>y:</label>' +\n '<input type=\"text\" id=\"' + id + '_jGraduate_cy\" size=\"3\" title=\"Enter y value between 0.0 and 1.0\"/>' +\n '</div>' +\n '</div>' +\n '<div class=\"jGraduate_StopSection\">' +\n '<label class=\"jGraduate_Form_Heading\">Focal Point</label>' +\n '<div class=\"jGraduate_Form_Section\">' +\n '<label>Match center: <input type=\"checkbox\" checked=\"checked\" id=\"' + id + '_jGraduate_match_ctr\"/></label><br/>' +\n '<label>x:</label>' +\n '<input type=\"text\" id=\"' + id + '_jGraduate_fx\" size=\"3\" title=\"Enter x value between 0.0 and 1.0\"/>' +\n '<label>y:</label>' +\n '<input type=\"text\" id=\"' + id + '_jGraduate_fy\" size=\"3\" title=\"Enter y value between 0.0 and 1.0\"/>' +\n '</div>' +\n '</div>' +\n '</div>' +\n '<div class=\"jGraduate_StopSection jGraduate_SpreadMethod\">' +\n '<label class=\"jGraduate_Form_Heading\">Spread method</label>' +\n '<div class=\"jGraduate_Form_Section\">' +\n '<select class=\"jGraduate_spreadMethod\">' +\n '<option value=pad selected>Pad</option>' +\n '<option value=reflect>Reflect</option>' +\n '<option value=repeat>Repeat</option>' +\n '</select>' +\n '</div>' +\n '</div>' +\n '<div class=\"jGraduate_Form\">' +\n '<div class=\"jGraduate_Slider jGraduate_RadiusField jGraduate_rg_field\">' +\n '<label class=\"prelabel\">Radius:</label>' +\n '<div id=\"' + id + '_jGraduate_Radius\" class=\"jGraduate_SliderBar jGraduate_Radius\" title=\"Click to set radius\">' +\n '<img id=\"' + id + '_jGraduate_RadiusArrows\" class=\"jGraduate_RadiusArrows\" src=\"' + $settings.images.clientPath + 'rangearrows2.gif\">' +\n '</div>' +\n '<label><input type=\"text\" id=\"' + id + '_jGraduate_RadiusInput\" size=\"3\" value=\"100\"/>%</label>' +\n '</div>' +\n '<div class=\"jGraduate_Slider jGraduate_EllipField jGraduate_rg_field\">' +\n '<label class=\"prelabel\">Ellip:</label>' +\n '<div id=\"' + id + '_jGraduate_Ellip\" class=\"jGraduate_SliderBar jGraduate_Ellip\" title=\"Click to set Ellip\">' +\n '<img id=\"' + id + '_jGraduate_EllipArrows\" class=\"jGraduate_EllipArrows\" src=\"' + $settings.images.clientPath + 'rangearrows2.gif\">' +\n '</div>' +\n '<label><input type=\"text\" id=\"' + id + '_jGraduate_EllipInput\" size=\"3\" value=\"0\"/>%</label>' +\n '</div>' +\n '<div class=\"jGraduate_Slider jGraduate_AngleField jGraduate_rg_field\">' +\n '<label class=\"prelabel\">Angle:</label>' +\n '<div id=\"' + id + '_jGraduate_Angle\" class=\"jGraduate_SliderBar jGraduate_Angle\" title=\"Click to set Angle\">' +\n '<img id=\"' + id + '_jGraduate_AngleArrows\" class=\"jGraduate_AngleArrows\" src=\"' + $settings.images.clientPath + 'rangearrows2.gif\">' +\n '</div>' +\n '<label><input type=\"text\" id=\"' + id + '_jGraduate_AngleInput\" size=\"3\" value=\"0\"/>deg</label>' +\n '</div>' +\n '<div class=\"jGraduate_Slider jGraduate_OpacField\">' +\n '<label class=\"prelabel\">Opac:</label>' +\n '<div id=\"' + id + '_jGraduate_Opac\" class=\"jGraduate_SliderBar jGraduate_Opac\" title=\"Click to set Opac\">' +\n '<img id=\"' + id + '_jGraduate_OpacArrows\" class=\"jGraduate_OpacArrows\" src=\"' + $settings.images.clientPath + 'rangearrows2.gif\">' +\n '</div>' +\n '<label><input type=\"text\" id=\"' + id + '_jGraduate_OpacInput\" size=\"3\" value=\"100\"/>%</label>' +\n '</div>' +\n '</div>' +\n '<div class=\"jGraduate_OkCancel\">' +\n '<input type=\"button\" id=\"' + id + '_jGraduate_Ok\" class=\"jGraduate_Ok\" value=\"OK\"/>' +\n '<input type=\"button\" id=\"' + id + '_jGraduate_Cancel\" class=\"jGraduate_Cancel\" value=\"Cancel\"/>' +\n '</div>'\n );\n\n // --------------\n // Set up all the SVG elements (the gradient, stops and rectangle)\n const MAX = 256,\n MARGINX = 0,\n MARGINY = 0,\n // STOP_RADIUS = 15 / 2,\n SIZEX = MAX - 2 * MARGINX,\n SIZEY = MAX - 2 * MARGINY;\n\n const attrInput = {};\n\n const SLIDERW = 145;\n $('.jGraduate_SliderBar').width(SLIDERW);\n\n const container = $('#' + id + '_jGraduate_GradContainer')[0];\n\n const svg = mkElem('svg', {\n id: id + '_jgraduate_svg',\n width: MAX,\n height: MAX,\n xmlns: ns.svg\n }, container);\n\n // This wasn't working as designed\n // let curType;\n // curType = curType || $this.paint.type;\n\n // if we are sent a gradient, import it\n let curType = $this.paint.type;\n\n let grad = $this.paint[curType];\n let curGradient = grad;\n\n const gradalpha = $this.paint.alpha;\n\n const isSolid = curType === 'solidColor';\n\n // Make any missing gradients\n switch (curType) {\n case 'solidColor':\n // fall through\n case 'linearGradient':\n if (!isSolid) {\n curGradient.id = id + '_lg_jgraduate_grad';\n grad = curGradient = svg.appendChild(curGradient); // .cloneNode(true));\n }\n mkElem('radialGradient', {\n id: id + '_rg_jgraduate_grad'\n }, svg);\n if (curType === 'linearGradient') { break; }\n // fall through\n case 'radialGradient':\n if (!isSolid) {\n curGradient.id = id + '_rg_jgraduate_grad';\n grad = curGradient = svg.appendChild(curGradient); // .cloneNode(true));\n }\n mkElem('linearGradient', {\n id: id + '_lg_jgraduate_grad'\n }, svg);\n }\n\n let stopGroup; // eslint-disable-line prefer-const\n if (isSolid) {\n grad = curGradient = $('#' + id + '_lg_jgraduate_grad')[0];\n color = $this.paint[curType];\n mkStop(0, '#' + color, 1);\n\n const type = typeof $settings.newstop;\n\n if (type === 'string') {\n switch ($settings.newstop) {\n case 'same':\n mkStop(1, '#' + color, 1);\n break;\n\n case 'inverse': {\n // Invert current color for second stop\n let inverted = '';\n for (let i = 0; i < 6; i += 2) {\n // const ch = color.substr(i, 2);\n let inv = (255 - parseInt(color.substr(i, 2), 16)).toString(16);\n if (inv.length < 2) inv = 0 + inv;\n inverted += inv;\n }\n mkStop(1, '#' + inverted, 1);\n break;\n } case 'white':\n mkStop(1, '#ffffff', 1);\n break;\n\n case 'black':\n mkStop(1, '#000000', 1);\n break;\n }\n } else if (type === 'object') {\n const opac = ('opac' in $settings.newstop) ? $settings.newstop.opac : 1;\n mkStop(1, ($settings.newstop.color || '#' + color), opac);\n }\n }\n\n const x1 = parseFloat(grad.getAttribute('x1') || 0.0),\n y1 = parseFloat(grad.getAttribute('y1') || 0.0),\n x2 = parseFloat(grad.getAttribute('x2') || 1.0),\n y2 = parseFloat(grad.getAttribute('y2') || 0.0);\n\n const cx = parseFloat(grad.getAttribute('cx') || 0.5),\n cy = parseFloat(grad.getAttribute('cy') || 0.5),\n fx = parseFloat(grad.getAttribute('fx') || cx),\n fy = parseFloat(grad.getAttribute('fy') || cy);\n\n const previewRect = mkElem('rect', {\n id: id + '_jgraduate_rect',\n x: MARGINX,\n y: MARGINY,\n width: SIZEX,\n height: SIZEY,\n fill: 'url(#' + id + '_jgraduate_grad)',\n 'fill-opacity': gradalpha / 100\n }, svg);\n\n // stop visuals created here\n const beginCoord = $('<div/>').attr({\n class: 'grad_coord jGraduate_lg_field',\n title: 'Begin Stop'\n }).text(1).css({\n top: y1 * MAX,\n left: x1 * MAX\n }).data('coord', 'start').appendTo(container);\n\n const endCoord = beginCoord.clone().text(2).css({\n top: y2 * MAX,\n left: x2 * MAX\n }).attr('title', 'End stop').data('coord', 'end').appendTo(container);\n\n const centerCoord = $('<div/>').attr({\n class: 'grad_coord jGraduate_rg_field',\n title: 'Center stop'\n }).text('C').css({\n top: cy * MAX,\n left: cx * MAX\n }).data('coord', 'center').appendTo(container);\n\n const focusCoord = centerCoord.clone().text('F').css({\n top: fy * MAX,\n left: fx * MAX,\n display: 'none'\n }).attr('title', 'Focus point').data('coord', 'focus').appendTo(container);\n\n focusCoord[0].id = id + '_jGraduate_focusCoord';\n\n // const coords = $(idref + ' .grad_coord');\n\n // $(container).hover(function () {\n // coords.animate({\n // opacity: 1\n // }, 500);\n // }, function () {\n // coords.animate({\n // opacity: .2\n // }, 500);\n // });\n\n let showFocus;\n $.each(['x1', 'y1', 'x2', 'y2', 'cx', 'cy', 'fx', 'fy'], function (i, attr) {\n const isRadial = isNaN(attr[1]);\n\n let attrval = curGradient.getAttribute(attr);\n if (!attrval) {\n // Set defaults\n if (isRadial) {\n // For radial points\n attrval = '0.5';\n } else {\n // Only x2 is 1\n attrval = attr === 'x2' ? '1.0' : '0.0';\n }\n }\n\n attrInput[attr] = $('#' + id + '_jGraduate_' + attr)\n .val(attrval)\n .change(function () {\n // TODO: Support values < 0 and > 1 (zoomable preview?)\n if (isNaN(parseFloat(this.value)) || this.value < 0) {\n this.value = 0.0;\n } else if (this.value > 1) {\n this.value = 1.0;\n }\n\n if (!(attr[0] === 'f' && !showFocus)) {\n if ((isRadial && curType === 'radialGradient') || (!isRadial && curType === 'linearGradient')) {\n curGradient.setAttribute(attr, this.value);\n }\n }\n\n const $elem = isRadial\n ? attr[0] === 'c' ? centerCoord : focusCoord\n : attr[1] === '1' ? beginCoord : endCoord;\n\n const cssName = attr.includes('x') ? 'left' : 'top';\n\n $elem.css(cssName, this.value * MAX);\n }).change();\n });\n\n /**\n *\n * @param {Float} n\n * @param {Float|string} colr\n * @param {Float} opac\n * @param {boolean} [sel]\n * @param {SVGStopElement} [stopElem]\n * @returns {SVGStopElement}\n */\n function mkStop (n, colr, opac, sel, stopElem) {\n const stop = stopElem || mkElem('stop', {\n 'stop-color': colr,\n 'stop-opacity': opac,\n offset: n\n }, curGradient);\n if (stopElem) {\n colr = stopElem.getAttribute('stop-color');\n opac = stopElem.getAttribute('stop-opacity');\n n = stopElem.getAttribute('offset');\n } else {\n curGradient.append(stop);\n }\n if (opac === null) opac = 1;\n\n const pickerD = 'M-6.2,0.9c3.6-4,6.7-4.3,6.7-12.4c-0.2,7.9,3.1,8.8,6.5,12.4c3.5,3.8,2.9,9.6,0,12.3c-3.1,2.8-10.4,2.7-13.2,0C-9.6,9.9-9.4,4.4-6.2,0.9z';\n\n const pathbg = mkElem('path', {\n d: pickerD,\n fill: 'url(#jGraduate_trans)',\n transform: 'translate(' + (10 + n * MAX) + ', 26)'\n }, stopGroup);\n\n const path = mkElem('path', {\n d: pickerD,\n fill: colr,\n 'fill-opacity': opac,\n transform: 'translate(' + (10 + n * MAX) + ', 26)',\n stroke: '#000',\n 'stroke-width': 1.5\n }, stopGroup);\n\n $(path).mousedown(function (e) {\n selectStop(this);\n drag = curStop;\n $win.mousemove(dragColor).mouseup(remDrags);\n stopOffset = stopMakerDiv.offset();\n e.preventDefault();\n return false;\n }).data('stop', stop).data('bg', pathbg).dblclick(function () {\n $('div.jGraduate_LightBox').show();\n const colorhandle = this; // eslint-disable-line consistent-this\n let stopOpacity = Number(stop.getAttribute('stop-opacity')) || 1;\n let stopColor = stop.getAttribute('stop-color') || 1;\n let thisAlpha = (parseFloat(stopOpacity) * 255).toString(16);\n while (thisAlpha.length < 2) { thisAlpha = '0' + thisAlpha; }\n colr = stopColor.substr(1) + thisAlpha;\n $('#' + id + '_jGraduate_stopPicker').css({left: 100, bottom: 15}).jPicker({\n window: {title: 'Pick the start color and opacity for the gradient'},\n images: {clientPath: $settings.images.clientPath},\n color: {active: colr, alphaSupport: true}\n }, function (clr, arg2) {\n stopColor = clr.val('hex') ? ('#' + clr.val('hex')) : 'none';\n stopOpacity = clr.val('a') !== null ? clr.val('a') / 256 : 1;\n colorhandle.setAttribute('fill', stopColor);\n colorhandle.setAttribute('fill-opacity', stopOpacity);\n stop.setAttribute('stop-color', stopColor);\n stop.setAttribute('stop-opacity', stopOpacity);\n $('div.jGraduate_LightBox').hide();\n $('#' + id + '_jGraduate_stopPicker').hide();\n }, null, function () {\n $('div.jGraduate_LightBox').hide();\n $('#' + id + '_jGraduate_stopPicker').hide();\n });\n });\n\n $(curGradient).find('stop').each(function () {\n const curS = $(this);\n if (Number(this.getAttribute('offset')) > n) {\n if (!colr) {\n const newcolor = this.getAttribute('stop-color');\n const newopac = this.getAttribute('stop-opacity');\n stop.setAttribute('stop-color', newcolor);\n path.setAttribute('fill', newcolor);\n stop.setAttribute('stop-opacity', newopac === null ? 1 : newopac);\n path.setAttribute('fill-opacity', newopac === null ? 1 : newopac);\n }\n curS.before(stop);\n return false;\n }\n return true;\n });\n if (sel) selectStop(path);\n return stop;\n }\n\n /**\n *\n * @returns {void}\n */\n function remStop () {\n delStop.setAttribute('display', 'none');\n const path = $(curStop);\n const stop = path.data('stop');\n const bg = path.data('bg');\n $([curStop, stop, bg]).remove();\n }\n\n const stopMakerDiv = $('#' + id + '_jGraduate_StopSlider');\n\n let stops, curStop, drag;\n\n const delStop = mkElem('path', {\n d: 'm9.75,-6l-19.5,19.5m0,-19.5l19.5,19.5',\n fill: 'none',\n stroke: '#D00',\n 'stroke-width': 5,\n display: 'none'\n }, undefined); // stopMakerSVG);\n\n /**\n * @param {Element} item\n * @returns {void}\n */\n function selectStop (item) {\n if (curStop) curStop.setAttribute('stroke', '#000');\n item.setAttribute('stroke', 'blue');\n curStop = item;\n // stops = $('stop');\n // opac_select.val(curStop.attr('fill-opacity') || 1);\n // root.append(delStop);\n }\n\n let stopOffset;\n\n /**\n *\n * @returns {void}\n */\n function remDrags () {\n $win.unbind('mousemove', dragColor);\n if (delStop.getAttribute('display') !== 'none') {\n remStop();\n }\n drag = null;\n }\n\n let scaleX = 1, scaleY = 1, angle = 0;\n\n let cX = cx;\n let cY = cy;\n /**\n *\n * @returns {void}\n */\n function xform () {\n const rot = angle ? 'rotate(' + angle + ',' + cX + ',' + cY + ') ' : '';\n if (scaleX === 1 && scaleY === 1) {\n curGradient.removeAttribute('gradientTransform');\n // $('#ang').addClass('dis');\n } else {\n const x = -cX * (scaleX - 1);\n const y = -cY * (scaleY - 1);\n curGradient.setAttribute('gradientTransform', rot + 'translate(' + x + ',' + y + ') scale(' + scaleX + ',' + scaleY + ')');\n // $('#ang').removeClass('dis');\n }\n }\n\n /**\n * @param {Event} evt\n * @returns {void}\n */\n function dragColor (evt) {\n let x = evt.pageX - stopOffset.left;\n const y = evt.pageY - stopOffset.top;\n x = x < 10\n ? 10\n : x > MAX + 10\n ? MAX + 10\n : x;\n\n const xfStr = 'translate(' + x + ', 26)';\n if (y < -60 || y > 130) {\n delStop.setAttribute('display', 'block');\n delStop.setAttribute('transform', xfStr);\n } else {\n delStop.setAttribute('display', 'none');\n }\n\n drag.setAttribute('transform', xfStr);\n $.data(drag, 'bg').setAttribute('transform', xfStr);\n const stop = $.data(drag, 'stop');\n const sX = (x - 10) / MAX;\n\n stop.setAttribute('offset', sX);\n\n let last = 0;\n $(curGradient).find('stop').each(function (i) {\n const cur = this.getAttribute('offset');\n const t = $(this);\n if (cur < last) {\n t.prev().before(t);\n stops = $(curGradient).find('stop');\n }\n last = cur;\n });\n }\n\n const stopMakerSVG = mkElem('svg', {\n width: '100%',\n height: 45\n }, stopMakerDiv[0]);\n\n const transPattern = mkElem('pattern', {\n width: 16,\n height: 16,\n patternUnits: 'userSpaceOnUse',\n id: 'jGraduate_trans'\n }, stopMakerSVG);\n\n const transImg = mkElem('image', {\n width: 16,\n height: 16\n }, transPattern);\n\n const bgImage = $settings.images.clientPath + 'map-opacity.png';\n\n transImg.setAttributeNS(ns.xlink, 'xlink:href', bgImage);\n\n $(stopMakerSVG).click(function (evt) {\n stopOffset = stopMakerDiv.offset();\n const {target} = evt;\n if (target.tagName === 'path') return;\n let x = evt.pageX - stopOffset.left - 8;\n x = x < 10 ? 10 : x > MAX + 10 ? MAX + 10 : x;\n mkStop(x / MAX, 0, 0, true);\n evt.stopPropagation();\n });\n\n $(stopMakerSVG).mouseover(function () {\n stopMakerSVG.append(delStop);\n });\n\n stopGroup = mkElem('g', {}, stopMakerSVG);\n\n mkElem('line', {\n x1: 10,\n y1: 15,\n x2: MAX + 10,\n y2: 15,\n 'stroke-width': 2,\n stroke: '#000'\n }, stopMakerSVG);\n\n const spreadMethodOpt = gradPicker.find('.jGraduate_spreadMethod').change(function () {\n curGradient.setAttribute('spreadMethod', $(this).val());\n });\n\n // handle dragging the stop around the swatch\n let draggingCoord = null;\n\n const onCoordDrag = function (evt) {\n let x = evt.pageX - offset.left;\n let y = evt.pageY - offset.top;\n\n // clamp stop to the swatch\n x = x < 0 ? 0 : x > MAX ? MAX : x;\n y = y < 0 ? 0 : y > MAX ? MAX : y;\n\n draggingCoord.css('left', x).css('top', y);\n\n // calculate stop offset\n const fracx = x / SIZEX;\n const fracy = y / SIZEY;\n\n const type = draggingCoord.data('coord');\n const grd = curGradient;\n\n switch (type) {\n case 'start':\n attrInput.x1.val(fracx);\n attrInput.y1.val(fracy);\n grd.setAttribute('x1', fracx);\n grd.setAttribute('y1', fracy);\n break;\n case 'end':\n attrInput.x2.val(fracx);\n attrInput.y2.val(fracy);\n grd.setAttribute('x2', fracx);\n grd.setAttribute('y2', fracy);\n break;\n case 'center':\n attrInput.cx.val(fracx);\n attrInput.cy.val(fracy);\n grd.setAttribute('cx', fracx);\n grd.setAttribute('cy', fracy);\n cX = fracx;\n cY = fracy;\n xform();\n break;\n case 'focus':\n attrInput.fx.val(fracx);\n attrInput.fy.val(fracy);\n grd.setAttribute('fx', fracx);\n grd.setAttribute('fy', fracy);\n xform();\n }\n\n evt.preventDefault();\n };\n\n const onCoordUp = function () {\n draggingCoord = null;\n $win.unbind('mousemove', onCoordDrag).unbind('mouseup', onCoordUp);\n };\n\n // Linear gradient\n // (function () {\n\n stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop');\n\n let numstops = stops.length;\n // if there are not at least two stops, then\n if (numstops < 2) {\n while (numstops < 2) {\n curGradient.append(document.createElementNS(ns.svg, 'stop'));\n ++numstops;\n }\n stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop');\n }\n\n for (let i = 0; i < numstops; i++) {\n mkStop(0, 0, 0, 0, stops[i]);\n }\n\n spreadMethodOpt.val(curGradient.getAttribute('spreadMethod') || 'pad');\n\n let offset;\n\n // No match, so show focus point\n showFocus = false;\n\n previewRect.setAttribute('fill-opacity', gradalpha / 100);\n\n $('#' + id + ' div.grad_coord').mousedown(function (evt) {\n evt.preventDefault();\n draggingCoord = $(this);\n // const sPos = draggingCoord.offset();\n offset = draggingCoord.parent().offset();\n $win.mousemove(onCoordDrag).mouseup(onCoordUp);\n });\n\n // bind GUI elements\n $('#' + id + '_jGraduate_Ok').bind('click', function () {\n $this.paint.type = curType;\n $this.paint[curType] = curGradient.cloneNode(true);\n $this.paint.solidColor = null;\n okClicked();\n });\n $('#' + id + '_jGraduate_Cancel').bind('click', function (paint) {\n cancelClicked();\n });\n\n if (curType === 'radialGradient') {\n if (showFocus) {\n focusCoord.show();\n } else {\n focusCoord.hide();\n attrInput.fx.val('');\n attrInput.fy.val('');\n }\n }\n\n $('#' + id + '_jGraduate_match_ctr')[0].checked = !showFocus;\n\n let lastfx, lastfy;\n\n $('#' + id + '_jGraduate_match_ctr').change(function () {\n showFocus = !this.checked;\n focusCoord.toggle(showFocus);\n attrInput.fx.val('');\n attrInput.fy.val('');\n const grd = curGradient;\n if (!showFocus) {\n lastfx = grd.getAttribute('fx');\n lastfy = grd.getAttribute('fy');\n grd.removeAttribute('fx');\n grd.removeAttribute('fy');\n } else {\n const fX = lastfx || 0.5;\n const fY = lastfy || 0.5;\n grd.setAttribute('fx', fX);\n grd.setAttribute('fy', fY);\n attrInput.fx.val(fX);\n attrInput.fy.val(fY);\n }\n });\n\n stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop');\n numstops = stops.length;\n // if there are not at least two stops, then\n if (numstops < 2) {\n while (numstops < 2) {\n curGradient.append(document.createElementNS(ns.svg, 'stop'));\n ++numstops;\n }\n stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop');\n }\n\n let slider;\n\n const setSlider = function (e) {\n const {offset: {left}} = slider;\n const div = slider.parent;\n let x = (e.pageX - left - parseInt(div.css('border-left-width')));\n if (x > SLIDERW) x = SLIDERW;\n if (x <= 0) x = 0;\n const posx = x - 5;\n x /= SLIDERW;\n\n switch (slider.type) {\n case 'radius':\n x = (x * 2) ** 2.5;\n if (x > 0.98 && x < 1.02) x = 1;\n if (x <= 0.01) x = 0.01;\n curGradient.setAttribute('r', x);\n break;\n case 'opacity':\n $this.paint.alpha = parseInt(x * 100);\n previewRect.setAttribute('fill-opacity', x);\n break;\n case 'ellip':\n scaleX = 1;\n scaleY = 1;\n if (x < 0.5) {\n x /= 0.5; // 0.001\n scaleX = x <= 0 ? 0.01 : x;\n } else if (x > 0.5) {\n x /= 0.5; // 2\n x = 2 - x;\n scaleY = x <= 0 ? 0.01 : x;\n }\n xform();\n x -= 1;\n if (scaleY === x + 1) {\n x = Math.abs(x);\n }\n break;\n case 'angle':\n x -= 0.5;\n angle = x *= 180;\n xform();\n x /= 100;\n break;\n }\n slider.elem.css({'margin-left': posx});\n x = Math.round(x * 100);\n slider.input.val(x);\n };\n\n let ellipVal = 0, angleVal = 0;\n\n if (curType === 'radialGradient') {\n const tlist = curGradient.gradientTransform.baseVal;\n if (tlist.numberOfItems === 2) {\n const t = tlist.getItem(0);\n const s = tlist.getItem(1);\n if (t.type === 2 && s.type === 3) {\n const m = s.matrix;\n if (m.a !== 1) {\n ellipVal = Math.round(-(1 - m.a) * 100);\n } else if (m.d !== 1) {\n ellipVal = Math.round((1 - m.d) * 100);\n }\n }\n } else if (tlist.numberOfItems === 3) {\n // Assume [R][T][S]\n const r = tlist.getItem(0);\n const t = tlist.getItem(1);\n const s = tlist.getItem(2);\n\n if (r.type === 4 &&\n t.type === 2 &&\n s.type === 3\n ) {\n angleVal = Math.round(r.angle);\n const m = s.matrix;\n if (m.a !== 1) {\n ellipVal = Math.round(-(1 - m.a) * 100);\n } else if (m.d !== 1) {\n ellipVal = Math.round((1 - m.d) * 100);\n }\n }\n }\n }\n\n const sliders = {\n radius: {\n handle: '#' + id + '_jGraduate_RadiusArrows',\n input: '#' + id + '_jGraduate_RadiusInput',\n val: (curGradient.getAttribute('r') || 0.5) * 100\n },\n opacity: {\n handle: '#' + id + '_jGraduate_OpacArrows',\n input: '#' + id + '_jGraduate_OpacInput',\n val: $this.paint.alpha || 100\n },\n ellip: {\n handle: '#' + id + '_jGraduate_EllipArrows',\n input: '#' + id + '_jGraduate_EllipInput',\n val: ellipVal\n },\n angle: {\n handle: '#' + id + '_jGraduate_AngleArrows',\n input: '#' + id + '_jGraduate_AngleInput',\n val: angleVal\n }\n };\n\n $.each(sliders, function (type, data) {\n const handle = $(data.handle);\n handle.mousedown(function (evt) {\n const parent = handle.parent();\n slider = {\n type,\n elem: handle,\n input: $(data.input),\n parent,\n offset: parent.offset()\n };\n $win.mousemove(dragSlider).mouseup(stopSlider);\n evt.preventDefault();\n });\n\n $(data.input).val(data.val).change(function () {\n const isRad = curType === 'radialGradient';\n let val = Number(this.value);\n let xpos = 0;\n switch (type) {\n case 'radius':\n if (isRad) curGradient.setAttribute('r', val / 100);\n xpos = (((val / 100) ** (1 / 2.5)) / 2) * SLIDERW;\n break;\n\n case 'opacity':\n $this.paint.alpha = val;\n previewRect.setAttribute('fill-opacity', val / 100);\n xpos = val * (SLIDERW / 100);\n break;\n\n case 'ellip':\n scaleX = scaleY = 1;\n if (val === 0) {\n xpos = SLIDERW * 0.5;\n break;\n }\n if (val > 99.5) val = 99.5;\n if (val > 0) {\n scaleY = 1 - (val / 100);\n } else {\n scaleX = -(val / 100) - 1;\n }\n\n xpos = SLIDERW * ((val + 100) / 2) / 100;\n if (isRad) xform();\n break;\n\n case 'angle':\n angle = val;\n xpos = angle / 180;\n xpos += 0.5;\n xpos *= SLIDERW;\n if (isRad) xform();\n }\n if (xpos > SLIDERW) {\n xpos = SLIDERW;\n } else if (xpos < 0) {\n xpos = 0;\n }\n handle.css({'margin-left': xpos - 5});\n }).change();\n });\n\n const dragSlider = function (evt) {\n setSlider(evt);\n evt.preventDefault();\n };\n\n const stopSlider = function (evt) {\n $win.unbind('mousemove', dragSlider).unbind('mouseup', stopSlider);\n slider = null;\n };\n\n // --------------\n let thisAlpha = ($this.paint.alpha * 255 / 100).toString(16);\n while (thisAlpha.length < 2) { thisAlpha = '0' + thisAlpha; }\n thisAlpha = thisAlpha.split('.')[0];\n color = $this.paint.solidColor === 'none' ? '' : $this.paint.solidColor + thisAlpha;\n\n if (!isSolid) {\n color = stops[0].getAttribute('stop-color');\n }\n\n // This should be done somewhere else, probably\n $.extend($.fn.jPicker.defaults.window, {\n alphaSupport: true, effects: {type: 'show', speed: 0}\n });\n\n colPicker.jPicker(\n {\n window: {title: $settings.window.pickerTitle},\n images: {clientPath: $settings.images.clientPath},\n color: {active: color, alphaSupport: true}\n },\n function (clr) {\n $this.paint.type = 'solidColor';\n $this.paint.alpha = clr.val('ahex') ? Math.round((clr.val('a') / 255) * 100) : 100;\n $this.paint.solidColor = clr.val('hex') ? clr.val('hex') : 'none';\n $this.paint.radialGradient = null;\n okClicked();\n },\n null,\n function () { cancelClicked(); }\n );\n\n const tabs = $(idref + ' .jGraduate_tabs li');\n tabs.click(function () {\n tabs.removeClass('jGraduate_tab_current');\n $(this).addClass('jGraduate_tab_current');\n $(idref + ' > div').hide();\n const type = $(this).attr('data-type');\n /* const container = */ $(idref + ' .jGraduate_gradPick').show();\n if (type === 'rg' || type === 'lg') {\n // Show/hide appropriate fields\n $('.jGraduate_' + type + '_field').show();\n $('.jGraduate_' + (type === 'lg' ? 'rg' : 'lg') + '_field').hide();\n\n $('#' + id + '_jgraduate_rect')[0].setAttribute('fill', 'url(#' + id + '_' + type + '_jgraduate_grad)');\n\n // Copy stops\n\n curType = type === 'lg' ? 'linearGradient' : 'radialGradient';\n\n $('#' + id + '_jGraduate_OpacInput').val($this.paint.alpha).change();\n\n const newGrad = $('#' + id + '_' + type + '_jgraduate_grad')[0];\n\n if (curGradient !== newGrad) {\n const curStops = $(curGradient).find('stop');\n $(newGrad).empty().append(curStops);\n curGradient = newGrad;\n const sm = spreadMethodOpt.val();\n curGradient.setAttribute('spreadMethod', sm);\n }\n showFocus = type === 'rg' && curGradient.getAttribute('fx') !== null && !(cx === fx && cy === fy);\n $('#' + id + '_jGraduate_focusCoord').toggle(showFocus);\n if (showFocus) {\n $('#' + id + '_jGraduate_match_ctr')[0].checked = false;\n }\n } else {\n $(idref + ' .jGraduate_gradPick').hide();\n $(idref + ' .jGraduate_colPick').show();\n }\n });\n $(idref + ' > div').hide();\n tabs.removeClass('jGraduate_tab_current');\n let tab;\n switch ($this.paint.type) {\n case 'linearGradient':\n tab = $(idref + ' .jGraduate_tab_lingrad');\n break;\n case 'radialGradient':\n tab = $(idref + ' .jGraduate_tab_radgrad');\n break;\n default:\n tab = $(idref + ' .jGraduate_tab_color');\n break;\n }\n $this.show();\n\n // jPicker will try to show after a 0ms timeout, so need to fire this after that\n setTimeout(() => {\n tab.addClass('jGraduate_tab_current').click();\n }, 10);\n });\n };\n return $;\n}\n","/* eslint-disable no-bitwise */\n/**\n * @file jPicker (Adapted from version 1.1.6)\n *\n * jQuery Plugin for Photoshop style color picker\n *\n * @module jPicker\n * @copyright (c) 2010 Christopher T. Tillman\n * Digital Magic Productions, Inc. ({@link http://www.digitalmagicpro.com/})\n * FREE to use, alter, copy, sell, and especially ENHANCE\n * @license MIT\n *\n * Painstakingly ported from John Dyers' excellent work on his own color picker based on the Prototype framework.\n *\n * John Dyers' website: {@link http://johndyer.name}\n * Color Picker page: {@link http://johndyer.name/photoshop-like-javascript-color-picker/}\n */\n\n/**\n* @external Math\n*/\n/**\n* @memberof external:Math\n* @param {Float} value\n* @param {Float} precision\n* @returns {Float}\n*/\nfunction toFixedNumeric (value, precision) {\n if (precision === undefined) precision = 0;\n return Math.round(value * (10 ** precision)) / (10 ** precision);\n}\n\n/**\n * Whether a value is `null` or `undefined`.\n * @param {any} val\n * @returns {boolean}\n */\nconst isNullish = (val) => {\n return val === null || val === undefined;\n};\n\n/**\n* @function module:jPicker.jPicker\n* @param {external:jQuery} $ The jQuery object to wrap (with {@link external:jQuery.loadingStylesheets}, {@link external:jQuery.fn.$.fn.jPicker}, {@link external:jQuery.fn.$.fn.jPicker.defaults})\n* @returns {external:jQuery}\n*/\nconst jPicker = function ($) {\n if (!$.loadingStylesheets) {\n /**\n * @name loadingStylesheets\n * @type {string[]}\n * @memberof external:jQuery\n */\n $.loadingStylesheets = [];\n }\n const stylesheet = 'jgraduate/css/jPicker.css';\n if (!$.loadingStylesheets.includes(stylesheet)) {\n $.loadingStylesheets.push(stylesheet);\n }\n /**\n * @typedef {PlainObject} module:jPicker.SliderOptions\n * @property {external:jQuery|PlainObject} arrow\n * @property {string} arrow.image Not in use?\n * @property {Float} arrow.width\n * @property {Float} arrow.height\n * @property {PlainObject} map\n * @property {Float} map.width\n * @property {Float} map.height\n */\n\n /**\n * Encapsulate slider functionality for the ColorMap and ColorBar -\n * could be useful to use a jQuery UI draggable for this with certain extensions.\n * @memberof module:jPicker\n */\n class Slider {\n /**\n * @param {external:jQuery} bar\n * @param {module:jPicker.SliderOptions} options\n */\n constructor (bar, options) {\n const that = this;\n /**\n * Fire events on the supplied `context`\n * @param {module:jPicker.JPickerInit} context\n * @returns {void}\n */\n function fireChangeEvents (context) {\n changeEvents.forEach((changeEvent) => {\n changeEvent.call(that, that, context);\n });\n }\n\n /**\n * Bind the mousedown to the bar not the arrow for quick snapping to the clicked location.\n * @param {external:jQuery.Event} e\n * @returns {void}\n */\n function mouseDown (e) {\n const off = bar.offset();\n offset = {l: off.left | 0, t: off.top | 0};\n clearTimeout(timeout);\n // using setTimeout for visual updates - once the style is updated the browser will re-render internally allowing the next Javascript to run\n timeout = setTimeout(function () {\n setValuesFromMousePosition.call(that, e);\n }, 0);\n // Bind mousemove and mouseup event to the document so it responds when dragged of of the bar - we will unbind these when on mouseup to save processing\n $(document).bind('mousemove', mouseMove).bind('mouseup', mouseUp);\n e.preventDefault(); // don't try to select anything or drag the image to the desktop\n }\n /**\n * Set the values as the mouse moves.\n * @param {external:jQuery.Event} e\n * @returns {false}\n */\n function mouseMove (e) {\n clearTimeout(timeout);\n timeout = setTimeout(function () {\n setValuesFromMousePosition.call(that, e);\n }, 0);\n e.stopPropagation();\n e.preventDefault();\n return false;\n }\n /**\n * Unbind the document events - they aren't needed when not dragging.\n * @param {external:jQuery.Event} e\n * @returns {false}\n */\n function mouseUp (e) {\n $(document).unbind('mouseup', mouseUp).unbind('mousemove', mouseMove);\n e.stopPropagation();\n e.preventDefault();\n return false;\n }\n\n /**\n * Calculate mouse position and set value within the current range.\n * @param {Event} e\n * @returns {void}\n */\n function setValuesFromMousePosition (e) {\n const barW = bar.w, // local copies for YUI compressor\n barH = bar.h;\n let locX = e.pageX - offset.l,\n locY = e.pageY - offset.t;\n // keep the arrow within the bounds of the bar\n if (locX < 0) locX = 0;\n else if (locX > barW) locX = barW;\n if (locY < 0) locY = 0;\n else if (locY > barH) locY = barH;\n val.call(that, 'xy', {\n x: ((locX / barW) * rangeX) + minX,\n y: ((locY / barH) * rangeY) + minY\n });\n }\n /**\n *\n * @returns {void}\n */\n function draw () {\n const\n barW = bar.w,\n barH = bar.h,\n arrowW = arrow.w,\n arrowH = arrow.h;\n let arrowOffsetX = 0,\n arrowOffsetY = 0;\n setTimeout(function () {\n if (rangeX > 0) { // range is greater than zero\n // constrain to bounds\n if (x === maxX) arrowOffsetX = barW;\n else arrowOffsetX = ((x / rangeX) * barW) | 0;\n }\n if (rangeY > 0) { // range is greater than zero\n // constrain to bounds\n if (y === maxY) arrowOffsetY = barH;\n else arrowOffsetY = ((y / rangeY) * barH) | 0;\n }\n // if arrow width is greater than bar width, center arrow and prevent horizontal dragging\n if (arrowW >= barW) arrowOffsetX = (barW >> 1) - (arrowW >> 1); // number >> 1 - superfast bitwise divide by two and truncate (move bits over one bit discarding lowest)\n else arrowOffsetX -= arrowW >> 1;\n // if arrow height is greater than bar height, center arrow and prevent vertical dragging\n if (arrowH >= barH) arrowOffsetY = (barH >> 1) - (arrowH >> 1);\n else arrowOffsetY -= arrowH >> 1;\n // set the arrow position based on these offsets\n arrow.css({left: arrowOffsetX + 'px', top: arrowOffsetY + 'px'});\n });\n }\n\n /**\n * Get or set a value.\n * @param {?(\"xy\"|\"x\"|\"y\")} name\n * @param {module:math.XYObject} value\n * @param {module:jPicker.Slider} context\n * @returns {module:math.XYObject|Float|void}\n */\n function val (name, value, context) {\n const set = value !== undefined;\n if (!set) {\n if (isNullish(name)) name = 'xy';\n switch (name.toLowerCase()) {\n case 'x': return x;\n case 'y': return y;\n case 'xy':\n default: return {x, y};\n }\n }\n if (!isNullish(context) && context === that) return undefined;\n let changed = false;\n\n let newX, newY;\n if (isNullish(name)) name = 'xy';\n switch (name.toLowerCase()) {\n case 'x':\n newX = (value && ((value.x && value.x | 0) || value | 0)) || 0;\n break;\n case 'y':\n newY = (value && ((value.y && value.y | 0) || value | 0)) || 0;\n break;\n case 'xy':\n default:\n newX = (value && value.x && value.x | 0) || 0;\n newY = (value && value.y && value.y | 0) || 0;\n break;\n }\n if (!isNullish(newX)) {\n if (newX < minX) newX = minX;\n else if (newX > maxX) newX = maxX;\n if (x !== newX) {\n x = newX;\n changed = true;\n }\n }\n if (!isNullish(newY)) {\n if (newY < minY) newY = minY;\n else if (newY > maxY) newY = maxY;\n if (y !== newY) {\n y = newY;\n changed = true;\n }\n }\n changed && fireChangeEvents.call(that, context || that);\n return undefined;\n }\n\n /**\n * @typedef {PlainObject} module:jPicker.MinMaxRangeX\n * @property {Float} minX\n * @property {Float} maxX\n * @property {Float} rangeX\n */\n /**\n * @typedef {PlainObject} module:jPicker.MinMaxRangeY\n * @property {Float} minY\n * @property {Float} maxY\n * @property {Float} rangeY\n */\n /**\n * @typedef {module:jPicker.MinMaxRangeY|module:jPicker.MinMaxRangeX} module:jPicker.MinMaxRangeXY\n */\n\n /**\n *\n * @param {\"minx\"|\"maxx\"|\"rangex\"|\"miny\"|\"maxy\"|\"rangey\"|\"all\"} name\n * @param {module:jPicker.MinMaxRangeXY} value\n * @returns {module:jPicker.MinMaxRangeXY|module:jPicker.MinMaxRangeX|module:jPicker.MinMaxRangeY|void}\n */\n function range (name, value) {\n const set = value !== undefined;\n if (!set) {\n if (isNullish(name)) name = 'all';\n switch (name.toLowerCase()) {\n case 'minx': return minX;\n case 'maxx': return maxX;\n case 'rangex': return {minX, maxX, rangeX};\n case 'miny': return minY;\n case 'maxy': return maxY;\n case 'rangey': return {minY, maxY, rangeY};\n case 'all':\n default: return {minX, maxX, rangeX, minY, maxY, rangeY};\n }\n }\n let // changed = false,\n newMinX,\n newMaxX,\n newMinY,\n newMaxY;\n if (isNullish(name)) name = 'all';\n switch (name.toLowerCase()) {\n case 'minx':\n newMinX = (value && ((value.minX && value.minX | 0) || value | 0)) || 0;\n break;\n case 'maxx':\n newMaxX = (value && ((value.maxX && value.maxX | 0) || value | 0)) || 0;\n break;\n case 'rangex':\n newMinX = (value && value.minX && value.minX | 0) || 0;\n newMaxX = (value && value.maxX && value.maxX | 0) || 0;\n break;\n case 'miny':\n newMinY = (value && ((value.minY && value.minY | 0) || value | 0)) || 0;\n break;\n case 'maxy':\n newMaxY = (value && ((value.maxY && value.maxY | 0) || value | 0)) || 0;\n break;\n case 'rangey':\n newMinY = (value && value.minY && value.minY | 0) || 0;\n newMaxY = (value && value.maxY && value.maxY | 0) || 0;\n break;\n case 'all':\n default:\n newMinX = (value && value.minX && value.minX | 0) || 0;\n newMaxX = (value && value.maxX && value.maxX | 0) || 0;\n newMinY = (value && value.minY && value.minY | 0) || 0;\n newMaxY = (value && value.maxY && value.maxY | 0) || 0;\n break;\n }\n\n if (!isNullish(newMinX) && minX !== newMinX) {\n minX = newMinX;\n rangeX = maxX - minX;\n }\n if (!isNullish(newMaxX) && maxX !== newMaxX) {\n maxX = newMaxX;\n rangeX = maxX - minX;\n }\n if (!isNullish(newMinY) && minY !== newMinY) {\n minY = newMinY;\n rangeY = maxY - minY;\n }\n if (!isNullish(newMaxY) && maxY !== newMaxY) {\n maxY = newMaxY;\n rangeY = maxY - minY;\n }\n return undefined;\n }\n /**\n * @param {GenericCallback} callback\n * @returns {void}\n */\n function bind (callback) { // eslint-disable-line promise/prefer-await-to-callbacks\n if (typeof callback === 'function') changeEvents.push(callback);\n }\n /**\n * @param {GenericCallback} callback\n * @returns {void}\n */\n function unbind (callback) { // eslint-disable-line promise/prefer-await-to-callbacks\n if (typeof callback !== 'function') return;\n let i;\n while ((i = changeEvents.includes(callback))) changeEvents.splice(i, 1);\n }\n /**\n *\n * @returns {void}\n */\n function destroy () {\n // unbind all possible events and null objects\n $(document).unbind('mouseup', mouseUp).unbind('mousemove', mouseMove);\n bar.unbind('mousedown', mouseDown);\n bar = null;\n arrow = null;\n changeEvents = null;\n }\n let offset,\n timeout,\n x = 0,\n y = 0,\n minX = 0,\n maxX = 100,\n rangeX = 100,\n minY = 0,\n maxY = 100,\n rangeY = 100,\n arrow = bar.find('img:first'), // the arrow image to drag\n changeEvents = [];\n\n $.extend(\n true,\n // public properties, methods, and event bindings - these we need\n // to access from other controls\n that,\n {\n val,\n range,\n bind,\n unbind,\n destroy\n }\n );\n // initialize this control\n arrow.src = options.arrow && options.arrow.image;\n arrow.w = (options.arrow && options.arrow.width) || arrow.width();\n arrow.h = (options.arrow && options.arrow.height) || arrow.height();\n bar.w = (options.map && options.map.width) || bar.width();\n bar.h = (options.map && options.map.height) || bar.height();\n // bind mousedown event\n bar.bind('mousedown', mouseDown);\n bind.call(that, draw);\n }\n }\n\n /**\n * Controls for all the input elements for the typing in color values.\n */\n class ColorValuePicker {\n /**\n * @param {external:jQuery} picker\n * @param {external:jQuery.jPicker.Color} color\n * @param {external:jQuery.fn.$.fn.jPicker} bindedHex\n * @param {Float} alphaPrecision\n */\n constructor (picker, color, bindedHex, alphaPrecision) {\n const that = this; // private properties and methods\n const inputs = picker.find('td.Text input');\n // input box key down - use arrows to alter color\n /**\n *\n * @param {Event} e\n * @returns {Event|false|void}\n */\n function keyDown (e) {\n if (e.target.value === '' && e.target !== hex.get(0) && ((!isNullish(bindedHex) && e.target !== bindedHex.get(0)) || isNullish(bindedHex))) return undefined;\n if (!validateKey(e)) return e;\n switch (e.target) {\n case red.get(0):\n switch (e.keyCode) {\n case 38:\n red.val(setValueInRange.call(that, (red.val() << 0) + 1, 0, 255));\n color.val('r', red.val(), e.target);\n return false;\n case 40:\n red.val(setValueInRange.call(that, (red.val() << 0) - 1, 0, 255));\n color.val('r', red.val(), e.target);\n return false;\n }\n break;\n case green.get(0):\n switch (e.keyCode) {\n case 38:\n green.val(setValueInRange.call(that, (green.val() << 0) + 1, 0, 255));\n color.val('g', green.val(), e.target);\n return false;\n case 40:\n green.val(setValueInRange.call(that, (green.val() << 0) - 1, 0, 255));\n color.val('g', green.val(), e.target);\n return false;\n }\n break;\n case blue.get(0):\n switch (e.keyCode) {\n case 38:\n blue.val(setValueInRange.call(that, (blue.val() << 0) + 1, 0, 255));\n color.val('b', blue.val(), e.target);\n return false;\n case 40:\n blue.val(setValueInRange.call(that, (blue.val() << 0) - 1, 0, 255));\n color.val('b', blue.val(), e.target);\n return false;\n }\n break;\n case alpha && alpha.get(0):\n switch (e.keyCode) {\n case 38:\n alpha.val(setValueInRange.call(that, parseFloat(alpha.val()) + 1, 0, 100));\n color.val('a', toFixedNumeric((alpha.val() * 255) / 100, alphaPrecision), e.target);\n return false;\n case 40:\n alpha.val(setValueInRange.call(that, parseFloat(alpha.val()) - 1, 0, 100));\n color.val('a', toFixedNumeric((alpha.val() * 255) / 100, alphaPrecision), e.target);\n return false;\n }\n break;\n case hue.get(0):\n switch (e.keyCode) {\n case 38:\n hue.val(setValueInRange.call(that, (hue.val() << 0) + 1, 0, 360));\n color.val('h', hue.val(), e.target);\n return false;\n case 40:\n hue.val(setValueInRange.call(that, (hue.val() << 0) - 1, 0, 360));\n color.val('h', hue.val(), e.target);\n return false;\n }\n break;\n case saturation.get(0):\n switch (e.keyCode) {\n case 38:\n saturation.val(setValueInRange.call(that, (saturation.val() << 0) + 1, 0, 100));\n color.val('s', saturation.val(), e.target);\n return false;\n case 40:\n saturation.val(setValueInRange.call(that, (saturation.val() << 0) - 1, 0, 100));\n color.val('s', saturation.val(), e.target);\n return false;\n }\n break;\n case value.get(0):\n switch (e.keyCode) {\n case 38:\n value.val(setValueInRange.call(that, (value.val() << 0) + 1, 0, 100));\n color.val('v', value.val(), e.target);\n return false;\n case 40:\n value.val(setValueInRange.call(that, (value.val() << 0) - 1, 0, 100));\n color.val('v', value.val(), e.target);\n return false;\n }\n break;\n }\n return undefined;\n }\n // input box key up - validate value and set color\n /**\n * @param {Event} e\n * @returns {Event|void}\n * @todo Why is this returning an event?\n */\n function keyUp (e) {\n if (e.target.value === '' && e.target !== hex.get(0) &&\n ((!isNullish(bindedHex) && e.target !== bindedHex.get(0)) ||\n isNullish(bindedHex))) return undefined;\n if (!validateKey(e)) return e;\n switch (e.target) {\n case red.get(0):\n red.val(setValueInRange.call(that, red.val(), 0, 255));\n color.val('r', red.val(), e.target);\n break;\n case green.get(0):\n green.val(setValueInRange.call(that, green.val(), 0, 255));\n color.val('g', green.val(), e.target);\n break;\n case blue.get(0):\n blue.val(setValueInRange.call(that, blue.val(), 0, 255));\n color.val('b', blue.val(), e.target);\n break;\n case alpha && alpha.get(0):\n alpha.val(setValueInRange.call(that, alpha.val(), 0, 100));\n color.val('a', toFixedNumeric((alpha.val() * 255) / 100, alphaPrecision), e.target);\n break;\n case hue.get(0):\n hue.val(setValueInRange.call(that, hue.val(), 0, 360));\n color.val('h', hue.val(), e.target);\n break;\n case saturation.get(0):\n saturation.val(setValueInRange.call(that, saturation.val(), 0, 100));\n color.val('s', saturation.val(), e.target);\n break;\n case value.get(0):\n value.val(setValueInRange.call(that, value.val(), 0, 100));\n color.val('v', value.val(), e.target);\n break;\n case hex.get(0):\n hex.val(hex.val().replace(/[^a-fA-F\\d]/g, '').toLowerCase().substring(0, 6));\n bindedHex && bindedHex.val(hex.val());\n color.val('hex', hex.val() !== '' ? hex.val() : null, e.target);\n break;\n case bindedHex && bindedHex.get(0):\n bindedHex.val(bindedHex.val().replace(/[^a-fA-F\\d]/g, '').toLowerCase().substring(0, 6));\n hex.val(bindedHex.val());\n color.val('hex', bindedHex.val() !== '' ? bindedHex.val() : null, e.target);\n break;\n case ahex && ahex.get(0):\n ahex.val(ahex.val().replace(/[^a-fA-F\\d]/g, '').toLowerCase().substring(0, 2));\n color.val('a', !isNullish(ahex.val()) ? parseInt(ahex.val(), 16) : null, e.target);\n break;\n }\n return undefined;\n }\n // input box blur - reset to original if value empty\n /**\n * @param {Event} e\n * @returns {void}\n */\n function blur (e) {\n if (!isNullish(color.val())) {\n switch (e.target) {\n case red.get(0): red.val(color.val('r')); break;\n case green.get(0): green.val(color.val('g')); break;\n case blue.get(0): blue.val(color.val('b')); break;\n case alpha && alpha.get(0): alpha.val(toFixedNumeric((color.val('a') * 100) / 255, alphaPrecision)); break;\n case hue.get(0): hue.val(color.val('h')); break;\n case saturation.get(0): saturation.val(color.val('s')); break;\n case value.get(0): value.val(color.val('v')); break;\n case hex.get(0):\n case bindedHex && bindedHex.get(0):\n hex.val(color.val('hex'));\n bindedHex && bindedHex.val(color.val('hex'));\n break;\n case ahex && ahex.get(0): ahex.val(color.val('ahex').substring(6)); break;\n }\n }\n }\n /**\n * @param {Event} e\n * @returns {boolean}\n */\n function validateKey (e) {\n switch (e.keyCode) {\n case 9:\n case 16:\n case 29:\n case 37:\n case 39:\n return false;\n case 'c'.charCodeAt():\n case 'v'.charCodeAt():\n if (e.ctrlKey) return false;\n }\n return true;\n }\n\n /**\n * Constrain value within range.\n * @param {Float|string} value\n * @param {Float} min\n * @param {Float} max\n * @returns {Float|string} Returns a number or numeric string\n */\n function setValueInRange (value, min, max) {\n if (value === '' || isNaN(value)) return min;\n if (value > max) return max;\n if (value < min) return min;\n return value;\n }\n /**\n * @param {external:jQuery} ui\n * @param {Element} context\n * @returns {void}\n */\n function colorChanged (ui, context) {\n const all = ui.val('all');\n if (context !== red.get(0)) red.val(!isNullish(all) ? all.r : '');\n if (context !== green.get(0)) green.val(!isNullish(all) ? all.g : '');\n if (context !== blue.get(0)) blue.val(!isNullish(all) ? all.b : '');\n if (alpha && context !== alpha.get(0)) alpha.val(!isNullish(all) ? toFixedNumeric((all.a * 100) / 255, alphaPrecision) : '');\n if (context !== hue.get(0)) hue.val(!isNullish(all) ? all.h : '');\n if (context !== saturation.get(0)) saturation.val(!isNullish(all) ? all.s : '');\n if (context !== value.get(0)) value.val(!isNullish(all) ? all.v : '');\n if (context !== hex.get(0) && ((bindedHex && context !== bindedHex.get(0)) || !bindedHex)) hex.val(!isNullish(all) ? all.hex : '');\n if (bindedHex && context !== bindedHex.get(0) && context !== hex.get(0)) bindedHex.val(!isNullish(all) ? all.hex : '');\n if (ahex && context !== ahex.get(0)) ahex.val(!isNullish(all) ? all.ahex.substring(6) : '');\n }\n /**\n * Unbind all events and null objects.\n * @returns {void}\n */\n function destroy () {\n red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).add(hex).add(bindedHex).add(ahex).unbind('keyup', keyUp).unbind('blur', blur);\n red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).unbind('keydown', keyDown);\n color.unbind(colorChanged);\n red = null;\n green = null;\n blue = null;\n alpha = null;\n hue = null;\n saturation = null;\n value = null;\n hex = null;\n ahex = null;\n }\n let\n red = inputs.eq(3),\n green = inputs.eq(4),\n blue = inputs.eq(5),\n alpha = inputs.length > 7 ? inputs.eq(6) : null,\n hue = inputs.eq(0),\n saturation = inputs.eq(1),\n value = inputs.eq(2),\n hex = inputs.eq(inputs.length > 7 ? 7 : 6),\n ahex = inputs.length > 7 ? inputs.eq(8) : null;\n $.extend(true, that, {\n // public properties and methods\n destroy\n });\n red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).add(hex).add(bindedHex).add(ahex).bind('keyup', keyUp).bind('blur', blur);\n red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).bind('keydown', keyDown);\n color.bind(colorChanged);\n }\n }\n\n /**\n * @typedef {PlainObject} module:jPicker.JPickerInit\n * @property {Integer} [a]\n * @property {Integer} [b]\n * @property {Integer} [g]\n * @property {Integer} [h]\n * @property {Integer} [r]\n * @property {Integer} [s]\n * @property {Integer} [v]\n * @property {string} [hex]\n * @property {string} [ahex]\n */\n\n /* eslint-disable jsdoc/require-property */\n /**\n * @namespace {PlainObject} jPicker\n * @memberof external:jQuery\n */\n $.jPicker = /** @lends external:jQuery.jPicker */ {\n /* eslint-enable jsdoc/require-property */\n /**\n * Array holding references to each active instance of the jPicker control.\n * @type {external:jQuery.fn.$.fn.jPicker[]}\n */\n List: [],\n /**\n * Color object - we will be able to assign by any color space type or\n * retrieve any color space info.\n * We want this public so we can optionally assign new color objects to\n * initial values using inputs other than a string hex value (also supported)\n * Note: JSDoc didn't document when expressed here as an ES6 Class.\n * @namespace\n * @class\n * @memberof external:jQuery.jPicker\n * @param {module:jPicker.JPickerInit} init\n * @returns {external:jQuery.jPicker.Color}\n */\n Color: function (init) { // eslint-disable-line object-shorthand\n const that = this;\n /**\n *\n * @param {module:jPicker.Slider} context\n * @returns {void}\n */\n function fireChangeEvents (context) {\n for (let i = 0; i < changeEvents.length; i++) changeEvents[i].call(that, that, context);\n }\n\n /**\n * @param {string|\"ahex\"|\"hex\"|\"all\"|\"\"|null|void} name String composed of letters \"r\", \"g\", \"b\", \"a\", \"h\", \"s\", and/or \"v\"\n * @param {module:jPicker.RGBA|module:jPicker.JPickerInit|string} [value]\n * @param {external:jQuery.jPicker.Color} context\n * @returns {module:jPicker.JPickerInit|string|null|void}\n */\n function val (name, value, context) {\n // Kind of ugly\n const set = Boolean(value);\n if (set && value.ahex === '') value.ahex = '00000000';\n if (!set) {\n let ret;\n if (isNullish(name) || name === '') name = 'all';\n if (isNullish(r)) return null;\n switch (name.toLowerCase()) {\n case 'ahex': return ColorMethods.rgbaToHex({r, g, b, a});\n case 'hex': return val('ahex').substring(0, 6);\n case 'all': return {\n r, g, b, a, h, s, v,\n hex: val.call(that, 'hex'),\n ahex: val.call(that, 'ahex')\n };\n default: {\n ret = {};\n const nameLength = name.length;\n [...name].forEach((ch) => {\n switch (ch) {\n case 'r':\n if (nameLength === 1) ret = r;\n else ret.r = r;\n break;\n case 'g':\n if (nameLength === 1) ret = g;\n else ret.g = g;\n break;\n case 'b':\n if (nameLength === 1) ret = b;\n else ret.b = b;\n break;\n case 'a':\n if (nameLength === 1) ret = a;\n else ret.a = a;\n break;\n case 'h':\n if (nameLength === 1) ret = h;\n else ret.h = h;\n break;\n case 's':\n if (nameLength === 1) ret = s;\n else ret.s = s;\n break;\n case 'v':\n if (nameLength === 1) ret = v;\n else ret.v = v;\n break;\n }\n });\n }\n }\n return typeof ret === 'object' && !Object.keys(ret).length\n ? val.call(that, 'all')\n : ret;\n }\n if (!isNullish(context) && context === that) return undefined;\n if (isNullish(name)) name = '';\n\n let changed = false;\n if (isNullish(value)) {\n if (!isNullish(r)) {\n r = null;\n changed = true;\n }\n if (!isNullish(g)) {\n g = null;\n changed = true;\n }\n if (!isNullish(b)) {\n b = null;\n changed = true;\n }\n if (!isNullish(a)) {\n a = null;\n changed = true;\n }\n if (!isNullish(h)) {\n h = null;\n changed = true;\n }\n if (!isNullish(s)) {\n s = null;\n changed = true;\n }\n if (!isNullish(v)) {\n v = null;\n changed = true;\n }\n changed && fireChangeEvents.call(that, context || that);\n return undefined;\n }\n switch (name.toLowerCase()) {\n case 'ahex':\n case 'hex': {\n const ret = ColorMethods.hexToRgba((value && (value.ahex || value.hex)) || value || 'none');\n val.call(that, 'rgba', {\n r: ret.r,\n g: ret.g,\n b: ret.b,\n a: name === 'ahex'\n ? ret.a\n : !isNullish(a)\n ? a\n : 255\n }, context);\n break;\n } default: {\n if (value && (!isNullish(value.ahex) || !isNullish(value.hex))) {\n val.call(that, 'ahex', value.ahex || value.hex || '00000000', context);\n return undefined;\n }\n const newV = {};\n let rgb = false, hsv = false;\n if (value.r !== undefined && !name.includes('r')) name += 'r';\n if (value.g !== undefined && !name.includes('g')) name += 'g';\n if (value.b !== undefined && !name.includes('b')) name += 'b';\n if (value.a !== undefined && !name.includes('a')) name += 'a';\n if (value.h !== undefined && !name.includes('h')) name += 'h';\n if (value.s !== undefined && !name.includes('s')) name += 's';\n if (value.v !== undefined && !name.includes('v')) name += 'v';\n [...name].forEach((ch) => {\n switch (ch) {\n case 'r':\n if (hsv) return;\n rgb = true;\n newV.r = (value.r && value.r | 0) || (value | 0) || 0;\n if (newV.r < 0) newV.r = 0;\n else if (newV.r > 255) newV.r = 255;\n if (r !== newV.r) {\n ({r} = newV);\n changed = true;\n }\n break;\n case 'g':\n if (hsv) return;\n rgb = true;\n newV.g = (value && value.g && value.g | 0) || (value && value | 0) || 0;\n if (newV.g < 0) newV.g = 0;\n else if (newV.g > 255) newV.g = 255;\n if (g !== newV.g) {\n ({g} = newV);\n changed = true;\n }\n break;\n case 'b':\n if (hsv) return;\n rgb = true;\n newV.b = (value && value.b && value.b | 0) || (value && value | 0) || 0;\n if (newV.b < 0) newV.b = 0;\n else if (newV.b > 255) newV.b = 255;\n if (b !== newV.b) {\n ({b} = newV);\n changed = true;\n }\n break;\n case 'a':\n newV.a = value && !isNullish(value.a) ? value.a | 0 : value | 0;\n if (newV.a < 0) newV.a = 0;\n else if (newV.a > 255) newV.a = 255;\n if (a !== newV.a) {\n ({a} = newV);\n changed = true;\n }\n break;\n case 'h':\n if (rgb) return;\n hsv = true;\n newV.h = (value && value.h && value.h | 0) || (value && value | 0) || 0;\n if (newV.h < 0) newV.h = 0;\n else if (newV.h > 360) newV.h = 360;\n if (h !== newV.h) {\n ({h} = newV);\n changed = true;\n }\n break;\n case 's':\n if (rgb) return;\n hsv = true;\n newV.s = !isNullish(value.s) ? value.s | 0 : value | 0;\n if (newV.s < 0) newV.s = 0;\n else if (newV.s > 100) newV.s = 100;\n if (s !== newV.s) {\n ({s} = newV);\n changed = true;\n }\n break;\n case 'v':\n if (rgb) return;\n hsv = true;\n newV.v = !isNullish(value.v) ? value.v | 0 : value | 0;\n if (newV.v < 0) newV.v = 0;\n else if (newV.v > 100) newV.v = 100;\n if (v !== newV.v) {\n ({v} = newV);\n changed = true;\n }\n break;\n }\n });\n if (changed) {\n if (rgb) {\n r = r || 0;\n g = g || 0;\n b = b || 0;\n const ret = ColorMethods.rgbToHsv({r, g, b});\n ({h, s, v} = ret);\n } else if (hsv) {\n h = h || 0;\n s = !isNullish(s) ? s : 100;\n v = !isNullish(v) ? v : 100;\n const ret = ColorMethods.hsvToRgb({h, s, v});\n ({r, g, b} = ret);\n }\n a = !isNullish(a) ? a : 255;\n fireChangeEvents.call(that, context || that);\n }\n break;\n }\n }\n return undefined;\n }\n /**\n * @param {GenericCallback} callback\n * @returns {void}\n */\n function bind (callback) { // eslint-disable-line promise/prefer-await-to-callbacks\n if (typeof callback === 'function') changeEvents.push(callback);\n }\n /**\n * @param {GenericCallback} callback\n * @returns {void}\n */\n function unbind (callback) { // eslint-disable-line promise/prefer-await-to-callbacks\n if (typeof callback !== 'function') return;\n let i;\n while ((i = changeEvents.includes(callback))) {\n changeEvents.splice(i, 1);\n }\n }\n /**\n * Unset `changeEvents`\n * @returns {void}\n */\n function destroy () {\n changeEvents = null;\n }\n let r, g, b, a, h, s, v, changeEvents = [];\n\n $.extend(true, that, {\n // public properties and methods\n val,\n bind,\n unbind,\n destroy\n });\n if (init) {\n if (!isNullish(init.ahex)) {\n val('ahex', init);\n } else if (!isNullish(init.hex)) {\n val(\n (!isNullish(init.a) ? 'a' : '') + 'hex',\n !isNullish(init.a)\n ? {ahex: init.hex + ColorMethods.intToHex(init.a)}\n : init\n );\n } else if (!isNullish(init.r) && !isNullish(init.g) && !isNullish(init.b)) {\n val('rgb' + (!isNullish(init.a) ? 'a' : ''), init);\n } else if (!isNullish(init.h) && !isNullish(init.s) && !isNullish(init.v)) {\n val('hsv' + (!isNullish(init.a) ? 'a' : ''), init);\n }\n }\n },\n /**\n * Color conversion methods - make public to give use to external scripts.\n * @namespace\n */\n ColorMethods: {\n /**\n * @typedef {PlainObject} module:jPicker.RGBA\n * @property {Integer} r\n * @property {Integer} g\n * @property {Integer} b\n * @property {Integer} a\n */\n /**\n * @typedef {PlainObject} module:jPicker.RGB\n * @property {Integer} r\n * @property {Integer} g\n * @property {Integer} b\n */\n /**\n * @param {string} hex\n * @returns {module:jPicker.RGBA}\n */\n hexToRgba (hex) {\n if (hex === '' || hex === 'none') return {r: null, g: null, b: null, a: null};\n hex = this.validateHex(hex);\n let r = '00', g = '00', b = '00', a = '255';\n if (hex.length === 6) hex += 'ff';\n if (hex.length > 6) {\n r = hex.substring(0, 2);\n g = hex.substring(2, 4);\n b = hex.substring(4, 6);\n a = hex.substring(6, hex.length);\n } else {\n if (hex.length > 4) {\n r = hex.substring(4, hex.length);\n hex = hex.substring(0, 4);\n }\n if (hex.length > 2) {\n g = hex.substring(2, hex.length);\n hex = hex.substring(0, 2);\n }\n if (hex.length > 0) b = hex.substring(0, hex.length);\n }\n return {\n r: this.hexToInt(r), g: this.hexToInt(g), b: this.hexToInt(b), a: this.hexToInt(a)\n };\n },\n /**\n * @param {string} hex\n * @returns {string}\n */\n validateHex (hex) {\n // if (typeof hex === 'object') return '';\n hex = hex.toLowerCase().replace(/[^a-f\\d]/g, '');\n if (hex.length > 8) hex = hex.substring(0, 8);\n return hex;\n },\n /**\n * @param {module:jPicker.RGBA} rgba\n * @returns {string}\n */\n rgbaToHex (rgba) {\n return this.intToHex(rgba.r) + this.intToHex(rgba.g) + this.intToHex(rgba.b) + this.intToHex(rgba.a);\n },\n /**\n * @param {Integer} dec\n * @returns {string}\n */\n intToHex (dec) {\n let result = (dec | 0).toString(16);\n if (result.length === 1) result = ('0' + result);\n return result.toLowerCase();\n },\n /**\n * @param {string} hex\n * @returns {Integer}\n */\n hexToInt (hex) {\n return parseInt(hex, 16);\n },\n /**\n * @typedef {PlainObject} module:jPicker.HSV\n * @property {Integer} h\n * @property {Integer} s\n * @property {Integer} v\n */\n /**\n * @param {module:jPicker.RGB} rgb\n * @returns {module:jPicker.HSV}\n */\n rgbToHsv (rgb) {\n const r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255, hsv = {h: 0, s: 0, v: 0};\n let min = 0, max = 0;\n if (r >= g && r >= b) {\n max = r;\n min = g > b ? b : g;\n } else if (g >= b && g >= r) {\n max = g;\n min = r > b ? b : r;\n } else {\n max = b;\n min = g > r ? r : g;\n }\n hsv.v = max;\n hsv.s = max ? (max - min) / max : 0;\n let delta;\n if (!hsv.s) hsv.h = 0;\n else {\n delta = max - min;\n if (r === max) hsv.h = (g - b) / delta;\n else if (g === max) hsv.h = 2 + (b - r) / delta;\n else hsv.h = 4 + (r - g) / delta;\n hsv.h = parseInt(hsv.h * 60);\n if (hsv.h < 0) hsv.h += 360;\n }\n hsv.s = (hsv.s * 100) | 0;\n hsv.v = (hsv.v * 100) | 0;\n return hsv;\n },\n /**\n * @param {module:jPicker.HSV} hsv\n * @returns {module:jPicker.RGB}\n */\n hsvToRgb (hsv) {\n const rgb = {r: 0, g: 0, b: 0, a: 100};\n let {h, s, v} = hsv;\n if (s === 0) {\n if (v === 0) rgb.r = rgb.g = rgb.b = 0;\n else rgb.r = rgb.g = rgb.b = (v * 255 / 100) | 0;\n } else {\n if (h === 360) h = 0;\n h /= 60;\n s /= 100;\n v /= 100;\n const i = h | 0,\n f = h - i,\n p = v * (1 - s),\n q = v * (1 - (s * f)),\n t = v * (1 - (s * (1 - f)));\n switch (i) {\n case 0:\n rgb.r = v;\n rgb.g = t;\n rgb.b = p;\n break;\n case 1:\n rgb.r = q;\n rgb.g = v;\n rgb.b = p;\n break;\n case 2:\n rgb.r = p;\n rgb.g = v;\n rgb.b = t;\n break;\n case 3:\n rgb.r = p;\n rgb.g = q;\n rgb.b = v;\n break;\n case 4:\n rgb.r = t;\n rgb.g = p;\n rgb.b = v;\n break;\n case 5:\n rgb.r = v;\n rgb.g = p;\n rgb.b = q;\n break;\n }\n rgb.r = (rgb.r * 255) | 0;\n rgb.g = (rgb.g * 255) | 0;\n rgb.b = (rgb.b * 255) | 0;\n }\n return rgb;\n }\n }\n };\n const {Color, List, ColorMethods} = $.jPicker; // local copies for YUI compressor\n /* eslint-disable jsdoc/require-returns */\n /**\n * @function external:jQuery.fn.jPicker\n * @see {@link external:jQuery.fn.$.fn.jPicker}\n */\n /* eslint-enable jsdoc/require-returns */\n\n /**\n * Will be bound to active {@link jQuery.jPicker.Color}.\n * @callback module:jPicker.LiveCallback\n * @param {external:jQuery} ui\n * @param {Element} context\n * @returns {void}\n */\n /**\n * @callback module:jPicker.CommitCallback\n * @param {external:jQuery.jPicker.Color} activeColor\n * @param {external:jQuery} okButton\n * @returns {void} Return value not used.\n */\n /**\n * @callback module:jPicker.CancelCallback\n * @param {external:jQuery.jPicker.Color} activeColor\n * @param {external:jQuery} cancelButton\n * @returns {void} Return value not used.\n */\n /**\n * While it would seem this should specify the name `jPicker` for JSDoc, that doesn't\n * get us treated as a function as well as a namespace (even with `@function name`),\n * so we use an approach to add a redundant `$.fn.` in the name.\n * @namespace\n * @memberof external:jQuery.fn\n * @param {external:jQuery.fn.jPickerOptions} options\n * @param {module:jPicker.CommitCallback} [commitCallback]\n * @param {module:jPicker.LiveCallback} [liveCallback]\n * @param {module:jPicker.CancelCallback} [cancelCallback]\n * @returns {external:jQuery}\n */\n $.fn.jPicker = function (options, commitCallback, liveCallback, cancelCallback) {\n return this.each(function () {\n const that = this,\n settings = $.extend(true, {}, $.fn.jPicker.defaults, options); // local copies for YUI compressor\n if ($(that).get(0).nodeName.toLowerCase() === 'input') { // Add color picker icon if binding to an input element and bind the events to the input\n $.extend(true, settings, {\n window: {\n bindToInput: true,\n expandable: true,\n input: $(that)\n }\n });\n if ($(that).val() === '') {\n settings.color.active = new Color({hex: null});\n settings.color.current = new Color({hex: null});\n } else if (ColorMethods.validateHex($(that).val())) {\n settings.color.active = new Color({hex: $(that).val(), a: settings.color.active.val('a')});\n settings.color.current = new Color({hex: $(that).val(), a: settings.color.active.val('a')});\n }\n }\n if (settings.window.expandable) {\n $(that).after('<span class=\"jPicker\"><span class=\"Icon\"><span class=\"Color\">&nbsp;</span><span class=\"Alpha\">&nbsp;</span><span class=\"Image\" title=\"Click To Open Color Picker\">&nbsp;</span><span class=\"Container\">&nbsp;</span></span></span>');\n } else {\n settings.window.liveUpdate = false; // Basic control binding for inline use - You will need to override the liveCallback or commitCallback function to retrieve results\n }\n const isLessThanIE7 = parseFloat(navigator.appVersion.split('MSIE')[1]) < 7 && document.body.filters; // needed to run the AlphaImageLoader function for IE6\n // set color mode and update visuals for the new color mode\n /**\n *\n * @param {\"h\"|\"s\"|\"v\"|\"r\"|\"g\"|\"b\"|\"a\"} colorMode\n * @throws {Error} Invalid mode\n * @returns {void}\n */\n function setColorMode (colorMode) {\n const {active} = color, // local copies for YUI compressor\n // {clientPath} = images,\n hex = active.val('hex');\n let rgbMap, rgbBar;\n settings.color.mode = colorMode;\n switch (colorMode) {\n case 'h':\n setTimeout(function () {\n setBG.call(that, colorMapDiv, 'transparent');\n setImgLoc.call(that, colorMapL1, 0);\n setAlpha.call(that, colorMapL1, 100);\n setImgLoc.call(that, colorMapL2, 260);\n setAlpha.call(that, colorMapL2, 100);\n setBG.call(that, colorBarDiv, 'transparent');\n setImgLoc.call(that, colorBarL1, 0);\n setAlpha.call(that, colorBarL1, 100);\n setImgLoc.call(that, colorBarL2, 260);\n setAlpha.call(that, colorBarL2, 100);\n setImgLoc.call(that, colorBarL3, 260);\n setAlpha.call(that, colorBarL3, 100);\n setImgLoc.call(that, colorBarL4, 260);\n setAlpha.call(that, colorBarL4, 100);\n setImgLoc.call(that, colorBarL6, 260);\n setAlpha.call(that, colorBarL6, 100);\n }, 0);\n colorMap.range('all', {minX: 0, maxX: 100, minY: 0, maxY: 100});\n colorBar.range('rangeY', {minY: 0, maxY: 360});\n if (isNullish(active.val('ahex'))) break;\n colorMap.val('xy', {x: active.val('s'), y: 100 - active.val('v')}, colorMap);\n colorBar.val('y', 360 - active.val('h'), colorBar);\n break;\n case 's':\n setTimeout(function () {\n setBG.call(that, colorMapDiv, 'transparent');\n setImgLoc.call(that, colorMapL1, -260);\n setImgLoc.call(that, colorMapL2, -520);\n setImgLoc.call(that, colorBarL1, -260);\n setImgLoc.call(that, colorBarL2, -520);\n setImgLoc.call(that, colorBarL6, 260);\n setAlpha.call(that, colorBarL6, 100);\n }, 0);\n colorMap.range('all', {minX: 0, maxX: 360, minY: 0, maxY: 100});\n colorBar.range('rangeY', {minY: 0, maxY: 100});\n if (isNullish(active.val('ahex'))) break;\n colorMap.val('xy', {x: active.val('h'), y: 100 - active.val('v')}, colorMap);\n colorBar.val('y', 100 - active.val('s'), colorBar);\n break;\n case 'v':\n setTimeout(function () {\n setBG.call(that, colorMapDiv, '000000');\n setImgLoc.call(that, colorMapL1, -780);\n setImgLoc.call(that, colorMapL2, 260);\n setBG.call(that, colorBarDiv, hex);\n setImgLoc.call(that, colorBarL1, -520);\n setImgLoc.call(that, colorBarL2, 260);\n setAlpha.call(that, colorBarL2, 100);\n setImgLoc.call(that, colorBarL6, 260);\n setAlpha.call(that, colorBarL6, 100);\n }, 0);\n colorMap.range('all', {minX: 0, maxX: 360, minY: 0, maxY: 100});\n colorBar.range('rangeY', {minY: 0, maxY: 100});\n if (isNullish(active.val('ahex'))) break;\n colorMap.val('xy', {x: active.val('h'), y: 100 - active.val('s')}, colorMap);\n colorBar.val('y', 100 - active.val('v'), colorBar);\n break;\n case 'r':\n rgbMap = -1040;\n rgbBar = -780;\n colorMap.range('all', {minX: 0, maxX: 255, minY: 0, maxY: 255});\n colorBar.range('rangeY', {minY: 0, maxY: 255});\n if (isNullish(active.val('ahex'))) break;\n colorMap.val('xy', {x: active.val('b'), y: 255 - active.val('g')}, colorMap);\n colorBar.val('y', 255 - active.val('r'), colorBar);\n break;\n case 'g':\n rgbMap = -1560;\n rgbBar = -1820;\n colorMap.range('all', {minX: 0, maxX: 255, minY: 0, maxY: 255});\n colorBar.range('rangeY', {minY: 0, maxY: 255});\n if (isNullish(active.val('ahex'))) break;\n colorMap.val('xy', {x: active.val('b'), y: 255 - active.val('r')}, colorMap);\n colorBar.val('y', 255 - active.val('g'), colorBar);\n break;\n case 'b':\n rgbMap = -2080;\n rgbBar = -2860;\n colorMap.range('all', {minX: 0, maxX: 255, minY: 0, maxY: 255});\n colorBar.range('rangeY', {minY: 0, maxY: 255});\n if (isNullish(active.val('ahex'))) break;\n colorMap.val('xy', {x: active.val('r'), y: 255 - active.val('g')}, colorMap);\n colorBar.val('y', 255 - active.val('b'), colorBar);\n break;\n case 'a':\n setTimeout(function () {\n setBG.call(that, colorMapDiv, 'transparent');\n setImgLoc.call(that, colorMapL1, -260);\n setImgLoc.call(that, colorMapL2, -520);\n setImgLoc.call(that, colorBarL1, 260);\n setImgLoc.call(that, colorBarL2, 260);\n setAlpha.call(that, colorBarL2, 100);\n setImgLoc.call(that, colorBarL6, 0);\n setAlpha.call(that, colorBarL6, 100);\n }, 0);\n colorMap.range('all', {minX: 0, maxX: 360, minY: 0, maxY: 100});\n colorBar.range('rangeY', {minY: 0, maxY: 255});\n if (isNullish(active.val('ahex'))) break;\n colorMap.val('xy', {x: active.val('h'), y: 100 - active.val('v')}, colorMap);\n colorBar.val('y', 255 - active.val('a'), colorBar);\n break;\n default:\n throw new Error('Invalid Mode');\n }\n switch (colorMode) {\n case 'h':\n break;\n case 's':\n case 'v':\n case 'a':\n setTimeout(function () {\n setAlpha.call(that, colorMapL1, 100);\n setAlpha.call(that, colorBarL1, 100);\n setImgLoc.call(that, colorBarL3, 260);\n setAlpha.call(that, colorBarL3, 100);\n setImgLoc.call(that, colorBarL4, 260);\n setAlpha.call(that, colorBarL4, 100);\n }, 0);\n break;\n case 'r':\n case 'g':\n case 'b':\n setTimeout(function () {\n setBG.call(that, colorMapDiv, 'transparent');\n setBG.call(that, colorBarDiv, 'transparent');\n setAlpha.call(that, colorBarL1, 100);\n setAlpha.call(that, colorMapL1, 100);\n setImgLoc.call(that, colorMapL1, rgbMap);\n setImgLoc.call(that, colorMapL2, rgbMap - 260);\n setImgLoc.call(that, colorBarL1, rgbBar - 780);\n setImgLoc.call(that, colorBarL2, rgbBar - 520);\n setImgLoc.call(that, colorBarL3, rgbBar);\n setImgLoc.call(that, colorBarL4, rgbBar - 260);\n setImgLoc.call(that, colorBarL6, 260);\n setAlpha.call(that, colorBarL6, 100);\n }, 0);\n break;\n }\n if (isNullish(active.val('ahex'))) return;\n activeColorChanged.call(that, active);\n }\n /**\n * Update color when user changes text values.\n * @param {external:jQuery} ui\n * @param {?module:jPicker.Slider} context\n * @returns {void}\n */\n function activeColorChanged (ui, context) {\n if (isNullish(context) || (context !== colorBar && context !== colorMap)) positionMapAndBarArrows.call(that, ui, context);\n setTimeout(function () {\n updatePreview.call(that, ui);\n updateMapVisuals.call(that, ui);\n updateBarVisuals.call(that, ui);\n }, 0);\n }\n\n /**\n * User has dragged the ColorMap pointer.\n * @param {external:jQuery} ui\n * @param {?module:jPicker.Slider} context\n * @returns {void}\n */\n function mapValueChanged (ui, context) {\n const {active} = color;\n if (context !== colorMap && isNullish(active.val())) return;\n const xy = ui.val('all');\n switch (settings.color.mode) {\n case 'h':\n active.val('sv', {s: xy.x, v: 100 - xy.y}, context);\n break;\n case 's':\n case 'a':\n active.val('hv', {h: xy.x, v: 100 - xy.y}, context);\n break;\n case 'v':\n active.val('hs', {h: xy.x, s: 100 - xy.y}, context);\n break;\n case 'r':\n active.val('gb', {g: 255 - xy.y, b: xy.x}, context);\n break;\n case 'g':\n active.val('rb', {r: 255 - xy.y, b: xy.x}, context);\n break;\n case 'b':\n active.val('rg', {r: xy.x, g: 255 - xy.y}, context);\n break;\n }\n }\n\n /**\n * User has dragged the ColorBar slider.\n * @param {external:jQuery} ui\n * @param {?module:jPicker.Slider} context\n * @returns {void}\n */\n function colorBarValueChanged (ui, context) {\n const {active} = color;\n if (context !== colorBar && isNullish(active.val())) return;\n switch (settings.color.mode) {\n case 'h':\n active.val('h', {h: 360 - ui.val('y')}, context);\n break;\n case 's':\n active.val('s', {s: 100 - ui.val('y')}, context);\n break;\n case 'v':\n active.val('v', {v: 100 - ui.val('y')}, context);\n break;\n case 'r':\n active.val('r', {r: 255 - ui.val('y')}, context);\n break;\n case 'g':\n active.val('g', {g: 255 - ui.val('y')}, context);\n break;\n case 'b':\n active.val('b', {b: 255 - ui.val('y')}, context);\n break;\n case 'a':\n active.val('a', 255 - ui.val('y'), context);\n break;\n }\n }\n\n /**\n * Position map and bar arrows to match current color.\n * @param {external:jQuery} ui\n * @param {?module:jPicker.Slider} context\n * @returns {void}\n */\n function positionMapAndBarArrows (ui, context) {\n if (context !== colorMap) {\n switch (settings.color.mode) {\n case 'h': {\n const sv = ui.val('sv');\n colorMap.val('xy', {x: !isNullish(sv) ? sv.s : 100, y: 100 - (!isNullish(sv) ? sv.v : 100)}, context);\n break;\n } case 's':\n // Fall through\n case 'a': {\n const hv = ui.val('hv');\n colorMap.val('xy', {x: (hv && hv.h) || 0, y: 100 - (!isNullish(hv) ? hv.v : 100)}, context);\n break;\n } case 'v': {\n const hs = ui.val('hs');\n colorMap.val('xy', {x: (hs && hs.h) || 0, y: 100 - (!isNullish(hs) ? hs.s : 100)}, context);\n break;\n } case 'r': {\n const bg = ui.val('bg');\n colorMap.val('xy', {x: (bg && bg.b) || 0, y: 255 - ((bg && bg.g) || 0)}, context);\n break;\n } case 'g': {\n const br = ui.val('br');\n colorMap.val('xy', {x: (br && br.b) || 0, y: 255 - ((br && br.r) || 0)}, context);\n break;\n } case 'b': {\n const rg = ui.val('rg');\n colorMap.val('xy', {x: (rg && rg.r) || 0, y: 255 - ((rg && rg.g) || 0)}, context);\n break;\n }\n }\n }\n if (context !== colorBar) {\n switch (settings.color.mode) {\n case 'h':\n colorBar.val('y', 360 - (ui.val('h') || 0), context);\n break;\n case 's': {\n const s = ui.val('s');\n colorBar.val('y', 100 - (!isNullish(s) ? s : 100), context);\n break;\n } case 'v': {\n const v = ui.val('v');\n colorBar.val('y', 100 - (!isNullish(v) ? v : 100), context);\n break;\n } case 'r':\n colorBar.val('y', 255 - (ui.val('r') || 0), context);\n break;\n case 'g':\n colorBar.val('y', 255 - (ui.val('g') || 0), context);\n break;\n case 'b':\n colorBar.val('y', 255 - (ui.val('b') || 0), context);\n break;\n case 'a': {\n const a = ui.val('a');\n colorBar.val('y', 255 - (!isNullish(a) ? a : 255), context);\n break;\n }\n }\n }\n }\n /**\n * @param {external:jQuery} ui\n * @returns {void}\n */\n function updatePreview (ui) {\n try {\n const all = ui.val('all');\n activePreview.css({backgroundColor: (all && '#' + all.hex) || 'transparent'});\n setAlpha.call(that, activePreview, (all && toFixedNumeric((all.a * 100) / 255, 4)) || 0);\n } catch (e) { }\n }\n /**\n * @param {external:jQuery} ui\n * @returns {void}\n */\n function updateMapVisuals (ui) {\n switch (settings.color.mode) {\n case 'h':\n setBG.call(that, colorMapDiv, new Color({h: ui.val('h') || 0, s: 100, v: 100}).val('hex'));\n break;\n case 's':\n case 'a': {\n const s = ui.val('s');\n setAlpha.call(that, colorMapL2, 100 - (!isNullish(s) ? s : 100));\n break;\n } case 'v': {\n const v = ui.val('v');\n setAlpha.call(that, colorMapL1, !isNullish(v) ? v : 100);\n break;\n } case 'r':\n setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('r') || 0) / 255 * 100, 4));\n break;\n case 'g':\n setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('g') || 0) / 255 * 100, 4));\n break;\n case 'b':\n setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('b') || 0) / 255 * 100));\n break;\n }\n const a = ui.val('a');\n setAlpha.call(that, colorMapL3, toFixedNumeric(((255 - (a || 0)) * 100) / 255, 4));\n }\n /**\n * @param {external:jQuery} ui\n * @returns {void}\n */\n function updateBarVisuals (ui) {\n switch (settings.color.mode) {\n case 'h': {\n const a = ui.val('a');\n setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - (a || 0)) * 100) / 255, 4));\n break;\n } case 's': {\n const hva = ui.val('hva'),\n saturatedColor = new Color({h: (hva && hva.h) || 0, s: 100, v: !isNullish(hva) ? hva.v : 100});\n setBG.call(that, colorBarDiv, saturatedColor.val('hex'));\n setAlpha.call(that, colorBarL2, 100 - (!isNullish(hva) ? hva.v : 100));\n setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - ((hva && hva.a) || 0)) * 100) / 255, 4));\n break;\n } case 'v': {\n const hsa = ui.val('hsa'),\n valueColor = new Color({h: (hsa && hsa.h) || 0, s: !isNullish(hsa) ? hsa.s : 100, v: 100});\n setBG.call(that, colorBarDiv, valueColor.val('hex'));\n setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - ((hsa && hsa.a) || 0)) * 100) / 255, 4));\n break;\n } case 'r':\n case 'g':\n case 'b': {\n const rgba = ui.val('rgba');\n let hValue = 0, vValue = 0;\n if (settings.color.mode === 'r') {\n hValue = (rgba && rgba.b) || 0;\n vValue = (rgba && rgba.g) || 0;\n } else if (settings.color.mode === 'g') {\n hValue = (rgba && rgba.b) || 0;\n vValue = (rgba && rgba.r) || 0;\n } else if (settings.color.mode === 'b') {\n hValue = (rgba && rgba.r) || 0;\n vValue = (rgba && rgba.g) || 0;\n }\n const middle = vValue > hValue ? hValue : vValue;\n setAlpha.call(that, colorBarL2, hValue > vValue ? toFixedNumeric(((hValue - vValue) / (255 - vValue)) * 100, 4) : 0);\n setAlpha.call(that, colorBarL3, vValue > hValue ? toFixedNumeric(((vValue - hValue) / (255 - hValue)) * 100, 4) : 0);\n setAlpha.call(that, colorBarL4, toFixedNumeric((middle / 255) * 100, 4));\n setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - ((rgba && rgba.a) || 0)) * 100) / 255, 4));\n break;\n } case 'a': {\n const a = ui.val('a');\n setBG.call(that, colorBarDiv, ui.val('hex') || '000000');\n setAlpha.call(that, colorBarL5, !isNullish(a) ? 0 : 100);\n setAlpha.call(that, colorBarL6, !isNullish(a) ? 100 : 0);\n break;\n }\n }\n }\n /**\n * @param {external:jQuery} el\n * @param {string} [c=\"transparent\"]\n * @returns {void}\n */\n function setBG (el, c) {\n el.css({backgroundColor: (c && c.length === 6 && '#' + c) || 'transparent'});\n }\n\n /**\n * @param {external:jQuery} img\n * @param {string} src The image source\n * @returns {void}\n */\n function setImg (img, src) {\n if (isLessThanIE7 && (src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png'))) {\n img.attr('pngSrc', src);\n img.css({backgroundImage: 'none', filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\\'' + src + '\\', sizingMethod=\\'scale\\')'});\n } else img.css({backgroundImage: 'url(\\'' + src + '\\')'});\n }\n /**\n * @param {external:jQuery} img\n * @param {Float} y\n * @returns {void}\n */\n function setImgLoc (img, y) {\n img.css({top: y + 'px'});\n }\n /**\n * @param {external:jQuery} obj\n * @param {Float} alpha\n * @returns {void}\n */\n function setAlpha (obj, alpha) {\n obj.css({visibility: alpha > 0 ? 'visible' : 'hidden'});\n if (alpha > 0 && alpha < 100) {\n if (isLessThanIE7) {\n const src = obj.attr('pngSrc');\n if (!isNullish(src) && (\n src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png')\n )) {\n obj.css({\n filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\\'' + src +\n '\\', sizingMethod=\\'scale\\') progid:DXImageTransform.Microsoft.Alpha(opacity=' + alpha + ')'\n });\n } else obj.css({opacity: toFixedNumeric(alpha / 100, 4)});\n } else obj.css({opacity: toFixedNumeric(alpha / 100, 4)});\n } else if (alpha === 0 || alpha === 100) {\n if (isLessThanIE7) {\n const src = obj.attr('pngSrc');\n if (!isNullish(src) && (\n src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png')\n )) {\n obj.css({\n filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\\'' + src +\n '\\', sizingMethod=\\'scale\\')'\n });\n } else obj.css({opacity: ''});\n } else obj.css({opacity: ''});\n }\n }\n\n /**\n * Revert color to original color when opened.\n * @returns {void}\n */\n function revertColor () {\n color.active.val('ahex', color.current.val('ahex'));\n }\n /**\n * Commit the color changes.\n * @returns {void}\n */\n function commitColor () {\n color.current.val('ahex', color.active.val('ahex'));\n }\n /**\n * @param {Event} e\n * @returns {void}\n */\n function radioClicked (e) {\n $(this).parents('tbody:first').find('input:radio[value!=\"' + e.target.value + '\"]').removeAttr('checked');\n setColorMode.call(that, e.target.value);\n }\n /**\n *\n * @returns {void}\n */\n function currentClicked () {\n revertColor.call(that);\n }\n /**\n *\n * @returns {void}\n */\n function cancelClicked () {\n revertColor.call(that);\n settings.window.expandable && hide.call(that);\n typeof cancelCallback === 'function' && cancelCallback.call(that, color.active, cancelButton);\n }\n /**\n *\n * @returns {void}\n */\n function okClicked () {\n commitColor.call(that);\n settings.window.expandable && hide.call(that);\n typeof commitCallback === 'function' && commitCallback.call(that, color.active, okButton);\n }\n /**\n *\n * @returns {void}\n */\n function iconImageClicked () {\n show.call(that);\n }\n /**\n * @param {external:jQuery} ui\n * @returns {void}\n */\n function currentColorChanged (ui) {\n const hex = ui.val('hex');\n currentPreview.css({backgroundColor: (hex && '#' + hex) || 'transparent'});\n setAlpha.call(that, currentPreview, toFixedNumeric(((ui.val('a') || 0) * 100) / 255, 4));\n }\n /**\n * @param {external:jQuery} ui\n * @returns {void}\n */\n function expandableColorChanged (ui) {\n const hex = ui.val('hex');\n const va = ui.val('va');\n iconColor.css({backgroundColor: (hex && '#' + hex) || 'transparent'});\n setAlpha.call(that, iconAlpha, toFixedNumeric(((255 - ((va && va.a) || 0)) * 100) / 255, 4));\n if (settings.window.bindToInput && settings.window.updateInputColor) {\n settings.window.input.css({\n backgroundColor: (hex && '#' + hex) || 'transparent',\n color: isNullish(va) || va.v > 75 ? '#000000' : '#ffffff'\n });\n }\n }\n /**\n * @param {Event} e\n * @returns {void}\n */\n function moveBarMouseDown (e) {\n // const {element} = settings.window, // local copies for YUI compressor\n // {page} = settings.window;\n elementStartX = parseInt(container.css('left'));\n elementStartY = parseInt(container.css('top'));\n pageStartX = e.pageX;\n pageStartY = e.pageY;\n // bind events to document to move window - we will unbind these on mouseup\n $(document).bind('mousemove', documentMouseMove).bind('mouseup', documentMouseUp);\n e.preventDefault(); // prevent attempted dragging of the column\n }\n /**\n * @param {Event} e\n * @returns {false}\n */\n function documentMouseMove (e) {\n container.css({\n left: elementStartX - (pageStartX - e.pageX) + 'px',\n top: elementStartY - (pageStartY - e.pageY) + 'px'\n });\n if (settings.window.expandable && !$.support.boxModel) {\n container.prev().css({\n left: container.css('left'),\n top: container.css('top')\n });\n }\n e.stopPropagation();\n e.preventDefault();\n return false;\n }\n /**\n * @param {Event} e\n * @returns {false}\n */\n function documentMouseUp (e) {\n $(document).unbind('mousemove', documentMouseMove).unbind('mouseup', documentMouseUp);\n e.stopPropagation();\n e.preventDefault();\n return false;\n }\n /**\n * @param {Event} e\n * @returns {false}\n */\n function quickPickClicked (e) {\n e.preventDefault();\n e.stopPropagation();\n color.active.val('ahex', $(this).attr('title') || null, e.target);\n return false;\n }\n /**\n *\n * @returns {void}\n */\n function show () {\n color.current.val('ahex', color.active.val('ahex'));\n /**\n *\n * @returns {void}\n */\n function attachIFrame () {\n if (!settings.window.expandable || $.support.boxModel) return;\n const table = container.find('table:first');\n container.before('<iframe/>');\n container.prev().css({\n width: table.width(),\n height: container.height(),\n opacity: 0,\n position: 'absolute',\n left: container.css('left'),\n top: container.css('top')\n });\n }\n if (settings.window.expandable) {\n $(document.body).children('div.jPicker.Container').css({zIndex: 10});\n container.css({zIndex: 20});\n }\n switch (settings.window.effects.type) {\n case 'fade':\n container.fadeIn(settings.window.effects.speed.show, attachIFrame);\n break;\n case 'slide':\n container.slideDown(settings.window.effects.speed.show, attachIFrame);\n break;\n case 'show':\n default:\n container.show(settings.window.effects.speed.show, attachIFrame);\n break;\n }\n }\n /**\n *\n * @returns {void}\n */\n function hide () {\n /**\n *\n * @returns {void}\n */\n function removeIFrame () {\n if (settings.window.expandable) container.css({zIndex: 10});\n if (!settings.window.expandable || $.support.boxModel) return;\n container.prev().remove();\n }\n switch (settings.window.effects.type) {\n case 'fade':\n container.fadeOut(settings.window.effects.speed.hide, removeIFrame);\n break;\n case 'slide':\n container.slideUp(settings.window.effects.speed.hide, removeIFrame);\n break;\n case 'show':\n default:\n container.hide(settings.window.effects.speed.hide, removeIFrame);\n break;\n }\n }\n /**\n *\n * @returns {void}\n */\n function initialize () {\n const win = settings.window,\n popup = win.expandable ? $(that).next().find('.Container:first') : null;\n container = win.expandable ? $('<div/>') : $(that);\n container.addClass('jPicker Container');\n if (win.expandable) container.hide();\n container.get(0).onselectstart = function (e) {\n if (e.target.nodeName.toLowerCase() !== 'input') return false;\n return true;\n };\n // inject html source code - we are using a single table for this control - I know tables are considered bad, but it takes care of equal height columns and\n // this control really is tabular data, so I believe it is the right move\n const all = color.active.val('all');\n if (win.alphaPrecision < 0) win.alphaPrecision = 0;\n else if (win.alphaPrecision > 2) win.alphaPrecision = 2;\n const controlHtml = `<table class=\"jPicker\" cellpadding=\"0\" cellspacing=\"0\">\n <tbody>\n ${win.expandable ? '<tr><td class=\"Move\" colspan=\"5\">&nbsp;</td></tr>' : ''}\n <tr>\n <td rowspan=\"9\"><h2 class=\"Title\">${win.title || localization.text.title}</h2><div class=\"Map\"><span class=\"Map1\">&nbsp;</span><span class=\"Map2\">&nbsp;</span><span class=\"Map3\">&nbsp;</span><img src=\"${images.clientPath + images.colorMap.arrow.file}\" class=\"Arrow\"/></div></td>\n <td rowspan=\"9\"><div class=\"Bar\"><span class=\"Map1\">&nbsp;</span><span class=\"Map2\">&nbsp;</span><span class=\"Map3\">&nbsp;</span><span class=\"Map4\">&nbsp;</span><span class=\"Map5\">&nbsp;</span><span class=\"Map6\">&nbsp;</span><img src=\"${images.clientPath + images.colorBar.arrow.file}\" class=\"Arrow\"/></div></td>\n <td colspan=\"2\" class=\"Preview\">${localization.text.newColor}<div><span class=\"Active\" title=\"${localization.tooltips.colors.newColor}\">&nbsp;</span><span class=\"Current\" title=\"${localization.tooltips.colors.currentColor}\">&nbsp;</span></div>${localization.text.currentColor}</td>\n <td rowspan=\"9\" class=\"Button\"><input type=\"button\" class=\"Ok\" value=\"${localization.text.ok}\" title=\"${localization.tooltips.buttons.ok}\"/><input type=\"button\" class=\"Cancel\" value=\"${localization.text.cancel}\" title=\"${localization.tooltips.buttons.cancel}\"/><hr/><div class=\"Grid\">&nbsp;</div></td>\n </tr>\n <tr class=\"Hue\">\n <td class=\"Radio\"><label title=\"${localization.tooltips.hue.radio}\"><input type=\"radio\" value=\"h\"${settings.color.mode === 'h' ? ' checked=\"checked\"' : ''}/>H:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"${!isNullish(all) ? all.h : ''}\" title=\"${localization.tooltips.hue.textbox}\"/>&nbsp;&deg;</td>\n </tr>\n <tr class=\"Saturation\">\n <td class=\"Radio\"><label title=\"${localization.tooltips.saturation.radio}\"><input type=\"radio\" value=\"s\"${settings.color.mode === 's' ? ' checked=\"checked\"' : ''}/>S:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"${!isNullish(all) ? all.s : ''}\" title=\"${localization.tooltips.saturation.textbox}\"/>&nbsp;%</td>\n </tr>\n <tr class=\"Value\">\n <td class=\"Radio\"><label title=\"${localization.tooltips.value.radio}\"><input type=\"radio\" value=\"v\"${settings.color.mode === 'v' ? ' checked=\"checked\"' : ''}/>V:</label><br/><br/></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"${!isNullish(all) ? all.v : ''}\" title=\"${localization.tooltips.value.textbox}\"/>&nbsp;%<br/><br/></td>\n </tr>\n <tr class=\"Red\">\n <td class=\"Radio\"><label title=\"${localization.tooltips.red.radio}\"><input type=\"radio\" value=\"r\"${settings.color.mode === 'r' ? ' checked=\"checked\"' : ''}/>R:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"${!isNullish(all) ? all.r : ''}\" title=\"${localization.tooltips.red.textbox}\"/></td>\n </tr>\n <tr class=\"Green\">\n <td class=\"Radio\"><label title=\"${localization.tooltips.green.radio}\"><input type=\"radio\" value=\"g\"${settings.color.mode === 'g' ? ' checked=\"checked\"' : ''}/>G:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"${!isNullish(all) ? all.g : ''}\" title=\"${localization.tooltips.green.textbox}\"/></td>\n </tr>\n <tr class=\"Blue\">\n <td class=\"Radio\"><label title=\"${localization.tooltips.blue.radio}\"><input type=\"radio\" value=\"b\"${settings.color.mode === 'b' ? ' checked=\"checked\"' : ''}/>B:</label></td>\n <td class=\"Text\"><input type=\"text\" maxlength=\"3\" value=\"${!isNullish(all) ? all.b : ''}\" title=\"${localization.tooltips.blue.textbox}\"/></td>\n </tr>\n <tr class=\"Alpha\">\n <td class=\"Radio\">${win.alphaSupport ? `<label title=\"${localization.tooltips.alpha.radio}\"><input type=\"radio\" value=\"a\"${settings.color.mode === 'a' ? ' checked=\"checked\"' : ''}/>A:</label>` : '&nbsp;'}</td>\n <td class=\"Text\">${win.alphaSupport ? `<input type=\"text\" maxlength=\"${3 + win.alphaPrecision}\" value=\"${!isNullish(all) ? toFixedNumeric((all.a * 100) / 255, win.alphaPrecision) : ''}\" title=\"${localization.tooltips.alpha.textbox}\"/>&nbsp;%` : '&nbsp;'}</td>\n </tr>\n <tr class=\"Hex\">\n <td colspan=\"2\" class=\"Text\"><label title=\"${localization.tooltips.hex.textbox}\">#:<input type=\"text\" maxlength=\"6\" class=\"Hex\" value=\"${!isNullish(all) ? all.hex : ''}\"/></label>${win.alphaSupport ? `<input type=\"text\" maxlength=\"2\" class=\"AHex\" value=\"${!isNullish(all) ? all.ahex.substring(6) : ''}\" title=\"${localization.tooltips.hex.alpha}\"/></td>` : '&nbsp;'}\n </tr>\n </tbody></table>`;\n if (win.expandable) {\n container.html(controlHtml);\n if (!$(document.body).children('div.jPicker.Container').length) {\n $(document.body).prepend(container);\n } else {\n $(document.body).children('div.jPicker.Container:last').after(container);\n }\n container.mousedown(\n function () {\n $(document.body).children('div.jPicker.Container').css({zIndex: 10});\n container.css({zIndex: 20});\n }\n );\n container.css( // positions must be set and display set to absolute before source code injection or IE will size the container to fit the window\n {\n left:\n win.position.x === 'left'\n ? (popup.offset().left - 530 - (win.position.y === 'center' ? 25 : 0)) + 'px'\n : win.position.x === 'center'\n ? (popup.offset().left - 260) + 'px'\n : win.position.x === 'right'\n ? (popup.offset().left - 10 + (win.position.y === 'center' ? 25 : 0)) + 'px'\n : win.position.x === 'screenCenter'\n ? (($(document).width() >> 1) - 260) + 'px'\n : (popup.offset().left + parseInt(win.position.x)) + 'px',\n position: 'absolute',\n top: win.position.y === 'top'\n ? (popup.offset().top - 312) + 'px'\n : win.position.y === 'center'\n ? (popup.offset().top - 156) + 'px'\n : win.position.y === 'bottom'\n ? (popup.offset().top + 25) + 'px'\n : (popup.offset().top + parseInt(win.position.y)) + 'px'\n }\n );\n } else {\n container = $(that);\n container.html(controlHtml);\n }\n // initialize the objects to the source code just injected\n const tbody = container.find('tbody:first');\n colorMapDiv = tbody.find('div.Map:first');\n colorBarDiv = tbody.find('div.Bar:first');\n const MapMaps = colorMapDiv.find('span');\n const BarMaps = colorBarDiv.find('span');\n colorMapL1 = MapMaps.filter('.Map1:first');\n colorMapL2 = MapMaps.filter('.Map2:first');\n colorMapL3 = MapMaps.filter('.Map3:first');\n colorBarL1 = BarMaps.filter('.Map1:first');\n colorBarL2 = BarMaps.filter('.Map2:first');\n colorBarL3 = BarMaps.filter('.Map3:first');\n colorBarL4 = BarMaps.filter('.Map4:first');\n colorBarL5 = BarMaps.filter('.Map5:first');\n colorBarL6 = BarMaps.filter('.Map6:first');\n // create color pickers and maps\n colorMap = new Slider(\n colorMapDiv,\n {\n map: {\n width: images.colorMap.width,\n height: images.colorMap.height\n },\n arrow: {\n image: images.clientPath + images.colorMap.arrow.file,\n width: images.colorMap.arrow.width,\n height: images.colorMap.arrow.height\n }\n }\n );\n colorMap.bind(mapValueChanged);\n colorBar = new Slider(\n colorBarDiv,\n {\n map: {\n width: images.colorBar.width,\n height: images.colorBar.height\n },\n arrow: {\n image: images.clientPath + images.colorBar.arrow.file,\n width: images.colorBar.arrow.width,\n height: images.colorBar.arrow.height\n }\n }\n );\n colorBar.bind(colorBarValueChanged);\n colorPicker = new ColorValuePicker(\n tbody,\n color.active,\n win.expandable && win.bindToInput ? win.input : null,\n win.alphaPrecision\n );\n const hex = !isNullish(all) ? all.hex : null,\n preview = tbody.find('.Preview'),\n button = tbody.find('.Button');\n activePreview = preview.find('.Active:first').css({backgroundColor: (hex && '#' + hex) || 'transparent'});\n currentPreview = preview.find('.Current:first').css({backgroundColor: (hex && '#' + hex) || 'transparent'}).bind('click', currentClicked);\n setAlpha.call(that, currentPreview, toFixedNumeric((color.current.val('a') * 100) / 255, 4));\n okButton = button.find('.Ok:first').bind('click', okClicked);\n cancelButton = button.find('.Cancel:first').bind('click', cancelClicked);\n grid = button.find('.Grid:first');\n setTimeout(function () {\n setImg.call(that, colorMapL1, images.clientPath + 'Maps.png');\n setImg.call(that, colorMapL2, images.clientPath + 'Maps.png');\n setImg.call(that, colorMapL3, images.clientPath + 'map-opacity.png');\n setImg.call(that, colorBarL1, images.clientPath + 'Bars.png');\n setImg.call(that, colorBarL2, images.clientPath + 'Bars.png');\n setImg.call(that, colorBarL3, images.clientPath + 'Bars.png');\n setImg.call(that, colorBarL4, images.clientPath + 'Bars.png');\n setImg.call(that, colorBarL5, images.clientPath + 'bar-opacity.png');\n setImg.call(that, colorBarL6, images.clientPath + 'AlphaBar.png');\n setImg.call(that, preview.find('div:first'), images.clientPath + 'preview-opacity.png');\n }, 0);\n tbody.find('td.Radio input').bind('click', radioClicked);\n // initialize quick list\n if (color.quickList && color.quickList.length > 0) {\n let html = '';\n for (let i = 0; i < color.quickList.length; i++) {\n /* if default colors are hex strings, change them to color objects */\n if ((typeof (color.quickList[i])).toString().toLowerCase() === 'string') {\n color.quickList[i] = new Color({hex: color.quickList[i]});\n }\n const alpha = color.quickList[i].val('a');\n let ahex = color.quickList[i].val('ahex');\n if (!win.alphaSupport && ahex) ahex = ahex.substring(0, 6) + 'ff';\n const quickHex = color.quickList[i].val('hex');\n if (!ahex) ahex = '00000000';\n html += '<span class=\"QuickColor\"' + (' title=\"#' + ahex + '\"') + ' style=\"background-color:' + ((quickHex && '#' + quickHex) || '') + ';' + (quickHex ? '' : 'background-image:url(' + images.clientPath + 'NoColor.png)') + (win.alphaSupport && alpha && alpha < 255 ? ';opacity:' + toFixedNumeric(alpha / 255, 4) + ';filter:Alpha(opacity=' + toFixedNumeric(alpha / 2.55, 4) + ')' : '') + '\">&nbsp;</span>';\n }\n setImg.call(that, grid, images.clientPath + 'bar-opacity.png');\n grid.html(html);\n grid.find('.QuickColor').click(quickPickClicked);\n }\n setColorMode.call(that, settings.color.mode);\n color.active.bind(activeColorChanged);\n typeof liveCallback === 'function' && color.active.bind(liveCallback);\n color.current.bind(currentColorChanged);\n // bind to input\n if (win.expandable) {\n that.icon = popup.parents('.Icon:first');\n iconColor = that.icon.find('.Color:first').css({backgroundColor: (hex && '#' + hex) || 'transparent'});\n iconAlpha = that.icon.find('.Alpha:first');\n setImg.call(that, iconAlpha, images.clientPath + 'bar-opacity.png');\n setAlpha.call(that, iconAlpha, toFixedNumeric(((255 - (!isNullish(all) ? all.a : 0)) * 100) / 255, 4));\n iconImage = that.icon.find('.Image:first').css({\n backgroundImage: 'url(\\'' + images.clientPath + images.picker.file + '\\')'\n }).bind('click', iconImageClicked);\n if (win.bindToInput && win.updateInputColor) {\n win.input.css({\n backgroundColor: (hex && '#' + hex) || 'transparent',\n color: isNullish(all) || all.v > 75 ? '#000000' : '#ffffff'\n });\n }\n moveBar = tbody.find('.Move:first').bind('mousedown', moveBarMouseDown);\n color.active.bind(expandableColorChanged);\n } else show.call(that);\n }\n /**\n *\n * @returns {void}\n */\n function destroy () {\n container.find('td.Radio input').unbind('click', radioClicked);\n currentPreview.unbind('click', currentClicked);\n cancelButton.unbind('click', cancelClicked);\n okButton.unbind('click', okClicked);\n if (settings.window.expandable) {\n iconImage.unbind('click', iconImageClicked);\n moveBar.unbind('mousedown', moveBarMouseDown);\n that.icon = null;\n }\n container.find('.QuickColor').unbind('click', quickPickClicked);\n colorMapDiv = null;\n colorBarDiv = null;\n colorMapL1 = null;\n colorMapL2 = null;\n colorMapL3 = null;\n colorBarL1 = null;\n colorBarL2 = null;\n colorBarL3 = null;\n colorBarL4 = null;\n colorBarL5 = null;\n colorBarL6 = null;\n colorMap.destroy();\n colorMap = null;\n colorBar.destroy();\n colorBar = null;\n colorPicker.destroy();\n colorPicker = null;\n activePreview = null;\n currentPreview = null;\n okButton = null;\n cancelButton = null;\n grid = null;\n commitCallback = null;\n cancelCallback = null;\n liveCallback = null;\n container.html('');\n for (let i = 0; i < List.length; i++) {\n if (List[i] === that) {\n List.splice(i, 1);\n i--; // Decrement to ensure we don't miss next item (lgtm warning)\n }\n }\n }\n const {images, localization} = settings; // local copies for YUI compressor\n const color = {\n active: (typeof settings.color.active).toString().toLowerCase() === 'string'\n ? new Color({ahex: !settings.window.alphaSupport && settings.color.active\n ? settings.color.active.substring(0, 6) + 'ff'\n : settings.color.active\n })\n : new Color({ahex: !settings.window.alphaSupport &&\n settings.color.active.val('ahex')\n ? settings.color.active.val('ahex').substring(0, 6) + 'ff'\n : settings.color.active.val('ahex')\n }),\n current: (typeof settings.color.active).toString().toLowerCase() === 'string'\n ? new Color({ahex: !settings.window.alphaSupport && settings.color.active\n ? settings.color.active.substring(0, 6) + 'ff'\n : settings.color.active})\n : new Color({ahex: !settings.window.alphaSupport &&\n settings.color.active.val('ahex')\n ? settings.color.active.val('ahex').substring(0, 6) + 'ff'\n : settings.color.active.val('ahex')\n }),\n quickList: settings.color.quickList\n };\n\n if (typeof commitCallback !== 'function') {\n commitCallback = null;\n }\n if (typeof liveCallback !== 'function') {\n liveCallback = null;\n }\n if (typeof cancelCallback !== 'function') {\n cancelCallback = null;\n }\n\n let elementStartX = null, // Used to record the starting css positions for dragging the control\n elementStartY = null,\n pageStartX = null, // Used to record the mousedown coordinates for dragging the control\n pageStartY = null,\n container = null,\n colorMapDiv = null,\n colorBarDiv = null,\n colorMapL1 = null, // different layers of colorMap and colorBar\n colorMapL2 = null,\n colorMapL3 = null,\n colorBarL1 = null,\n colorBarL2 = null,\n colorBarL3 = null,\n colorBarL4 = null,\n colorBarL5 = null,\n colorBarL6 = null,\n colorMap = null, // color maps\n colorBar = null,\n colorPicker = null,\n activePreview = null, // color boxes above the radio buttons\n currentPreview = null,\n okButton = null,\n cancelButton = null,\n grid = null, // preset colors grid\n iconColor = null, // iconColor for popup icon\n iconAlpha = null, // iconAlpha for popup icon\n iconImage = null, // iconImage popup icon\n moveBar = null; // drag bar\n\n $.extend(true, that, {\n // public properties, methods, and callbacks\n commitCallback, // commitCallback function can be overridden to return the selected color to a method you specify when the user clicks \"OK\"\n liveCallback, // liveCallback function can be overridden to return the selected color to a method you specify in live mode (continuous update)\n cancelCallback, // cancelCallback function can be overridden to a method you specify when the user clicks \"Cancel\"\n color,\n show,\n hide,\n destroy // destroys this control entirely, removing all events and objects, and removing itself from the List\n });\n List.push(that);\n setTimeout(function () {\n initialize.call(that);\n }, 0);\n });\n };\n /**\n * @typedef {PlainObject} external:jQuery.fn.jPickerOptionsIconInfo\n * @property {string} file Color Map/Color Bar/Color Picker arrow icon\n * @property {Float} width\n * @property {Float} height\n */\n /**\n * @typedef {PlainObject} external:jQuery.fn.jPickerOptionsImagesDimensionsArrow\n * @property {Float} width\n * @property {Float} height\n * @property {external:jQuery.fn.jPickerOptionsIconInfo} arrow\n */\n /**\n * @typedef {PlainObject} external:jQuery.fn.jPickerOptionsRadioTextboxLocale\n * @property {string} radio\n * @property {string} textbox\n */\n /**\n * @typedef {PlainObject} external:jQuery.fn.jPickerOptions\n * @property {PlainObject} window\n * @property {string|null} window.title Any title for the jPicker window itself - displays\n * \"Drag Markers To Pick A Color\" if left null\n * @property {PlainObject} window.effects\n * @property {\"slide\"|\"show\"|\"fade\"} window.effects.type Effect used to show/hide an expandable picker\n * @property {PlainObject} window.effects.speed\n * @property {\"fast\"|\"slow\"|Float} window.effects.speed.show Duration of \"show\" effect. Time in milliseconds.\n * @property {\"fast\"|\"slow\"|Float} window.effects.speed.hide Duration of \"hide\" effect. Time in milliseconds\n * @property {PlainObject} window.position\n * @property {\"left\"|\"center\"|\"right\"|\"screenCenter\"|Float} window.position.x Relative px value\n * @property {\"top\"|\"bottom\"|\"center\"|Float} window.position.y Relative px value\n * @property {boolean} window.expandable Defaults to large static picker - set to `true` to make an expandable\n * picker (small icon with popup) - set automatically when binded to input element; added by `$.fn.jPicker`\n * @property {boolean} window.liveUpdate Set `false` if you want the user to have to click \"OK\" before the\n * binded input box updates values (always `true` for expandable picker)\n * @property {boolean} window.alphaSupport Set to `true` to enable alpha picking\n * @property {Float} window.alphaPrecision Set decimal precision for alpha percentage display - hex codes do\n * not map directly to percentage integers - range 0-2\n * @property {boolean} window.updateInputColor Set to `false` to prevent binded input colors from changing\n * @property {boolean} [window.bindToInput] Added by `$.fn.jPicker`\n * @property {external:jQuery} [window.input] Added by `$.fn.jPicker`\n * @property {PlainObject} color\n * @property {\"h\"|\"s\"|\"v\"|\"r\"|\"g\"|\"b\"|\"a\"} color.mode Symbols stand for \"h\" (hue), \"s\" (saturation), \"v\" (value), \"r\" (red), \"g\" (green), \"b\" (blue), \"a\" (alpha)\n * @property {Color|string} color.active Strings are HEX values (e.g. #ffc000) WITH OR WITHOUT the \"#\" prefix\n * @property {Color[]|string[]} color.quickList The quick pick color list\n * Strings are HEX values (e.g. #ffc000) WITH OR WITHOUT the \"#\" prefix\n * @property {PlainObject} images\n * @property {string} images.clientPath Path to image files\n * @property {external:jQuery.fn.jPickerOptionsImagesDimensionsArrow} images.colorMap\n * @property {external:jQuery.fn.jPickerOptionsImagesDimensionsArrow} images.colorBar\n * @property {external:jQuery.fn.jPickerOptionsIconInfo} images.picker\n * @property {PlainObject} localization alter these to change the text presented by the picker (e.g. different language)\n * @property {PlainObject} localization.text\n * @property {string} localization.text.title\n * @property {string} localization.text.newColor\n * @property {string} localization.text.currentColor\n * @property {string} localization.text.ok\n * @property {string} localization.text.cancel\n * @property {PlainObject} localization.tooltips\n * @property {PlainObject} localization.tooltips.colors\n * @property {string} localization.tooltips.colors.newColor\n * @property {string} localization.tooltips.colors.currentColor\n * @property {PlainObject} localization.tooltips.buttons\n * @property {string} localization.tooltips.buttons.ok\n * @property {string} localization.tooltips.buttons.cancel\n * @property {external:jQuery.fn.jPickerOptionsRadioTextboxLocale} localization.tooltips.hue\n * @property {external:jQuery.fn.jPickerOptionsRadioTextboxLocale} localization.tooltips.saturation\n * @property {external:jQuery.fn.jPickerOptionsRadioTextboxLocale} localization.tooltips.value\n * @property {external:jQuery.fn.jPickerOptionsRadioTextboxLocale} localization.tooltips.red\n * @property {external:jQuery.fn.jPickerOptionsRadioTextboxLocale} localization.tooltips.green\n * @property {external:jQuery.fn.jPickerOptionsRadioTextboxLocale} localization.tooltips.blue\n * @property {external:jQuery.fn.jPickerOptionsRadioTextboxLocale} localization.tooltips.alpha\n * @property {PlainObject} localization.tooltips.hex\n * @property {string} localization.tooltips.hex.textbox\n * @property {string} localization.tooltips.hex.alpha\n */\n /**\n * The jPicker defaults - you can change anything in this section (such as the\n * clientPath to your images) without fear of breaking the program.\n * @namespace {external:jQuery.fn.jPickerOptions} defaults\n * @memberof external:jQuery.fn.$.fn.jPicker\n * @borrows external:jQuery.fn.jPickerOptions as external:jQuery.fn.jPicker.defaults\n * @see Source for all of the values\n */\n $.fn.jPicker.defaults = {\n window: {\n title: null,\n effects: {\n type: 'slide',\n speed: {\n show: 'slow',\n hide: 'fast'\n }\n },\n position: {\n x: 'screenCenter',\n y: 'top'\n },\n expandable: false,\n liveUpdate: true,\n alphaSupport: false,\n alphaPrecision: 0,\n updateInputColor: true\n },\n color: {\n mode: 'h',\n active: new Color({ahex: '#ffcc00ff'}),\n quickList: [\n new Color({h: 360, s: 33, v: 100}),\n new Color({h: 360, s: 66, v: 100}),\n new Color({h: 360, s: 100, v: 100}),\n new Color({h: 360, s: 100, v: 75}),\n new Color({h: 360, s: 100, v: 50}),\n new Color({h: 180, s: 0, v: 100}),\n new Color({h: 30, s: 33, v: 100}),\n new Color({h: 30, s: 66, v: 100}),\n new Color({h: 30, s: 100, v: 100}),\n new Color({h: 30, s: 100, v: 75}),\n new Color({h: 30, s: 100, v: 50}),\n new Color({h: 180, s: 0, v: 90}),\n new Color({h: 60, s: 33, v: 100}),\n new Color({h: 60, s: 66, v: 100}),\n new Color({h: 60, s: 100, v: 100}),\n new Color({h: 60, s: 100, v: 75}),\n new Color({h: 60, s: 100, v: 50}),\n new Color({h: 180, s: 0, v: 80}),\n new Color({h: 90, s: 33, v: 100}),\n new Color({h: 90, s: 66, v: 100}),\n new Color({h: 90, s: 100, v: 100}),\n new Color({h: 90, s: 100, v: 75}),\n new Color({h: 90, s: 100, v: 50}),\n new Color({h: 180, s: 0, v: 70}),\n new Color({h: 120, s: 33, v: 100}),\n new Color({h: 120, s: 66, v: 100}),\n new Color({h: 120, s: 100, v: 100}),\n new Color({h: 120, s: 100, v: 75}),\n new Color({h: 120, s: 100, v: 50}),\n new Color({h: 180, s: 0, v: 60}),\n new Color({h: 150, s: 33, v: 100}),\n new Color({h: 150, s: 66, v: 100}),\n new Color({h: 150, s: 100, v: 100}),\n new Color({h: 150, s: 100, v: 75}),\n new Color({h: 150, s: 100, v: 50}),\n new Color({h: 180, s: 0, v: 50}),\n new Color({h: 180, s: 33, v: 100}),\n new Color({h: 180, s: 66, v: 100}),\n new Color({h: 180, s: 100, v: 100}),\n new Color({h: 180, s: 100, v: 75}),\n new Color({h: 180, s: 100, v: 50}),\n new Color({h: 180, s: 0, v: 40}),\n new Color({h: 210, s: 33, v: 100}),\n new Color({h: 210, s: 66, v: 100}),\n new Color({h: 210, s: 100, v: 100}),\n new Color({h: 210, s: 100, v: 75}),\n new Color({h: 210, s: 100, v: 50}),\n new Color({h: 180, s: 0, v: 30}),\n new Color({h: 240, s: 33, v: 100}),\n new Color({h: 240, s: 66, v: 100}),\n new Color({h: 240, s: 100, v: 100}),\n new Color({h: 240, s: 100, v: 75}),\n new Color({h: 240, s: 100, v: 50}),\n new Color({h: 180, s: 0, v: 20}),\n new Color({h: 270, s: 33, v: 100}),\n new Color({h: 270, s: 66, v: 100}),\n new Color({h: 270, s: 100, v: 100}),\n new Color({h: 270, s: 100, v: 75}),\n new Color({h: 270, s: 100, v: 50}),\n new Color({h: 180, s: 0, v: 10}),\n new Color({h: 300, s: 33, v: 100}),\n new Color({h: 300, s: 66, v: 100}),\n new Color({h: 300, s: 100, v: 100}),\n new Color({h: 300, s: 100, v: 75}),\n new Color({h: 300, s: 100, v: 50}),\n new Color({h: 180, s: 0, v: 0}),\n new Color({h: 330, s: 33, v: 100}),\n new Color({h: 330, s: 66, v: 100}),\n new Color({h: 330, s: 100, v: 100}),\n new Color({h: 330, s: 100, v: 75}),\n new Color({h: 330, s: 100, v: 50}),\n new Color()\n ]\n },\n images: {\n clientPath: '/jPicker/images/',\n colorMap: {\n width: 256,\n height: 256,\n arrow: {\n file: 'mappoint.gif',\n width: 15,\n height: 15\n }\n },\n colorBar: {\n width: 20,\n height: 256,\n arrow: {\n file: 'rangearrows.gif',\n width: 20,\n height: 7\n }\n },\n picker: {\n file: 'picker.gif',\n width: 25,\n height: 24\n }\n },\n localization: {\n text: {\n title: 'Drag Markers To Pick A Color',\n newColor: 'new',\n currentColor: 'current',\n ok: 'OK',\n cancel: 'Cancel'\n },\n tooltips: {\n colors: {\n newColor: 'New Color - Press &ldquo;OK&rdquo; To Commit',\n currentColor: 'Click To Revert To Original Color'\n },\n buttons: {\n ok: 'Commit To This Color Selection',\n cancel: 'Cancel And Revert To Original Color'\n },\n hue: {\n radio: 'Set To &ldquo;Hue&rdquo; Color Mode',\n textbox: 'Enter A &ldquo;Hue&rdquo; Value (0-360&deg;)'\n },\n saturation: {\n radio: 'Set To &ldquo;Saturation&rdquo; Color Mode',\n textbox: 'Enter A &ldquo;Saturation&rdquo; Value (0-100%)'\n },\n value: {\n radio: 'Set To &ldquo;Value&rdquo; Color Mode',\n textbox: 'Enter A &ldquo;Value&rdquo; Value (0-100%)'\n },\n red: {\n radio: 'Set To &ldquo;Red&rdquo; Color Mode',\n textbox: 'Enter A &ldquo;Red&rdquo; Value (0-255)'\n },\n green: {\n radio: 'Set To &ldquo;Green&rdquo; Color Mode',\n textbox: 'Enter A &ldquo;Green&rdquo; Value (0-255)'\n },\n blue: {\n radio: 'Set To &ldquo;Blue&rdquo; Color Mode',\n textbox: 'Enter A &ldquo;Blue&rdquo; Value (0-255)'\n },\n alpha: {\n radio: 'Set To &ldquo;Alpha&rdquo; Color Mode',\n textbox: 'Enter A &ldquo;Alpha&rdquo; Value (0-100)'\n },\n hex: {\n textbox: 'Enter A &ldquo;Hex&rdquo; Color Value (#000000-#ffffff)',\n alpha: 'Enter A &ldquo;Alpha&rdquo; Value (#00-#ff)'\n }\n }\n }\n };\n return $;\n};\n\nexport default jPicker;\n","/* eslint-disable unicorn/no-fn-reference-in-iterator */\n/* globals jQuery */\n/**\n * Localizing script for SVG-edit UI.\n * @module locale\n * @license MIT\n *\n * @copyright 2010 Narendra Sisodya\n * @copyright 2010 Alexis Deveria\n *\n */\n\n/**\n * Used, for example, in the ImageLibs extension, to present libraries\n * (with name/URL/description) in order.\n * @typedef {GenericArray<module:locale.LocaleStrings>} module:locale.LocaleArray\n*/\n/**\n * The string keys of the object are two-letter language codes.\n * @tutorial LocaleDocs\n * @typedef {PlainObject<string, string|module:locale.LocaleStrings|module:locale.LocaleArray>} module:locale.LocaleStrings\n */\n// keyed to an array of objects with \"id\" and \"title\" or \"textContent\" properties\n/**\n * @typedef {PlainObject<string, string>} module:locale.LocaleSelectorValue\n */\n\nimport {importSetGlobalDefault} from '../external/dynamic-import-polyfill/importModule.js';\n\nconst $ = jQuery;\n\nlet langParam;\n\n/**\n * Looks for elements to localize using the supplied `obj` to indicate\n * on which selectors (or IDs if `ids` is set to `true`) to set its\n * strings (with selectors relative to the editor root element). All\n * keys will be translated, but for each selector, only the first item\n * found matching will be modified.\n * If the type is `content`, the selector-identified element's children\n * will be checked, and the first (non-empty) text (placeholder) node\n * found will have its text replaced.\n * If the type is `title`, the element's `title`\n * property will be set.\n * If the type is `aria-label`, the element's `aria-label` attribute\n * will be set (i.e., instructions for screen readers when there is\n * otherwise no visible text to be read for the function of the form\n * control).\n * @param {\"content\"|\"title\"} type\n * @param {module:locale.LocaleSelectorValue} obj Selectors or IDs keyed to strings\n * @param {boolean} ids\n * @returns {void}\n*/\nexport const setStrings = function (type, obj, ids) {\n // Root element to look for element from\n const parent = $('#svg_editor').parent();\n Object.entries(obj).forEach(([sel, val]) => {\n if (!val) {\n console.log(sel); // eslint-disable-line no-console\n return; // keep old text when has no translation\n }\n\n if (ids) { sel = '#' + sel; }\n const $elem = parent.find(sel);\n if ($elem.length) {\n const elem = $elem[0];\n\n switch (type) {\n case 'aria-label':\n elem.setAttribute('aria-label', val);\n break;\n case 'content':\n [...elem.childNodes].some((node) => {\n if (node.nodeType === 3 /* Node.TEXT_NODE */ &&\n node.textContent.trim()\n ) {\n node.textContent = val;\n return true;\n }\n return false;\n });\n break;\n\n case 'title':\n elem.title = val;\n break;\n }\n } else {\n console.log('Missing element for localization: ' + sel); // eslint-disable-line no-console\n }\n });\n};\n\n/**\n* The \"data\" property is generally set to an an array of objects with\n* \"id\" and \"title\" or \"textContent\" properties.\n* @typedef {PlainObject} module:locale.AddLangExtensionLocaleData\n* @property {module:locale.LocaleStrings[]} data See {@tutorial LocaleDocs}\n*/\n\n/**\n* @interface module:locale.LocaleEditorInit\n*/\n/**\n * @function module:locale.LocaleEditorInit#addLangData\n * @param {string} langParam\n * @returns {module:locale.AddLangExtensionLocaleData}\n*/\n\nlet editor_;\n/**\n * Sets the current editor instance (on which `addLangData`) exists.\n * @function init\n * @memberof module:locale\n * @param {module:locale.LocaleEditorInit} editor\n * @returns {void}\n*/\nexport const init = (editor) => {\n editor_ = editor;\n};\n\n/**\n* @typedef {PlainObject} module:locale.LangAndData\n* @property {string} langParam\n* @property {module:locale.LocaleStrings} langData\n*/\n\n/**\n* @function module:locale.readLang\n* @param {module:locale.LocaleStrings} langData See {@tutorial LocaleDocs}\n* @fires module:svgcanvas.SvgCanvas#event:ext_addLangData\n* @returns {Promise<module:locale.LangAndData>} Resolves to [`LangAndData`]{@link module:locale.LangAndData}\n*/\nexport const readLang = async function (langData) {\n const more = await editor_.addLangData(langParam);\n $.each(more, function (i, m) {\n if (m.data) {\n langData = $.merge(langData, m.data);\n }\n });\n\n // Old locale file, do nothing for now.\n if (!langData.tools) { return undefined; }\n\n const {\n tools,\n // misc,\n properties, config, layers, common, ui\n } = langData;\n\n setStrings('content', {\n // Todo: Add this powered by (probably by default) but with config to remove\n // copyrightLabel: misc.powered_by, // Currently commented out in svg-editor.html\n curve_segments: properties.curve_segments,\n fitToContent: tools.fitToContent,\n fit_to_all: tools.fit_to_all,\n fit_to_canvas: tools.fit_to_canvas,\n fit_to_layer_content: tools.fit_to_layer_content,\n fit_to_sel: tools.fit_to_sel,\n\n icon_large: config.icon_large,\n icon_medium: config.icon_medium,\n icon_small: config.icon_small,\n icon_xlarge: config.icon_xlarge,\n image_opt_embed: config.image_opt_embed,\n image_opt_ref: config.image_opt_ref,\n includedImages: config.included_images,\n\n largest_object: tools.largest_object,\n\n layersLabel: layers.layers,\n page: tools.page,\n relativeToLabel: tools.relativeTo,\n selLayerLabel: layers.move_elems_to,\n selectedPredefined: config.select_predefined,\n\n selected_objects: tools.selected_objects,\n smallest_object: tools.smallest_object,\n straight_segments: properties.straight_segments,\n\n svginfo_bg_url: config.editor_img_url + ':',\n svginfo_bg_note: config.editor_bg_note,\n svginfo_change_background: config.background,\n svginfo_dim: config.doc_dims,\n svginfo_editor_prefs: config.editor_prefs,\n svginfo_height: common.height,\n svginfo_icons: config.icon_size,\n svginfo_image_props: config.image_props,\n svginfo_lang: config.language,\n svginfo_title: config.doc_title,\n svginfo_width: common.width,\n\n tool_docprops_cancel: common.cancel,\n tool_docprops_save: common.ok,\n\n tool_source_cancel: common.cancel,\n tool_source_save: common.ok,\n\n tool_prefs_cancel: common.cancel,\n tool_prefs_save: common.ok,\n\n sidepanel_handle: layers.layers.split('').join(' '),\n\n tool_clear: tools.new_doc,\n tool_docprops: tools.docprops,\n tool_export: tools.export_img,\n tool_import: tools.import_doc,\n tool_open: tools.open_doc,\n tool_save: tools.save_doc,\n tool_editor_prefs: config.editor_prefs,\n tool_editor_homepage: tools.editor_homepage,\n\n svginfo_units_rulers: config.units_and_rulers,\n svginfo_rulers_onoff: config.show_rulers,\n svginfo_unit: config.base_unit,\n\n svginfo_grid_settings: config.grid,\n svginfo_snap_onoff: config.snapping_onoff,\n svginfo_snap_step: config.snapping_stepsize,\n svginfo_grid_color: config.grid_color\n }, true);\n\n // Context menus\n const opts = {};\n [\n 'cut', 'copy', 'paste', 'paste_in_place', 'delete',\n 'group', 'ungroup', 'move_front', 'move_up',\n 'move_down', 'move_back'\n ].forEach((item) => {\n opts['#cmenu_canvas a[href=\"#' + item + '\"]'] = tools[item];\n });\n\n ['dupe', 'merge_down', 'merge_all'].forEach((item) => {\n opts['#cmenu_layers a[href=\"#' + item + '\"]'] = layers[item];\n });\n\n opts['#cmenu_layers a[href=\"#delete\"]'] = layers.del;\n\n setStrings('content', opts);\n\n const ariaLabels = {};\n Object.entries({\n tool_blur: properties.blur,\n tool_position: tools.align_to_page,\n tool_font_family: properties.font_family,\n zoom_panel: ui.zoom_level,\n stroke_linejoin: properties.linejoin_miter,\n stroke_linecap: properties.linecap_butt,\n tool_opacity: properties.opacity\n }).forEach(([id, value]) => {\n ariaLabels['#' + id + ' button'] = value;\n });\n Object.entries({\n group_opacity: properties.opacity,\n zoom: ui.zoom_level\n }).forEach(([id, value]) => {\n ariaLabels['#' + id] = value;\n });\n setStrings('aria-label', ariaLabels);\n\n setStrings('title', {\n align_relative_to: tools.align_relative_to,\n circle_cx: properties.circle_cx,\n circle_cy: properties.circle_cy,\n circle_r: properties.circle_r,\n cornerRadiusLabel: properties.corner_radius,\n ellipse_cx: properties.ellipse_cx,\n ellipse_cy: properties.ellipse_cy,\n ellipse_rx: properties.ellipse_rx,\n ellipse_ry: properties.ellipse_ry,\n fill_color: properties.fill_color,\n font_family: properties.font_family,\n idLabel: properties.id,\n image_height: properties.image_height,\n image_url: properties.image_url,\n image_width: properties.image_width,\n layer_delete: layers.del,\n layer_down: layers.move_down,\n layer_new: layers.new,\n layer_rename: layers.rename,\n layer_moreopts: common.more_opts,\n layer_up: layers.move_up,\n line_x1: properties.line_x1,\n line_x2: properties.line_x2,\n line_y1: properties.line_y1,\n line_y2: properties.line_y2,\n linecap_butt: properties.linecap_butt,\n linecap_round: properties.linecap_round,\n linecap_square: properties.linecap_square,\n linejoin_bevel: properties.linejoin_bevel,\n linejoin_miter: properties.linejoin_miter,\n linejoin_round: properties.linejoin_round,\n main_icon: tools.main_menu,\n palette: ui.palette_info,\n zoom_panel: ui.zoom_level,\n path_node_x: properties.node_x,\n path_node_y: properties.node_y,\n rect_height_tool: properties.rect_height,\n rect_width_tool: properties.rect_width,\n seg_type: properties.seg_type,\n selLayerNames: layers.move_selected,\n selected_x: properties.pos_x,\n selected_y: properties.pos_y,\n stroke_color: properties.stroke_color,\n stroke_style: properties.stroke_style,\n stroke_width: properties.stroke_width,\n svginfo_title: config.doc_title,\n text: properties.text_contents,\n toggle_stroke_tools: ui.toggle_stroke_tools,\n tool_add_subpath: tools.add_subpath,\n tool_alignbottom: tools.align_bottom,\n tool_aligncenter: tools.align_center,\n tool_alignleft: tools.align_left,\n tool_alignmiddle: tools.align_middle,\n tool_alignright: tools.align_right,\n tool_aligntop: tools.align_top,\n tool_angle: properties.angle,\n tool_blur: properties.blur,\n tool_bold: properties.bold,\n tool_circle: tools.mode_circle,\n tool_clone: tools.clone,\n tool_clone_multi: tools.clone,\n tool_delete: tools.del,\n tool_delete_multi: tools.del,\n tool_ellipse: tools.mode_ellipse,\n tool_fhellipse: tools.mode_fhellipse,\n tool_fhpath: tools.mode_fhpath,\n tool_fhrect: tools.mode_fhrect,\n tool_font_size: properties.font_size,\n tool_group_elements: tools.group_elements,\n tool_make_link: tools.make_link,\n tool_link_url: tools.set_link_url,\n tool_image: tools.mode_image,\n tool_italic: properties.italic,\n tool_line: tools.mode_line,\n tool_move_bottom: tools.move_bottom,\n tool_move_top: tools.move_top,\n tool_node_clone: tools.node_clone,\n tool_node_delete: tools.node_delete,\n tool_node_link: tools.node_link,\n tool_opacity: properties.opacity,\n tool_openclose_path: tools.openclose_path,\n tool_path: tools.mode_path,\n tool_position: tools.align_to_page,\n tool_rect: tools.mode_rect,\n tool_redo: tools.redo,\n tool_reorient: tools.reorient_path,\n tool_select: tools.mode_select,\n tool_source: tools.source_save,\n tool_square: tools.mode_square,\n tool_text: tools.mode_text,\n tool_topath: tools.to_path,\n tool_undo: tools.undo,\n tool_ungroup: tools.ungroup,\n tool_wireframe: tools.wireframe_mode,\n tool_zoom: tools.mode_zoom,\n url_notice: tools.no_embed\n\n }, true);\n\n return {langParam, langData};\n};\n\n/**\n *\n * @function module:locale.putLocale\n * @param {string} givenParam\n * @param {string[]} goodLangs\n * @param {{langPath: string}} conf\n * @fires module:svgcanvas.SvgCanvas#event:ext_addLangData\n * @fires module:svgcanvas.SvgCanvas#event:ext_langReady\n * @fires module:svgcanvas.SvgCanvas#event:ext_langChanged\n * @returns {Promise<module:locale.LangAndData>} Resolves to result of {@link module:locale.readLang}\n*/\nexport const putLocale = async function (givenParam, goodLangs, conf) {\n if (givenParam) {\n langParam = givenParam;\n } else if (navigator.userLanguage) { // Explorer\n langParam = navigator.userLanguage;\n } else if (navigator.language) { // FF, Opera, ...\n langParam = navigator.language;\n }\n\n console.log('Lang: ' + langParam); // eslint-disable-line no-console\n\n // Set to English if language is not in list of good langs\n if (!goodLangs.includes(langParam) && langParam !== 'test') {\n langParam = 'en';\n }\n\n const url = conf.langPath + 'lang.' + langParam + '.js';\n return readLang(\n // Todo: Replace this with `return import(url);` when\n // `import()` widely supported\n await importSetGlobalDefault(url, {\n global: 'svgEditorLang_' + langParam.replace(/-/g, '_')\n })\n );\n};\n","function _slicedToArray(arr, i) {\n return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();\n}\n\nfunction _arrayWithHoles(arr) {\n if (Array.isArray(arr)) return arr;\n}\n\nfunction _iterableToArrayLimit(arr, i) {\n if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === \"[object Arguments]\")) {\n return;\n }\n\n var _arr = [];\n var _n = true;\n var _d = false;\n var _e = undefined;\n\n try {\n for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {\n _arr.push(_s.value);\n\n if (i && _arr.length === i) break;\n }\n } catch (err) {\n _d = true;\n _e = err;\n } finally {\n try {\n if (!_n && _i[\"return\"] != null) _i[\"return\"]();\n } finally {\n if (_d) throw _e;\n }\n }\n\n return _arr;\n}\n\nfunction _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance\");\n}\n\nfunction loadStylesheets(stylesheets) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n beforeDefault = _ref.before,\n afterDefault = _ref.after,\n faviconDefault = _ref.favicon,\n canvasDefault = _ref.canvas,\n _ref$image = _ref.image,\n imageDefault = _ref$image === void 0 ? true : _ref$image,\n acceptErrors = _ref.acceptErrors;\n\n stylesheets = Array.isArray(stylesheets) ? stylesheets : [stylesheets];\n\n function setupLink(stylesheetURL) {\n var options = {};\n\n if (Array.isArray(stylesheetURL)) {\n var _stylesheetURL = stylesheetURL;\n\n var _stylesheetURL2 = _slicedToArray(_stylesheetURL, 2);\n\n stylesheetURL = _stylesheetURL2[0];\n var _stylesheetURL2$ = _stylesheetURL2[1];\n options = _stylesheetURL2$ === void 0 ? {} : _stylesheetURL2$;\n }\n\n var _options = options,\n _options$favicon = _options.favicon,\n favicon = _options$favicon === void 0 ? faviconDefault : _options$favicon;\n var _options2 = options,\n _options2$before = _options2.before,\n before = _options2$before === void 0 ? beforeDefault : _options2$before,\n _options2$after = _options2.after,\n after = _options2$after === void 0 ? afterDefault : _options2$after,\n _options2$canvas = _options2.canvas,\n canvas = _options2$canvas === void 0 ? canvasDefault : _options2$canvas,\n _options2$image = _options2.image,\n image = _options2$image === void 0 ? imageDefault : _options2$image;\n\n function addLink() {\n if (before) {\n before.before(link);\n } else if (after) {\n after.after(link);\n } else {\n // eslint-disable-next-line unicorn/prefer-node-append\n document.head.appendChild(link);\n }\n }\n\n var link = document.createElement('link'); // eslint-disable-next-line promise/avoid-new\n\n return new Promise(function (resolve, reject) {\n var rej = reject;\n\n if (acceptErrors) {\n rej = typeof acceptErrors === 'function' ? function (error) {\n acceptErrors({\n error: error,\n stylesheetURL: stylesheetURL,\n options: options,\n resolve: resolve,\n reject: reject\n });\n } : resolve;\n }\n\n if (stylesheetURL.endsWith('.css')) {\n favicon = false;\n } else if (stylesheetURL.endsWith('.ico')) {\n favicon = true;\n }\n\n if (favicon) {\n link.rel = 'shortcut icon';\n link.type = 'image/x-icon';\n\n if (image === false) {\n link.href = stylesheetURL;\n addLink();\n resolve(link);\n return;\n }\n\n var cnv = document.createElement('canvas');\n cnv.width = 16;\n cnv.height = 16;\n var context = cnv.getContext('2d');\n var img = document.createElement('img');\n img.addEventListener('error', function (error) {\n reject(error);\n });\n img.addEventListener('load', function () {\n context.drawImage(img, 0, 0);\n link.href = canvas ? cnv.toDataURL('image/x-icon') : stylesheetURL;\n addLink();\n resolve(link);\n });\n img.src = stylesheetURL;\n return;\n }\n\n link.rel = 'stylesheet';\n link.type = 'text/css';\n link.href = stylesheetURL;\n addLink();\n link.addEventListener('error', function (error) {\n rej(error);\n });\n link.addEventListener('load', function () {\n resolve(link);\n });\n });\n }\n\n return Promise.all(stylesheets.map(function (stylesheetURL) {\n return setupLink(stylesheetURL);\n }));\n}\n\nexport default loadStylesheets;\n","/* globals jQuery */\n/**\n* The main module for the visual SVG Editor.\n*\n* @license MIT\n*\n* @copyright 2010 Alexis Deveria\n* 2010 Pavol Rusnak\n* 2010 Jeff Schiller\n* 2010 Narendra Sisodiya\n* 2014 Brett Zamir\n* @exports module:SVGEditor\n* @borrows module:locale.putLocale as putLocale\n* @borrows module:locale.readLang as readLang\n* @borrows module:locale.setStrings as setStrings\n*/\n\nimport './touch.js';\nimport {NS} from './namespaces.js';\nimport {isWebkit, isChrome, isGecko, isIE, isMac, isTouch} from './browser.js';\nimport * as Utils from './utilities.js';\nimport {getTypeMap, convertUnit, isValidUnit} from './units.js';\nimport {\n hasCustomHandler, getCustomHandler, injectExtendedContextMenuItemsIntoDom\n} from './contextmenu.js';\nimport {importSetGlobalDefault} from './external/dynamic-import-polyfill/importModule.js';\nimport deparam from './external/deparam/deparam.esm.js';\n\nimport SvgCanvas from './svgcanvas.js';\nimport Layer from './layer.js';\n\nimport jQueryPluginJSHotkeys from './js-hotkeys/jquery.hotkeys.min.js';\nimport jQueryPluginSVGIcons from './svgicons/jQuery.svgIcons.js';\nimport jQueryPluginJGraduate from './jgraduate/jQuery.jGraduate.js';\nimport jQueryPluginSpinButton from './spinbtn/jQuery.SpinButton.js';\nimport jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`\nimport jQueryPluginContextMenu from './contextmenu/jQuery.contextMenu.js';\nimport jQueryPluginJPicker from './jgraduate/jQuery.jPicker.js';\nimport jQueryPluginDBox from './dbox.js';\n\nimport {\n readLang, putLocale,\n setStrings,\n init as localeInit\n} from './locale/locale.js';\nimport loadStylesheets from './external/load-stylesheets/index-es.js';\n\nconst editor = {};\n\nconst $ = [\n jQueryPluginJSHotkeys, jQueryPluginSVGIcons, jQueryPluginJGraduate,\n jQueryPluginSpinButton, jQueryPluginSVG, jQueryPluginContextMenu, jQueryPluginJPicker\n].reduce((jq, func) => func(jq), jQuery);\n\n/*\nif (!$.loadingStylesheets) {\n $.loadingStylesheets = [];\n}\n*/\n\nconst homePage = 'https://github.com/SVG-Edit/svgedit';\n\nconst stylesheet = 'svg-editor.css';\nif (!$.loadingStylesheets.includes(stylesheet)) {\n $.loadingStylesheets.push(stylesheet);\n}\nconst favicon = 'images/logo.png';\nif ($.loadingStylesheets.some((item) => {\n return !Array.isArray(item) || item[0] !== favicon;\n})) {\n $.loadingStylesheets.push([favicon, {favicon: true}]);\n}\n\n// EDITOR PROPERTIES: (defined below)\n// curPrefs, curConfig, canvas, storage, uiStrings\n//\n// STATE MAINTENANCE PROPERTIES\n/**\n* @type {Float}\n*/\neditor.tool_scale = 1; // Dependent on icon size, so any use to making configurable instead? Used by `jQuery.SpinButton.js`\n/**\n* @type {Integer}\n*/\neditor.exportWindowCt = 0;\n/**\n* @type {boolean}\n*/\neditor.langChanged = false;\n/**\n* @type {boolean}\n*/\neditor.showSaveWarning = false;\n/**\n * Will be set to a boolean by `ext-storage.js`\n * @type {\"ignore\"|\"waiting\"|\"closed\"}\n*/\neditor.storagePromptState = 'ignore';\n\nconst callbacks = [],\n /**\n * @typedef {\"s\"|\"m\"|\"l\"|\"xl\"|Float} module:SVGEditor.IconSize\n */\n /**\n * Preferences.\n * @interface module:SVGEditor.Prefs\n * @property {string} [lang=\"en\"] Two-letter language code. The language must exist in the Editor Preferences language list. Defaults to \"en\" if `locale.js` detection does not detect another language.\n * @property {module:SVGEditor.IconSize} [iconsize=\"s\"|\"m\"] Size of the toolbar icons. Will default to 's' if the window height is smaller than the minimum height and 'm' otherwise.\n * @property {string} [bkgd_color=\"#FFF\"] Color hex for canvas background color. Defaults to white.\n * @property {string} [bkgd_url=\"\"] Background raster image URL. This image will fill the background of the document; useful for tracing purposes.\n * @property {\"embed\"|\"ref\"} [img_save=\"embed\"] Defines whether included raster images should be saved as Data URIs when possible, or as URL references. Settable in the Document Properties dialog.\n * @property {boolean} [save_notice_done=false] Used to track alert status\n * @property {boolean} [export_notice_done=false] Used to track alert status\n * @todo `save_notice_done` and `export_notice_done` should be changed to flags rather than preferences\n */\n /**\n * @namespace {module:SVGEditor.Prefs} defaultPrefs\n * @memberof module:SVGEditor~\n * @implements {module:SVGEditor.Prefs}\n */\n // The iteration algorithm for defaultPrefs does not currently support array/objects\n defaultPrefs = /** @lends module:SVGEditor~defaultPrefs */ {\n // EDITOR OPTIONS (DIALOG)\n /**\n * Default to \"en\" if locale.js detection does not detect another language.\n */\n lang: '',\n /**\n * Will default to 's' if the window height is smaller than the minimum\n * height and 'm' otherwise.\n */\n iconsize: '',\n bkgd_color: '#FFF',\n bkgd_url: '',\n // DOCUMENT PROPERTIES (DIALOG)\n img_save: 'embed',\n // ALERT NOTICES\n // Only shows in UI as far as alert notices, but useful to remember, so keeping as pref\n save_notice_done: false,\n export_notice_done: false\n },\n /**\n * @name module:SVGEditor~defaultExtensions\n * @type {string[]}\n */\n defaultExtensions = [\n 'ext-connector.js',\n 'ext-eyedropper.js',\n 'ext-grid.js',\n 'ext-imagelib.js',\n 'ext-markers.js',\n 'ext-overview_window.js',\n 'ext-panning.js',\n 'ext-polygon.js',\n 'ext-shapes.js',\n 'ext-star.js',\n 'ext-storage.js'\n ],\n /**\n * @typedef {\"@default\"|string} module:SVGEditor.Stylesheet `@default` will automatically load all of the default CSS paths for SVGEditor\n */\n /**\n * @typedef {GenericArray} module:SVGEditor.XYDimensions\n * @property {Integer} length 2\n * @property {Float} 0\n * @property {Float} 1\n */\n /**\n * @tutorial ConfigOptions\n * @interface module:SVGEditor.Config\n * @property {string} [canvasName=\"default\"] Used to namespace storage provided via `ext-storage.js`; you can use this if you wish to have multiple independent instances of SVG Edit on the same domain\n * @property {boolean} [no_save_warning=false] If `true`, prevents the warning dialog box from appearing when closing/reloading the page. Mostly useful for testing.\n * @property {string} [imgPath=\"images/\"] The path where the SVG icons are located, with trailing slash. Note that as of version 2.7, this is not configurable by URL for security reasons.\n * @property {string} [langPath=\"locale/\"] The path where the language files are located, with trailing slash. Default will be changed to `../dist/locale/` if this is a modular load. Note that as of version 2.7, this is not configurable by URL for security reasons.\n * @property {string} [extPath=\"extensions/\"] The path used for extension files, with trailing slash. Default will be changed to `../dist/extensions/` if this is a modular load. Note that as of version 2.7, this is not configurable by URL for security reasons.\n * @property {string} [canvgPath=\"canvg/\"] The path used for `canvg` files, with trailing slash. Default will be changed to `../dist/` if this is a modular load.\n * @property {string} [jspdfPath=\"jspdf/\"] The path used for `jsPDF` files, with trailing slash. Default will be changed to `../dist/` if this is a modular load.\n * @property {string} [extIconsPath=\"extensions/\"] The path used for extension icons, with trailing slash.\n * @property {string} [jGraduatePath=\"jgraduate/images/\"] The path where jGraduate images are located. Note that as of version 2.7, this is not configurable by URL for security reasons.\n * @property {boolean} [preventAllURLConfig=false] Set to `true` to override the ability for URLs to set non-content configuration (including extension config). Must be set early, i.e., in `svgedit-config-iife.js`; extension loading is too late!\n * @property {boolean} [preventURLContentLoading=false] Set to `true` to override the ability for URLs to set URL-based SVG content. Must be set early, i.e., in `svgedit-config-iife.js`; extension loading is too late!\n * @property {boolean} [lockExtensions=false] Set to `true` to override the ability for URLs to set their own extensions; disallowed in URL setting. There is no need for this when `preventAllURLConfig` is used. Must be set early, i.e., in `svgedit-config-iife.js`; extension loading is too late!\n * @property {boolean} [noDefaultExtensions=false] If set to `true`, prohibits automatic inclusion of default extensions (though \"extensions\" can still be used to add back any desired default extensions along with any other extensions). This can only be meaningfully used in `svgedit-config-iife.js` or in the URL\n * @property {boolean} [noStorageOnLoad=false] Some interaction with `ext-storage.js`; prevent even the loading of previously saved local storage.\n * @property {boolean} [forceStorage=false] Some interaction with `ext-storage.js`; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not (and may be required by law in some regions)\n * @property {boolean} [emptyStorageOnDecline=false] Used by `ext-storage.js`; empty any prior storage if the user declines to store\n * @property {boolean} [avoidClientSide=false] DEPRECATED (use `avoidClientSideDownload` instead); Used by `ext-server_opensave.js`; set to `true` if you wish to always save to server and not only as fallback when client support is lacking\n * @property {boolean} [avoidClientSideDownload=false] Used by `ext-server_opensave.js`; set to `true` if you wish to always save to server and not only as fallback when client support is lacking\n * @property {boolean} [avoidClientSideOpen=false] Used by `ext-server_opensave.js`; set to `true` if you wish to always open from the server and not only as fallback when FileReader client support is lacking\n * @property {string[]} [extensions=module:SVGEditor~defaultExtensions] Extensions to load on startup. Use an array in `setConfig` and comma separated file names in the URL. Extension names must begin with \"ext-\". Note that as of version 2.7, paths containing \"/\", \"\\\", or \":\", are disallowed for security reasons. Although previous versions of this list would entirely override the default list, as of version 2.7, the defaults will always be added to this explicit list unless the configuration `noDefaultExtensions` is included.\n * @property {module:SVGEditor.Stylesheet[]} [stylesheets=[\"@default\"]] An array of required stylesheets to load in parallel; include the value `\"@default\"` within this array to ensure all default stylesheets are loaded.\n * @property {string[]} [allowedOrigins=[]] Used by `ext-xdomain-messaging.js` to indicate which origins are permitted for cross-domain messaging (e.g., between the embedded editor and main editor code). Besides explicit domains, one might add '*' to allow all domains (not recommended for privacy/data integrity of your user's content!), `window.location.origin` for allowing the same origin (should be safe if you trust all apps on your domain), 'null' to allow `file:///` URL usage\n * @property {null|PlainObject} [colorPickerCSS=null] Object of CSS properties mapped to values (for jQuery) to apply to the color picker. See {@link http://api.jquery.com/css/#css-properties}. A `null` value (the default) will cause the CSS to default to `left` with a position equal to that of the `fill_color` or `stroke_color` element minus 140, and a `bottom` equal to 40\n * @property {string} [paramurl] This was available via URL only. Allowed an un-encoded URL within the query string (use \"url\" or \"source\" with a data: URI instead)\n * @property {Float} [canvas_expansion=3] The minimum area visible outside the canvas, as a multiple of the image dimensions. The larger the number, the more one can scroll outside the canvas.\n * @property {PlainObject} [initFill] Init fill properties\n * @property {string} [initFill.color=\"FF0000\"] The initial fill color. Must be a hex code string. Defaults to solid red.\n * @property {Float} [initFill.opacity=1] The initial fill opacity. Must be a number between 0 and 1\n * @property {PlainObject} [initStroke] Init stroke properties\n * @property {Float} [initStroke.width=5] The initial stroke width. Must be a positive number.\n * @property {string} [initStroke.color=\"000000\"] The initial stroke color. Must be a hex code. Defaults to solid black.\n * @property {Float} [initStroke.opacity=1] The initial stroke opacity. Must be a number between 0 and 1.\n * @property {PlainObject} text Text style properties\n * @property {Float} [text.stroke_width=0] Text stroke width\n * @property {Float} [text.font_size=24] Text font size\n * @property {string} [text.font_family=\"serif\"] Text font family\n * @property {Float} [initOpacity=1] Initial opacity (multiplied by 100)\n * @property {module:SVGEditor.XYDimensions} [dimensions=[640, 480]] The default width/height of a new document. Use an array in `setConfig` (e.g., `[800, 600]`) and comma separated numbers in the URL.\n * @property {boolean} [gridSnapping=false] Enable snap to grid by default. Set in Editor Options.\n * @property {string} [gridColor=\"#000\"] Accepts hex, e.g., '#000'. Set in Editor Options. Defaults to black.\n * @property {string} [baseUnit=\"px\"] Set in Editor Options.\n * @property {Float} [snappingStep=10] Set the default grid snapping value. Set in Editor Options.\n * @property {boolean} [showRulers=true] Initial state of ruler display (v2.6). Set in Editor Options.\n * @property {string} [initTool=\"select\"] The initially selected tool. Must be either the ID of the button for the tool, or the ID without `tool_` prefix (e.g., \"select\").\n * @property {boolean} [wireframe=false] Start in wireframe mode\n * @property {boolean} [showlayers=false] Open the layers side-panel by default.\n * @property {\"new\"|\"same\"} [exportWindowType=\"new\"] Can be \"new\" or \"same\" to indicate whether new windows will be generated for each export; the `window.name` of the export window is namespaced based on the `canvasName` (and incremented if \"new\" is selected as the type). Introduced 2.8.\n * @property {boolean} [showGrid=false] Set by `ext-grid.js`; determines whether or not to show the grid by default\n * @property {boolean} [show_outside_canvas=true] Defines whether or not elements outside the canvas should be visible. Set and used in `svgcanvas.js`.\n * @property {boolean} [selectNew=true] If true, will replace the selection with the current element and automatically select element objects (when not in \"path\" mode) after they are created, showing their grips (v2.6). Set and used in `svgcanvas.js` (`mouseUp`).\n * @todo Some others could be preferences as well (e.g., preventing URL changing of extensions, defaultExtensions, stylesheets, colorPickerCSS); Change the following to preferences and add pref controls where missing to the UI (e.g., `canvas_expansion`, `initFill`, `initStroke`, `text`, `initOpacity`, `dimensions`, `initTool`, `wireframe`, `showlayers`, `gridSnapping`, `gridColor`, `baseUnit`, `snappingStep`, `showRulers`, `exportWindowType`, `showGrid`, `show_outside_canvas`, `selectNew`)?\n */\n /**\n * @namespace {module:SVGEditor.Config} defaultConfig\n * @memberof module:SVGEditor~\n * @implements {module:SVGEditor.Config}\n */\n defaultConfig = {\n canvasName: 'default',\n canvas_expansion: 3,\n initFill: {\n color: 'FF0000', // solid red\n opacity: 1\n },\n initStroke: {\n width: 5,\n color: '000000', // solid black\n opacity: 1\n },\n text: {\n stroke_width: 0,\n font_size: 24,\n font_family: 'serif'\n },\n initOpacity: 1,\n colorPickerCSS: null, // Defaults to 'left' with a position equal to that of the fill_color or stroke_color element minus 140, and a 'bottom' equal to 40\n initTool: 'select',\n exportWindowType: 'new', // 'same' (todo: also support 'download')\n wireframe: false,\n showlayers: false,\n no_save_warning: false,\n // PATH CONFIGURATION\n // The following path configuration items are disallowed in the URL (as should any future path configurations)\n langPath: 'locale/', // Default will be changed if this is a non-modular load\n extPath: 'extensions/', // Default will be changed if this is a non-modular load\n canvgPath: 'canvg/', // Default will be changed if this is a non-modular load\n jspdfPath: 'jspdf/', // Default will be changed if this is a non-modular load\n imgPath: 'images/',\n jGraduatePath: 'jgraduate/images/',\n extIconsPath: 'extensions/',\n // DOCUMENT PROPERTIES\n // Change the following to a preference (already in the Document Properties dialog)?\n dimensions: [640, 480],\n // EDITOR OPTIONS\n // Change the following to preferences (already in the Editor Options dialog)?\n gridSnapping: false,\n gridColor: '#000',\n baseUnit: 'px',\n snappingStep: 10,\n showRulers: true,\n // URL BEHAVIOR CONFIGURATION\n preventAllURLConfig: false,\n preventURLContentLoading: false,\n // EXTENSION CONFIGURATION (see also preventAllURLConfig)\n lockExtensions: false, // Disallowed in URL setting\n noDefaultExtensions: false, // noDefaultExtensions can only be meaningfully used in `svgedit-config-iife.js` or in the URL\n // EXTENSION-RELATED (GRID)\n showGrid: false, // Set by ext-grid.js\n // EXTENSION-RELATED (STORAGE)\n noStorageOnLoad: false, // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage\n forceStorage: false, // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not\n emptyStorageOnDecline: false, // Used by ext-storage.js; empty any prior storage if the user declines to store\n // EXTENSION (CLIENT VS. SERVER SAVING/OPENING)\n avoidClientSide: false, // Deprecated in favor of `avoidClientSideDownload`\n avoidClientSideDownload: false,\n avoidClientSideOpen: false\n },\n /**\n * LOCALE.\n * @name module:SVGEditor.uiStrings\n * @type {PlainObject}\n */\n uiStrings = editor.uiStrings = {};\n\nlet svgCanvas, urldata = {},\n isReady = false,\n customExportImage = false,\n customExportPDF = false,\n curPrefs = {},\n // Note: The difference between Prefs and Config is that Prefs\n // can be changed in the UI and are stored in the browser,\n // while config cannot\n curConfig = {\n // We do not put on defaultConfig to simplify object copying\n // procedures (we obtain instead from defaultExtensions)\n extensions: [],\n stylesheets: [],\n /**\n * Can use `location.origin` to indicate the current\n * origin. Can contain a '*' to allow all domains or 'null' (as\n * a string) to support all `file:///` URLs. Cannot be set by\n * URL for security reasons (not safe, at least for\n * privacy or data integrity of SVG content).\n * Might have been fairly safe to allow\n * `new URL(location.href).origin` by default but\n * avoiding it ensures some more security that even third\n * party apps on the same domain also cannot communicate\n * with this app by default.\n * For use with `ext-xdomain-messaging.js`\n * @todo We might instead make as a user-facing preference.\n */\n allowedOrigins: []\n };\n\n/**\n *\n * @param {string} str SVG string\n * @param {PlainObject} [opts={}]\n * @param {boolean} [opts.noAlert]\n * @throws {Error} Upon failure to load SVG\n * @returns {Promise<void>} Resolves to undefined upon success (or if `noAlert` is\n * falsey, though only until after the `alert` is closed); rejects if SVG\n * loading fails and `noAlert` is truthy.\n */\nasync function loadSvgString (str, {noAlert} = {}) {\n const success = svgCanvas.setSvgString(str) !== false;\n if (success) {\n return;\n }\n\n if (!noAlert) {\n await $.alert(uiStrings.notification.errorLoadingSVG);\n return;\n }\n throw new Error('Error loading SVG');\n}\n\n/**\n * @function module:SVGEditor~getImportLocale\n * @param {PlainObject} defaults\n * @param {string} defaults.defaultLang\n * @param {string} defaults.defaultName\n * @returns {module:SVGEditor~ImportLocale}\n */\nfunction getImportLocale ({defaultLang, defaultName}) {\n /**\n * @function module:SVGEditor~ImportLocale\n * @param {PlainObject} localeInfo\n * @param {string} [localeInfo.name] Defaults to `defaultName` of {@link module:SVGEditor~getImportLocale}\n * @param {string} [localeInfo.lang=defaultLang] Defaults to `defaultLang` of {@link module:SVGEditor~getImportLocale}\n * @returns {Promise<module:locale.LocaleStrings>} Resolves to {@link module:locale.LocaleStrings}\n */\n return async function importLocaleDefaulting ({name = defaultName, lang = defaultLang} = {}) {\n /**\n *\n * @param {string} language\n * @returns {Promise<module:locale.LocaleStrings>} Resolves to {@link module:locale.LocaleStrings}\n */\n function importLocale (language) {\n const url = `${curConfig.extPath}ext-locale/${name}/${language}.js`;\n return importSetGlobalDefault(url, {\n global: `svgEditorExtensionLocale_${name}_${language.replace(/-/g, '_')}`\n });\n }\n try {\n return await importLocale(lang);\n } catch (err) {\n return importLocale('en');\n }\n };\n}\n\n/**\n* EXPORTS.\n*/\n\n/**\n* Store and retrieve preferences.\n* @param {string} key The preference name to be retrieved or set\n* @param {string} [val] The value. If the value supplied is missing or falsey, no change to the preference will\n* be made unless `mayBeEmpty` is set.\n* @param {boolean} [mayBeEmpty] If value may be falsey.\n* @returns {string|void} If val is missing or falsey and `mayBeEmpty` is not set, the\n* value of the previously stored preference will be returned.\n* @todo Review whether any remaining existing direct references to\n* getting `curPrefs` can be changed to use `svgEditor.pref()` getting to ensure\n* `defaultPrefs` fallback (also for sake of `allowInitialUserOverride`);\n* specifically, `bkgd_color` could be changed so that the pref dialog has a\n* button to auto-calculate background, but otherwise uses `svgEditor.pref()` to\n* be able to get default prefs or overridable settings\n*/\neditor.pref = function (key, val, mayBeEmpty) {\n if (mayBeEmpty || val) {\n curPrefs[key] = val;\n /**\n * @name curPrefs\n * @memberof module:SVGEditor\n * @implements {module:SVGEditor.Prefs}\n */\n editor.curPrefs = curPrefs; // Update exported value\n return undefined;\n }\n return (key in curPrefs) ? curPrefs[key] : defaultPrefs[key];\n};\n\n/*\n* EDITOR PUBLIC METHODS\n// Todo: Sort these methods per invocation order, ideally with init at the end\n// Todo: Prevent execution until init executes if dependent on it?\n*/\neditor.putLocale = putLocale;\neditor.readLang = readLang;\neditor.setStrings = setStrings;\n\n/**\n* Where permitted, sets canvas and/or `defaultPrefs` based on previous\n* storage. This will override URL settings (for security reasons) but\n* not `svgedit-config-iife.js` configuration (unless initial user\n* overriding is explicitly permitted there via `allowInitialUserOverride`).\n* @todo Split `allowInitialUserOverride` into `allowOverrideByURL` and\n* `allowOverrideByUserStorage` so `svgedit-config-iife.js` can disallow some\n* individual items for URL setting but allow for user storage AND/OR\n* change URL setting so that it always uses a different namespace,\n* so it won't affect pre-existing user storage (but then if users saves\n* that, it will then be subject to tampering\n* @returns {void}\n*/\neditor.loadContentAndPrefs = function () {\n if (!curConfig.forceStorage &&\n (curConfig.noStorageOnLoad ||\n !document.cookie.match(/(?:^|;\\s*)svgeditstore=(?:prefsAndContent|prefsOnly)/)\n )\n ) {\n return;\n }\n\n // LOAD CONTENT\n if (editor.storage && // Cookies do not have enough available memory to hold large documents\n (curConfig.forceStorage ||\n (!curConfig.noStorageOnLoad &&\n document.cookie.match(/(?:^|;\\s*)svgeditstore=prefsAndContent/))\n )\n ) {\n const name = 'svgedit-' + curConfig.canvasName;\n const cached = editor.storage.getItem(name);\n if (cached) {\n editor.loadFromString(cached);\n }\n }\n\n // LOAD PREFS\n Object.keys(defaultPrefs).forEach((key) => {\n const storeKey = 'svg-edit-' + key;\n if (editor.storage) {\n const val = editor.storage.getItem(storeKey);\n if (val) {\n defaultPrefs[key] = String(val); // Convert to string for FF (.value fails in Webkit)\n }\n } else if (window.widget) {\n defaultPrefs[key] = window.widget.preferenceForKey(storeKey);\n } else {\n const result = document.cookie.match(new RegExp('(?:^|;\\\\s*)' + Utils.regexEscape(encodeURIComponent(storeKey)) + '=([^;]+)'));\n defaultPrefs[key] = result ? decodeURIComponent(result[1]) : '';\n }\n });\n};\n\n/**\n* Allows setting of preferences or configuration (including extensions).\n* @param {module:SVGEditor.Config|module:SVGEditor.Prefs} opts The preferences or configuration (including extensions). See the tutorial on {@tutorial ConfigOptions} for info on config and preferences.\n* @param {PlainObject} [cfgCfg] Describes configuration which applies to the\n* particular batch of supplied options\n* @param {boolean} [cfgCfg.allowInitialUserOverride=false] Set to true if you wish\n* to allow initial overriding of settings by the user via the URL\n* (if permitted) or previously stored preferences (if permitted);\n* note that it will be too late if you make such calls in extension\n* code because the URL or preference storage settings will\n* have already taken place.\n* @param {boolean} [cfgCfg.overwrite=true] Set to false if you wish to\n* prevent the overwriting of prior-set preferences or configuration\n* (URL settings will always follow this requirement for security\n* reasons, so `svgedit-config-iife.js` settings cannot be overridden unless it\n* explicitly permits via `allowInitialUserOverride` but extension config\n* can be overridden as they will run after URL settings). Should\n* not be needed in `svgedit-config-iife.js`.\n* @returns {void}\n*/\neditor.setConfig = function (opts, cfgCfg) {\n cfgCfg = cfgCfg || {};\n /**\n *\n * @param {module:SVGEditor.Config|module:SVGEditor.Prefs} cfgObj\n * @param {string} key\n * @param {any} val See {@link module:SVGEditor.Config} or {@link module:SVGEditor.Prefs}\n * @returns {void}\n */\n function extendOrAdd (cfgObj, key, val) {\n if (cfgObj[key] && typeof cfgObj[key] === 'object') {\n $.extend(true, cfgObj[key], val);\n } else {\n cfgObj[key] = val;\n }\n }\n Object.entries(opts).forEach(function ([key, val]) {\n // Only allow prefs defined in defaultPrefs or...\n if ({}.hasOwnProperty.call(defaultPrefs, key)) {\n if (cfgCfg.overwrite === false && (\n curConfig.preventAllURLConfig ||\n {}.hasOwnProperty.call(curPrefs, key)\n )) {\n return;\n }\n if (cfgCfg.allowInitialUserOverride === true) {\n defaultPrefs[key] = val;\n } else {\n editor.pref(key, val);\n }\n } else if (['extensions', 'stylesheets', 'allowedOrigins'].includes(key)) {\n if (cfgCfg.overwrite === false &&\n (\n curConfig.preventAllURLConfig ||\n ['allowedOrigins', 'stylesheets'].includes(key) ||\n (key === 'extensions' && curConfig.lockExtensions)\n )\n ) {\n return;\n }\n curConfig[key] = curConfig[key].concat(val); // We will handle any dupes later\n // Only allow other curConfig if defined in defaultConfig\n } else if ({}.hasOwnProperty.call(defaultConfig, key)) {\n if (cfgCfg.overwrite === false && (\n curConfig.preventAllURLConfig ||\n {}.hasOwnProperty.call(curConfig, key)\n )) {\n return;\n }\n // Potentially overwriting of previously set config\n if ({}.hasOwnProperty.call(curConfig, key)) {\n if (cfgCfg.overwrite === false) {\n return;\n }\n extendOrAdd(curConfig, key, val);\n } else if (cfgCfg.allowInitialUserOverride === true) {\n extendOrAdd(defaultConfig, key, val);\n } else if (defaultConfig[key] && typeof defaultConfig[key] === 'object') {\n curConfig[key] = Array.isArray(defaultConfig[key]) ? [] : {};\n $.extend(true, curConfig[key], val); // Merge properties recursively, e.g., on initFill, initStroke objects\n } else {\n curConfig[key] = val;\n }\n }\n });\n /**\n * @name curConfig\n * @memberof module:SVGEditor\n * @implements {module:SVGEditor.Config}\n */\n editor.curConfig = curConfig; // Update exported value\n};\n\n/**\n* All methods are optional.\n* @interface module:SVGEditor.CustomHandler\n* @type {PlainObject}\n*/\n/**\n* Its responsibilities are:\n* - invoke a file chooser dialog in 'open' mode\n* - let user pick a SVG file\n* - calls [svgCanvas.setSvgString()]{@link module:svgcanvas.SvgCanvas#setSvgString} with the string contents of that file.\n* Not passed any parameters.\n* @function module:SVGEditor.CustomHandler#open\n* @returns {void}\n*/\n/**\n* Its responsibilities are:\n* - accept the string contents of the current document\n* - invoke a file chooser dialog in 'save' mode\n* - save the file to location chosen by the user.\n* @function module:SVGEditor.CustomHandler#save\n* @param {external:Window} win\n* @param {module:svgcanvas.SvgCanvas#event:saved} svgStr A string of the SVG\n* @listens module:svgcanvas.SvgCanvas#event:saved\n* @returns {void}\n*/\n/**\n* Its responsibilities (with regard to the object it is supplied in its 2nd argument) are:\n* - inform user of any issues supplied via the \"issues\" property\n* - convert the \"svg\" property SVG string into an image for export;\n* utilize the properties \"type\" (currently 'PNG', 'JPEG', 'BMP',\n* 'WEBP', 'PDF'), \"mimeType\", and \"quality\" (for 'JPEG' and 'WEBP'\n* types) to determine the proper output.\n* @function module:SVGEditor.CustomHandler#exportImage\n* @param {external:Window} win\n* @param {module:svgcanvas.SvgCanvas#event:exported} data\n* @listens module:svgcanvas.SvgCanvas#event:exported\n* @returns {void}\n*/\n/**\n* @function module:SVGEditor.CustomHandler#exportPDF\n* @param {external:Window} win\n* @param {module:svgcanvas.SvgCanvas#event:exportedPDF} data\n* @listens module:svgcanvas.SvgCanvas#event:exportedPDF\n* @returns {void}\n*/\n\n/**\n* Allows one to override default SVGEdit `open`, `save`, and\n* `export` editor behaviors.\n* @param {module:SVGEditor.CustomHandler} opts Extension mechanisms may call `setCustomHandlers` with three functions: `opts.open`, `opts.save`, and `opts.exportImage`\n* @returns {Promise<void>}\n*/\neditor.setCustomHandlers = function (opts) {\n return editor.ready(function () {\n if (opts.open) {\n $('#tool_open > input[type=\"file\"]').remove();\n $('#tool_open').show();\n svgCanvas.open = opts.open;\n }\n if (opts.save) {\n editor.showSaveWarning = false;\n svgCanvas.bind('saved', opts.save);\n }\n if (opts.exportImage) {\n customExportImage = opts.exportImage;\n svgCanvas.bind('exported', customExportImage); // canvg and our RGBColor will be available to the method\n }\n if (opts.exportPDF) {\n customExportPDF = opts.exportPDF;\n svgCanvas.bind('exportedPDF', customExportPDF); // jsPDF and our RGBColor will be available to the method\n }\n });\n};\n\n/**\n* @param {boolean} arg\n* @returns {void}\n*/\neditor.randomizeIds = function (arg) {\n svgCanvas.randomizeIds(arg);\n};\n\n/**\n* Auto-run after a Promise microtask.\n* @returns {void}\n*/\neditor.init = function () {\n const modularVersion = !('svgEditor' in window) ||\n !window.svgEditor ||\n window.svgEditor.modules !== false;\n if (!modularVersion) {\n Object.assign(defaultConfig, {\n langPath: '../dist/locale/',\n extPath: '../dist/extensions/',\n canvgPath: '../dist/',\n jspdfPath: '../dist/'\n });\n }\n\n // const host = location.hostname,\n // onWeb = host && host.includes('.');\n // Some FF versions throw security errors here when directly accessing\n try {\n if ('localStorage' in window) { // && onWeb removed so Webkit works locally\n /**\n * The built-in interface implemented by `localStorage`\n * @external Storage\n */\n /**\n * @name storage\n * @memberof module:SVGEditor\n * @type {external:Storage}\n */\n editor.storage = localStorage;\n }\n } catch (err) {}\n\n // Todo: Avoid const-defined functions and group functions together, etc. where possible\n const goodLangs = [];\n $('#lang_select option').each(function () {\n goodLangs.push(this.value);\n });\n\n /**\n * Sets up current preferences based on defaults.\n * @returns {void}\n */\n function setupCurPrefs () {\n curPrefs = $.extend(true, {}, defaultPrefs, curPrefs); // Now safe to merge with priority for curPrefs in the event any are already set\n // Export updated prefs\n editor.curPrefs = curPrefs;\n }\n\n /**\n * Sets up current config based on defaults.\n * @returns {void}\n */\n function setupCurConfig () {\n curConfig = $.extend(true, {}, defaultConfig, curConfig); // Now safe to merge with priority for curConfig in the event any are already set\n\n // Now deal with extensions and other array config\n if (!curConfig.noDefaultExtensions) {\n curConfig.extensions = curConfig.extensions.concat(defaultExtensions);\n }\n // ...and remove any dupes\n ['extensions', 'stylesheets', 'allowedOrigins'].forEach(function (cfg) {\n curConfig[cfg] = $.grep(curConfig[cfg], function (n, i) { // Supposedly faster than filter per http://amandeep1986.blogspot.hk/2015/02/jquery-grep-vs-js-filter.html\n return i === curConfig[cfg].indexOf(n);\n });\n });\n // Export updated config\n editor.curConfig = curConfig;\n }\n (() => {\n // Load config/data from URL if given\n const {search, searchParams} = new URL(location);\n\n if (search) {\n urldata = deparam(searchParams.toString(), true);\n\n ['initStroke', 'initFill'].forEach((prop) => {\n if (searchParams.has(`${prop}[color]`)) {\n // Restore back to original non-deparamed value to avoid color\n // strings being converted to numbers\n urldata[prop].color = searchParams.get(`${prop}[color]`);\n }\n });\n\n if (searchParams.has('bkgd_color')) {\n urldata.bkgd_color = '#' + searchParams.get('bkgd_color');\n }\n\n if (urldata.dimensions) {\n urldata.dimensions = urldata.dimensions.split(',');\n }\n\n if (urldata.extensions) {\n // For security reasons, disallow cross-domain or cross-folder\n // extensions via URL\n urldata.extensions = urldata.extensions.match(/[:/\\\\]/)\n ? ''\n : urldata.extensions.split(',');\n }\n\n // Disallowing extension paths via URL for\n // security reasons, even for same-domain\n // ones given potential to interact in undesirable\n // ways with other script resources\n [\n 'langPath', 'extPath', 'canvgPath', 'jspdfPath',\n 'imgPath', 'jGraduatePath', 'extIconsPath'\n ].forEach(function (pathConfig) {\n if (urldata[pathConfig]) {\n delete urldata[pathConfig];\n }\n });\n\n // Note: `source` and `url` (as with `storagePrompt` later) are not\n // set on config but are used below\n editor.setConfig(urldata, {overwrite: false});\n setupCurConfig();\n\n if (!curConfig.preventURLContentLoading) {\n let {source} = urldata;\n if (!source) { // urldata.source may have been null if it ended with '='\n const src = searchParams.get('source');\n if (src && src.startsWith('data:')) {\n source = src;\n }\n }\n if (source) {\n if (source.startsWith('data:')) {\n editor.loadFromDataURI(source);\n } else {\n editor.loadFromString(source);\n }\n return;\n }\n if (urldata.url) {\n editor.loadFromURL(urldata.url);\n return;\n }\n }\n if (!urldata.noStorageOnLoad || curConfig.forceStorage) {\n editor.loadContentAndPrefs();\n }\n } else {\n setupCurConfig();\n editor.loadContentAndPrefs();\n }\n })();\n setupCurPrefs();\n\n /**\n * Called internally.\n * @param {string|Element|external:jQuery} elem\n * @param {string|external:jQuery} iconId\n * @param {Float} forcedSize Not in use\n * @returns {void}\n */\n const setIcon = editor.setIcon = function (elem, iconId, forcedSize) {\n const icon = (typeof iconId === 'string') ? $.getSvgIcon(iconId, true) : iconId.clone();\n if (!icon) {\n // Todo: Investigate why this still occurs in some cases\n console.log('NOTE: Icon image missing: ' + iconId); // eslint-disable-line no-console\n return;\n }\n $(elem).empty().append(icon);\n };\n\n /**\n * @fires module:svgcanvas.SvgCanvas#event:ext_addLangData\n * @fires module:svgcanvas.SvgCanvas#event:ext_langReady\n * @fires module:svgcanvas.SvgCanvas#event:ext_langChanged\n * @fires module:svgcanvas.SvgCanvas#event:extensions_added\n * @returns {Promise<module:locale.LangAndData>} Resolves to result of {@link module:locale.readLang}\n */\n const extAndLocaleFunc = async function () {\n // const lang = ('lang' in curPrefs) ? curPrefs.lang : null;\n const {langParam, langData} = await editor.putLocale(\n editor.pref('lang'), goodLangs, curConfig\n );\n await setLang(langParam, langData);\n\n const {ok, cancel} = uiStrings.common;\n jQueryPluginDBox($, {ok, cancel});\n\n setIcons(); // Wait for dbox as needed for i18n\n\n try {\n await Promise.all(\n curConfig.extensions.map(async (extname) => {\n const extName = extname.match(/^ext-(.+)\\.js/);\n // const {extName} = extname.match(/^ext-(?<extName>.+)\\.js/).groups;\n if (!extName) { // Ensure URL cannot specify some other unintended file in the extPath\n return undefined;\n }\n const url = curConfig.extPath + extname;\n // Todo: Replace this with `return import(url);` when\n // `import()` widely supported\n /**\n * @tutorial ExtensionDocs\n * @typedef {PlainObject} module:SVGEditor.ExtensionObject\n * @property {string} [name] Name of the extension. Used internally; no need for i18n. Defaults to extension name without beginning \"ext-\" or ending \".js\".\n * @property {module:svgcanvas.ExtensionInitCallback} [init]\n */\n try {\n /**\n * @type {module:SVGEditor.ExtensionObject}\n */\n const imported = await importSetGlobalDefault(url, {\n global: 'svgEditorExtension_' + extName[1].replace(/-/g, '_')\n // global: 'svgEditorExtension_' + extName.replace(/-/g, '_')\n });\n const {name = extName[1], init} = imported;\n // const {name = extName, init} = imported;\n const importLocale = getImportLocale({defaultLang: langParam, defaultName: name});\n return editor.addExtension(name, (init && init.bind(editor)), {$, importLocale});\n } catch (err) {\n // Todo: Add config to alert any errors\n console.log(err); // eslint-disable-line no-console\n console.error('Extension failed to load: ' + extname + '; ' + err); // eslint-disable-line no-console\n return undefined;\n }\n })\n );\n svgCanvas.bind(\n 'extensions_added',\n /**\n * @param {external:Window} win\n * @param {module:svgcanvas.SvgCanvas#event:extensions_added} data\n * @listens module:svgcanvas.SvgCanvas#event:extensions_added\n * @returns {void}\n */\n (win, data) => {\n extensionsAdded = true;\n Actions.setAll();\n\n $('.flyout_arrow_horiz:empty').each(function () {\n $(this).append($.getSvgIcon('arrow_right', true).width(5).height(5));\n });\n\n if (editor.storagePromptState === 'ignore') {\n updateCanvas(true);\n }\n\n messageQueue.forEach(\n /**\n * @param {module:svgcanvas.SvgCanvas#event:message} messageObj\n * @fires module:svgcanvas.SvgCanvas#event:message\n * @returns {void}\n */\n (messageObj) => {\n svgCanvas.call('message', messageObj);\n }\n );\n }\n );\n svgCanvas.call('extensions_added');\n } catch (err) {\n // Todo: Report errors through the UI\n console.log(err); // eslint-disable-line no-console\n }\n };\n\n const stateObj = {tool_scale: editor.tool_scale};\n\n /**\n *\n * @returns {void}\n */\n const setFlyoutPositions = function () {\n $('.tools_flyout').each(function () {\n const shower = $('#' + this.id + '_show');\n const {left, top} = shower.offset();\n const w = shower.outerWidth();\n $(this).css({left: (left + w) * editor.tool_scale, top});\n });\n };\n\n /**\n * @type {string}\n */\n const uaPrefix = (function () {\n const regex = /^(?:Moz|Webkit|Khtml|O|ms|Icab)(?=[A-Z])/;\n const someScript = document.getElementsByTagName('script')[0];\n for (const prop in someScript.style) {\n if (regex.test(prop)) {\n // test is faster than match, so it's better to perform\n // that on the lot and match only when necessary\n return prop.match(regex)[0];\n }\n }\n // Nothing found so far?\n if ('WebkitOpacity' in someScript.style) { return 'Webkit'; }\n if ('KhtmlOpacity' in someScript.style) { return 'Khtml'; }\n\n return '';\n }());\n\n /**\n * @param {external:jQuery} elems\n * @param {Float} scale\n * @returns {void}\n */\n const scaleElements = function (elems, scale) {\n // const prefix = '-' + uaPrefix.toLowerCase() + '-'; // Currently unused\n const sides = ['top', 'left', 'bottom', 'right'];\n\n elems.each(function () {\n // Handled in CSS\n // this.style[uaPrefix + 'Transform'] = 'scale(' + scale + ')';\n const el = $(this);\n const w = el.outerWidth() * (scale - 1);\n const h = el.outerHeight() * (scale - 1);\n // const margins = {}; // Currently unused\n\n for (let i = 0; i < 4; i++) {\n const s = sides[i];\n let cur = el.data('orig_margin-' + s);\n if (Utils.isNullish(cur)) {\n cur = parseInt(el.css('margin-' + s));\n // Cache the original margin\n el.data('orig_margin-' + s, cur);\n }\n let val = cur * scale;\n if (s === 'right') {\n val += w;\n } else if (s === 'bottom') {\n val += h;\n }\n\n el.css('margin-' + s, val);\n // el.css('outline', '1px solid red');\n }\n });\n };\n\n /**\n * Called internally.\n * @param {module:SVGEditor.IconSize} size\n * @returns {void}\n */\n const setIconSize = editor.setIconSize = function (size) {\n // const elems = $('.tool_button, .push_button, .tool_button_current, .disabled, .icon_label, #url_notice, #tool_open');\n const selToscale = '#tools_top .toolset, #editor_panel > *, #history_panel > *,' +\n ' #main_button, #tools_left > *, #path_node_panel > *, #multiselected_panel > *,' +\n ' #g_panel > *, #tool_font_size > *, .tools_flyout';\n\n const elems = $(selToscale);\n\n let scale = 1;\n if (typeof size === 'number') {\n scale = size;\n } else {\n const iconSizes = {s: 0.75, m: 1, l: 1.25, xl: 1.5};\n scale = iconSizes[size];\n }\n\n stateObj.tool_scale = editor.tool_scale = scale;\n\n setFlyoutPositions();\n // $('.tools_flyout').each(function () {\n // const pos = $(this).position();\n // console.log($(this), pos.left+(34 * scale));\n // $(this).css({left: pos.left+(34 * scale), top: pos.top+(77 * scale)});\n // console.log('l', $(this).css('left'));\n // });\n //\n // const scale = .75;\n\n const hiddenPs = elems.parents(':hidden');\n hiddenPs.css('visibility', 'hidden').show();\n scaleElements(elems, scale);\n hiddenPs.css('visibility', 'visible').hide();\n // return;\n\n editor.pref('iconsize', size);\n $('#iconsize').val(size);\n\n // Change icon size\n // $('.tool_button, .push_button, .tool_button_current, .disabled, .icon_label, #url_notice, #tool_open')\n // .find('> svg, > img').each(function () {\n // this.setAttribute('width',size_num);\n // this.setAttribute('height',size_num);\n // });\n //\n // $.resizeSvgIcons({\n // '.flyout_arrow_horiz > svg, .flyout_arrow_horiz > img': size_num / 5,\n // '#logo > svg, #logo > img': size_num * 1.3,\n // '#tools_bottom .icon_label > *': (size_num === 16 ? 18 : size_num * .75)\n // });\n // if (size != 's') {\n // $.resizeSvgIcons({'#layerbuttons svg, #layerbuttons img': size_num * .6});\n // }\n\n // Note that all rules will be prefixed with '#svg_editor' when parsed\n const cssResizeRules = {\n // '.tool_button,\\\n // .push_button,\\\n // .tool_button_current,\\\n // .push_button_pressed,\\\n // .disabled,\\\n // .icon_label,\\\n // .tools_flyout .tool_button': {\n // width: {s: '16px', l: '32px', xl: '48px'},\n // height: {s: '16px', l: '32px', xl: '48px'},\n // padding: {s: '1px', l: '2px', xl: '3px'}\n // },\n // '.tool_sep': {\n // height: {s: '16px', l: '32px', xl: '48px'},\n // margin: {s: '2px 2px', l: '2px 5px', xl: '2px 8px'}\n // },\n // '#main_icon': {\n // width: {s: '31px', l: '53px', xl: '75px'},\n // height: {s: '22px', l: '42px', xl: '64px'}\n // },\n '#tools_top': {\n left: 50 + $('#main_button').width(),\n height: 72\n },\n '#tools_left': {\n width: 31,\n top: 74\n },\n 'div#workarea': {\n left: 38,\n top: 74\n }\n // '#tools_bottom': {\n // left: {s: '27px', l: '46px', xl: '65px'},\n // height: {s: '58px', l: '98px', xl: '145px'}\n // },\n // '#color_tools': {\n // 'border-spacing': {s: '0 1px'},\n // 'margin-top': {s: '-1px'}\n // },\n // '#color_tools .icon_label': {\n // width: {l:'43px', xl: '60px'}\n // },\n // '.color_tool': {\n // height: {s: '20px'}\n // },\n // '#tool_opacity': {\n // top: {s: '1px'},\n // height: {s: 'auto', l:'auto', xl:'auto'}\n // },\n // '#tools_top input, #tools_bottom input': {\n // 'margin-top': {s: '2px', l: '4px', xl: '5px'},\n // height: {s: 'auto', l: 'auto', xl: 'auto'},\n // border: {s: '1px solid #555', l: 'auto', xl: 'auto'},\n // 'font-size': {s: '.9em', l: '1.2em', xl: '1.4em'}\n // },\n // '#zoom_panel': {\n // 'margin-top': {s: '3px', l: '4px', xl: '5px'}\n // },\n // '#copyright, #tools_bottom .label': {\n // 'font-size': {l: '1.5em', xl: '2em'},\n // 'line-height': {s: '15px'}\n // },\n // '#tools_bottom_2': {\n // width: {l: '295px', xl: '355px'},\n // top: {s: '4px'}\n // },\n // '#tools_top > div, #tools_top': {\n // 'line-height': {s: '17px', l: '34px', xl: '50px'}\n // },\n // '.dropdown button': {\n // height: {s: '18px', l: '34px', xl: '40px'},\n // 'line-height': {s: '18px', l: '34px', xl: '40px'},\n // 'margin-top': {s: '3px'}\n // },\n // '#tools_top label, #tools_bottom label': {\n // 'font-size': {s: '1em', l: '1.5em', xl: '2em'},\n // height: {s: '25px', l: '42px', xl: '64px'}\n // },\n // 'div.toolset': {\n // height: {s: '25px', l: '42px', xl: '64px'}\n // },\n // '#tool_bold, #tool_italic': {\n // 'font-size': {s: '1.5em', l: '3em', xl: '4.5em'}\n // },\n // '#sidepanels': {\n // top: {s: '50px', l: '88px', xl: '125px'},\n // bottom: {s: '51px', l: '68px', xl: '65px'}\n // },\n // '#layerbuttons': {\n // width: {l: '130px', xl: '175px'},\n // height: {l: '24px', xl: '30px'}\n // },\n // '#layerlist': {\n // width: {l: '128px', xl: '150px'}\n // },\n // '.layer_button': {\n // width: {l: '19px', xl: '28px'},\n // height: {l: '19px', xl: '28px'}\n // },\n // 'input.spin-button': {\n // 'background-image': {l: 'url('images/spinbtn_updn_big.png')', xl: 'url('images/spinbtn_updn_big.png')'},\n // 'background-position': {l: '100% -5px', xl: '100% -2px'},\n // 'padding-right': {l: '24px', xl: '24px' }\n // },\n // 'input.spin-button.up': {\n // 'background-position': {l: '100% -45px', xl: '100% -42px'}\n // },\n // 'input.spin-button.down': {\n // 'background-position': {l: '100% -85px', xl: '100% -82px'}\n // },\n // '#position_opts': {\n // width: {all: (size_num*4) +'px'}\n // }\n };\n\n let ruleElem = $('#tool_size_rules');\n if (!ruleElem.length) {\n ruleElem = $('<style id=\"tool_size_rules\"></style>').appendTo('head');\n } else {\n ruleElem.empty();\n }\n\n if (size !== 'm') {\n let styleStr = '';\n $.each(cssResizeRules, function (selector, rules) {\n selector = '#svg_editor ' + selector.replace(/,/g, ', #svg_editor');\n styleStr += selector + '{';\n $.each(rules, function (prop, values) {\n let val;\n if (typeof values === 'number') {\n val = (values * scale) + 'px';\n } else if (values[size] || values.all) {\n val = (values[size] || values.all);\n }\n styleStr += (prop + ':' + val + ';');\n });\n styleStr += '}';\n });\n // this.style[uaPrefix + 'Transform'] = 'scale(' + scale + ')';\n const prefix = '-' + uaPrefix.toLowerCase() + '-';\n styleStr += (selToscale + '{' + prefix + 'transform: scale(' + scale + ');}' +\n ' #svg_editor div.toolset .toolset {' + prefix + 'transform: scale(1); margin: 1px !important;}' + // Hack for markers\n ' #svg_editor .ui-slider {' + prefix + 'transform: scale(' + (1 / scale) + ');}' // Hack for sliders\n );\n ruleElem.text(styleStr);\n }\n\n setFlyoutPositions();\n };\n\n /**\n * Setup SVG icons.\n * @returns {void}\n */\n function setIcons () {\n $.svgIcons(curConfig.imgPath + 'svg_edit_icons.svg', {\n w: 24, h: 24,\n id_match: false,\n no_img: !isWebkit(), // Opera & Firefox 4 gives odd behavior w/images\n fallback_path: curConfig.imgPath,\n // Todo: Set `alts: {}` with keys as the IDs in fallback set to\n // `uiStrings` (localized) values\n fallback: {\n logo: 'logo.png',\n\n select: 'select.png',\n select_node: 'select_node.png',\n\n square: 'square.png',\n rect: 'rect.png',\n fh_rect: 'freehand-square.png',\n circle: 'circle.png',\n ellipse: 'ellipse.png',\n fh_ellipse: 'freehand-circle.png',\n pencil: 'fhpath.png',\n pen: 'line.png',\n text: 'text.png',\n path: 'path.png',\n add_subpath: 'add_subpath.png',\n close_path: 'closepath.png',\n open_path: 'openpath.png',\n\n image: 'image.png',\n zoom: 'zoom.png',\n\n arrow_right: 'flyouth.png',\n arrow_right_big: 'arrow_right_big.png',\n arrow_down: 'dropdown.gif',\n fill: 'fill.png',\n stroke: 'stroke.png',\n opacity: 'opacity.png',\n\n new_image: 'clear.png',\n save: 'save.png',\n export: 'export.png',\n open: 'open.png',\n import: 'import.png',\n docprops: 'document-properties.png',\n source: 'source.png',\n wireframe: 'wireframe.png',\n\n undo: 'undo.png',\n redo: 'redo.png',\n\n clone: 'clone.png',\n delete: 'delete.png',\n go_up: 'go-up.png',\n go_down: 'go-down.png',\n context_menu: 'context_menu.png',\n move_bottom: 'move_bottom.png',\n move_top: 'move_top.png',\n to_path: 'to_path.png',\n link_controls: 'link_controls.png',\n reorient: 'reorient.png',\n group_elements: 'shape_group_elements.png',\n\n ungroup: 'shape_ungroup.png',\n unlink_use: 'unlink_use.png',\n width: 'width.png',\n height: 'height.png',\n c_radius: 'c_radius.png',\n angle: 'angle.png',\n blur: 'blur.png',\n fontsize: 'fontsize.png',\n align: 'align.png',\n\n align_left: 'align-left.png',\n align_center: 'align-center.png',\n align_right: 'align-right.png',\n align_top: 'align-top.png',\n align_middle: 'align-middle.png',\n align_bottom: 'align-bottom.png',\n\n linecap_butt: 'linecap_butt.png',\n linecap_square: 'linecap_square.png',\n linecap_round: 'linecap_round.png',\n linejoin_miter: 'linejoin_miter.png',\n linejoin_bevel: 'linejoin_bevel.png',\n linejoin_round: 'linejoin_round.png',\n eye: 'eye.png',\n no_color: 'no_color.png',\n\n ok: 'save.png',\n cancel: 'cancel.png',\n warning: 'warning.png',\n\n node_delete: 'node_delete.png',\n node_clone: 'node_clone.png',\n\n globe_link: 'globe_link.png',\n config: 'config.png'\n },\n placement: {\n '#logo': 'logo',\n\n '#tool_clear div,#layer_new': 'new_image',\n '#tool_save div': 'save',\n '#tool_export div': 'export',\n '#tool_open div': 'open',\n '#tool_import div': 'import',\n '#tool_source': 'source',\n '#tool_docprops > div': 'docprops',\n '#tool_editor_prefs > div': 'config',\n '#tool_editor_homepage > div': 'globe_link',\n '#tool_wireframe': 'wireframe',\n\n '#tool_undo': 'undo',\n '#tool_redo': 'redo',\n\n '#tool_select': 'select',\n '#tool_fhpath': 'pencil',\n '#tool_line': 'pen',\n '#tool_rect,#tools_rect_show': 'rect',\n '#tool_square': 'square',\n '#tool_fhrect': 'fh_rect',\n '#tool_ellipse,#tools_ellipse_show': 'ellipse',\n '#tool_circle': 'circle',\n '#tool_fhellipse': 'fh_ellipse',\n '#tool_path': 'path',\n '#tool_text,#layer_rename': 'text',\n '#tool_image': 'image',\n '#tool_zoom': 'zoom',\n\n '#tool_clone,#tool_clone_multi': 'clone',\n '#tool_node_clone': 'node_clone',\n '#layer_delete,#tool_delete,#tool_delete_multi': 'delete',\n '#tool_node_delete': 'node_delete',\n '#tool_add_subpath': 'add_subpath',\n '#tool_openclose_path': 'open_path',\n '#tool_move_top': 'move_top',\n '#tool_move_bottom': 'move_bottom',\n '#tool_topath': 'to_path',\n '#tool_node_link': 'link_controls',\n '#tool_reorient': 'reorient',\n '#tool_group_elements': 'group_elements',\n '#tool_ungroup': 'ungroup',\n '#tool_unlink_use': 'unlink_use',\n\n '#tool_alignleft, #tool_posleft': 'align_left',\n '#tool_aligncenter, #tool_poscenter': 'align_center',\n '#tool_alignright, #tool_posright': 'align_right',\n '#tool_aligntop, #tool_postop': 'align_top',\n '#tool_alignmiddle, #tool_posmiddle': 'align_middle',\n '#tool_alignbottom, #tool_posbottom': 'align_bottom',\n '#cur_position': 'align',\n\n '#linecap_butt,#cur_linecap': 'linecap_butt',\n '#linecap_round': 'linecap_round',\n '#linecap_square': 'linecap_square',\n\n '#linejoin_miter,#cur_linejoin': 'linejoin_miter',\n '#linejoin_round': 'linejoin_round',\n '#linejoin_bevel': 'linejoin_bevel',\n\n '#url_notice': 'warning',\n\n '#layer_up': 'go_up',\n '#layer_down': 'go_down',\n '#layer_moreopts': 'context_menu',\n '#layerlist td.layervis': 'eye',\n\n '#tool_source_save,#tool_docprops_save,#tool_prefs_save': 'ok',\n '#tool_source_cancel,#tool_docprops_cancel,#tool_prefs_cancel': 'cancel',\n\n '#rwidthLabel, #iwidthLabel': 'width',\n '#rheightLabel, #iheightLabel': 'height',\n '#cornerRadiusLabel span': 'c_radius',\n '#angleLabel': 'angle',\n '#linkLabel,#tool_make_link,#tool_make_link_multi': 'globe_link',\n '#zoomLabel': 'zoom',\n '#tool_fill label': 'fill',\n '#tool_stroke .icon_label': 'stroke',\n '#group_opacityLabel': 'opacity',\n '#blurLabel': 'blur',\n '#font_sizeLabel': 'fontsize',\n\n '.flyout_arrow_horiz': 'arrow_right',\n '.dropdown button, #main_button .dropdown': 'arrow_down',\n '#palette .palette_item:first, #fill_bg, #stroke_bg': 'no_color'\n },\n resize: {\n '#logo .svg_icon': 28,\n '.flyout_arrow_horiz .svg_icon': 5,\n '.layer_button .svg_icon, #layerlist td.layervis .svg_icon': 14,\n '.dropdown button .svg_icon': 7,\n '#main_button .dropdown .svg_icon': 9,\n '.palette_item:first .svg_icon': 15,\n '#fill_bg .svg_icon, #stroke_bg .svg_icon': 16,\n '.toolbar_button button .svg_icon': 16,\n '.stroke_tool div div .svg_icon': 20,\n '#tools_bottom label .svg_icon': 18\n },\n async callback (icons) {\n $('.toolbar_button button > svg, .toolbar_button button > img').each(function () {\n $(this).parent().prepend(this);\n });\n\n const tleft = $('#tools_left');\n\n let minHeight;\n if (tleft.length) {\n minHeight = tleft.offset().top + tleft.outerHeight();\n }\n\n const size = editor.pref('iconsize');\n editor.setIconSize(size || ($(window).height() < minHeight ? 's' : 'm'));\n\n // Look for any missing flyout icons from plugins\n $('.tools_flyout').each(function () {\n const shower = $('#' + this.id + '_show');\n const sel = shower.attr('data-curopt');\n // Check if there's an icon here\n if (!shower.children('svg, img').length) {\n const clone = $(sel).children().clone();\n if (clone.length) {\n clone[0].removeAttribute('style'); // Needed for Opera\n shower.append(clone);\n }\n }\n });\n\n /**\n * Since stylesheets may be added out of order, we indicate the desired order\n * for defaults and others after them (in an indeterminate order).\n * @param {string} stylesheetFile\n * @returns {Integer|PositiveInfinity}\n */\n function getStylesheetPriority (stylesheetFile) {\n switch (stylesheetFile) {\n case 'jgraduate/css/jPicker.css':\n return 1;\n case 'jgraduate/css/jGraduate.css':\n return 2;\n case 'svg-editor.css':\n return 3;\n case 'spinbtn/jQuery.SpinButton.css':\n return 4;\n default:\n return Infinity;\n }\n }\n let stylesheets = $.loadingStylesheets.sort((a, b) => {\n const priorityA = getStylesheetPriority(a);\n const priorityB = getStylesheetPriority(b);\n if (priorityA === priorityB) {\n return 0;\n }\n return priorityA > priorityB;\n });\n if (curConfig.stylesheets.length) {\n // Ensure a copy with unique items\n stylesheets = [...new Set(curConfig.stylesheets)];\n const idx = stylesheets.indexOf('@default');\n if (idx > -1) {\n stylesheets.splice(idx, 1, ...$.loadingStylesheets);\n }\n }\n await loadStylesheets(stylesheets, {\n acceptErrors ({stylesheetURL, reject, resolve}) {\n if ($.loadingStylesheets.includes(stylesheetURL)) {\n reject(new Error(`Missing expected stylesheet: ${stylesheetURL}`));\n return;\n }\n resolve();\n }\n });\n $('#svg_container')[0].style.visibility = 'visible';\n await editor.runCallbacks();\n }\n });\n }\n /**\n * @name module:SVGEditor.canvas\n * @type {module:svgcanvas.SvgCanvas}\n */\n editor.canvas = svgCanvas = new SvgCanvas(\n document.getElementById('svgcanvas'),\n curConfig\n );\n const palette = [\n // Todo: Make into configuration item?\n '#000000', '#3f3f3f', '#7f7f7f', '#bfbfbf', '#ffffff',\n '#ff0000', '#ff7f00', '#ffff00', '#7fff00',\n '#00ff00', '#00ff7f', '#00ffff', '#007fff',\n '#0000ff', '#7f00ff', '#ff00ff', '#ff007f',\n '#7f0000', '#7f3f00', '#7f7f00', '#3f7f00',\n '#007f00', '#007f3f', '#007f7f', '#003f7f',\n '#00007f', '#3f007f', '#7f007f', '#7f003f',\n '#ffaaaa', '#ffd4aa', '#ffffaa', '#d4ffaa',\n '#aaffaa', '#aaffd4', '#aaffff', '#aad4ff',\n '#aaaaff', '#d4aaff', '#ffaaff', '#ffaad4'\n ],\n modKey = (isMac() ? 'meta+' : 'ctrl+'), // ⌘\n path = svgCanvas.pathActions,\n {undoMgr} = svgCanvas,\n workarea = $('#workarea'),\n canvMenu = $('#cmenu_canvas'),\n // layerMenu = $('#cmenu_layers'), // Unused\n paintBox = {fill: null, stroke: null};\n\n let resizeTimer, curScrollPos;\n let exportWindow = null,\n defaultImageURL = curConfig.imgPath + 'logo.png',\n zoomInIcon = 'crosshair',\n zoomOutIcon = 'crosshair',\n uiContext = 'toolbars';\n\n // For external openers\n (function () {\n // let the opener know SVG Edit is ready (now that config is set up)\n const w = window.opener || window.parent;\n if (w) {\n try {\n /**\n * Triggered on a containing `document` (of `window.opener`\n * or `window.parent`) when the editor is loaded.\n * @event module:SVGEditor#event:svgEditorReadyEvent\n * @type {Event}\n * @property {true} bubbles\n * @property {true} cancelable\n */\n /**\n * @name module:SVGEditor.svgEditorReadyEvent\n * @type {module:SVGEditor#event:svgEditorReadyEvent}\n */\n const svgEditorReadyEvent = new w.CustomEvent('svgEditorReady', {\n bubbles: true,\n cancelable: true\n });\n w.document.documentElement.dispatchEvent(svgEditorReadyEvent);\n } catch (e) {}\n }\n }());\n\n /**\n *\n * @returns {void}\n */\n const setSelectMode = function () {\n const curr = $('.tool_button_current');\n if (curr.length && curr[0].id !== 'tool_select') {\n curr.removeClass('tool_button_current').addClass('tool_button');\n $('#tool_select').addClass('tool_button_current').removeClass('tool_button');\n $('#styleoverrides').text(`\n #svgcanvas svg * {\n cursor: move;\n pointer-events: all;\n }\n #svgcanvas svg {\n cursor: default;\n }\n `);\n }\n svgCanvas.setMode('select');\n workarea.css('cursor', 'auto');\n };\n\n // used to make the flyouts stay on the screen longer the very first time\n // const flyoutspeed = 1250; // Currently unused\n // let textBeingEntered = false; // Currently unused\n const origTitle = $('title:first').text();\n // Make [1,2,5] array\n const rIntervals = [];\n for (let i = 0.1; i < 1e5; i *= 10) {\n rIntervals.push(i);\n rIntervals.push(2 * i);\n rIntervals.push(5 * i);\n }\n\n /**\n * This function highlights the layer passed in (by fading out the other layers).\n * If no layer is passed in, this function restores the other layers.\n * @param {string} [layerNameToHighlight]\n * @returns {void}\n */\n const toggleHighlightLayer = function (layerNameToHighlight) {\n let i;\n const curNames = [], numLayers = svgCanvas.getCurrentDrawing().getNumLayers();\n for (i = 0; i < numLayers; i++) {\n curNames[i] = svgCanvas.getCurrentDrawing().getLayerName(i);\n }\n\n if (layerNameToHighlight) {\n curNames.forEach((curName) => {\n if (curName !== layerNameToHighlight) {\n svgCanvas.getCurrentDrawing().setLayerOpacity(curName, 0.5);\n }\n });\n } else {\n curNames.forEach((curName) => {\n svgCanvas.getCurrentDrawing().setLayerOpacity(curName, 1.0);\n });\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const populateLayers = function () {\n svgCanvas.clearSelection();\n const layerlist = $('#layerlist tbody').empty();\n const selLayerNames = $('#selLayerNames').empty();\n const drawing = svgCanvas.getCurrentDrawing();\n const currentLayerName = drawing.getCurrentLayerName();\n const icon = $.getSvgIcon('eye');\n let layer = svgCanvas.getCurrentDrawing().getNumLayers();\n // we get the layers in the reverse z-order (the layer rendered on top is listed first)\n while (layer--) {\n const name = drawing.getLayerName(layer);\n const layerTr = $('<tr class=\"layer\">').toggleClass('layersel', name === currentLayerName);\n const layerVis = $('<td class=\"layervis\">').toggleClass('layerinvis', !drawing.getLayerVisibility(name));\n const layerName = $('<td class=\"layername\">' + name + '</td>');\n layerlist.append(layerTr.append(layerVis, layerName));\n selLayerNames.append('<option value=\"' + name + '\">' + name + '</option>');\n }\n if (icon !== undefined) {\n const copy = icon.clone();\n $('td.layervis', layerlist).append(copy);\n $.resizeSvgIcons({'td.layervis .svg_icon': 14});\n }\n // handle selection of layer\n $('#layerlist td.layername')\n .mouseup(function (evt) {\n $('#layerlist tr.layer').removeClass('layersel');\n $(this.parentNode).addClass('layersel');\n svgCanvas.setCurrentLayer(this.textContent);\n evt.preventDefault();\n })\n .mouseover(function () {\n toggleHighlightLayer(this.textContent);\n })\n .mouseout(function () {\n toggleHighlightLayer();\n });\n $('#layerlist td.layervis').click(function () {\n const row = $(this.parentNode).prevAll().length;\n const name = $('#layerlist tr.layer:eq(' + row + ') td.layername').text();\n const vis = $(this).hasClass('layerinvis');\n svgCanvas.setLayerVisibility(name, vis);\n $(this).toggleClass('layerinvis');\n });\n\n // if there were too few rows, let's add a few to make it not so lonely\n let num = 5 - $('#layerlist tr.layer').size();\n while (num-- > 0) {\n // TODO: there must a better way to do this\n layerlist.append('<tr><td style=\"color:white\">_</td><td/></tr>');\n }\n };\n\n let editingsource = false;\n let origSource = '';\n\n /**\n * @param {Event} [e] Not used.\n * @param {boolean} forSaving\n * @returns {void}\n */\n const showSourceEditor = function (e, forSaving) {\n if (editingsource) { return; }\n\n editingsource = true;\n origSource = svgCanvas.getSvgString();\n $('#save_output_btns').toggle(Boolean(forSaving));\n $('#tool_source_back').toggle(!forSaving);\n $('#svg_source_textarea').val(origSource);\n $('#svg_source_editor').fadeIn();\n $('#svg_source_textarea').focus();\n };\n\n let selectedElement = null;\n let multiselected = false;\n\n /**\n * @param {boolean} editmode\n * @param {module:svgcanvas.SvgCanvas#event:selected} elems\n * @returns {void}\n */\n const togglePathEditMode = function (editmode, elems) {\n $('#path_node_panel').toggle(editmode);\n $('#tools_bottom_2,#tools_bottom_3').toggle(!editmode);\n if (editmode) {\n // Change select icon\n $('.tool_button_current').removeClass('tool_button_current').addClass('tool_button');\n $('#tool_select').addClass('tool_button_current').removeClass('tool_button');\n setIcon('#tool_select', 'select_node');\n multiselected = false;\n if (elems.length) {\n selectedElement = elems[0];\n }\n } else {\n setTimeout(() => {\n setIcon('#tool_select', 'select');\n }, 1000);\n }\n };\n\n /**\n * @type {module:svgcanvas.EventHandler}\n * @param {external:Window} wind\n * @param {module:svgcanvas.SvgCanvas#event:saved} svg The SVG source\n * @listens module:svgcanvas.SvgCanvas#event:saved\n * @returns {void}\n */\n const saveHandler = function (wind, svg) {\n editor.showSaveWarning = false;\n\n // by default, we add the XML prolog back, systems integrating SVG-edit (wikis, CMSs)\n // can just provide their own custom save handler and might not want the XML prolog\n svg = '<?xml version=\"1.0\"?>\\n' + svg;\n\n // IE9 doesn't allow standalone Data URLs\n // https://connect.microsoft.com/IE/feedback/details/542600/data-uri-images-fail-when-loaded-by-themselves\n if (isIE()) {\n showSourceEditor(0, true);\n return;\n }\n\n // Since saving SVGs by opening a new window was removed in Chrome use artificial link-click\n // https://stackoverflow.com/questions/45603201/window-is-not-allowed-to-navigate-top-frame-navigations-to-data-urls\n const a = document.createElement('a');\n a.href = 'data:image/svg+xml;base64,' + Utils.encode64(svg);\n a.download = 'icon.svg';\n a.style.display = 'none';\n document.body.append(a); // Need to append for Firefox\n\n a.click();\n\n // Alert will only appear the first time saved OR the\n // first time the bug is encountered\n let done = editor.pref('save_notice_done');\n\n if (done !== 'all') {\n let note = uiStrings.notification.saveFromBrowser.replace('%s', 'SVG');\n // Check if FF and has <defs/>\n if (isGecko()) {\n if (svg.includes('<defs')) {\n // warning about Mozilla bug #308590 when applicable (seems to be fixed now in Feb 2013)\n note += '\\n\\n' + uiStrings.notification.defsFailOnSave;\n editor.pref('save_notice_done', 'all');\n done = 'all';\n } else {\n editor.pref('save_notice_done', 'part');\n }\n } else {\n editor.pref('save_notice_done', 'all');\n }\n if (done !== 'part') {\n $.alert(note);\n }\n }\n };\n\n /**\n * @param {external:Window} win\n * @param {module:svgcanvas.SvgCanvas#event:exported} data\n * @listens module:svgcanvas.SvgCanvas#event:exported\n * @returns {void}\n */\n const exportHandler = function (win, data) {\n const {issues, exportWindowName} = data;\n\n exportWindow = window.open(Utils.blankPageObjectURL || '', exportWindowName); // A hack to get the window via JSON-able name without opening a new one\n\n if (!exportWindow || exportWindow.closed) {\n /* await */ $.alert(uiStrings.notification.popupWindowBlocked);\n return;\n }\n\n exportWindow.location.href = data.bloburl || data.datauri;\n const done = editor.pref('export_notice_done');\n if (done !== 'all') {\n let note = uiStrings.notification.saveFromBrowser.replace('%s', data.type);\n\n // Check if there are issues\n if (issues.length) {\n const pre = '\\n \\u2022 ';\n note += ('\\n\\n' + uiStrings.notification.noteTheseIssues + pre + issues.join(pre));\n }\n\n // Note that this will also prevent the notice even though new issues may appear later.\n // May want to find a way to deal with that without annoying the user\n editor.pref('export_notice_done', 'all');\n exportWindow.alert(note);\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const operaRepaint = function () {\n // Repaints canvas in Opera. Needed for stroke-dasharray change as well as fill change\n if (!window.opera) {\n return;\n }\n $('<p/>').hide().appendTo('body').remove();\n };\n\n /**\n *\n * @param {Element} opt\n * @param {boolean} changeElem\n * @returns {void}\n */\n function setStrokeOpt (opt, changeElem) {\n const {id} = opt;\n const bits = id.split('_');\n const [pre, val] = bits;\n\n if (changeElem) {\n svgCanvas.setStrokeAttr('stroke-' + pre, val);\n }\n operaRepaint();\n setIcon('#cur_' + pre, id, 20);\n $(opt).addClass('current').siblings().removeClass('current');\n }\n\n /**\n * This is a common function used when a tool has been clicked (chosen).\n * It does several common things:\n * - Removes the `tool_button_current` class from whatever tool currently has it.\n * - Hides any flyouts.\n * - Adds the `tool_button_current` class to the button passed in.\n * @function module:SVGEDitor.toolButtonClick\n * @param {string|Element} button The DOM element or string selector representing the toolbar button\n * @param {boolean} noHiding Whether not to hide any flyouts\n * @returns {boolean} Whether the button was disabled or not\n */\n const toolButtonClick = editor.toolButtonClick = function (button, noHiding) {\n if ($(button).hasClass('disabled')) { return false; }\n if ($(button).parent().hasClass('tools_flyout')) { return true; }\n const fadeFlyouts = 'normal';\n if (!noHiding) {\n $('.tools_flyout').fadeOut(fadeFlyouts);\n }\n $('#styleoverrides').text('');\n workarea.css('cursor', 'auto');\n $('.tool_button_current').removeClass('tool_button_current').addClass('tool_button');\n $(button).addClass('tool_button_current').removeClass('tool_button');\n return true;\n };\n\n /**\n * Unless the select toolbar button is disabled, sets the button\n * and sets the select mode and cursor styles.\n * @function module:SVGEditor.clickSelect\n * @returns {void}\n */\n const clickSelect = editor.clickSelect = function () {\n if (toolButtonClick('#tool_select')) {\n svgCanvas.setMode('select');\n $('#styleoverrides').text(`\n #svgcanvas svg * {\n cursor: move;\n pointer-events: all;\n }\n #svgcanvas svg {\n cursor: default;\n }\n `);\n }\n };\n\n /**\n * Set a selected image's URL.\n * @function module:SVGEditor.setImageURL\n * @param {string} url\n * @returns {void}\n */\n const setImageURL = editor.setImageURL = function (url) {\n if (!url) {\n url = defaultImageURL;\n }\n svgCanvas.setImageURL(url);\n $('#image_url').val(url);\n\n if (url.startsWith('data:')) {\n // data URI found\n $('#image_url').hide();\n $('#change_image_url').show();\n } else {\n // regular URL\n svgCanvas.embedImage(url, function (dataURI) {\n // Couldn't embed, so show warning\n $('#url_notice').toggle(!dataURI);\n defaultImageURL = url;\n });\n $('#image_url').show();\n $('#change_image_url').hide();\n }\n };\n\n /**\n *\n * @param {string} color\n * @param {string} url\n * @returns {void}\n */\n function setBackground (color, url) {\n // if (color == editor.pref('bkgd_color') && url == editor.pref('bkgd_url')) { return; }\n editor.pref('bkgd_color', color);\n editor.pref('bkgd_url', url, true);\n\n // This should be done in svgcanvas.js for the borderRect fill\n svgCanvas.setBackground(color, url);\n }\n\n /**\n * @param {PlainObject} [opts={}]\n * @param {boolean} [opts.cancelDeletes=false}]\n * @returns {Promise<void>} Resolves to `undefined`\n */\n async function promptImgURL ({cancelDeletes = false} = {}) {\n let curhref = svgCanvas.getHref(selectedElement);\n curhref = curhref.startsWith('data:') ? '' : curhref;\n const url = await $.prompt(uiStrings.notification.enterNewImgURL, curhref);\n if (url) {\n setImageURL(url);\n } else if (cancelDeletes) {\n svgCanvas.deleteSelectedElements();\n }\n }\n\n /**\n * @param {Element} elem\n * @returns {void}\n */\n const setInputWidth = function (elem) {\n const w = Math.min(Math.max(12 + elem.value.length * 6, 50), 300);\n $(elem).width(w);\n };\n\n /**\n *\n * @param {HTMLDivElement} [scanvas]\n * @param {Float} [zoom]\n * @returns {void}\n */\n function updateRulers (scanvas, zoom) {\n if (!zoom) { zoom = svgCanvas.getZoom(); }\n if (!scanvas) { scanvas = $('#svgcanvas'); }\n\n let d, i;\n const limit = 30000;\n const contentElem = svgCanvas.getContentElem();\n const units = getTypeMap();\n const unit = units[curConfig.baseUnit]; // 1 = 1px\n\n // draw x ruler then y ruler\n for (d = 0; d < 2; d++) {\n const isX = (d === 0);\n const dim = isX ? 'x' : 'y';\n const lentype = isX ? 'width' : 'height';\n const contentDim = Number(contentElem.getAttribute(dim));\n\n const $hcanvOrig = $('#ruler_' + dim + ' canvas:first');\n\n // Bit of a hack to fully clear the canvas in Safari & IE9\n const $hcanv = $hcanvOrig.clone();\n $hcanvOrig.replaceWith($hcanv);\n\n const hcanv = $hcanv[0];\n\n // Set the canvas size to the width of the container\n let rulerLen = scanvas[lentype]();\n const totalLen = rulerLen;\n hcanv.parentNode.style[lentype] = totalLen + 'px';\n let ctx = hcanv.getContext('2d');\n let ctxArr, num, ctxArrNum;\n\n ctx.fillStyle = 'rgb(200,0,0)';\n ctx.fillRect(0, 0, hcanv.width, hcanv.height);\n\n // Remove any existing canvasses\n $hcanv.siblings().remove();\n\n // Create multiple canvases when necessary (due to browser limits)\n if (rulerLen >= limit) {\n ctxArrNum = parseInt(rulerLen / limit) + 1;\n ctxArr = [];\n ctxArr[0] = ctx;\n let copy;\n for (i = 1; i < ctxArrNum; i++) {\n hcanv[lentype] = limit;\n copy = hcanv.cloneNode(true);\n hcanv.parentNode.append(copy);\n ctxArr[i] = copy.getContext('2d');\n }\n\n copy[lentype] = rulerLen % limit;\n\n // set copy width to last\n rulerLen = limit;\n }\n\n hcanv[lentype] = rulerLen;\n\n const uMulti = unit * zoom;\n\n // Calculate the main number interval\n const rawM = 50 / uMulti;\n let multi = 1;\n for (i = 0; i < rIntervals.length; i++) {\n num = rIntervals[i];\n multi = num;\n if (rawM <= num) {\n break;\n }\n }\n\n const bigInt = multi * uMulti;\n\n ctx.font = '9px sans-serif';\n\n let rulerD = ((contentDim / uMulti) % multi) * uMulti;\n let labelPos = rulerD - bigInt;\n // draw big intervals\n let ctxNum = 0;\n while (rulerD < totalLen) {\n labelPos += bigInt;\n // const realD = rulerD - contentDim; // Currently unused\n\n const curD = Math.round(rulerD) + 0.5;\n if (isX) {\n ctx.moveTo(curD, 15);\n ctx.lineTo(curD, 0);\n } else {\n ctx.moveTo(15, curD);\n ctx.lineTo(0, curD);\n }\n\n num = (labelPos - contentDim) / uMulti;\n let label;\n if (multi >= 1) {\n label = Math.round(num);\n } else {\n const decs = String(multi).split('.')[1].length;\n label = num.toFixed(decs);\n }\n\n // Change 1000s to Ks\n if (label !== 0 && label !== 1000 && label % 1000 === 0) {\n label = (label / 1000) + 'K';\n }\n\n if (isX) {\n ctx.fillText(label, rulerD + 2, 8);\n } else {\n // draw label vertically\n const str = String(label).split('');\n for (i = 0; i < str.length; i++) {\n ctx.fillText(str[i], 1, (rulerD + 9) + i * 9);\n }\n }\n\n const part = bigInt / 10;\n // draw the small intervals\n for (i = 1; i < 10; i++) {\n let subD = Math.round(rulerD + part * i) + 0.5;\n if (ctxArr && subD > rulerLen) {\n ctxNum++;\n ctx.stroke();\n if (ctxNum >= ctxArrNum) {\n i = 10;\n rulerD = totalLen;\n continue;\n }\n ctx = ctxArr[ctxNum];\n rulerD -= limit;\n subD = Math.round(rulerD + part * i) + 0.5;\n }\n\n // odd lines are slighly longer\n const lineNum = (i % 2) ? 12 : 10;\n if (isX) {\n ctx.moveTo(subD, 15);\n ctx.lineTo(subD, lineNum);\n } else {\n ctx.moveTo(15, subD);\n ctx.lineTo(lineNum, subD);\n }\n }\n rulerD += bigInt;\n }\n ctx.strokeStyle = '#000';\n ctx.stroke();\n }\n }\n\n /**\n * @function module:SVGEditor.updateCanvas\n * @param {boolean} center\n * @param {module:math.XYObject} newCtr\n * @returns {void}\n */\n const updateCanvas = editor.updateCanvas = function (center, newCtr) {\n const zoom = svgCanvas.getZoom();\n const wArea = workarea;\n const cnvs = $('#svgcanvas');\n\n let w = workarea.width(), h = workarea.height();\n const wOrig = w, hOrig = h;\n const oldCtr = {\n x: wArea[0].scrollLeft + wOrig / 2,\n y: wArea[0].scrollTop + hOrig / 2\n };\n const multi = curConfig.canvas_expansion;\n w = Math.max(wOrig, svgCanvas.contentW * zoom * multi);\n h = Math.max(hOrig, svgCanvas.contentH * zoom * multi);\n\n if (w === wOrig && h === hOrig) {\n workarea.css('overflow', 'hidden');\n } else {\n workarea.css('overflow', 'scroll');\n }\n\n const oldCanY = cnvs.height() / 2;\n const oldCanX = cnvs.width() / 2;\n cnvs.width(w).height(h);\n const newCanY = h / 2;\n const newCanX = w / 2;\n const offset = svgCanvas.updateCanvas(w, h);\n\n const ratio = newCanX / oldCanX;\n\n const scrollX = w / 2 - wOrig / 2; // eslint-disable-line no-shadow\n const scrollY = h / 2 - hOrig / 2; // eslint-disable-line no-shadow\n\n if (!newCtr) {\n const oldDistX = oldCtr.x - oldCanX;\n const newX = newCanX + oldDistX * ratio;\n\n const oldDistY = oldCtr.y - oldCanY;\n const newY = newCanY + oldDistY * ratio;\n\n newCtr = {\n x: newX,\n y: newY\n };\n } else {\n newCtr.x += offset.x;\n newCtr.y += offset.y;\n }\n\n if (center) {\n // Go to top-left for larger documents\n if (svgCanvas.contentW > wArea.width()) {\n // Top-left\n workarea[0].scrollLeft = offset.x - 10;\n workarea[0].scrollTop = offset.y - 10;\n } else {\n // Center\n wArea[0].scrollLeft = scrollX;\n wArea[0].scrollTop = scrollY;\n }\n } else {\n wArea[0].scrollLeft = newCtr.x - wOrig / 2;\n wArea[0].scrollTop = newCtr.y - hOrig / 2;\n }\n if (curConfig.showRulers) {\n updateRulers(cnvs, zoom);\n workarea.scroll();\n }\n\n if (urldata.storagePrompt !== true && editor.storagePromptState === 'ignore') {\n $('#dialog_box').hide();\n }\n };\n\n /**\n * @fires module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate\n * @returns {void}\n */\n const updateToolButtonState = function () {\n const bNoFill = (svgCanvas.getColor('fill') === 'none');\n const bNoStroke = (svgCanvas.getColor('stroke') === 'none');\n const buttonsNeedingStroke = ['#tool_fhpath', '#tool_line'];\n const buttonsNeedingFillAndStroke = [\n '#tools_rect .tool_button', '#tools_ellipse .tool_button',\n '#tool_text', '#tool_path'\n ];\n\n if (bNoStroke) {\n buttonsNeedingStroke.forEach((btn) => {\n if ($(btn).hasClass('tool_button_current')) {\n clickSelect();\n }\n $(btn).addClass('disabled');\n });\n } else {\n buttonsNeedingStroke.forEach((btn) => {\n $(btn).removeClass('disabled');\n });\n }\n\n if (bNoStroke && bNoFill) {\n buttonsNeedingFillAndStroke.forEach((btn) => {\n if ($(btn).hasClass('tool_button_current')) {\n clickSelect();\n }\n $(btn).addClass('disabled');\n });\n } else {\n buttonsNeedingFillAndStroke.forEach((btn) => {\n $(btn).removeClass('disabled');\n });\n }\n\n svgCanvas.runExtensions(\n 'toolButtonStateUpdate',\n /** @type {module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate} */ {\n nofill: bNoFill,\n nostroke: bNoStroke\n }\n );\n\n // Disable flyouts if all inside are disabled\n $('.tools_flyout').each(function () {\n const shower = $('#' + this.id + '_show');\n let hasEnabled = false;\n $(this).children().each(function () {\n if (!$(this).hasClass('disabled')) {\n hasEnabled = true;\n }\n });\n shower.toggleClass('disabled', !hasEnabled);\n });\n\n operaRepaint();\n };\n\n /**\n * Updates the toolbar (colors, opacity, etc) based on the selected element.\n * This function also updates the opacity and id elements that are in the\n * context panel.\n * @returns {void}\n */\n const updateToolbar = function () {\n let i, len;\n if (!Utils.isNullish(selectedElement)) {\n switch (selectedElement.tagName) {\n case 'use':\n case 'image':\n case 'foreignObject':\n break;\n case 'g':\n case 'a': {\n // Look for common styles\n const childs = selectedElement.getElementsByTagName('*');\n let gWidth = null;\n for (i = 0, len = childs.length; i < len; i++) {\n const swidth = childs[i].getAttribute('stroke-width');\n\n if (i === 0) {\n gWidth = swidth;\n } else if (gWidth !== swidth) {\n gWidth = null;\n }\n }\n\n $('#stroke_width').val(gWidth === null ? '' : gWidth);\n\n paintBox.fill.update(true);\n paintBox.stroke.update(true);\n\n break;\n } default: {\n paintBox.fill.update(true);\n paintBox.stroke.update(true);\n\n $('#stroke_width').val(selectedElement.getAttribute('stroke-width') || 1);\n $('#stroke_style').val(selectedElement.getAttribute('stroke-dasharray') || 'none');\n\n let attr = selectedElement.getAttribute('stroke-linejoin') || 'miter';\n\n if ($('#linejoin_' + attr).length) {\n setStrokeOpt($('#linejoin_' + attr)[0]);\n }\n\n attr = selectedElement.getAttribute('stroke-linecap') || 'butt';\n\n if ($('#linecap_' + attr).length) {\n setStrokeOpt($('#linecap_' + attr)[0]);\n }\n }\n }\n }\n\n // All elements including image and group have opacity\n if (!Utils.isNullish(selectedElement)) {\n const opacPerc = (selectedElement.getAttribute('opacity') || 1.0) * 100;\n $('#group_opacity').val(opacPerc);\n $('#opac_slider').slider('option', 'value', opacPerc);\n $('#elem_id').val(selectedElement.id);\n $('#elem_class').val(selectedElement.getAttribute('class'));\n }\n\n updateToolButtonState();\n };\n\n /**\n * Updates the context panel tools based on the selected element.\n * @returns {void}\n */\n const updateContextPanel = function () {\n let elem = selectedElement;\n // If element has just been deleted, consider it null\n if (!Utils.isNullish(elem) && !elem.parentNode) { elem = null; }\n const currentLayerName = svgCanvas.getCurrentDrawing().getCurrentLayerName();\n const currentMode = svgCanvas.getMode();\n const unit = curConfig.baseUnit !== 'px' ? curConfig.baseUnit : null;\n\n const isNode = currentMode === 'pathedit'; // elem ? (elem.id && elem.id.startsWith('pathpointgrip')) : false;\n const menuItems = $('#cmenu_canvas li');\n $('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,' +\n '#ellipse_panel, #line_panel, #text_panel, #image_panel, #container_panel,' +\n ' #use_panel, #a_panel').hide();\n if (!Utils.isNullish(elem)) {\n const elname = elem.nodeName;\n // If this is a link with no transform and one child, pretend\n // its child is selected\n // if (elname === 'a') { // && !$(elem).attr('transform')) {\n // elem = elem.firstChild;\n // }\n\n const angle = svgCanvas.getRotationAngle(elem);\n $('#angle').val(angle);\n\n const blurval = svgCanvas.getBlur(elem);\n $('#blur').val(blurval);\n $('#blur_slider').slider('option', 'value', blurval);\n\n if (svgCanvas.addedNew) {\n if (elname === 'image' && svgCanvas.getMode() === 'image') {\n // Prompt for URL if not a data URL\n if (!svgCanvas.getHref(elem).startsWith('data:')) {\n /* await */ promptImgURL({cancelDeletes: true});\n }\n }\n /* else if (elname == 'text') {\n // TODO: Do something here for new text\n } */\n }\n\n if (!isNode && currentMode !== 'pathedit') {\n $('#selected_panel').show();\n // Elements in this array already have coord fields\n if (['line', 'circle', 'ellipse'].includes(elname)) {\n $('#xy_panel').hide();\n } else {\n let x, y;\n\n // Get BBox vals for g, polyline and path\n if (['g', 'polyline', 'path'].includes(elname)) {\n const bb = svgCanvas.getStrokedBBox([elem]);\n if (bb) {\n ({x, y} = bb);\n }\n } else {\n x = elem.getAttribute('x');\n y = elem.getAttribute('y');\n }\n\n if (unit) {\n x = convertUnit(x);\n y = convertUnit(y);\n }\n\n $('#selected_x').val(x || 0);\n $('#selected_y').val(y || 0);\n $('#xy_panel').show();\n }\n\n // Elements in this array cannot be converted to a path\n const noPath = !['image', 'text', 'path', 'g', 'use'].includes(elname);\n $('#tool_topath').toggle(noPath);\n $('#tool_reorient').toggle(elname === 'path');\n $('#tool_reorient').toggleClass('disabled', angle === 0);\n } else {\n const point = path.getNodePoint();\n $('#tool_add_subpath').removeClass('push_button_pressed').addClass('tool_button');\n $('#tool_node_delete').toggleClass('disabled', !path.canDeleteNodes);\n\n // Show open/close button based on selected point\n setIcon('#tool_openclose_path', path.closed_subpath ? 'open_path' : 'close_path');\n\n if (point) {\n const segType = $('#seg_type');\n if (unit) {\n point.x = convertUnit(point.x);\n point.y = convertUnit(point.y);\n }\n $('#path_node_x').val(point.x);\n $('#path_node_y').val(point.y);\n if (point.type) {\n segType.val(point.type).removeAttr('disabled');\n } else {\n segType.val(4).attr('disabled', 'disabled');\n }\n }\n return;\n }\n\n // update contextual tools here\n const panels = {\n g: [],\n a: [],\n rect: ['rx', 'width', 'height'],\n image: ['width', 'height'],\n circle: ['cx', 'cy', 'r'],\n ellipse: ['cx', 'cy', 'rx', 'ry'],\n line: ['x1', 'y1', 'x2', 'y2'],\n text: [],\n use: []\n };\n\n const {tagName} = elem;\n\n // if ($(elem).data('gsvg')) {\n // $('#g_panel').show();\n // }\n\n let linkHref = null;\n if (tagName === 'a') {\n linkHref = svgCanvas.getHref(elem);\n $('#g_panel').show();\n }\n\n if (elem.parentNode.tagName === 'a') {\n if (!$(elem).siblings().length) {\n $('#a_panel').show();\n linkHref = svgCanvas.getHref(elem.parentNode);\n }\n }\n\n // Hide/show the make_link buttons\n $('#tool_make_link, #tool_make_link').toggle(!linkHref);\n\n if (linkHref) {\n $('#link_url').val(linkHref);\n }\n\n if (panels[tagName]) {\n const curPanel = panels[tagName];\n\n $('#' + tagName + '_panel').show();\n\n $.each(curPanel, function (i, item) {\n let attrVal = elem.getAttribute(item);\n if (curConfig.baseUnit !== 'px' && elem[item]) {\n const bv = elem[item].baseVal.value;\n attrVal = convertUnit(bv);\n }\n $('#' + tagName + '_' + item).val(attrVal || 0);\n });\n\n if (tagName === 'text') {\n $('#text_panel').css('display', 'inline');\n $('#tool_font_size').css('display', 'inline');\n if (svgCanvas.getItalic()) {\n $('#tool_italic').addClass('push_button_pressed').removeClass('tool_button');\n } else {\n $('#tool_italic').removeClass('push_button_pressed').addClass('tool_button');\n }\n if (svgCanvas.getBold()) {\n $('#tool_bold').addClass('push_button_pressed').removeClass('tool_button');\n } else {\n $('#tool_bold').removeClass('push_button_pressed').addClass('tool_button');\n }\n $('#font_family').val(elem.getAttribute('font-family'));\n $('#font_size').val(elem.getAttribute('font-size'));\n $('#text').val(elem.textContent);\n if (svgCanvas.addedNew) {\n // Timeout needed for IE9\n setTimeout(function () {\n $('#text').focus().select();\n }, 100);\n }\n // text\n } else if (tagName === 'image' && svgCanvas.getMode() === 'image') {\n setImageURL(svgCanvas.getHref(elem));\n // image\n } else if (tagName === 'g' || tagName === 'use') {\n $('#container_panel').show();\n const title = svgCanvas.getTitle();\n const label = $('#g_title')[0];\n label.value = title;\n setInputWidth(label);\n $('#g_title').prop('disabled', tagName === 'use');\n }\n }\n menuItems[(tagName === 'g' ? 'en' : 'dis') + 'ableContextMenuItems']('#ungroup');\n menuItems[((tagName === 'g' || !multiselected) ? 'dis' : 'en') + 'ableContextMenuItems']('#group');\n // if (!Utils.isNullish(elem))\n } else if (multiselected) {\n $('#multiselected_panel').show();\n menuItems\n .enableContextMenuItems('#group')\n .disableContextMenuItems('#ungroup');\n } else {\n menuItems.disableContextMenuItems('#delete,#cut,#copy,#group,#ungroup,#move_front,#move_up,#move_down,#move_back');\n }\n\n // update history buttons\n $('#tool_undo').toggleClass('disabled', undoMgr.getUndoStackSize() === 0);\n $('#tool_redo').toggleClass('disabled', undoMgr.getRedoStackSize() === 0);\n\n svgCanvas.addedNew = false;\n\n if ((elem && !isNode) || multiselected) {\n // update the selected elements' layer\n $('#selLayerNames').removeAttr('disabled').val(currentLayerName);\n\n // Enable regular menu options\n canvMenu.enableContextMenuItems(\n '#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back'\n );\n } else {\n $('#selLayerNames').attr('disabled', 'disabled');\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const updateWireFrame = function () {\n // Test support\n if (supportsNonSS) { return; }\n\n const rule = `\n #workarea.wireframe #svgcontent * {\n stroke-width: ${1 / svgCanvas.getZoom()}px;\n }\n `;\n $('#wireframe_rules').text(workarea.hasClass('wireframe') ? rule : '');\n };\n\n let curContext = '';\n\n /**\n * @param {string} [title=svgCanvas.getDocumentTitle()]\n * @returns {void}\n */\n const updateTitle = function (title) {\n title = title || svgCanvas.getDocumentTitle();\n const newTitle = origTitle + (title ? ': ' + title : '');\n\n // Remove title update with current context info, isn't really necessary\n // if (curContext) {\n // new_title = new_title + curContext;\n // }\n $('title:first').text(newTitle);\n };\n\n // called when we've selected a different element\n /**\n *\n * @param {external:Window} win\n * @param {module:svgcanvas.SvgCanvas#event:selected} elems Array of elements that were selected\n * @listens module:svgcanvas.SvgCanvas#event:selected\n * @fires module:svgcanvas.SvgCanvas#event:ext_selectedChanged\n * @returns {void}\n */\n const selectedChanged = function (win, elems) {\n const mode = svgCanvas.getMode();\n if (mode === 'select') {\n setSelectMode();\n }\n const isNode = mode === 'pathedit';\n // if elems[1] is present, then we have more than one element\n selectedElement = (elems.length === 1 || Utils.isNullish(elems[1]) ? elems[0] : null);\n multiselected = (elems.length >= 2 && !Utils.isNullish(elems[1]));\n if (!Utils.isNullish(selectedElement)) {\n // unless we're already in always set the mode of the editor to select because\n // upon creation of a text element the editor is switched into\n // select mode and this event fires - we need our UI to be in sync\n\n if (!isNode) {\n updateToolbar();\n }\n } // if (!Utils.isNullish(elem))\n\n // Deal with pathedit mode\n togglePathEditMode(isNode, elems);\n updateContextPanel();\n svgCanvas.runExtensions('selectedChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext_selectedChanged} */ {\n elems,\n selectedElement,\n multiselected\n });\n };\n\n // Call when part of element is in process of changing, generally\n // on mousemove actions like rotate, move, etc.\n /**\n * @param {external:Window} win\n * @param {module:svgcanvas.SvgCanvas#event:transition} elems\n * @listens module:svgcanvas.SvgCanvas#event:transition\n * @fires module:svgcanvas.SvgCanvas#event:ext_elementTransition\n * @returns {void}\n */\n const elementTransition = function (win, elems) {\n const mode = svgCanvas.getMode();\n const elem = elems[0];\n\n if (!elem) {\n return;\n }\n\n multiselected = (elems.length >= 2 && !Utils.isNullish(elems[1]));\n // Only updating fields for single elements for now\n if (!multiselected) {\n switch (mode) {\n case 'rotate': {\n const ang = svgCanvas.getRotationAngle(elem);\n $('#angle').val(ang);\n $('#tool_reorient').toggleClass('disabled', ang === 0);\n break;\n\n // TODO: Update values that change on move/resize, etc\n // } case 'select': {\n // } case 'resize': {\n // break;\n // }\n }\n }\n }\n svgCanvas.runExtensions('elementTransition', /** @type {module:svgcanvas.SvgCanvas#event:ext_elementTransition} */ {\n elems\n });\n };\n\n /**\n * Test whether an element is a layer or not.\n * @param {SVGGElement} elem - The SVGGElement to test.\n * @returns {boolean} True if the element is a layer\n */\n function isLayer (elem) {\n return elem && elem.tagName === 'g' && Layer.CLASS_REGEX.test(elem.getAttribute('class'));\n }\n\n // called when any element has changed\n /**\n * @param {external:Window} win\n * @param {module:svgcanvas.SvgCanvas#event:changed} elems\n * @listens module:svgcanvas.SvgCanvas#event:changed\n * @fires module:svgcanvas.SvgCanvas#event:ext_elementChanged\n * @returns {void}\n */\n const elementChanged = function (win, elems) {\n const mode = svgCanvas.getMode();\n if (mode === 'select') {\n setSelectMode();\n }\n\n elems.forEach((elem) => {\n const isSvgElem = (elem && elem.tagName === 'svg');\n if (isSvgElem || isLayer(elem)) {\n populateLayers();\n // if the element changed was the svg, then it could be a resolution change\n if (isSvgElem) {\n updateCanvas();\n }\n // Update selectedElement if element is no longer part of the image.\n // This occurs for the text elements in Firefox\n } else if (elem && selectedElement && Utils.isNullish(selectedElement.parentNode)) {\n // || elem && elem.tagName == \"path\" && !multiselected) { // This was added in r1430, but not sure why\n selectedElement = elem;\n }\n });\n\n editor.showSaveWarning = true;\n\n // we update the contextual panel with potentially new\n // positional/sizing information (we DON'T want to update the\n // toolbar here as that creates an infinite loop)\n // also this updates the history buttons\n\n // we tell it to skip focusing the text control if the\n // text element was previously in focus\n updateContextPanel();\n\n // In the event a gradient was flipped:\n if (selectedElement && mode === 'select') {\n paintBox.fill.update();\n paintBox.stroke.update();\n }\n\n svgCanvas.runExtensions('elementChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext_elementChanged} */ {\n elems\n });\n };\n\n /**\n * @returns {void}\n */\n const zoomDone = function () {\n updateWireFrame();\n // updateCanvas(); // necessary?\n };\n\n /**\n * @typedef {PlainObject} module:SVGEditor.BBoxObjectWithFactor (like `DOMRect`)\n * @property {Float} x\n * @property {Float} y\n * @property {Float} width\n * @property {Float} height\n * @property {Float} [factor] Needed if width or height are 0\n * @property {Float} [zoom]\n * @see module:svgcanvas.SvgCanvas#event:zoomed\n */\n\n /**\n * @function module:svgcanvas.SvgCanvas#zoomChanged\n * @param {external:Window} win\n * @param {module:svgcanvas.SvgCanvas#event:zoomed} bbox\n * @param {boolean} autoCenter\n * @listens module:svgcanvas.SvgCanvas#event:zoomed\n * @returns {void}\n */\n const zoomChanged = svgCanvas.zoomChanged = function (win, bbox, autoCenter) {\n const scrbar = 15,\n // res = svgCanvas.getResolution(), // Currently unused\n wArea = workarea;\n // const canvasPos = $('#svgcanvas').position(); // Currently unused\n const zInfo = svgCanvas.setBBoxZoom(bbox, wArea.width() - scrbar, wArea.height() - scrbar);\n if (!zInfo) { return; }\n const zoomlevel = zInfo.zoom,\n bb = zInfo.bbox;\n\n if (zoomlevel < 0.001) {\n changeZoom({value: 0.1});\n return;\n }\n\n $('#zoom').val((zoomlevel * 100).toFixed(1));\n\n if (autoCenter) {\n updateCanvas();\n } else {\n updateCanvas(false, {x: bb.x * zoomlevel + (bb.width * zoomlevel) / 2, y: bb.y * zoomlevel + (bb.height * zoomlevel) / 2});\n }\n\n if (svgCanvas.getMode() === 'zoom' && bb.width) {\n // Go to select if a zoom box was drawn\n setSelectMode();\n }\n\n zoomDone();\n };\n\n /**\n * @type {module:jQuerySpinButton.ValueCallback}\n */\n const changeZoom = function (ctl) {\n const zoomlevel = ctl.value / 100;\n if (zoomlevel < 0.001) {\n ctl.value = 0.1;\n return;\n }\n const zoom = svgCanvas.getZoom();\n const wArea = workarea;\n\n zoomChanged(window, {\n width: 0,\n height: 0,\n // center pt of scroll position\n x: (wArea[0].scrollLeft + wArea.width() / 2) / zoom,\n y: (wArea[0].scrollTop + wArea.height() / 2) / zoom,\n zoom: zoomlevel\n }, true);\n };\n\n $('#cur_context_panel').delegate('a', 'click', function () {\n const link = $(this);\n if (link.attr('data-root')) {\n svgCanvas.leaveContext();\n } else {\n svgCanvas.setContext(link.text());\n }\n svgCanvas.clearSelection();\n return false;\n });\n\n /**\n * @param {external:Window} win\n * @param {module:svgcanvas.SvgCanvas#event:contextset} context\n * @listens module:svgcanvas.SvgCanvas#event:contextset\n * @returns {void}\n */\n const contextChanged = function (win, context) {\n let linkStr = '';\n if (context) {\n let str = '';\n linkStr = '<a href=\"#\" data-root=\"y\">' + svgCanvas.getCurrentDrawing().getCurrentLayerName() + '</a>';\n\n $(context).parentsUntil('#svgcontent > g').andSelf().each(function () {\n if (this.id) {\n str += ' > ' + this.id;\n if (this !== context) {\n linkStr += ' > <a href=\"#\">' + this.id + '</a>';\n } else {\n linkStr += ' > ' + this.id;\n }\n }\n });\n\n curContext = str;\n } else {\n curContext = null;\n }\n $('#cur_context_panel').toggle(Boolean(context)).html(linkStr);\n\n updateTitle();\n };\n\n /**\n * Makes sure the current selected paint is available to work with.\n * @returns {void}\n */\n const prepPaints = function () {\n paintBox.fill.prep();\n paintBox.stroke.prep();\n };\n\n const flyoutFuncs = {};\n\n /**\n *\n * @returns {void}\n */\n const setFlyoutTitles = function () {\n $('.tools_flyout').each(function () {\n const shower = $('#' + this.id + '_show');\n if (shower.data('isLibrary')) {\n return;\n }\n\n const tooltips = $(this).children().map(function () {\n return this.title;\n }).get();\n shower[0].title = tooltips.join(' / ');\n });\n };\n\n const allHolders = {};\n /**\n * @param {PlainObject<string, module:SVGEditor.ToolButton>} holders Key is a selector\n * @returns {void}\n */\n const setupFlyouts = function (holders) {\n $.each(holders, function (holdSel, btnOpts) {\n if (!allHolders[holdSel]) {\n allHolders[holdSel] = [];\n }\n allHolders[holdSel].push(...btnOpts);\n\n const buttons = $(holdSel).children().not('.tool_button_evt_handled');\n const showSel = holdSel + '_show';\n const shower = $(showSel);\n let def = false;\n buttons.addClass('tool_button tool_button_evt_handled')\n .unbind('click mousedown mouseup') // may not be necessary\n .each(function () {\n // Get this button's options\n const idSel = '#' + this.getAttribute('id');\n const [i, opts] = Object.entries(btnOpts).find(([_, {sel}]) => {\n return sel === idSel;\n });\n\n // Remember the function that goes with this ID\n flyoutFuncs[opts.sel] = opts.fn;\n\n if (opts.isDefault) { def = i; }\n\n /**\n * Clicking the icon in flyout should set this set's icon.\n * @param {Event} ev\n * @returns {boolean}\n */\n const flyoutAction = function (ev) {\n let options = opts;\n // Find the currently selected tool if comes from keystroke\n if (ev.type === 'keydown') {\n const flyoutIsSelected = $(options.parent + '_show').hasClass('tool_button_current');\n const currentOperation = $(options.parent + '_show').attr('data-curopt');\n Object.entries(holders[opts.parent]).some(([j, tool]) => {\n if (tool.sel !== currentOperation) {\n return false;\n }\n if (!ev.shiftKey || !flyoutIsSelected) {\n options = tool;\n } else {\n // If flyout is selected, allow shift key to iterate through subitems\n j = parseInt(j);\n // Use `allHolders` to include both extension `includeWith` and toolbarButtons\n options = allHolders[opts.parent][j + 1] ||\n holders[opts.parent][0];\n }\n return true;\n });\n }\n if ($(this).hasClass('disabled')) { return false; }\n if (toolButtonClick(showSel)) {\n options.fn();\n }\n let icon;\n if (options.icon) {\n icon = $.getSvgIcon(options.icon, true);\n } else {\n icon = $(options.sel).children().eq(0).clone();\n }\n\n icon[0].setAttribute('width', shower.width());\n icon[0].setAttribute('height', shower.height());\n shower.children(':not(.flyout_arrow_horiz)').remove();\n shower.append(icon).attr('data-curopt', options.sel); // This sets the current mode\n return true;\n };\n\n $(this).mouseup(flyoutAction);\n\n if (opts.key) {\n $(document).bind('keydown', opts.key[0] + ' shift+' + opts.key[0], flyoutAction);\n }\n return true;\n });\n\n if (def) {\n shower.attr('data-curopt', btnOpts[def].sel);\n } else if (!shower.attr('data-curopt')) {\n // Set first as default\n shower.attr('data-curopt', btnOpts[0].sel);\n }\n\n let timer;\n\n // Clicking the \"show\" icon should set the current mode\n shower.mousedown(function (evt) {\n if (shower.hasClass('disabled')) {\n return false;\n }\n const holder = $(holdSel);\n const pos = $(showSel).position();\n const l = pos.left + 34;\n const w = holder.width() * -1;\n const time = holder.data('shown_popop') ? 200 : 0;\n timer = setTimeout(function () {\n // Show corresponding menu\n if (!shower.data('isLibrary')) {\n holder.css('left', w).show().animate({\n left: l\n }, 150);\n } else {\n holder.css('left', l).show();\n }\n holder.data('shown_popop', true);\n }, time);\n evt.preventDefault();\n return true;\n }).mouseup(function (evt) {\n clearTimeout(timer);\n const opt = $(this).attr('data-curopt');\n // Is library and popped up, so do nothing\n if (shower.data('isLibrary') && $(showSel.replace('_show', '')).is(':visible')) {\n toolButtonClick(showSel, true);\n return;\n }\n if (toolButtonClick(showSel) && flyoutFuncs[opt]) {\n flyoutFuncs[opt]();\n }\n });\n // $('#tools_rect').mouseleave(function () { $('#tools_rect').fadeOut(); });\n });\n setFlyoutTitles();\n setFlyoutPositions();\n };\n\n /**\n * @param {string} id\n * @param {external:jQuery} child\n * @returns {external:jQuery}\n */\n const makeFlyoutHolder = function (id, child) {\n const div = $('<div>', {\n class: 'tools_flyout',\n id\n }).appendTo('#svg_editor').append(child);\n\n return div;\n };\n\n /**\n * @param {string} elemSel\n * @param {string} listSel\n * @param {external:jQuery.Function} callback\n * @param {PlainObject} opts\n * @param {boolean} opts.dropUp\n * @param {boolean} opts.seticon\n * @param {boolean} opts.multiclick\n * @todo Combine this with `addDropDown` or find other way to optimize.\n * @returns {void}\n */\n const addAltDropDown = function (elemSel, listSel, callback, opts) {\n const button = $(elemSel);\n const {dropUp} = opts;\n const list = $(listSel);\n if (dropUp) {\n $(elemSel).addClass('dropup');\n }\n list.find('li').bind('mouseup', function (...args) {\n if (opts.seticon) {\n setIcon('#cur_' + button[0].id, $(this).children());\n $(this).addClass('current').siblings().removeClass('current');\n }\n callback.apply(this, ...args);\n });\n\n let onButton = false;\n $(window).mouseup(function (evt) {\n if (!onButton) {\n button.removeClass('down');\n list.hide();\n list.css({top: 0, left: 0});\n }\n onButton = false;\n });\n\n // const height = list.height(); // Currently unused\n button.bind('mousedown', function () {\n const off = button.offset();\n if (dropUp) {\n off.top -= list.height();\n off.left += 8;\n } else {\n off.top += button.height();\n }\n list.offset(off);\n\n if (!button.hasClass('down')) {\n list.show();\n onButton = true;\n } else {\n // CSS position must be reset for Webkit\n list.hide();\n list.css({top: 0, left: 0});\n }\n button.toggleClass('down');\n }).hover(function () {\n onButton = true;\n }).mouseout(function () {\n onButton = false;\n });\n\n if (opts.multiclick) {\n list.mousedown(function () {\n onButton = true;\n });\n }\n };\n\n const extsPreLang = [];\n /**\n * @param {external:Window} win\n * @param {module:svgcanvas.SvgCanvas#event:extension_added} ext\n * @listens module:svgcanvas.SvgCanvas#event:extension_added\n * @returns {Promise<void>|void} Resolves to `undefined`\n */\n const extAdded = async function (win, ext) {\n if (!ext) {\n return undefined;\n }\n let cbCalled = false;\n let resizeDone = false;\n\n if (ext.langReady) {\n if (editor.langChanged) { // We check for this since the \"lang\" pref could have been set by storage\n const lang = editor.pref('lang');\n await ext.langReady({\n lang,\n uiStrings,\n importLocale: getImportLocale({defaultLang: lang, defaultName: ext.name})\n });\n loadedExtensionNames.push(ext.name);\n } else {\n extsPreLang.push(ext);\n }\n }\n\n /**\n * Clear resize timer if present and if not previously performed,\n * perform an icon resize.\n * @returns {void}\n */\n function prepResize () {\n if (resizeTimer) {\n clearTimeout(resizeTimer);\n resizeTimer = null;\n }\n if (!resizeDone) {\n resizeTimer = setTimeout(function () {\n resizeDone = true;\n setIconSize(editor.pref('iconsize'));\n }, 50);\n }\n }\n\n /**\n *\n * @returns {void}\n */\n const runCallback = function () {\n if (ext.callback && !cbCalled) {\n cbCalled = true;\n ext.callback.call(editor);\n }\n };\n\n const btnSelects = [];\n\n /**\n * @typedef {PlainObject} module:SVGEditor.ContextTool\n * @property {string} panel The ID of the existing panel to which the tool is being added. Required.\n * @property {string} id The ID of the actual tool element. Required.\n * @property {PlainObject<string, external:jQuery.Function>|PlainObject<\"change\", external:jQuery.Function>} events DOM event names keyed to associated functions. Example: `{change () { alert('Option was changed') } }`. \"change\" event is one specifically handled for the \"button-select\" type. Required.\n * @property {string} title The tooltip text that will appear when the user hovers over the tool. Required.\n * @property {\"tool_button\"|\"select\"|\"button-select\"|\"input\"|string} type The type of tool being added. Expected.\n * @property {PlainObject<string, string>} [options] List of options and their labels for select tools. Example: `{1: 'One', 2: 'Two', all: 'All' }`. Required by \"select\" tools.\n * @property {string} [container_id] The ID to be given to the tool's container element.\n * @property {string} [defval] Default value\n * @property {string|Integer} [colnum] Added as part of the option list class.\n * @property {string} [label] Label associated with the tool, visible in the UI\n * @property {Integer} [size] Value of the \"size\" attribute of the tool input\n * @property {module:jQuerySpinButton.SpinButtonConfig} [spindata] When added to a tool of type \"input\", this tool becomes a \"spinner\" which allows the number to be in/decreased.\n */\n if (ext.context_tools) {\n $.each(ext.context_tools, function (i, tool) {\n // Add select tool\n const contId = tool.container_id ? (' id=\"' + tool.container_id + '\"') : '';\n\n let panel = $('#' + tool.panel);\n // create the panel if it doesn't exist\n if (!panel.length) {\n panel = $('<div>', {id: tool.panel}).appendTo('#tools_top');\n }\n\n let html;\n // TODO: Allow support for other types, or adding to existing tool\n switch (tool.type) {\n case 'tool_button': {\n html = '<div class=\"tool_button\">' + tool.id + '</div>';\n const div = $(html).appendTo(panel);\n if (tool.events) {\n $.each(tool.events, function (evt, func) {\n $(div).bind(evt, func);\n });\n }\n break;\n } case 'select': {\n html = '<label' + contId + '>' +\n '<select id=\"' + tool.id + '\">';\n $.each(tool.options, function (val, text) {\n const sel = (val === tool.defval) ? ' selected' : '';\n html += '<option value=\"' + val + '\"' + sel + '>' + text + '</option>';\n });\n html += '</select></label>';\n // Creates the tool, hides & adds it, returns the select element\n const sel = $(html).appendTo(panel).find('select');\n\n $.each(tool.events, function (evt, func) {\n $(sel).bind(evt, func);\n });\n break;\n } case 'button-select': {\n html = '<div id=\"' + tool.id + '\" class=\"dropdown toolset\" title=\"' + tool.title + '\">' +\n '<div id=\"cur_' + tool.id + '\" class=\"icon_label\"></div><button></button></div>';\n\n const list = $('<ul id=\"' + tool.id + '_opts\"></ul>').appendTo('#option_lists');\n\n if (tool.colnum) {\n list.addClass('optcols' + tool.colnum);\n }\n\n // Creates the tool, hides & adds it, returns the select element\n /* const dropdown = */ $(html).appendTo(panel).children();\n\n btnSelects.push({\n elem: ('#' + tool.id),\n list: ('#' + tool.id + '_opts'),\n title: tool.title,\n callback: tool.events.change,\n cur: ('#cur_' + tool.id)\n });\n\n break;\n } case 'input': {\n html = '<label' + contId + '>' +\n '<span id=\"' + tool.id + '_label\">' +\n tool.label + ':</span>' +\n '<input id=\"' + tool.id + '\" title=\"' + tool.title +\n '\" size=\"' + (tool.size || '4') +\n '\" value=\"' + (tool.defval || '') + '\" type=\"text\"/></label>';\n\n // Creates the tool, hides & adds it, returns the select element\n\n // Add to given tool.panel\n const inp = $(html).appendTo(panel).find('input');\n\n if (tool.spindata) {\n inp.SpinButton(tool.spindata);\n }\n\n if (tool.events) {\n $.each(tool.events, function (evt, func) {\n inp.bind(evt, func);\n });\n }\n break;\n } default:\n break;\n }\n });\n }\n\n const {svgicons} = ext;\n if (ext.buttons) {\n const fallbackObj = {},\n altsObj = {},\n placementObj = {},\n holders = {};\n\n /**\n * @typedef {GenericArray} module:SVGEditor.KeyArray\n * @property {string} 0 The key to bind (on `keydown`)\n * @property {boolean} 1 Whether to `preventDefault` on the `keydown` event\n * @property {boolean} 2 Not apparently in use (NoDisableInInput)\n */\n /**\n * @typedef {string|module:SVGEditor.KeyArray} module:SVGEditor.Key\n */\n /**\n * @typedef {PlainObject} module:SVGEditor.Button\n * @property {string} id A unique identifier for this button. If SVG icons are used, this must match the ID used in the icon file. Required.\n * @property {\"mode_flyout\"|\"mode\"|\"context\"|\"app_menu\"} type Type of button. Required.\n * @property {string} title The tooltip text that will appear when the user hovers over the icon. Required.\n * @property {PlainObject<string, external:jQuery.Function>|PlainObject<\"click\", external:jQuery.Function>} events DOM event names with associated functions. Example: `{click () { alert('Button was clicked') } }`. Click is used with `includeWith` and `type` of \"mode_flyout\" (and \"mode\"); any events may be added if `list` is not present. Expected.\n * @property {string} panel The ID of the context panel to be included, if type is \"context\". Required only if type is \"context\".\n * @property {string} icon The file path to the raster version of the icon image source. Required only if no `svgicons` is supplied from [ExtensionInitResponse]{@link module:svgcanvas.ExtensionInitResponse}.\n * @property {string} [svgicon] If absent, will utilize the button \"id\"; used to set \"placement\" on the `svgIcons` call\n * @property {string} [list] Points to the \"id\" of a `context_tools` item of type \"button-select\" into which the button will be added as a panel list item\n * @property {Integer} [position] The numeric index for placement; defaults to last position (as of the time of extension addition) if not present. For use with {@link http://api.jquery.com/eq/}.\n * @property {boolean} [isDefault] Whether or not the button is the default. Used with `list`.\n * @property {PlainObject} [includeWith] Object with flyout menu data\n * @property {boolean} [includeWith.isDefault] Indicates whether button is default in flyout list or not.\n * @property {string} includeWith.button jQuery selector of the existing button to be joined. Example: '#tool_line'. Required if `includeWith` is used.\n * @property {\"last\"|Integer} [includeWith.position] Position of icon in flyout list; will be added to end if not indicated. Integer is for use with {@link http://api.jquery.com/eq/}.\n * @property {module:SVGEditor.Key} [key] The key to bind to the button\n */\n // Add buttons given by extension\n $.each(ext.buttons, function (i, /** @type {module:SVGEditor.Button} */ btn) {\n let {id} = btn;\n let num = i;\n // Give button a unique ID\n while ($('#' + id).length) {\n id = btn.id + '_' + (++num);\n }\n\n let icon;\n if (!svgicons) {\n icon = $(\n '<img src=\"' + btn.icon +\n (btn.title ? '\" alt=\"' + btn.title : '') +\n '\">'\n );\n } else {\n fallbackObj[id] = btn.icon;\n altsObj[id] = btn.title;\n const svgicon = btn.svgicon || btn.id;\n if (btn.type === 'app_menu') {\n placementObj['#' + id + ' > div'] = svgicon;\n } else {\n placementObj['#' + id] = svgicon;\n }\n }\n\n let cls, parent;\n\n // Set button up according to its type\n switch (btn.type) {\n case 'mode_flyout':\n case 'mode':\n cls = 'tool_button';\n parent = '#tools_left';\n break;\n case 'context':\n cls = 'tool_button';\n parent = '#' + btn.panel;\n // create the panel if it doesn't exist\n if (!$(parent).length) {\n $('<div>', {id: btn.panel}).appendTo('#tools_top');\n }\n break;\n case 'app_menu':\n cls = '';\n parent = '#main_menu ul';\n break;\n }\n let flyoutHolder, showBtn, refData, refBtn;\n const button = $((btn.list || btn.type === 'app_menu') ? '<li/>' : '<div/>')\n .attr('id', id)\n .attr('title', btn.title)\n .addClass(cls);\n if (!btn.includeWith && !btn.list) {\n if ('position' in btn) {\n if ($(parent).children().eq(btn.position).length) {\n $(parent).children().eq(btn.position).before(button);\n } else {\n $(parent).children().last().after(button);\n }\n } else {\n button.appendTo(parent);\n }\n\n if (btn.type === 'mode_flyout') {\n // Add to flyout menu / make flyout menu\n // const opts = btn.includeWith;\n // // opts.button, default, position\n refBtn = $(button);\n\n flyoutHolder = refBtn.parent();\n // Create a flyout menu if there isn't one already\n let tlsId;\n if (!refBtn.parent().hasClass('tools_flyout')) {\n // Create flyout placeholder\n tlsId = refBtn[0].id.replace('tool_', 'tools_');\n showBtn = refBtn.clone()\n .attr('id', tlsId + '_show')\n .append($('<div>', {class: 'flyout_arrow_horiz'}));\n\n refBtn.before(showBtn);\n\n // Create a flyout div\n flyoutHolder = makeFlyoutHolder(tlsId, refBtn);\n flyoutHolder.data('isLibrary', true);\n showBtn.data('isLibrary', true);\n }\n // refData = Actions.getButtonData(opts.button);\n\n placementObj['#' + tlsId + '_show'] = btn.id;\n // TODO: Find way to set the current icon using the iconloader if this is not default\n\n // Include data for extension button as well as ref button\n /* curH = */ holders['#' + flyoutHolder[0].id] = [{\n sel: '#' + id,\n fn: btn.events.click,\n icon: btn.id,\n // key: btn.key,\n isDefault: true\n }]; // , refData\n //\n // // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}\n //\n // const pos = ('position' in opts)?opts.position:'last';\n // const len = flyoutHolder.children().length;\n //\n // // Add at given position or end\n // if (!isNaN(pos) && pos >= 0 && pos < len) {\n // flyoutHolder.children().eq(pos).before(button);\n // } else {\n // flyoutHolder.append(button);\n // curH.reverse();\n // }\n } else if (btn.type === 'app_menu') {\n button.append('<div>').append(btn.title);\n }\n } else if (btn.list) {\n // Add button to list\n button.addClass('push_button');\n $('#' + btn.list + '_opts').append(button);\n if (btn.isDefault) {\n $('#cur_' + btn.list).append(button.children().clone());\n const svgicon = btn.svgicon || btn.id;\n placementObj['#cur_' + btn.list] = svgicon;\n }\n } else if (btn.includeWith) {\n // Add to flyout menu / make flyout menu\n const opts = btn.includeWith;\n // opts.button, default, position\n refBtn = $(opts.button);\n\n flyoutHolder = refBtn.parent();\n // Create a flyout menu if there isn't one already\n let tlsId;\n if (!refBtn.parent().hasClass('tools_flyout')) {\n // Create flyout placeholder\n tlsId = refBtn[0].id.replace('tool_', 'tools_');\n showBtn = refBtn.clone()\n .attr('id', tlsId + '_show')\n .append($('<div>', {class: 'flyout_arrow_horiz'}));\n\n refBtn.before(showBtn);\n // Create a flyout div\n flyoutHolder = makeFlyoutHolder(tlsId, refBtn);\n }\n\n refData = Actions.getButtonData(opts.button);\n\n if (opts.isDefault) {\n placementObj['#' + tlsId + '_show'] = btn.id;\n }\n // TODO: Find way to set the current icon using the iconloader if this is not default\n\n // Include data for extension button as well as ref button\n const curH = holders['#' + flyoutHolder[0].id] = [{\n sel: '#' + id,\n fn: btn.events.click,\n icon: btn.id,\n key: btn.key,\n isDefault: Boolean(btn.includeWith && btn.includeWith.isDefault)\n }, refData];\n\n // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}\n\n const pos = ('position' in opts) ? opts.position : 'last';\n const len = flyoutHolder.children().length;\n\n // Add at given position or end\n if (!isNaN(pos) && pos >= 0 && pos < len) {\n flyoutHolder.children().eq(pos).before(button);\n } else {\n flyoutHolder.append(button);\n curH.reverse();\n }\n }\n\n if (!svgicons) {\n button.append(icon);\n }\n\n if (!btn.list) {\n // Add given events to button\n $.each(btn.events, function (name, func) {\n if (name === 'click' && btn.type === 'mode') {\n // `touch.js` changes `touchstart` to `mousedown`,\n // so we must map extension click events as well\n if (isTouch() && name === 'click') {\n name = 'mousedown';\n }\n if (btn.includeWith) {\n button.bind(name, func);\n } else {\n button.bind(name, function () {\n if (toolButtonClick(button)) {\n func();\n }\n });\n }\n if (btn.key) {\n $(document).bind('keydown', btn.key, func);\n if (btn.title) {\n button.attr('title', btn.title + ' [' + btn.key + ']');\n }\n }\n } else {\n button.bind(name, func);\n }\n });\n }\n\n setupFlyouts(holders);\n });\n\n $.each(btnSelects, function () {\n addAltDropDown(this.elem, this.list, this.callback, {seticon: true});\n });\n\n if (svgicons) {\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n $.svgIcons(svgicons, {\n w: 24, h: 24,\n id_match: false,\n no_img: (!isWebkit()),\n fallback: fallbackObj,\n placement: placementObj,\n callback (icons) {\n // Non-ideal hack to make the icon match the current size\n // if (curPrefs.iconsize && curPrefs.iconsize !== 'm') {\n if (editor.pref('iconsize') !== 'm') {\n prepResize();\n }\n runCallback();\n resolve();\n }\n });\n });\n }\n }\n return runCallback();\n };\n\n /**\n * @param {string} color\n * @param {Float} opac\n * @param {string} type\n * @returns {module:jGraduate~Paint}\n */\n const getPaint = function (color, opac, type) {\n // update the editor's fill paint\n const opts = {alpha: opac};\n if (color.startsWith('url(#')) {\n let refElem = svgCanvas.getRefElem(color);\n if (refElem) {\n refElem = refElem.cloneNode(true);\n } else {\n refElem = $('#' + type + '_color defs *')[0];\n }\n opts[refElem.tagName] = refElem;\n } else if (color.startsWith('#')) {\n opts.solidColor = color.substr(1);\n } else {\n opts.solidColor = 'none';\n }\n return new $.jGraduate.Paint(opts);\n };\n\n // $('#text').focus(function () { textBeingEntered = true; });\n // $('#text').blur(function () { textBeingEntered = false; });\n\n // bind the selected event to our function that handles updates to the UI\n svgCanvas.bind('selected', selectedChanged);\n svgCanvas.bind('transition', elementTransition);\n svgCanvas.bind('changed', elementChanged);\n svgCanvas.bind('saved', saveHandler);\n svgCanvas.bind('exported', exportHandler);\n svgCanvas.bind('exportedPDF', function (win, data) {\n if (!data.output) { // Ignore Chrome\n return;\n }\n const {exportWindowName} = data;\n if (exportWindowName) {\n exportWindow = window.open('', exportWindowName); // A hack to get the window via JSON-able name without opening a new one\n }\n if (!exportWindow || exportWindow.closed) {\n /* await */ $.alert(uiStrings.notification.popupWindowBlocked);\n return;\n }\n exportWindow.location.href = data.output;\n });\n svgCanvas.bind('zoomed', zoomChanged);\n svgCanvas.bind('zoomDone', zoomDone);\n svgCanvas.bind(\n 'updateCanvas',\n /**\n * @param {external:Window} win\n * @param {PlainObject} centerInfo\n * @param {false} centerInfo.center\n * @param {module:math.XYObject} centerInfo.newCtr\n * @listens module:svgcanvas.SvgCanvas#event:updateCanvas\n * @returns {void}\n */\n function (win, {center, newCtr}) {\n updateCanvas(center, newCtr);\n }\n );\n svgCanvas.bind('contextset', contextChanged);\n svgCanvas.bind('extension_added', extAdded);\n svgCanvas.textActions.setInputElem($('#text')[0]);\n\n let str = '<div class=\"palette_item\" data-rgb=\"none\"></div>';\n $.each(palette, function (i, item) {\n str += '<div class=\"palette_item\" style=\"background-color: ' + item +\n ';\" data-rgb=\"' + item + '\"></div>';\n });\n $('#palette').append(str);\n\n // Set up editor background functionality\n const colorBlocks = ['#FFF', '#888', '#000', 'chessboard'];\n str = '';\n $.each(colorBlocks, function (i, e) {\n if (e === 'chessboard') {\n str += '<div class=\"color_block\" data-bgcolor=\"' + e + '\" style=\"background-image:url(data:image/gif;base64,R0lGODlhEAAQAIAAAP///9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG+gq4jM3IFLJgpswNly/XkcBpIiVaInlLJr9FZWAQA7);\"></div>';\n } else {\n str += '<div class=\"color_block\" data-bgcolor=\"' + e + '\" style=\"background-color:' + e + ';\"></div>';\n }\n });\n $('#bg_blocks').append(str);\n const blocks = $('#bg_blocks div');\n const curBg = 'cur_background';\n blocks.each(function () {\n const blk = $(this);\n blk.click(function () {\n blocks.removeClass(curBg);\n $(this).addClass(curBg);\n });\n });\n\n setBackground(editor.pref('bkgd_color'), editor.pref('bkgd_url'));\n\n $('#image_save_opts input').val([editor.pref('img_save')]);\n\n /**\n * @type {module:jQuerySpinButton.ValueCallback}\n */\n const changeRectRadius = function (ctl) {\n svgCanvas.setRectRadius(ctl.value);\n };\n\n /**\n * @type {module:jQuerySpinButton.ValueCallback}\n */\n const changeFontSize = function (ctl) {\n svgCanvas.setFontSize(ctl.value);\n };\n\n /**\n * @type {module:jQuerySpinButton.ValueCallback}\n */\n const changeStrokeWidth = function (ctl) {\n let val = ctl.value;\n if (val === 0 && selectedElement && ['line', 'polyline'].includes(selectedElement.nodeName)) {\n val = ctl.value = 1;\n }\n svgCanvas.setStrokeWidth(val);\n };\n\n /**\n * @type {module:jQuerySpinButton.ValueCallback}\n */\n const changeRotationAngle = function (ctl) {\n svgCanvas.setRotationAngle(ctl.value);\n $('#tool_reorient').toggleClass('disabled', parseInt(ctl.value) === 0);\n };\n\n /**\n * @param {external:jQuery.fn.SpinButton} ctl Spin Button\n * @param {string} [val=ctl.value]\n * @returns {void}\n */\n const changeOpacity = function (ctl, val) {\n if (Utils.isNullish(val)) { val = ctl.value; }\n $('#group_opacity').val(val);\n if (!ctl || !ctl.handle) {\n $('#opac_slider').slider('option', 'value', val);\n }\n svgCanvas.setOpacity(val / 100);\n };\n\n /**\n * @param {external:jQuery.fn.SpinButton} ctl Spin Button\n * @param {string} [val=ctl.value]\n * @param {boolean} noUndo\n * @returns {void}\n */\n const changeBlur = function (ctl, val, noUndo) {\n if (Utils.isNullish(val)) { val = ctl.value; }\n $('#blur').val(val);\n let complete = false;\n if (!ctl || !ctl.handle) {\n $('#blur_slider').slider('option', 'value', val);\n complete = true;\n }\n if (noUndo) {\n svgCanvas.setBlurNoUndo(val);\n } else {\n svgCanvas.setBlur(val, complete);\n }\n };\n\n $('#stroke_style').change(function () {\n svgCanvas.setStrokeAttr('stroke-dasharray', $(this).val());\n operaRepaint();\n });\n\n $('#stroke_linejoin').change(function () {\n svgCanvas.setStrokeAttr('stroke-linejoin', $(this).val());\n operaRepaint();\n });\n\n // Lose focus for select elements when changed (Allows keyboard shortcuts to work better)\n $('select').change(function () { $(this).blur(); });\n\n // fired when user wants to move elements to another layer\n let promptMoveLayerOnce = false;\n $('#selLayerNames').change(async function () {\n const destLayer = this.options[this.selectedIndex].value;\n const confirmStr = uiStrings.notification.QmoveElemsToLayer.replace('%s', destLayer);\n /**\n * @param {boolean} ok\n * @returns {void}\n */\n const moveToLayer = function (ok) {\n if (!ok) { return; }\n promptMoveLayerOnce = true;\n svgCanvas.moveSelectedToLayer(destLayer);\n svgCanvas.clearSelection();\n populateLayers();\n };\n if (destLayer) {\n if (promptMoveLayerOnce) {\n moveToLayer(true);\n } else {\n const ok = await $.confirm(confirmStr);\n if (!ok) {\n return;\n }\n moveToLayer(true);\n }\n }\n });\n\n $('#font_family').change(function () {\n svgCanvas.setFontFamily(this.value);\n });\n\n $('#seg_type').change(function () {\n svgCanvas.setSegType($(this).val());\n });\n\n $('#text').bind('keyup input', function () {\n svgCanvas.setTextContent(this.value);\n });\n\n $('#image_url').change(function () {\n setImageURL(this.value);\n });\n\n $('#link_url').change(function () {\n if (this.value.length) {\n svgCanvas.setLinkURL(this.value);\n } else {\n svgCanvas.removeHyperlink();\n }\n });\n\n $('#g_title').change(function () {\n svgCanvas.setGroupTitle(this.value);\n });\n\n $('.attr_changer').change(function () {\n const attr = this.getAttribute('data-attr');\n let val = this.value;\n const valid = isValidUnit(attr, val, selectedElement);\n\n if (!valid) {\n this.value = selectedElement.getAttribute(attr);\n /* await */ $.alert(uiStrings.notification.invalidAttrValGiven);\n return false;\n }\n\n if (attr !== 'id' && attr !== 'class') {\n if (isNaN(val)) {\n val = svgCanvas.convertToNum(attr, val);\n } else if (curConfig.baseUnit !== 'px') {\n // Convert unitless value to one with given unit\n\n const unitData = getTypeMap();\n\n if (selectedElement[attr] || svgCanvas.getMode() === 'pathedit' || attr === 'x' || attr === 'y') {\n val *= unitData[curConfig.baseUnit];\n }\n }\n }\n\n // if the user is changing the id, then de-select the element first\n // change the ID, then re-select it with the new ID\n if (attr === 'id') {\n const elem = selectedElement;\n svgCanvas.clearSelection();\n elem.id = val;\n svgCanvas.addToSelection([elem], true);\n } else {\n svgCanvas.changeSelectedAttribute(attr, val);\n }\n this.blur();\n return true;\n });\n\n // Prevent selection of elements when shift-clicking\n $('#palette').mouseover(function () {\n const inp = $('<input type=\"hidden\">');\n $(this).append(inp);\n inp.focus().remove();\n });\n\n $('.palette_item').mousedown(function (evt) {\n // shift key or right click for stroke\n const picker = evt.shiftKey || evt.button === 2 ? 'stroke' : 'fill';\n let color = $(this).data('rgb');\n let paint;\n\n // Webkit-based browsers returned 'initial' here for no stroke\n if (color === 'none' || color === 'transparent' || color === 'initial') {\n color = 'none';\n paint = new $.jGraduate.Paint();\n } else {\n paint = new $.jGraduate.Paint({alpha: 100, solidColor: color.substr(1)});\n }\n\n paintBox[picker].setPaint(paint);\n svgCanvas.setColor(picker, color);\n\n if (color !== 'none' && svgCanvas.getPaintOpacity(picker) !== 1) {\n svgCanvas.setPaintOpacity(picker, 1.0);\n }\n updateToolButtonState();\n }).bind('contextmenu', function (e) { e.preventDefault(); });\n\n $('#toggle_stroke_tools').on('click', function () {\n $('#tools_bottom').toggleClass('expanded');\n });\n\n (function () {\n const wArea = workarea[0];\n\n let lastX = null, lastY = null,\n panning = false, keypan = false;\n\n $('#svgcanvas').bind('mousemove mouseup', function (evt) {\n if (panning === false) { return true; }\n\n wArea.scrollLeft -= (evt.clientX - lastX);\n wArea.scrollTop -= (evt.clientY - lastY);\n\n lastX = evt.clientX;\n lastY = evt.clientY;\n\n if (evt.type === 'mouseup') { panning = false; }\n return false;\n }).mousedown(function (evt) {\n if (evt.button === 1 || keypan === true) {\n panning = true;\n lastX = evt.clientX;\n lastY = evt.clientY;\n return false;\n }\n return true;\n });\n\n $(window).mouseup(function () {\n panning = false;\n });\n\n $(document).bind('keydown', 'space', function (evt) {\n svgCanvas.spaceKey = keypan = true;\n evt.preventDefault();\n }).bind('keyup', 'space', function (evt) {\n evt.preventDefault();\n svgCanvas.spaceKey = keypan = false;\n }).bind('keydown', 'shift', function (evt) {\n if (svgCanvas.getMode() === 'zoom') {\n workarea.css('cursor', zoomOutIcon);\n }\n }).bind('keyup', 'shift', function (evt) {\n if (svgCanvas.getMode() === 'zoom') {\n workarea.css('cursor', zoomInIcon);\n }\n });\n\n /**\n * @param {boolean} active\n * @returns {void}\n */\n editor.setPanning = function (active) {\n svgCanvas.spaceKey = keypan = active;\n };\n }());\n\n (function () {\n const button = $('#main_icon');\n const overlay = $('#main_icon span');\n const list = $('#main_menu');\n\n let onButton = false;\n let height = 0;\n let jsHover = true;\n let setClick = false;\n\n /*\n // Currently unused\n const hideMenu = function () {\n list.fadeOut(200);\n };\n */\n\n $(window).mouseup(function (evt) {\n if (!onButton) {\n button.removeClass('buttondown');\n // do not hide if it was the file input as that input needs to be visible\n // for its change event to fire\n if (evt.target.tagName !== 'INPUT') {\n list.fadeOut(200);\n } else if (!setClick) {\n setClick = true;\n $(evt.target).click(function () {\n list.css('margin-left', '-9999px').show();\n });\n }\n }\n onButton = false;\n }).mousedown(function (evt) {\n // $('.contextMenu').hide();\n const islib = $(evt.target).closest('div.tools_flyout, .contextMenu').length;\n if (!islib) {\n $('.tools_flyout:visible,.contextMenu').fadeOut(250);\n }\n });\n\n overlay.bind('mousedown', function () {\n if (!button.hasClass('buttondown')) {\n // Margin must be reset in case it was changed before;\n list.css('margin-left', 0).show();\n if (!height) {\n height = list.height();\n }\n // Using custom animation as slideDown has annoying 'bounce effect'\n list.css('height', 0).animate({\n height\n }, 200);\n onButton = true;\n } else {\n list.fadeOut(200);\n }\n button.toggleClass('buttondown buttonup');\n }).hover(function () {\n onButton = true;\n }).mouseout(function () {\n onButton = false;\n });\n\n const listItems = $('#main_menu li');\n\n // Check if JS method of hovering needs to be used (Webkit bug)\n listItems.mouseover(function () {\n jsHover = ($(this).css('background-color') === 'rgba(0, 0, 0, 0)');\n\n listItems.unbind('mouseover');\n if (jsHover) {\n listItems.mouseover(function () {\n this.style.backgroundColor = '#FFC';\n }).mouseout(function () {\n this.style.backgroundColor = 'transparent';\n return true;\n });\n }\n });\n }());\n // Made public for UI customization.\n // TODO: Group UI functions into a public editor.ui interface.\n /**\n * See {@link http://api.jquery.com/bind/#bind-eventType-eventData-handler}.\n * @callback module:SVGEditor.DropDownCallback\n * @param {external:jQuery.Event} ev See {@link http://api.jquery.com/Types/#Event}\n * @listens external:jQuery.Event\n * @returns {void|boolean} Calls `preventDefault()` and `stopPropagation()`\n */\n /**\n * @param {Element|string} elem DOM Element or selector\n * @param {module:SVGEditor.DropDownCallback} callback Mouseup callback\n * @param {boolean} dropUp\n * @returns {void}\n */\n editor.addDropDown = function (elem, callback, dropUp) {\n if (!$(elem).length) { return; } // Quit if called on non-existent element\n const button = $(elem).find('button');\n const list = $(elem).find('ul').attr('id', $(elem)[0].id + '-list');\n if (dropUp) {\n $(elem).addClass('dropup');\n } else {\n // Move list to place where it can overflow container\n $('#option_lists').append(list);\n }\n list.find('li').bind('mouseup', callback);\n\n let onButton = false;\n $(window).mouseup(function (evt) {\n if (!onButton) {\n button.removeClass('down');\n list.hide();\n }\n onButton = false;\n });\n\n button.bind('mousedown', function () {\n if (!button.hasClass('down')) {\n if (!dropUp) {\n const pos = $(elem).position();\n list.css({\n top: pos.top + 24,\n left: pos.left - 10\n });\n }\n list.show();\n onButton = true;\n } else {\n list.hide();\n }\n button.toggleClass('down');\n }).hover(function () {\n onButton = true;\n }).mouseout(function () {\n onButton = false;\n });\n };\n\n editor.addDropDown('#font_family_dropdown', function () {\n $('#font_family').val($(this).text()).change();\n });\n\n editor.addDropDown('#opacity_dropdown', function () {\n if ($(this).find('div').length) { return; }\n const perc = parseInt($(this).text().split('%')[0]);\n changeOpacity(false, perc);\n }, true);\n\n // For slider usage, see: http://jqueryui.com/demos/slider/\n $('#opac_slider').slider({\n start () {\n $('#opacity_dropdown li:not(.special)').hide();\n },\n stop () {\n $('#opacity_dropdown li').show();\n $(window).mouseup();\n },\n slide (evt, ui) {\n changeOpacity(ui);\n }\n });\n\n editor.addDropDown('#blur_dropdown', $.noop);\n\n let slideStart = false;\n $('#blur_slider').slider({\n max: 10,\n step: 0.1,\n stop (evt, ui) {\n slideStart = false;\n changeBlur(ui);\n $('#blur_dropdown li').show();\n $(window).mouseup();\n },\n start () {\n slideStart = true;\n },\n slide (evt, ui) {\n changeBlur(ui, null, slideStart);\n }\n });\n\n editor.addDropDown('#zoom_dropdown', function () {\n const item = $(this);\n const val = item.data('val');\n if (val) {\n zoomChanged(window, val);\n } else {\n changeZoom({value: parseFloat(item.text())});\n }\n }, true);\n\n addAltDropDown('#stroke_linecap', '#linecap_opts', function () {\n setStrokeOpt(this, true);\n }, {dropUp: true});\n\n addAltDropDown('#stroke_linejoin', '#linejoin_opts', function () {\n setStrokeOpt(this, true);\n }, {dropUp: true});\n\n addAltDropDown('#tool_position', '#position_opts', function () {\n const letter = this.id.replace('tool_pos', '').charAt(0);\n svgCanvas.alignSelectedElements(letter, 'page');\n }, {multiclick: true});\n\n /*\n\n When a flyout icon is selected\n (if flyout) {\n - Change the icon\n - Make pressing the button run its stuff\n }\n - Run its stuff\n\n When its shortcut key is pressed\n - If not current in list, do as above\n , else:\n - Just run its stuff\n\n */\n\n // Unfocus text input when workarea is mousedowned.\n (function () {\n let inp;\n /**\n *\n * @returns {void}\n */\n const unfocus = function () {\n $(inp).blur();\n };\n\n $('#svg_editor').find('button, select, input:not(#text)').focus(function () {\n inp = this; // eslint-disable-line consistent-this\n uiContext = 'toolbars';\n workarea.mousedown(unfocus);\n }).blur(function () {\n uiContext = 'canvas';\n workarea.unbind('mousedown', unfocus);\n // Go back to selecting text if in textedit mode\n if (svgCanvas.getMode() === 'textedit') {\n $('#text').focus();\n }\n });\n }());\n\n /**\n *\n * @returns {void}\n */\n const clickFHPath = function () {\n if (toolButtonClick('#tool_fhpath')) {\n svgCanvas.setMode('fhpath');\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickLine = function () {\n if (toolButtonClick('#tool_line')) {\n svgCanvas.setMode('line');\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickSquare = function () {\n if (toolButtonClick('#tool_square')) {\n svgCanvas.setMode('square');\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickRect = function () {\n if (toolButtonClick('#tool_rect')) {\n svgCanvas.setMode('rect');\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickFHRect = function () {\n if (toolButtonClick('#tool_fhrect')) {\n svgCanvas.setMode('fhrect');\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickCircle = function () {\n if (toolButtonClick('#tool_circle')) {\n svgCanvas.setMode('circle');\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickEllipse = function () {\n if (toolButtonClick('#tool_ellipse')) {\n svgCanvas.setMode('ellipse');\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickFHEllipse = function () {\n if (toolButtonClick('#tool_fhellipse')) {\n svgCanvas.setMode('fhellipse');\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickImage = function () {\n if (toolButtonClick('#tool_image')) {\n svgCanvas.setMode('image');\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickZoom = function () {\n if (toolButtonClick('#tool_zoom')) {\n svgCanvas.setMode('zoom');\n workarea.css('cursor', zoomInIcon);\n }\n };\n\n /**\n * @param {Float} multiplier\n * @returns {void}\n */\n const zoomImage = function (multiplier) {\n const res = svgCanvas.getResolution();\n multiplier = multiplier ? res.zoom * multiplier : 1;\n // setResolution(res.w * multiplier, res.h * multiplier, true);\n $('#zoom').val(multiplier * 100);\n svgCanvas.setZoom(multiplier);\n zoomDone();\n updateCanvas(true);\n };\n\n /**\n *\n * @returns {void}\n */\n const dblclickZoom = function () {\n if (toolButtonClick('#tool_zoom')) {\n zoomImage();\n setSelectMode();\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickText = function () {\n if (toolButtonClick('#tool_text')) {\n svgCanvas.setMode('text');\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickPath = function () {\n if (toolButtonClick('#tool_path')) {\n svgCanvas.setMode('path');\n }\n };\n\n /**\n * Delete is a contextual tool that only appears in the ribbon if\n * an element has been selected.\n * @returns {void}\n */\n const deleteSelected = function () {\n if (!Utils.isNullish(selectedElement) || multiselected) {\n svgCanvas.deleteSelectedElements();\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const cutSelected = function () {\n if (!Utils.isNullish(selectedElement) || multiselected) {\n svgCanvas.cutSelectedElements();\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const copySelected = function () {\n if (!Utils.isNullish(selectedElement) || multiselected) {\n svgCanvas.copySelectedElements();\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const pasteInCenter = function () {\n const zoom = svgCanvas.getZoom();\n const x = (workarea[0].scrollLeft + workarea.width() / 2) / zoom - svgCanvas.contentW;\n const y = (workarea[0].scrollTop + workarea.height() / 2) / zoom - svgCanvas.contentH;\n svgCanvas.pasteElements('point', x, y);\n };\n\n /**\n *\n * @returns {void}\n */\n const moveToTopSelected = function () {\n if (!Utils.isNullish(selectedElement)) {\n svgCanvas.moveToTopSelectedElement();\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const moveToBottomSelected = function () {\n if (!Utils.isNullish(selectedElement)) {\n svgCanvas.moveToBottomSelectedElement();\n }\n };\n\n /**\n * @param {\"Up\"|\"Down\"} dir\n * @returns {void}\n */\n const moveUpDownSelected = function (dir) {\n if (!Utils.isNullish(selectedElement)) {\n svgCanvas.moveUpDownSelected(dir);\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const convertToPath = function () {\n if (!Utils.isNullish(selectedElement)) {\n svgCanvas.convertToPath();\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const reorientPath = function () {\n if (!Utils.isNullish(selectedElement)) {\n path.reorient();\n }\n };\n\n /**\n *\n * @returns {Promise<void>} Resolves to `undefined`\n */\n const makeHyperlink = async function () {\n if (!Utils.isNullish(selectedElement) || multiselected) {\n const url = await $.prompt(uiStrings.notification.enterNewLinkURL, 'http://');\n if (url) {\n svgCanvas.makeHyperlink(url);\n }\n }\n };\n\n /**\n * @param {Float} dx\n * @param {Float} dy\n * @returns {void}\n */\n const moveSelected = function (dx, dy) {\n if (!Utils.isNullish(selectedElement) || multiselected) {\n if (curConfig.gridSnapping) {\n // Use grid snap value regardless of zoom level\n const multi = svgCanvas.getZoom() * curConfig.snappingStep;\n dx *= multi;\n dy *= multi;\n }\n svgCanvas.moveSelectedElements(dx, dy);\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const linkControlPoints = function () {\n $('#tool_node_link').toggleClass('push_button_pressed tool_button');\n const linked = $('#tool_node_link').hasClass('push_button_pressed');\n path.linkControlPoints(linked);\n };\n\n /**\n *\n * @returns {void}\n */\n const clonePathNode = function () {\n if (path.getNodePoint()) {\n path.clonePathNode();\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const deletePathNode = function () {\n if (path.getNodePoint()) {\n path.deletePathNode();\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const addSubPath = function () {\n const button = $('#tool_add_subpath');\n const sp = !button.hasClass('push_button_pressed');\n button.toggleClass('push_button_pressed tool_button');\n path.addSubPath(sp);\n };\n\n /**\n *\n * @returns {void}\n */\n const opencloseSubPath = function () {\n path.opencloseSubPath();\n };\n\n /**\n *\n * @returns {void}\n */\n const selectNext = function () {\n svgCanvas.cycleElement(1);\n };\n\n /**\n *\n * @returns {void}\n */\n const selectPrev = function () {\n svgCanvas.cycleElement(0);\n };\n\n /**\n * @param {0|1} cw\n * @param {Integer} step\n * @returns {void}\n */\n const rotateSelected = function (cw, step) {\n if (Utils.isNullish(selectedElement) || multiselected) { return; }\n if (!cw) { step *= -1; }\n const angle = parseFloat($('#angle').val()) + step;\n svgCanvas.setRotationAngle(angle);\n updateContextPanel();\n };\n\n /**\n * @fires module:svgcanvas.SvgCanvas#event:ext_onNewDocument\n * @returns {Promise<void>} Resolves to `undefined`\n */\n const clickClear = async function () {\n const [x, y] = curConfig.dimensions;\n const ok = await $.confirm(uiStrings.notification.QwantToClear);\n if (!ok) {\n return;\n }\n setSelectMode();\n svgCanvas.clear();\n svgCanvas.setResolution(x, y);\n updateCanvas(true);\n zoomImage();\n populateLayers();\n updateContextPanel();\n prepPaints();\n svgCanvas.runExtensions('onNewDocument');\n };\n\n /**\n *\n * @returns {false}\n */\n const clickBold = function () {\n svgCanvas.setBold(!svgCanvas.getBold());\n updateContextPanel();\n return false;\n };\n\n /**\n *\n * @returns {false}\n */\n const clickItalic = function () {\n svgCanvas.setItalic(!svgCanvas.getItalic());\n updateContextPanel();\n return false;\n };\n\n /**\n *\n * @returns {void}\n */\n const clickSave = function () {\n // In the future, more options can be provided here\n const saveOpts = {\n images: editor.pref('img_save'),\n round_digits: 6\n };\n svgCanvas.save(saveOpts);\n };\n\n let loadingURL;\n /**\n *\n * @returns {Promise<void>} Resolves to `undefined`\n */\n const clickExport = async function () {\n const imgType = await $.select('Select an image type for export: ', [\n // See http://kangax.github.io/jstests/toDataUrl_mime_type_test/ for a useful list of MIME types and browser support\n // 'ICO', // Todo: Find a way to preserve transparency in SVG-Edit if not working presently and do full packaging for x-icon; then switch back to position after 'PNG'\n 'PNG',\n 'JPEG', 'BMP', 'WEBP', 'PDF'\n ], function () {\n const sel = $(this);\n if (sel.val() === 'JPEG' || sel.val() === 'WEBP') {\n if (!$('#image-slider').length) {\n $(`<div><label>${uiStrings.ui.quality}\n <input id=\"image-slider\"\n type=\"range\" min=\"1\" max=\"100\" value=\"92\" />\n </label></div>`).appendTo(sel.parent());\n }\n } else {\n $('#image-slider').parent().remove();\n }\n }); // todo: replace hard-coded msg with uiStrings.notification.\n if (!imgType) {\n return;\n }\n // Open placeholder window (prevents popup)\n let exportWindowName;\n\n /**\n *\n * @returns {void}\n */\n function openExportWindow () {\n const {loadingImage} = uiStrings.notification;\n if (curConfig.exportWindowType === 'new') {\n editor.exportWindowCt++;\n }\n exportWindowName = curConfig.canvasName + editor.exportWindowCt;\n let popHTML, popURL;\n if (loadingURL) {\n popURL = loadingURL;\n } else {\n popHTML = `<!DOCTYPE html><html>\n <head>\n <meta charset=\"utf-8\">\n <title>${loadingImage}</title>\n </head>\n <body><h1>${loadingImage}</h1></body>\n <html>`;\n if (typeof URL !== 'undefined' && URL.createObjectURL) {\n const blob = new Blob([popHTML], {type: 'text/html'});\n popURL = URL.createObjectURL(blob);\n } else {\n popURL = 'data:text/html;base64;charset=utf-8,' + Utils.encode64(popHTML);\n }\n loadingURL = popURL;\n }\n exportWindow = window.open(popURL, exportWindowName);\n }\n const chrome = isChrome();\n if (imgType === 'PDF') {\n if (!customExportPDF && !chrome) {\n openExportWindow();\n }\n svgCanvas.exportPDF(exportWindowName);\n } else {\n if (!customExportImage) {\n openExportWindow();\n }\n const quality = parseInt($('#image-slider').val()) / 100;\n /* const results = */ await svgCanvas.rasterExport(imgType, quality, exportWindowName);\n }\n };\n\n /**\n * By default, svgCanvas.open() is a no-op. It is up to an extension\n * mechanism (opera widget, etc.) to call `setCustomHandlers()` which\n * will make it do something.\n * @returns {void}\n */\n const clickOpen = function () {\n svgCanvas.open();\n };\n\n /**\n *\n * @returns {void}\n */\n const clickImport = function () {\n /* */\n };\n\n /**\n *\n * @returns {void}\n */\n const clickUndo = function () {\n if (undoMgr.getUndoStackSize() > 0) {\n undoMgr.undo();\n populateLayers();\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickRedo = function () {\n if (undoMgr.getRedoStackSize() > 0) {\n undoMgr.redo();\n populateLayers();\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickGroup = function () {\n // group\n if (multiselected) {\n svgCanvas.groupSelectedElements();\n // ungroup\n } else if (selectedElement) {\n svgCanvas.ungroupSelectedElement();\n }\n };\n\n /**\n *\n * @returns {void}\n */\n const clickClone = function () {\n svgCanvas.cloneSelectedElements(20, 20);\n };\n\n /**\n *\n * @returns {void}\n */\n const clickAlign = function () {\n const letter = this.id.replace('tool_align', '').charAt(0);\n svgCanvas.alignSelectedElements(letter, $('#align_relative_to').val());\n };\n\n /**\n *\n * @returns {void}\n */\n const clickWireframe = function () {\n $('#tool_wireframe').toggleClass('push_button_pressed tool_button');\n workarea.toggleClass('wireframe');\n\n if (supportsNonSS) { return; }\n const wfRules = $('#wireframe_rules');\n if (!wfRules.length) {\n /* wfRules = */ $('<style id=\"wireframe_rules\"></style>').appendTo('head');\n } else {\n wfRules.empty();\n }\n\n updateWireFrame();\n };\n\n $('#svg_docprops_container, #svg_prefs_container').draggable({\n cancel: 'button,fieldset',\n containment: 'window'\n }).css('position', 'absolute');\n\n let docprops = false;\n let preferences = false;\n\n /**\n *\n * @returns {void}\n */\n const showDocProperties = function () {\n if (docprops) { return; }\n docprops = true;\n\n // This selects the correct radio button by using the array notation\n $('#image_save_opts input').val([editor.pref('img_save')]);\n\n // update resolution option with actual resolution\n const res = svgCanvas.getResolution();\n if (curConfig.baseUnit !== 'px') {\n res.w = convertUnit(res.w) + curConfig.baseUnit;\n res.h = convertUnit(res.h) + curConfig.baseUnit;\n }\n\n $('#canvas_width').val(res.w);\n $('#canvas_height').val(res.h);\n $('#canvas_title').val(svgCanvas.getDocumentTitle());\n\n $('#svg_docprops').show();\n };\n\n /**\n *\n * @returns {void}\n */\n const showPreferences = function () {\n if (preferences) { return; }\n preferences = true;\n $('#main_menu').hide();\n\n // Update background color with current one\n const canvasBg = curPrefs.bkgd_color;\n const url = editor.pref('bkgd_url');\n blocks.each(function () {\n const blk = $(this);\n const isBg = blk.data('bgcolor') === canvasBg;\n blk.toggleClass(curBg, isBg);\n });\n if (!canvasBg) { blocks.eq(0).addClass(curBg); }\n if (url) {\n $('#canvas_bg_url').val(url);\n }\n $('#grid_snapping_on').prop('checked', curConfig.gridSnapping);\n $('#grid_snapping_step').attr('value', curConfig.snappingStep);\n $('#grid_color').attr('value', curConfig.gridColor);\n\n $('#svg_prefs').show();\n };\n\n /**\n *\n * @returns {void}\n */\n const openHomePage = function () {\n window.open(homePage, '_blank');\n };\n\n /**\n *\n * @returns {void}\n */\n const hideSourceEditor = function () {\n $('#svg_source_editor').hide();\n editingsource = false;\n $('#svg_source_textarea').blur();\n };\n\n /**\n *\n * @returns {Promise<void>} Resolves to `undefined`\n */\n const saveSourceEditor = async function () {\n if (!editingsource) { return; }\n\n const saveChanges = function () {\n svgCanvas.clearSelection();\n hideSourceEditor();\n zoomImage();\n populateLayers();\n updateTitle();\n prepPaints();\n };\n\n if (!svgCanvas.setSvgString($('#svg_source_textarea').val())) {\n const ok = await $.confirm(uiStrings.notification.QerrorsRevertToSource);\n if (!ok) {\n return;\n }\n saveChanges();\n return;\n }\n saveChanges();\n setSelectMode();\n };\n\n /**\n *\n * @returns {void}\n */\n const hideDocProperties = function () {\n $('#svg_docprops').hide();\n $('#canvas_width,#canvas_height').removeAttr('disabled');\n $('#resolution')[0].selectedIndex = 0;\n $('#image_save_opts input').val([editor.pref('img_save')]);\n docprops = false;\n };\n\n /**\n *\n * @returns {void}\n */\n const hidePreferences = function () {\n $('#svg_prefs').hide();\n preferences = false;\n };\n\n /**\n *\n * @returns {boolean} Whether there were problems saving the document properties\n */\n const saveDocProperties = function () {\n // set title\n const newTitle = $('#canvas_title').val();\n updateTitle(newTitle);\n svgCanvas.setDocumentTitle(newTitle);\n\n // update resolution\n const width = $('#canvas_width'), w = width.val();\n const height = $('#canvas_height'), h = height.val();\n\n if (w !== 'fit' && !isValidUnit('width', w)) {\n width.parent().addClass('error');\n /* await */ $.alert(uiStrings.notification.invalidAttrValGiven);\n return false;\n }\n\n width.parent().removeClass('error');\n\n if (h !== 'fit' && !isValidUnit('height', h)) {\n height.parent().addClass('error');\n /* await */ $.alert(uiStrings.notification.invalidAttrValGiven);\n return false;\n }\n\n height.parent().removeClass('error');\n\n if (!svgCanvas.setResolution(w, h)) {\n /* await */ $.alert(uiStrings.notification.noContentToFitTo);\n return false;\n }\n\n // Set image save option\n editor.pref('img_save', $('#image_save_opts :checked').val());\n updateCanvas();\n hideDocProperties();\n return true;\n };\n\n /**\n * Save user preferences based on current values in the UI.\n * @function module:SVGEditor.savePreferences\n * @returns {Promise<void>}\n */\n const savePreferences = editor.savePreferences = async function () {\n // Set background\n const color = $('#bg_blocks div.cur_background').data('bgcolor') || '#FFF';\n setBackground(color, $('#canvas_bg_url').val());\n\n // set language\n const lang = $('#lang_select').val();\n if (lang && lang !== editor.pref('lang')) {\n const {langParam, langData} = await editor.putLocale(lang, goodLangs, curConfig);\n await setLang(langParam, langData);\n }\n\n // set icon size\n setIconSize($('#iconsize').val());\n\n // set grid setting\n curConfig.gridSnapping = $('#grid_snapping_on')[0].checked;\n curConfig.snappingStep = $('#grid_snapping_step').val();\n curConfig.gridColor = $('#grid_color').val();\n curConfig.showRulers = $('#show_rulers')[0].checked;\n\n $('#rulers').toggle(curConfig.showRulers);\n if (curConfig.showRulers) { updateRulers(); }\n curConfig.baseUnit = $('#base_unit').val();\n\n svgCanvas.setConfig(curConfig);\n\n updateCanvas();\n hidePreferences();\n };\n\n let resetScrollPos = $.noop;\n\n /**\n *\n * @returns {Promise<void>} Resolves to `undefined`\n */\n const cancelOverlays = async function () {\n $('#dialog_box').hide();\n if (!editingsource && !docprops && !preferences) {\n if (curContext) {\n svgCanvas.leaveContext();\n }\n return;\n }\n\n if (editingsource) {\n if (origSource !== $('#svg_source_textarea').val()) {\n const ok = await $.confirm(uiStrings.notification.QignoreSourceChanges);\n if (ok) {\n hideSourceEditor();\n }\n } else {\n hideSourceEditor();\n }\n } else if (docprops) {\n hideDocProperties();\n } else if (preferences) {\n hidePreferences();\n }\n resetScrollPos();\n };\n\n const winWh = {width: $(window).width(), height: $(window).height()};\n\n // Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9)\n if (isIE()) {\n resetScrollPos = function () {\n if (workarea[0].scrollLeft === 0 && workarea[0].scrollTop === 0) {\n workarea[0].scrollLeft = curScrollPos.left;\n workarea[0].scrollTop = curScrollPos.top;\n }\n };\n\n curScrollPos = {\n left: workarea[0].scrollLeft,\n top: workarea[0].scrollTop\n };\n\n $(window).resize(resetScrollPos);\n editor.ready(function () {\n // TODO: Find better way to detect when to do this to minimize\n // flickering effect\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n setTimeout(function () {\n resetScrollPos();\n resolve();\n }, 500);\n });\n });\n\n workarea.scroll(function () {\n curScrollPos = {\n left: workarea[0].scrollLeft,\n top: workarea[0].scrollTop\n };\n });\n }\n\n $(window).resize(function (evt) {\n $.each(winWh, function (type, val) {\n const curval = $(window)[type]();\n workarea[0]['scroll' + (type === 'width' ? 'Left' : 'Top')] -= (curval - val) / 2;\n winWh[type] = curval;\n });\n setFlyoutPositions();\n });\n\n workarea.scroll(function () {\n // TODO: jQuery's scrollLeft/Top() wouldn't require a null check\n if ($('#ruler_x').length) {\n $('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft;\n }\n if ($('#ruler_y').length) {\n $('#ruler_y')[0].scrollTop = workarea[0].scrollTop;\n }\n });\n\n $('#url_notice').click(function () {\n /* await */ $.alert(this.title);\n });\n\n $('#change_image_url').click(promptImgURL);\n\n // added these event handlers for all the push buttons so they\n // behave more like buttons being pressed-in and not images\n (function () {\n const toolnames = [\n 'clear', 'open', 'save', 'source', 'delete',\n 'delete_multi', 'paste', 'clone', 'clone_multi',\n 'move_top', 'move_bottom'\n ];\n const curClass = 'tool_button_current';\n\n let allTools = '';\n\n $.each(toolnames, function (i, item) {\n allTools += (i ? ',' : '') + '#tool_' + item;\n });\n\n $(allTools).mousedown(function () {\n $(this).addClass(curClass);\n }).bind('mousedown mouseout', function () {\n $(this).removeClass(curClass);\n });\n\n $('#tool_undo, #tool_redo').mousedown(function () {\n if (!$(this).hasClass('disabled')) { $(this).addClass(curClass); }\n }).bind('mousedown mouseout', function () {\n $(this).removeClass(curClass);\n });\n }());\n\n // switch modifier key in tooltips if mac\n // NOTE: This code is not used yet until I can figure out how to successfully bind ctrl/meta\n // in Opera and Chrome\n if (isMac() && !window.opera) {\n const shortcutButtons = [\n 'tool_clear', 'tool_save', 'tool_source',\n 'tool_undo', 'tool_redo', 'tool_clone'\n ];\n let i = shortcutButtons.length;\n while (i--) {\n const button = document.getElementById(shortcutButtons[i]);\n if (button) {\n const {title} = button;\n const index = title.indexOf('Ctrl+');\n button.title = [\n title.substr(0, index),\n 'Cmd+',\n title.substr(index + 5)\n ].join('');\n }\n }\n }\n\n /**\n * @param {external:jQuery} elem\n * @todo Go back to the color boxes having white background-color and then setting\n * background-image to none.png (otherwise partially transparent gradients look weird)\n * @returns {void}\n */\n const colorPicker = function (elem) {\n const picker = elem.attr('id') === 'stroke_color' ? 'stroke' : 'fill';\n // const opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity'));\n const title = picker === 'stroke'\n ? uiStrings.ui.pick_stroke_paint_opacity\n : uiStrings.ui.pick_fill_paint_opacity;\n // let wasNone = false; // Currently unused\n const pos = elem.offset();\n let {paint} = paintBox[picker];\n $('#color_picker')\n .draggable({\n cancel: '.jGraduate_tabs, .jGraduate_colPick, .jGraduate_gradPick, .jPicker',\n containment: 'window'\n })\n .css(curConfig.colorPickerCSS || {left: pos.left - 140, bottom: 40})\n .jGraduate(\n {\n paint,\n window: {pickerTitle: title},\n images: {clientPath: curConfig.jGraduatePath},\n newstop: 'inverse'\n },\n function (p) {\n paint = new $.jGraduate.Paint(p);\n paintBox[picker].setPaint(paint);\n svgCanvas.setPaint(picker, paint);\n $('#color_picker').hide();\n },\n function () {\n $('#color_picker').hide();\n }\n );\n };\n\n /**\n * Paint box class.\n */\n class PaintBox {\n /**\n * @param {string|Element|external:jQuery} container\n * @param {\"fill\"} type\n */\n constructor (container, type) {\n const cur = curConfig[type === 'fill' ? 'initFill' : 'initStroke'];\n // set up gradients to be used for the buttons\n const svgdocbox = new DOMParser().parseFromString(\n `<svg xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"16.5\" height=\"16.5\"\n fill=\"#${cur.color}\" opacity=\"${cur.opacity}\"/>\n <defs><linearGradient id=\"gradbox_${PaintBox.ctr++}\"/></defs>\n </svg>`,\n 'text/xml'\n );\n\n let docElem = svgdocbox.documentElement;\n docElem = $(container)[0].appendChild(document.importNode(docElem, true));\n docElem.setAttribute('width', 16.5);\n\n this.rect = docElem.firstElementChild;\n this.defs = docElem.getElementsByTagName('defs')[0];\n this.grad = this.defs.firstElementChild;\n this.paint = new $.jGraduate.Paint({solidColor: cur.color});\n this.type = type;\n }\n\n /**\n * @param {module:jGraduate~Paint} paint\n * @param {boolean} apply\n * @returns {void}\n */\n setPaint (paint, apply) {\n this.paint = paint;\n\n const ptype = paint.type;\n const opac = paint.alpha / 100;\n\n let fillAttr = 'none';\n switch (ptype) {\n case 'solidColor':\n fillAttr = (paint[ptype] !== 'none') ? '#' + paint[ptype] : paint[ptype];\n break;\n case 'linearGradient':\n case 'radialGradient': {\n this.grad.remove();\n this.grad = this.defs.appendChild(paint[ptype]);\n const id = this.grad.id = 'gradbox_' + this.type;\n fillAttr = 'url(#' + id + ')';\n break;\n }\n }\n\n this.rect.setAttribute('fill', fillAttr);\n this.rect.setAttribute('opacity', opac);\n\n if (apply) {\n svgCanvas.setColor(this.type, this._paintColor, true);\n svgCanvas.setPaintOpacity(this.type, this._paintOpacity, true);\n }\n }\n\n /**\n * @param {boolean} apply\n * @returns {void}\n */\n update (apply) {\n if (!selectedElement) { return; }\n\n const {type} = this;\n switch (selectedElement.tagName) {\n case 'use':\n case 'image':\n case 'foreignObject':\n // These elements don't have fill or stroke, so don't change\n // the current value\n return;\n case 'g':\n case 'a': {\n const childs = selectedElement.getElementsByTagName('*');\n\n let gPaint = null;\n for (let i = 0, len = childs.length; i < len; i++) {\n const elem = childs[i];\n const p = elem.getAttribute(type);\n if (i === 0) {\n gPaint = p;\n } else if (gPaint !== p) {\n gPaint = null;\n break;\n }\n }\n\n if (gPaint === null) {\n // No common color, don't update anything\n this._paintColor = null;\n return;\n }\n this._paintColor = gPaint;\n this._paintOpacity = 1;\n break;\n } default: {\n this._paintOpacity = parseFloat(selectedElement.getAttribute(type + '-opacity'));\n if (isNaN(this._paintOpacity)) {\n this._paintOpacity = 1.0;\n }\n\n const defColor = type === 'fill' ? 'black' : 'none';\n this._paintColor = selectedElement.getAttribute(type) || defColor;\n }\n }\n\n if (apply) {\n svgCanvas.setColor(type, this._paintColor, true);\n svgCanvas.setPaintOpacity(type, this._paintOpacity, true);\n }\n\n this._paintOpacity *= 100;\n\n const paint = getPaint(this._paintColor, this._paintOpacity, type);\n // update the rect inside #fill_color/#stroke_color\n this.setPaint(paint);\n }\n\n /**\n * @returns {void}\n */\n prep () {\n const ptype = this.paint.type;\n\n switch (ptype) {\n case 'linearGradient':\n case 'radialGradient': {\n const paint = new $.jGraduate.Paint({copy: this.paint});\n svgCanvas.setPaint(this.type, paint);\n break;\n }\n }\n }\n }\n PaintBox.ctr = 0;\n\n paintBox.fill = new PaintBox('#fill_color', 'fill');\n paintBox.stroke = new PaintBox('#stroke_color', 'stroke');\n\n $('#stroke_width').val(curConfig.initStroke.width);\n $('#group_opacity').val(curConfig.initOpacity * 100);\n\n // Use this SVG elem to test vectorEffect support\n const testEl = paintBox.fill.rect.cloneNode(false);\n testEl.setAttribute('style', 'vector-effect:non-scaling-stroke');\n const supportsNonSS = (testEl.style.vectorEffect === 'non-scaling-stroke');\n testEl.removeAttribute('style');\n const svgdocbox = paintBox.fill.rect.ownerDocument;\n // Use this to test support for blur element. Seems to work to test support in Webkit\n const blurTest = svgdocbox.createElementNS(NS.SVG, 'feGaussianBlur');\n if (blurTest.stdDeviationX === undefined) {\n $('#tool_blur').hide();\n }\n $(blurTest).remove();\n\n // Test for zoom icon support\n (function () {\n const pre = '-' + uaPrefix.toLowerCase() + '-zoom-';\n const zoom = pre + 'in';\n workarea.css('cursor', zoom);\n if (workarea.css('cursor') === zoom) {\n zoomInIcon = zoom;\n zoomOutIcon = pre + 'out';\n }\n workarea.css('cursor', 'auto');\n }());\n\n // Test for embedImage support (use timeout to not interfere with page load)\n setTimeout(function () {\n svgCanvas.embedImage('images/logo.png', function (datauri) {\n if (!datauri) {\n // Disable option\n $('#image_save_opts [value=embed]').attr('disabled', 'disabled');\n $('#image_save_opts input').val(['ref']);\n editor.pref('img_save', 'ref');\n $('#image_opt_embed').css('color', '#666').attr(\n 'title',\n uiStrings.notification.featNotSupported\n );\n }\n });\n }, 1000);\n\n $('#fill_color, #tool_fill .icon_label').click(function () {\n colorPicker($('#fill_color'));\n updateToolButtonState();\n });\n\n $('#stroke_color, #tool_stroke .icon_label').click(function () {\n colorPicker($('#stroke_color'));\n updateToolButtonState();\n });\n\n $('#group_opacityLabel').click(function () {\n $('#opacity_dropdown button').mousedown();\n $(window).mouseup();\n });\n\n $('#zoomLabel').click(function () {\n $('#zoom_dropdown button').mousedown();\n $(window).mouseup();\n });\n\n $('#tool_move_top').mousedown(function (evt) {\n $('#tools_stacking').show();\n evt.preventDefault();\n });\n\n $('.layer_button').mousedown(function () {\n $(this).addClass('layer_buttonpressed');\n }).mouseout(function () {\n $(this).removeClass('layer_buttonpressed');\n }).mouseup(function () {\n $(this).removeClass('layer_buttonpressed');\n });\n\n $('.push_button').mousedown(function () {\n if (!$(this).hasClass('disabled')) {\n $(this).addClass('push_button_pressed').removeClass('push_button');\n }\n }).mouseout(function () {\n $(this).removeClass('push_button_pressed').addClass('push_button');\n }).mouseup(function () {\n $(this).removeClass('push_button_pressed').addClass('push_button');\n });\n\n // ask for a layer name\n $('#layer_new').click(async function () {\n let uniqName,\n i = svgCanvas.getCurrentDrawing().getNumLayers();\n do {\n uniqName = uiStrings.layers.layer + ' ' + (++i);\n } while (svgCanvas.getCurrentDrawing().hasLayer(uniqName));\n\n const newName = await $.prompt(uiStrings.notification.enterUniqueLayerName, uniqName);\n if (!newName) { return; }\n if (svgCanvas.getCurrentDrawing().hasLayer(newName)) {\n /* await */ $.alert(uiStrings.notification.dupeLayerName);\n return;\n }\n svgCanvas.createLayer(newName);\n updateContextPanel();\n populateLayers();\n });\n\n /**\n *\n * @returns {void}\n */\n function deleteLayer () {\n if (svgCanvas.deleteCurrentLayer()) {\n updateContextPanel();\n populateLayers();\n // This matches what SvgCanvas does\n // TODO: make this behavior less brittle (svg-editor should get which\n // layer is selected from the canvas and then select that one in the UI)\n $('#layerlist tr.layer').removeClass('layersel');\n $('#layerlist tr.layer:first').addClass('layersel');\n }\n }\n\n /**\n *\n * @returns {Promise<void>}\n */\n async function cloneLayer () {\n const name = svgCanvas.getCurrentDrawing().getCurrentLayerName() + ' copy';\n\n const newName = await $.prompt(uiStrings.notification.enterUniqueLayerName, name);\n if (!newName) { return; }\n if (svgCanvas.getCurrentDrawing().hasLayer(newName)) {\n /* await */ $.alert(uiStrings.notification.dupeLayerName);\n return;\n }\n svgCanvas.cloneLayer(newName);\n updateContextPanel();\n populateLayers();\n }\n\n /**\n *\n * @returns {void}\n */\n function mergeLayer () {\n if ($('#layerlist tr.layersel').index() === svgCanvas.getCurrentDrawing().getNumLayers() - 1) {\n return;\n }\n svgCanvas.mergeLayer();\n updateContextPanel();\n populateLayers();\n }\n\n /**\n * @param {Integer} pos\n * @returns {void}\n */\n function moveLayer (pos) {\n const total = svgCanvas.getCurrentDrawing().getNumLayers();\n\n let curIndex = $('#layerlist tr.layersel').index();\n if (curIndex > 0 || curIndex < total - 1) {\n curIndex += pos;\n svgCanvas.setCurrentLayerPosition(total - curIndex - 1);\n populateLayers();\n }\n }\n\n $('#layer_delete').click(deleteLayer);\n\n $('#layer_up').click(() => {\n moveLayer(-1);\n });\n\n $('#layer_down').click(() => {\n moveLayer(1);\n });\n\n $('#layer_rename').click(async function () {\n // const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused\n const oldName = $('#layerlist tr.layersel td.layername').text();\n const newName = await $.prompt(uiStrings.notification.enterNewLayerName, '');\n if (!newName) { return; }\n if (oldName === newName || svgCanvas.getCurrentDrawing().hasLayer(newName)) {\n /* await */ $.alert(uiStrings.notification.layerHasThatName);\n return;\n }\n\n svgCanvas.renameCurrentLayer(newName);\n populateLayers();\n });\n\n const SIDEPANEL_MAXWIDTH = 300;\n const SIDEPANEL_OPENWIDTH = 150;\n let sidedrag = -1, sidedragging = false, allowmove = false;\n\n /**\n * @param {Float} delta\n * @fires module:svgcanvas.SvgCanvas#event:ext_workareaResized\n * @returns {void}\n */\n const changeSidePanelWidth = function (delta) {\n const rulerX = $('#ruler_x');\n $('#sidepanels').width('+=' + delta);\n $('#layerpanel').width('+=' + delta);\n rulerX.css('right', parseInt(rulerX.css('right')) + delta);\n workarea.css('right', parseInt(workarea.css('right')) + delta);\n svgCanvas.runExtensions('workareaResized');\n };\n\n /**\n * @param {Event} evt\n * @returns {void}\n */\n const resizeSidePanel = function (evt) {\n if (!allowmove) { return; }\n if (sidedrag === -1) { return; }\n sidedragging = true;\n let deltaX = sidedrag - evt.pageX;\n const sideWidth = $('#sidepanels').width();\n if (sideWidth + deltaX > SIDEPANEL_MAXWIDTH) {\n deltaX = SIDEPANEL_MAXWIDTH - sideWidth;\n // sideWidth = SIDEPANEL_MAXWIDTH;\n } else if (sideWidth + deltaX < 2) {\n deltaX = 2 - sideWidth;\n // sideWidth = 2;\n }\n if (deltaX === 0) { return; }\n sidedrag -= deltaX;\n changeSidePanelWidth(deltaX);\n };\n\n /**\n * If width is non-zero, then fully close it; otherwise fully open it.\n * @param {boolean} close Forces the side panel closed\n * @returns {void}\n */\n const toggleSidePanel = function (close) {\n const dpr = window.devicePixelRatio || 1;\n const w = $('#sidepanels').width();\n const isOpened = (dpr < 1 ? w : w / dpr) > 2;\n const zoomAdjustedSidepanelWidth = (dpr < 1 ? 1 : dpr) * SIDEPANEL_OPENWIDTH;\n const deltaX = (isOpened || close ? 0 : zoomAdjustedSidepanelWidth) - w;\n changeSidePanelWidth(deltaX);\n };\n\n $('#sidepanel_handle')\n .mousedown(function (evt) {\n sidedrag = evt.pageX;\n $(window).mousemove(resizeSidePanel);\n allowmove = false;\n // Silly hack for Chrome, which always runs mousemove right after mousedown\n setTimeout(function () {\n allowmove = true;\n }, 20);\n })\n .mouseup(function (evt) {\n if (!sidedragging) { toggleSidePanel(); }\n sidedrag = -1;\n sidedragging = false;\n });\n\n $(window).mouseup(function () {\n sidedrag = -1;\n sidedragging = false;\n $('#svg_editor').unbind('mousemove', resizeSidePanel);\n });\n\n populateLayers();\n\n // function changeResolution (x,y) {\n // const {zoom} = svgCanvas.getResolution();\n // setResolution(x * zoom, y * zoom);\n // }\n\n const centerCanvas = () => {\n // this centers the canvas vertically in the workarea (horizontal handled in CSS)\n workarea.css('line-height', workarea.height() + 'px');\n };\n\n $(window).bind('load resize', centerCanvas);\n\n /**\n * @type {module:jQuerySpinButton.StepCallback}\n */\n function stepFontSize (elem, step) {\n const origVal = Number(elem.value);\n const sugVal = origVal + step;\n const increasing = sugVal >= origVal;\n if (step === 0) { return origVal; }\n\n if (origVal >= 24) {\n if (increasing) {\n return Math.round(origVal * 1.1);\n }\n return Math.round(origVal / 1.1);\n }\n if (origVal <= 1) {\n if (increasing) {\n return origVal * 2;\n }\n return origVal / 2;\n }\n return sugVal;\n }\n\n /**\n * @type {module:jQuerySpinButton.StepCallback}\n */\n function stepZoom (elem, step) {\n const origVal = Number(elem.value);\n if (origVal === 0) { return 100; }\n const sugVal = origVal + step;\n if (step === 0) { return origVal; }\n\n if (origVal >= 100) {\n return sugVal;\n }\n if (sugVal >= origVal) {\n return origVal * 2;\n }\n return origVal / 2;\n }\n\n // function setResolution (w, h, center) {\n // updateCanvas();\n // // w -= 0; h -= 0;\n // // $('#svgcanvas').css({width: w, height: h});\n // // $('#canvas_width').val(w);\n // // $('#canvas_height').val(h);\n // //\n // // if (center) {\n // // const wArea = workarea;\n // // const scrollY = h/2 - wArea.height()/2;\n // // const scrollX = w/2 - wArea.width()/2;\n // // wArea[0].scrollTop = scrollY;\n // // wArea[0].scrollLeft = scrollX;\n // // }\n // }\n\n $('#resolution').change(function () {\n const wh = $('#canvas_width,#canvas_height');\n if (!this.selectedIndex) {\n if ($('#canvas_width').val() === 'fit') {\n wh.removeAttr('disabled').val(100);\n }\n } else if (this.value === 'content') {\n wh.val('fit').attr('disabled', 'disabled');\n } else {\n const dims = this.value.split('x');\n $('#canvas_width').val(dims[0]);\n $('#canvas_height').val(dims[1]);\n wh.removeAttr('disabled');\n }\n });\n\n // Prevent browser from erroneously repopulating fields\n $('input,select').attr('autocomplete', 'off');\n\n const dialogSelectors = [\n '#tool_source_cancel', '#tool_docprops_cancel',\n '#tool_prefs_cancel', '.overlay'\n ];\n /* eslint-disable jsdoc/require-property */\n /**\n * Associate all button actions as well as non-button keyboard shortcuts.\n * @namespace {PlainObject} module:SVGEditor~Actions\n */\n const Actions = (function () {\n /* eslint-enable jsdoc/require-property */\n /**\n * @typedef {PlainObject} module:SVGEditor.ToolButton\n * @property {string} sel The CSS selector for the tool\n * @property {external:jQuery.Function} fn A handler to be attached to the `evt`\n * @property {string} evt The event for which the `fn` listener will be added\n * @property {module:SVGEditor.Key} [key] [key, preventDefault, NoDisableInInput]\n * @property {string} [parent] Selector\n * @property {boolean} [hidekey] Whether to show key value in title\n * @property {string} [icon] The button ID\n * @property {boolean} isDefault For flyout holders\n */\n /**\n *\n * @name module:SVGEditor~ToolButtons\n * @type {module:SVGEditor.ToolButton[]}\n */\n const toolButtons = [\n {sel: '#tool_select', fn: clickSelect, evt: 'click', key: ['V', true]},\n {sel: '#tool_fhpath', fn: clickFHPath, evt: 'click', key: ['Q', true]},\n {sel: '#tool_line', fn: clickLine, evt: 'click', key: ['L', true],\n parent: '#tools_line', prepend: true},\n {sel: '#tool_rect', fn: clickRect, evt: 'mouseup',\n key: ['R', true], parent: '#tools_rect', icon: 'rect'},\n {sel: '#tool_square', fn: clickSquare, evt: 'mouseup',\n parent: '#tools_rect', icon: 'square'},\n {sel: '#tool_fhrect', fn: clickFHRect, evt: 'mouseup',\n parent: '#tools_rect', icon: 'fh_rect'},\n {sel: '#tool_ellipse', fn: clickEllipse, evt: 'mouseup',\n key: ['E', true], parent: '#tools_ellipse', icon: 'ellipse'},\n {sel: '#tool_circle', fn: clickCircle, evt: 'mouseup',\n parent: '#tools_ellipse', icon: 'circle'},\n {sel: '#tool_fhellipse', fn: clickFHEllipse, evt: 'mouseup',\n parent: '#tools_ellipse', icon: 'fh_ellipse'},\n {sel: '#tool_path', fn: clickPath, evt: 'click', key: ['P', true]},\n {sel: '#tool_text', fn: clickText, evt: 'click', key: ['T', true]},\n {sel: '#tool_image', fn: clickImage, evt: 'mouseup'},\n {sel: '#tool_zoom', fn: clickZoom, evt: 'mouseup', key: ['Z', true]},\n {sel: '#tool_clear', fn: clickClear, evt: 'mouseup', key: ['N', true]},\n {sel: '#tool_save', fn () {\n if (editingsource) {\n saveSourceEditor();\n } else {\n clickSave();\n }\n }, evt: 'mouseup', key: ['S', true]},\n {sel: '#tool_export', fn: clickExport, evt: 'mouseup'},\n {sel: '#tool_open', fn: clickOpen, evt: 'mouseup', key: ['O', true]},\n {sel: '#tool_import', fn: clickImport, evt: 'mouseup'},\n {sel: '#tool_source', fn: showSourceEditor, evt: 'click', key: ['U', true]},\n {sel: '#tool_wireframe', fn: clickWireframe, evt: 'click', key: ['F', true]},\n {\n key: ['esc', false, false],\n fn () {\n if (dialogSelectors.every((sel) => {\n return $(sel + ':hidden').length;\n })) {\n svgCanvas.clearSelection();\n }\n },\n hidekey: true\n },\n {sel: dialogSelectors.join(','), fn: cancelOverlays, evt: 'click',\n key: ['esc', false, false], hidekey: true},\n {sel: '#tool_source_save', fn: saveSourceEditor, evt: 'click'},\n {sel: '#tool_docprops_save', fn: saveDocProperties, evt: 'click'},\n {sel: '#tool_docprops', fn: showDocProperties, evt: 'click'},\n {sel: '#tool_prefs_save', fn: savePreferences, evt: 'click'},\n {sel: '#tool_editor_prefs', fn: showPreferences, evt: 'click'},\n {sel: '#tool_editor_homepage', fn: openHomePage, evt: 'click'},\n {sel: '#tool_open', fn () { window.dispatchEvent(new CustomEvent('openImage')); }, evt: 'click'},\n {sel: '#tool_import', fn () { window.dispatchEvent(new CustomEvent('importImage')); }, evt: 'click'},\n {sel: '#tool_delete,#tool_delete_multi', fn: deleteSelected,\n evt: 'click', key: ['del/backspace', true]},\n {sel: '#tool_reorient', fn: reorientPath, evt: 'click'},\n {sel: '#tool_node_link', fn: linkControlPoints, evt: 'click'},\n {sel: '#tool_node_clone', fn: clonePathNode, evt: 'click'},\n {sel: '#tool_node_delete', fn: deletePathNode, evt: 'click'},\n {sel: '#tool_openclose_path', fn: opencloseSubPath, evt: 'click'},\n {sel: '#tool_add_subpath', fn: addSubPath, evt: 'click'},\n {sel: '#tool_move_top', fn: moveToTopSelected, evt: 'click', key: 'ctrl+shift+]'},\n {sel: '#tool_move_bottom', fn: moveToBottomSelected, evt: 'click', key: 'ctrl+shift+['},\n {sel: '#tool_topath', fn: convertToPath, evt: 'click'},\n {sel: '#tool_make_link,#tool_make_link_multi', fn: makeHyperlink, evt: 'click'},\n {sel: '#tool_undo', fn: clickUndo, evt: 'click'},\n {sel: '#tool_redo', fn: clickRedo, evt: 'click'},\n {sel: '#tool_clone,#tool_clone_multi', fn: clickClone, evt: 'click', key: ['D', true]},\n {sel: '#tool_group_elements', fn: clickGroup, evt: 'click', key: ['G', true]},\n {sel: '#tool_ungroup', fn: clickGroup, evt: 'click'},\n {sel: '#tool_unlink_use', fn: clickGroup, evt: 'click'},\n {sel: '[id^=tool_align]', fn: clickAlign, evt: 'click'},\n // these two lines are required to make Opera work properly with the flyout mechanism\n // {sel: '#tools_rect_show', fn: clickRect, evt: 'click'},\n // {sel: '#tools_ellipse_show', fn: clickEllipse, evt: 'click'},\n {sel: '#tool_bold', fn: clickBold, evt: 'mousedown'},\n {sel: '#tool_italic', fn: clickItalic, evt: 'mousedown'},\n {sel: '#sidepanel_handle', fn: toggleSidePanel, key: ['X']},\n {sel: '#copy_save_done', fn: cancelOverlays, evt: 'click'},\n\n // Shortcuts not associated with buttons\n\n {key: 'ctrl+left', fn () { rotateSelected(0, 1); }},\n {key: 'ctrl+right', fn () { rotateSelected(1, 1); }},\n {key: 'ctrl+shift+left', fn () { rotateSelected(0, 5); }},\n {key: 'ctrl+shift+right', fn () { rotateSelected(1, 5); }},\n {key: 'shift+O', fn: selectPrev},\n {key: 'shift+P', fn: selectNext},\n {key: [modKey + 'up', true], fn () { zoomImage(2); }},\n {key: [modKey + 'down', true], fn () { zoomImage(0.5); }},\n {key: [modKey + ']', true], fn () { moveUpDownSelected('Up'); }},\n {key: [modKey + '[', true], fn () { moveUpDownSelected('Down'); }},\n {key: ['up', true], fn () { moveSelected(0, -1); }},\n {key: ['down', true], fn () { moveSelected(0, 1); }},\n {key: ['left', true], fn () { moveSelected(-1, 0); }},\n {key: ['right', true], fn () { moveSelected(1, 0); }},\n {key: 'shift+up', fn () { moveSelected(0, -10); }},\n {key: 'shift+down', fn () { moveSelected(0, 10); }},\n {key: 'shift+left', fn () { moveSelected(-10, 0); }},\n {key: 'shift+right', fn () { moveSelected(10, 0); }},\n {key: ['alt+up', true], fn () { svgCanvas.cloneSelectedElements(0, -1); }},\n {key: ['alt+down', true], fn () { svgCanvas.cloneSelectedElements(0, 1); }},\n {key: ['alt+left', true], fn () { svgCanvas.cloneSelectedElements(-1, 0); }},\n {key: ['alt+right', true], fn () { svgCanvas.cloneSelectedElements(1, 0); }},\n {key: ['alt+shift+up', true], fn () { svgCanvas.cloneSelectedElements(0, -10); }},\n {key: ['alt+shift+down', true], fn () { svgCanvas.cloneSelectedElements(0, 10); }},\n {key: ['alt+shift+left', true], fn () { svgCanvas.cloneSelectedElements(-10, 0); }},\n {key: ['alt+shift+right', true], fn () { svgCanvas.cloneSelectedElements(10, 0); }},\n {key: 'a', fn () { svgCanvas.selectAllInCurrentLayer(); }},\n {key: modKey + 'a', fn () { svgCanvas.selectAllInCurrentLayer(); }},\n\n // Standard shortcuts\n {key: modKey + 'z', fn: clickUndo},\n {key: modKey + 'shift+z', fn: clickRedo},\n {key: modKey + 'y', fn: clickRedo},\n\n {key: modKey + 'x', fn: cutSelected},\n {key: modKey + 'c', fn: copySelected},\n {key: modKey + 'v', fn: pasteInCenter}\n ];\n\n // Tooltips not directly associated with a single function\n const keyAssocs = {\n '4/Shift+4': '#tools_rect_show',\n '5/Shift+5': '#tools_ellipse_show'\n };\n\n return {\n /** @lends module:SVGEditor~Actions */\n /**\n * @returns {void}\n */\n setAll () {\n const flyouts = {};\n\n $.each(toolButtons, function (i, opts) {\n // Bind function to button\n let btn;\n if (opts.sel) {\n btn = $(opts.sel);\n if (!btn.length) { return true; } // Skip if markup does not exist\n if (opts.evt) {\n // `touch.js` changes `touchstart` to `mousedown`,\n // so we must map tool button click events as well\n if (isTouch() && opts.evt === 'click') {\n opts.evt = 'mousedown';\n }\n btn[opts.evt](opts.fn);\n }\n\n // Add to parent flyout menu, if able to be displayed\n if (opts.parent && $(opts.parent + '_show').length) {\n let fH = $(opts.parent);\n if (!fH.length) {\n fH = makeFlyoutHolder(opts.parent.substr(1));\n }\n if (opts.prepend) {\n btn[0].style.margin = 'initial';\n }\n fH[opts.prepend ? 'prepend' : 'append'](btn);\n\n if (!Array.isArray(flyouts[opts.parent])) {\n flyouts[opts.parent] = [];\n }\n flyouts[opts.parent].push(opts);\n }\n }\n\n // Bind function to shortcut key\n if (opts.key) {\n // Set shortcut based on options\n let keyval,\n // disInInp = true,\n pd = false;\n if (Array.isArray(opts.key)) {\n keyval = opts.key[0];\n if (opts.key.length > 1) { pd = opts.key[1]; }\n // if (opts.key.length > 2) { disInInp = opts.key[2]; }\n } else {\n keyval = opts.key;\n }\n keyval = String(keyval);\n\n const {fn} = opts;\n $.each(keyval.split('/'), function (j, key) {\n $(document).bind('keydown', key, function (e) {\n fn();\n if (pd) {\n e.preventDefault();\n }\n // Prevent default on ALL keys?\n return false;\n });\n });\n\n // Put shortcut in title\n if (opts.sel && !opts.hidekey && btn.attr('title')) {\n const newTitle = btn.attr('title').split('[')[0] + ' (' + keyval + ')';\n keyAssocs[keyval] = opts.sel;\n // Disregard for menu items\n if (!btn.parents('#main_menu').length) {\n btn.attr('title', newTitle);\n }\n }\n }\n return true;\n });\n\n // Setup flyouts\n setupFlyouts(flyouts);\n\n // Misc additional actions\n\n // Make 'return' keypress trigger the change event\n $('.attr_changer, #image_url').bind(\n 'keydown',\n 'return',\n function (evt) {\n $(this).change();\n evt.preventDefault();\n }\n );\n\n $(window).bind('keydown', 'tab', function (e) {\n if (uiContext === 'canvas') {\n e.preventDefault();\n selectNext();\n }\n }).bind('keydown', 'shift+tab', function (e) {\n if (uiContext === 'canvas') {\n e.preventDefault();\n selectPrev();\n }\n });\n\n $('#tool_zoom').dblclick(dblclickZoom);\n },\n /**\n * @returns {void}\n */\n setTitles () {\n $.each(keyAssocs, function (keyval, sel) {\n const menu = ($(sel).parents('#main_menu').length);\n\n $(sel).each(function () {\n let t;\n if (menu) {\n t = $(this).text().split(' [')[0];\n } else {\n t = this.title.split(' [')[0];\n }\n let keyStr = '';\n // Shift+Up\n $.each(keyval.split('/'), function (i, key) {\n const modBits = key.split('+');\n let mod = '';\n if (modBits.length > 1) {\n mod = modBits[0] + '+';\n key = modBits[1];\n }\n keyStr += (i ? '/' : '') + mod + (uiStrings['key_' + key] || key);\n });\n if (menu) {\n this.lastChild.textContent = t + ' [' + keyStr + ']';\n } else {\n this.title = t + ' [' + keyStr + ']';\n }\n });\n });\n },\n /**\n * @param {string} sel Selector to match\n * @returns {module:SVGEditor.ToolButton}\n */\n getButtonData (sel) {\n return Object.values(toolButtons).find((btn) => {\n return btn.sel === sel;\n });\n }\n };\n }());\n\n // Select given tool\n editor.ready(function () {\n let tool;\n const itool = curConfig.initTool,\n container = $('#tools_left, #svg_editor .tools_flyout'),\n preTool = container.find('#tool_' + itool),\n regTool = container.find('#' + itool);\n if (preTool.length) {\n tool = preTool;\n } else if (regTool.length) {\n tool = regTool;\n } else {\n tool = $('#tool_select');\n }\n tool.click().mouseup();\n\n if (curConfig.wireframe) {\n $('#tool_wireframe').click();\n }\n\n if (curConfig.showlayers) {\n toggleSidePanel();\n }\n\n $('#rulers').toggle(Boolean(curConfig.showRulers));\n\n if (curConfig.showRulers) {\n $('#show_rulers')[0].checked = true;\n }\n\n if (curConfig.baseUnit) {\n $('#base_unit').val(curConfig.baseUnit);\n }\n\n if (curConfig.gridSnapping) {\n $('#grid_snapping_on')[0].checked = true;\n }\n\n if (curConfig.snappingStep) {\n $('#grid_snapping_step').val(curConfig.snappingStep);\n }\n\n if (curConfig.gridColor) {\n $('#grid_color').val(curConfig.gridColor);\n }\n });\n\n // init SpinButtons\n $('#rect_rx').SpinButton({\n min: 0, max: 1000, stateObj, callback: changeRectRadius\n });\n $('#stroke_width').SpinButton({\n min: 0, max: 99, smallStep: 0.1, stateObj, callback: changeStrokeWidth\n });\n $('#angle').SpinButton({\n min: -180, max: 180, step: 5, stateObj, callback: changeRotationAngle\n });\n $('#font_size').SpinButton({\n min: 0.001, stepfunc: stepFontSize, stateObj, callback: changeFontSize\n });\n $('#group_opacity').SpinButton({\n min: 0, max: 100, step: 5, stateObj, callback: changeOpacity\n });\n $('#blur').SpinButton({\n min: 0, max: 10, step: 0.1, stateObj, callback: changeBlur\n });\n $('#zoom').SpinButton({\n min: 0.001, max: 10000, step: 50, stepfunc: stepZoom,\n stateObj, callback: changeZoom\n // Set default zoom\n }).val(\n svgCanvas.getZoom() * 100\n );\n\n $('#workarea').contextMenu(\n {\n menu: 'cmenu_canvas',\n inSpeed: 0\n },\n function (action, el, pos) {\n switch (action) {\n case 'delete':\n deleteSelected();\n break;\n case 'cut':\n cutSelected();\n break;\n case 'copy':\n copySelected();\n break;\n case 'paste':\n svgCanvas.pasteElements();\n break;\n case 'paste_in_place':\n svgCanvas.pasteElements('in_place');\n break;\n case 'group':\n case 'group_elements':\n svgCanvas.groupSelectedElements();\n break;\n case 'ungroup':\n svgCanvas.ungroupSelectedElement();\n break;\n case 'move_front':\n moveToTopSelected();\n break;\n case 'move_up':\n moveUpDownSelected('Up');\n break;\n case 'move_down':\n moveUpDownSelected('Down');\n break;\n case 'move_back':\n moveToBottomSelected();\n break;\n default:\n if (hasCustomHandler(action)) {\n getCustomHandler(action).call();\n }\n break;\n }\n }\n );\n\n /**\n * Implements {@see module:jQueryContextMenu.jQueryContextMenuListener}.\n * @param {\"dupe\"|\"delete\"|\"merge_down\"|\"merge_all\"} action\n * @param {external:jQuery} el\n * @param {{x: Float, y: Float, docX: Float, docY: Float}} pos\n * @returns {void}\n */\n const lmenuFunc = function (action, el, pos) {\n switch (action) {\n case 'dupe':\n /* await */ cloneLayer();\n break;\n case 'delete':\n deleteLayer();\n break;\n case 'merge_down':\n mergeLayer();\n break;\n case 'merge_all':\n svgCanvas.mergeAllLayers();\n updateContextPanel();\n populateLayers();\n break;\n }\n };\n\n $('#layerlist').contextMenu(\n {\n menu: 'cmenu_layers',\n inSpeed: 0\n },\n lmenuFunc\n );\n\n $('#layer_moreopts').contextMenu(\n {\n menu: 'cmenu_layers',\n inSpeed: 0,\n allowLeft: true\n },\n lmenuFunc\n );\n\n $('.contextMenu li').mousedown(function (ev) {\n ev.preventDefault();\n });\n\n $('#cmenu_canvas li').disableContextMenu();\n canvMenu.enableContextMenuItems('#delete,#cut,#copy');\n\n /**\n * @returns {void}\n */\n function enableOrDisableClipboard () {\n let svgeditClipboard;\n try {\n svgeditClipboard = localStorage.getItem('svgedit_clipboard');\n } catch (err) {}\n canvMenu[(svgeditClipboard ? 'en' : 'dis') + 'ableContextMenuItems'](\n '#paste,#paste_in_place'\n );\n }\n enableOrDisableClipboard();\n\n window.addEventListener('storage', function (e) {\n if (e.key !== 'svgedit_clipboard') { return; }\n\n enableOrDisableClipboard();\n });\n\n window.addEventListener('beforeunload', function (e) {\n // Suppress warning if page is empty\n if (undoMgr.getUndoStackSize() === 0) {\n editor.showSaveWarning = false;\n }\n\n // showSaveWarning is set to 'false' when the page is saved.\n if (!curConfig.no_save_warning && editor.showSaveWarning) {\n // Browser already asks question about closing the page\n e.returnValue = uiStrings.notification.unsavedChanges; // Firefox needs this when beforeunload set by addEventListener (even though message is not used)\n return uiStrings.notification.unsavedChanges;\n }\n return true;\n });\n\n /**\n * Expose the `uiStrings`.\n * @function module:SVGEditor.canvas.getUIStrings\n * @returns {module:SVGEditor.uiStrings}\n */\n editor.canvas.getUIStrings = function () {\n return uiStrings;\n };\n\n /**\n * @returns {Promise<boolean>} Resolves to boolean indicating `true` if there were no changes\n * and `false` after the user confirms.\n */\n editor.openPrep = function () {\n $('#main_menu').hide();\n if (undoMgr.getUndoStackSize() === 0) {\n return true;\n }\n return $.confirm(uiStrings.notification.QwantToOpen);\n };\n\n /**\n *\n * @param {Event} e\n * @returns {void}\n */\n function onDragEnter (e) {\n e.stopPropagation();\n e.preventDefault();\n // and indicator should be displayed here, such as \"drop files here\"\n }\n\n /**\n *\n * @param {Event} e\n * @returns {void}\n */\n function onDragOver (e) {\n e.stopPropagation();\n e.preventDefault();\n }\n\n /**\n *\n * @param {Event} e\n * @returns {void}\n */\n function onDragLeave (e) {\n e.stopPropagation();\n e.preventDefault();\n // hypothetical indicator should be removed here\n }\n // Use HTML5 File API: http://www.w3.org/TR/FileAPI/\n // if browser has HTML5 File API support, then we will show the open menu item\n // and provide a file input to click. When that change event fires, it will\n // get the text contents of the file and send it to the canvas\n if (window.FileReader) {\n /**\n * @param {Event} e\n * @returns {void}\n */\n const importImage = function (e) {\n $.process_cancel(uiStrings.notification.loadingImage);\n e.stopPropagation();\n e.preventDefault();\n $('#workarea').removeAttr('style');\n $('#main_menu').hide();\n const file = (e.type === 'drop') ? e.dataTransfer.files[0] : this.files[0];\n if (!file) {\n $('#dialog_box').hide();\n return;\n }\n /* if (file.type === 'application/pdf') { // Todo: Handle PDF imports\n\n }\n else */\n if (!file.type.includes('image')) {\n return;\n }\n // Detected an image\n // svg handling\n let reader;\n if (file.type.includes('svg')) {\n reader = new FileReader();\n reader.onloadend = function (ev) {\n const newElement = svgCanvas.importSvgString(ev.target.result, true);\n svgCanvas.ungroupSelectedElement();\n svgCanvas.ungroupSelectedElement();\n svgCanvas.groupSelectedElements();\n svgCanvas.alignSelectedElements('m', 'page');\n svgCanvas.alignSelectedElements('c', 'page');\n // highlight imported element, otherwise we get strange empty selectbox\n svgCanvas.selectOnly([newElement]);\n $('#dialog_box').hide();\n };\n reader.readAsText(file);\n } else {\n // bitmap handling\n reader = new FileReader();\n reader.onloadend = function ({target: {result}}) {\n /**\n * Insert the new image until we know its dimensions.\n * @param {Float} width\n * @param {Float} height\n * @returns {void}\n */\n const insertNewImage = function (width, height) {\n const newImage = svgCanvas.addSVGElementFromJson({\n element: 'image',\n attr: {\n x: 0,\n y: 0,\n width,\n height,\n id: svgCanvas.getNextId(),\n style: 'pointer-events:inherit'\n }\n });\n svgCanvas.setHref(newImage, result);\n svgCanvas.selectOnly([newImage]);\n svgCanvas.alignSelectedElements('m', 'page');\n svgCanvas.alignSelectedElements('c', 'page');\n updateContextPanel();\n $('#dialog_box').hide();\n };\n // create dummy img so we know the default dimensions\n let imgWidth = 100;\n let imgHeight = 100;\n const img = new Image();\n img.style.opacity = 0;\n img.addEventListener('load', function () {\n imgWidth = img.offsetWidth || img.naturalWidth || img.width;\n imgHeight = img.offsetHeight || img.naturalHeight || img.height;\n insertNewImage(imgWidth, imgHeight);\n });\n img.src = result;\n };\n reader.readAsDataURL(file);\n }\n };\n\n workarea[0].addEventListener('dragenter', onDragEnter);\n workarea[0].addEventListener('dragover', onDragOver);\n workarea[0].addEventListener('dragleave', onDragLeave);\n workarea[0].addEventListener('drop', importImage);\n\n const open = $('<input type=\"file\">').change(async function (e) {\n const ok = await editor.openPrep();\n if (!ok) { return; }\n svgCanvas.clear();\n if (this.files.length === 1) {\n $.process_cancel(uiStrings.notification.loadingImage);\n const reader = new FileReader();\n reader.onloadend = async function ({target}) {\n await loadSvgString(target.result);\n updateCanvas();\n };\n reader.readAsText(this.files[0]);\n }\n });\n $('#tool_open').show();\n $(window).on('openImage', () => open.click());\n\n const imgImport = $('<input type=\"file\">').change(importImage);\n $('#tool_import').show();\n $(window).on('importImage', () => imgImport.click());\n }\n\n updateCanvas(true);\n // const revnums = 'svg-editor.js ($Rev$) ';\n // revnums += svgCanvas.getVersion();\n // $('#copyright')[0].setAttribute('title', revnums);\n\n const loadedExtensionNames = [];\n /**\n * @function module:SVGEditor.setLang\n * @param {string} lang The language code\n * @param {module:locale.LocaleStrings} allStrings See {@tutorial LocaleDocs}\n * @fires module:svgcanvas.SvgCanvas#event:ext_langReady\n * @fires module:svgcanvas.SvgCanvas#event:ext_langChanged\n * @returns {Promise<void>} A Promise which resolves to `undefined`\n */\n const setLang = editor.setLang = async function (lang, allStrings) {\n editor.langChanged = true;\n editor.pref('lang', lang);\n $('#lang_select').val(lang);\n if (!allStrings) {\n return;\n }\n // Todo: Remove `allStrings.lang` property in locale in\n // favor of just `lang`?\n document.documentElement.lang = allStrings.lang; // lang;\n // Todo: Add proper RTL Support!\n // Todo: Use RTL detection instead and take out of locales?\n // document.documentElement.dir = allStrings.dir;\n $.extend(uiStrings, allStrings);\n\n // const notif = allStrings.notification; // Currently unused\n // $.extend will only replace the given strings\n const oldLayerName = $('#layerlist tr.layersel td.layername').text();\n const renameLayer = (oldLayerName === uiStrings.common.layer + ' 1');\n\n svgCanvas.setUiStrings(allStrings);\n Actions.setTitles();\n\n if (renameLayer) {\n svgCanvas.renameCurrentLayer(uiStrings.common.layer + ' 1');\n populateLayers();\n }\n\n // In case extensions loaded before the locale, now we execute a callback on them\n if (extsPreLang.length) {\n await Promise.all(extsPreLang.map((ext) => {\n loadedExtensionNames.push(ext.name);\n return ext.langReady({\n lang,\n uiStrings,\n importLocale: getImportLocale({defaultLang: lang, defaultName: ext.name})\n });\n }));\n extsPreLang.length = 0;\n } else {\n loadedExtensionNames.forEach((loadedExtensionName) => {\n svgCanvas.runExtension(\n loadedExtensionName,\n 'langReady',\n /** @type {module:svgcanvas.SvgCanvas#event:ext_langReady} */ {\n lang, uiStrings, importLocale: getImportLocale({defaultLang: lang, defaultName: loadedExtensionName})\n }\n );\n });\n }\n svgCanvas.runExtensions('langChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext_langChanged} */ lang);\n\n // Update flyout tooltips\n setFlyoutTitles();\n\n // Copy title for certain tool elements\n const elems = {\n '#stroke_color': '#tool_stroke .icon_label, #tool_stroke .color_block',\n '#fill_color': '#tool_fill label, #tool_fill .color_block',\n '#linejoin_miter': '#cur_linejoin',\n '#linecap_butt': '#cur_linecap'\n };\n\n $.each(elems, function (source, dest) {\n $(dest).attr('title', $(source)[0].title);\n });\n\n // Copy alignment titles\n $('#multiselected_panel div[id^=tool_align]').each(function () {\n $('#tool_pos' + this.id.substr(10))[0].title = this.title;\n });\n };\n localeInit(\n /**\n * @implements {module:locale.LocaleEditorInit}\n */\n {\n /**\n * Gets an array of results from extensions with a `addLangData` method,\n * returning an object with a `data` property set to its locales (to be\n * merged with regular locales).\n * @param {string} langParam\n * @fires module:svgcanvas.SvgCanvas#event:ext_addLangData\n * @todo Can we forego this in favor of `langReady` (or forego `langReady`)?\n * @returns {module:locale.AddLangExtensionLocaleData[]}\n */\n addLangData (langParam) {\n return svgCanvas.runExtensions(\n 'addLangData',\n /**\n * @function\n * @type {module:svgcanvas.ExtensionVarBuilder}\n * @param {string} name\n * @returns {module:svgcanvas.SvgCanvas#event:ext_addLangData}\n */\n (name) => { // We pass in a function as we don't know the extension name here when defining this `addLangData` method\n return {\n lang: langParam,\n importLocale: getImportLocale({defaultLang: langParam, defaultName: name})\n };\n },\n true\n );\n },\n curConfig\n }\n );\n // Load extensions\n // Bit of a hack to run extensions in local Opera/IE9\n if (document.location.protocol === 'file:') {\n setTimeout(extAndLocaleFunc, 100);\n } else {\n // Returns a promise (if we wanted to fire 'extensions-loaded' event,\n // potentially useful to hide interface as some extension locales\n // are only available after this)\n extAndLocaleFunc();\n }\n};\n\n/**\n* @callback module:SVGEditor.ReadyCallback\n* @returns {Promise<void>|void}\n*/\n/**\n* Queues a callback to be invoked when the editor is ready (or\n* to be invoked immediately if it is already ready--i.e.,\n* if `runCallbacks` has been run).\n* @param {module:SVGEditor.ReadyCallback} cb Callback to be queued to invoke\n* @returns {Promise<ArbitraryCallbackResult>} Resolves when all callbacks, including the supplied have resolved\n*/\neditor.ready = function (cb) { // eslint-disable-line promise/prefer-await-to-callbacks\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n if (isReady) {\n resolve(cb()); // eslint-disable-line callback-return, promise/prefer-await-to-callbacks\n return;\n }\n callbacks.push([cb, resolve, reject]);\n });\n};\n\n/**\n* Invokes the callbacks previous set by `svgEditor.ready`\n* @returns {Promise<void>} Resolves to `undefined` if all callbacks succeeded and rejects otherwise\n*/\neditor.runCallbacks = async function () {\n try {\n await Promise.all(callbacks.map(([cb]) => {\n return cb(); // eslint-disable-line promise/prefer-await-to-callbacks\n }));\n } catch (err) {\n callbacks.forEach(([, , reject]) => {\n reject();\n });\n throw err;\n }\n callbacks.forEach(([, resolve]) => {\n resolve();\n });\n isReady = true;\n};\n\n/**\n* @param {string} str The SVG string to load\n* @param {PlainObject} [opts={}]\n* @param {boolean} [opts.noAlert=false] Option to avoid alert to user and instead get rejected promise\n* @returns {Promise<void>}\n*/\neditor.loadFromString = function (str, {noAlert} = {}) {\n return editor.ready(async function () {\n try {\n await loadSvgString(str, {noAlert});\n } catch (err) {\n if (noAlert) {\n throw err;\n }\n }\n });\n};\n\n/**\n* Not presently in use.\n* @param {PlainObject} featList\n* @returns {void}\n*/\neditor.disableUI = function (featList) {\n // $(function () {\n // $('#tool_wireframe, #tool_image, #main_button, #tool_source, #sidepanels').remove();\n // $('#tools_top').css('left', 5);\n // });\n};\n\n/**\n * @callback module:SVGEditor.URLLoadCallback\n * @param {boolean} success\n * @returns {void}\n */\n/**\n* @param {string} url URL from which to load an SVG string via Ajax\n* @param {PlainObject} [opts={}] May contain properties: `cache`, `callback`\n* @param {boolean} [opts.cache]\n* @param {boolean} [opts.noAlert]\n* @returns {Promise<void>} Resolves to `undefined` or rejects upon bad loading of\n* the SVG (or upon failure to parse the loaded string) when `noAlert` is\n* enabled\n*/\neditor.loadFromURL = function (url, {cache, noAlert} = {}) {\n return editor.ready(function () {\n return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new\n $.ajax({\n url,\n dataType: 'text',\n cache: Boolean(cache),\n beforeSend () {\n $.process_cancel(uiStrings.notification.loadingImage);\n },\n success (str) {\n resolve(loadSvgString(str, {noAlert}));\n },\n error (xhr, stat, err) {\n if (xhr.status !== 404 && xhr.responseText) {\n resolve(loadSvgString(xhr.responseText, {noAlert}));\n return;\n }\n if (noAlert) {\n reject(new Error('URLLoadFail'));\n return;\n }\n $.alert(uiStrings.notification.URLLoadFail + ': \\n' + err);\n resolve();\n },\n complete () {\n $('#dialog_box').hide();\n }\n });\n });\n });\n};\n\n/**\n* @param {string} str The Data URI to base64-decode (if relevant) and load\n* @param {PlainObject} [opts={}]\n* @param {boolean} [opts.noAlert]\n* @returns {Promise<void>} Resolves to `undefined` and rejects if loading SVG string fails and `noAlert` is enabled\n*/\neditor.loadFromDataURI = function (str, {noAlert} = {}) {\n return editor.ready(function () {\n let base64 = false;\n let pre = str.match(/^data:image\\/svg\\+xml;base64,/);\n if (pre) {\n base64 = true;\n } else {\n pre = str.match(/^data:image\\/svg\\+xml(?:;|;utf8)?,/);\n }\n if (pre) {\n pre = pre[0];\n }\n const src = str.slice(pre.length);\n return loadSvgString(base64 ? Utils.decode64(src) : decodeURIComponent(src), {noAlert});\n });\n};\n\n/**\n * @param {string} name Used internally; no need for i18n.\n * @param {module:svgcanvas.ExtensionInitCallback} init Config to be invoked on this module\n * @param {module:svgcanvas.ExtensionInitArgs} initArgs\n * @throws {Error} If called too early\n * @returns {Promise<void>} Resolves to `undefined`\n*/\neditor.addExtension = function (name, init, initArgs) {\n // Note that we don't want this on editor.ready since some extensions\n // may want to run before then (like server_opensave).\n // $(function () {\n if (!svgCanvas) {\n throw new Error('Extension added too early');\n }\n return svgCanvas.addExtension.call(this, name, init, initArgs);\n // });\n};\n\n// Defer injection to wait out initial menu processing. This probably goes\n// away once all context menu behavior is brought to context menu.\neditor.ready(() => {\n injectExtendedContextMenuItemsIntoDom();\n});\n\nlet extensionsAdded = false;\nconst messageQueue = [];\n/**\n * @param {PlainObject} info\n * @param {any} info.data\n * @param {string} info.origin\n * @fires module:svgcanvas.SvgCanvas#event:message\n * @returns {void}\n */\nconst messageListener = ({data, origin}) => { // eslint-disable-line no-shadow\n // console.log('data, origin, extensionsAdded', data, origin, extensionsAdded);\n const messageObj = {data, origin};\n if (!extensionsAdded) {\n messageQueue.push(messageObj);\n } else {\n // Extensions can handle messages at this stage with their own\n // canvas `message` listeners\n svgCanvas.call('message', messageObj);\n }\n};\nwindow.addEventListener('message', messageListener);\n\n// Run init once DOM is loaded\n// jQuery(editor.init);\n\n(async () => {\ntry {\n // We wait a micro-task to let the svgEditor variable be defined for module checks\n await Promise.resolve();\n editor.init();\n} catch (err) {\n console.error(err); // eslint-disable-line no-console\n}\n})();\n\nexport default editor;\n","// Todo: Update: https://github.com/jeresig/jquery.hotkeys\n/*\n * jQuery Hotkeys Plugin\n * Copyright 2010, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n *\n * http://github.com/jeresig/jquery.hotkeys\n *\n * Based upon the plugin by Tzury Bar Yochay:\n * http://github.com/tzuryby/hotkeys\n *\n * Original idea by:\n * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/\n*/\n\n// We *do* want to allow the escape key within textareas (and possibly tab too), so add the condition `n.which !== 27`\n\nexport default function(b){b.hotkeys={version:\"0.8\",specialKeys:{8:\"backspace\",9:\"tab\",13:\"return\",16:\"shift\",17:\"ctrl\",18:\"alt\",19:\"pause\",20:\"capslock\",27:\"esc\",32:\"space\",33:\"pageup\",34:\"pagedown\",35:\"end\",36:\"home\",37:\"left\",38:\"up\",39:\"right\",40:\"down\",45:\"insert\",46:\"del\",96:\"0\",97:\"1\",98:\"2\",99:\"3\",100:\"4\",101:\"5\",102:\"6\",103:\"7\",104:\"8\",105:\"9\",106:\"*\",107:\"+\",109:\"-\",110:\".\",111:\"/\",112:\"f1\",113:\"f2\",114:\"f3\",115:\"f4\",116:\"f5\",117:\"f6\",118:\"f7\",119:\"f8\",120:\"f9\",121:\"f10\",122:\"f11\",123:\"f12\",144:\"numlock\",145:\"scroll\",191:\"/\",224:\"meta\",219:\"[\",221:\"]\"},shiftNums:{\"`\":\"~\",\"1\":\"!\",\"2\":\"@\",\"3\":\"#\",\"4\":\"$\",\"5\":\"%\",\"6\":\"^\",\"7\":\"&\",\"8\":\"*\",\"9\":\"(\",\"0\":\")\",\"-\":\"_\",\"=\":\"+\",\";\":\": \",\"'\":'\"',\",\":\"<\",\".\":\">\",\"/\":\"?\",\"\\\\\":\"|\"}};function a(d){if(typeof d.data!==\"string\"){return}var c=d.handler,e=d.data.toLowerCase().split(\" \");d.handler=function(n){if(this!==n.target&&(n.which !== 27 && (/textarea|select/i.test(n.target.nodeName)||n.target.type===\"text\"))){return}var h=n.type!==\"keypress\"&&b.hotkeys.specialKeys[n.which],o=String.fromCharCode(n.which).toLowerCase(),k,m=\"\",g={};if(n.altKey&&h!==\"alt\"){m+=\"alt+\"}if(n.ctrlKey&&h!==\"ctrl\"){m+=\"ctrl+\"}if(n.metaKey&&!n.ctrlKey&&h!==\"meta\"){m+=\"meta+\"}if(n.shiftKey&&h!==\"shift\"){m+=\"shift+\"}if(h){g[m+h]=true}else{g[m+o]=true;g[m+b.hotkeys.shiftNums[o]]=true;if(m===\"shift+\"){g[b.hotkeys.shiftNums[o]]=true}}for(var j=0,f=e.length;j<f;j++){if(g[e[j]]){return c.apply(this,arguments)}}}}b.each([\"keydown\",\"keyup\",\"keypress\"],function(){b.event.special[this]={add:a}})\n\nreturn b;\n}\n","/**\n * SpinButton control.\n *\n * Adds bells and whistles to any ordinary textbox to\n * make it look and feel like a SpinButton Control.\n *\n * Supplies {@link external:jQuery.fn.SpinButton} (and also {@link external:jQuery.loadingStylesheets}).\n *\n * Originally written by George Adamson, Software Unity (george.jquery@softwareunity.com) August 2006:\n * - Added min/max options.\n * - Added step size option.\n * - Added bigStep (page up/down) option.\n *\n * Modifications made by Mark Gibson, (mgibson@designlinks.net) September 2006:\n * - Converted to jQuery plugin.\n * - Allow limited or unlimited min/max values.\n * - Allow custom class names, and add class to input element.\n * - Removed global vars.\n * - Reset (to original or through config) when invalid value entered.\n * - Repeat whilst holding mouse button down (with initial pause, like keyboard repeat).\n * - Support mouse wheel in Firefox.\n * - Fix double click in IE.\n * - Refactored some code and renamed some vars.\n *\n * Modifications by Jeff Schiller, June 2009:\n * - provide callback function for when the value changes based on the following\n * {@link https://www.mail-archive.com/jquery-en@googlegroups.com/msg36070.html}.\n *\n * Modifications by Jeff Schiller, July 2009:\n * - improve styling for widget in Opera.\n * - consistent key-repeat handling cross-browser.\n *\n * Modifications by Alexis Deveria, October 2009:\n * - provide \"stepfunc\" callback option to allow custom function to run when changing a value.\n * - Made adjustValue(0) only run on certain keyup events, not all.\n *\n * Tested in IE6, Opera9, Firefox 1.5.\n *\n * | Version | Date | Author | Notes |\n * |---------|------|--------|-------|\n * | v1.0 | 11 Aug 2006 | George Adamson | First release |\n * | v1.1 | Aug 2006 | George Adamson | Minor enhancements |\n * | v1.2 | 27 Sep 2006 | Mark Gibson | Major enhancements |\n * | v1.3a | 28 Sep 2006 | George Adamson | Minor enhancements |\n * | v1.4 | 18 Jun 2009 | Jeff Schiller | Added callback function |\n * | v1.5 | 06 Jul 2009 | Jeff Schiller | Fixes for Opera. |\n * | v1.6 | 13 Oct 2009 | Alexis Deveria | Added stepfunc function |\n * | v1.7 | 21 Oct 2009 | Alexis Deveria | Minor fixes.<br />Fast-repeat for keys and live updating as you type. |\n * | v1.8 | 12 Jan 2010 | Benjamin Thomas | Fixes for mouseout behavior.<br />Added smallStep |\n * | v1.9 | 20 May 2018 | Brett Zamir | Avoid SVGEdit dependency via `stateObj` config;<br />convert to ES6 module |\n * .\n *\n * @module jQuerySpinButton\n * @example\n // Create group of settings to initialise spinbutton(s). (Optional)\n const myOptions = {\n min: 0, // Set lower limit.\n max: 100, // Set upper limit.\n step: 1, // Set increment size.\n smallStep: 0.5, // Set shift-click increment size.\n stateObj: {tool_scale: 1}, // Object to allow passing in live-updating scale\n spinClass: mySpinBtnClass, // CSS class to style the spinbutton. (Class also specifies url of the up/down button image.)\n upClass: mySpinUpClass, // CSS class for style when mouse over up button.\n downClass: mySpinDnClass // CSS class for style when mouse over down button.\n };\n\n $(function () {\n // Initialise INPUT element(s) as SpinButtons: (passing options if desired)\n $('#myInputElement').SpinButton(myOptions);\n });\n */\n/**\n * @function module:jQuerySpinButton.jQuerySpinButton\n * @param {external:jQuery} $ The jQuery object to which to add the plug-in\n * @returns {external:jQuery}\n*/\nexport default function jQueryPluginSpinButton ($) {\n if (!$.loadingStylesheets) {\n $.loadingStylesheets = [];\n }\n const stylesheet = 'spinbtn/jQuery.SpinButton.css';\n if (!$.loadingStylesheets.includes(stylesheet)) {\n $.loadingStylesheets.push(stylesheet);\n }\n /**\n * @callback module:jQuerySpinButton.StepCallback\n * @param {external:jQuery} thisArg Value of `this`\n * @param {Float} i Value to adjust\n * @returns {Float}\n */\n /**\n * @callback module:jQuerySpinButton.ValueCallback\n * @param {external:jQuery.fn.SpinButton} thisArg Spin Button; check its `value` to see how it was changed.\n * @returns {void}\n */\n /**\n * @typedef {PlainObject} module:jQuerySpinButton.SpinButtonConfig\n * @property {Float} min Set lower limit\n * @property {Float} max Set upper limit.\n * @property {Float} step Set increment size.\n * @property {module:jQuerySpinButton.StepCallback} stepfunc Custom function to run when changing a value; called with `this` of object and the value to adjust and returns a float.\n * @property {module:jQuerySpinButton.ValueCallback} callback Called after value adjusted (with `this` of object)\n * @property {Float} smallStep Set shift-click increment size.\n * @property {PlainObject} stateObj Object to allow passing in live-updating scale\n * @property {Float} stateObj.tool_scale\n * @property {string} spinClass CSS class to style the spinbutton. (Class also specifies url of the up/down button image.)\n * @property {string} upClass CSS class for style when mouse over up button.\n * @property {string} downClass CSS class for style when mouse over down button.\n * @property {Float} page Value to be adjusted on page up/page down\n * @property {Float} reset Reset value when invalid value entered\n * @property {Float} delay Millisecond delay\n * @property {Float} interval Millisecond interval\n */\n /**\n * @function external:jQuery.fn.SpinButton\n * @param {module:jQuerySpinButton.SpinButtonConfig} cfg\n * @returns {external:jQuery}\n */\n $.fn.SpinButton = function (cfg) {\n cfg = cfg || {};\n\n /**\n *\n * @param {Element} el\n * @param {\"offsetLeft\"|\"offsetTop\"} prop\n * @returns {Integer}\n */\n function coord (el, prop) {\n const b = document.body;\n\n let c = el[prop];\n while ((el = el.offsetParent) && (el !== b)) {\n if (!$.browser.msie || (el.currentStyle.position !== 'relative')) {\n c += el[prop];\n }\n }\n\n return c;\n }\n\n return this.each(function () {\n this.repeating = false;\n\n // Apply specified options or defaults:\n // (Ought to refactor this some day to use $.extend() instead)\n this.spinCfg = {\n // min: cfg.min ? Number(cfg.min) : null,\n // max: cfg.max ? Number(cfg.max) : null,\n min: !isNaN(parseFloat(cfg.min)) ? Number(cfg.min) : null, // Fixes bug with min:0\n max: !isNaN(parseFloat(cfg.max)) ? Number(cfg.max) : null,\n step: cfg.step ? Number(cfg.step) : 1,\n stepfunc: cfg.stepfunc || false,\n page: cfg.page ? Number(cfg.page) : 10,\n upClass: cfg.upClass || 'up',\n downClass: cfg.downClass || 'down',\n reset: cfg.reset || this.value,\n delay: cfg.delay ? Number(cfg.delay) : 500,\n interval: cfg.interval ? Number(cfg.interval) : 100,\n _btn_width: 20,\n _direction: null,\n _delay: null,\n _repeat: null,\n callback: cfg.callback || null\n };\n\n // if a smallStep isn't supplied, use half the regular step\n this.spinCfg.smallStep = cfg.smallStep || this.spinCfg.step / 2;\n\n this.adjustValue = function (i) {\n let v;\n if (isNaN(this.value)) {\n v = this.spinCfg.reset;\n } else if (typeof this.spinCfg.stepfunc === 'function') {\n v = this.spinCfg.stepfunc(this, i);\n } else {\n // weirdest JavaScript bug ever: 5.1 + 0.1 = 5.199999999\n v = Number((Number(this.value) + Number(i)).toFixed(5));\n }\n if (this.spinCfg.min !== null) { v = Math.max(v, this.spinCfg.min); }\n if (this.spinCfg.max !== null) { v = Math.min(v, this.spinCfg.max); }\n this.value = v;\n if (typeof this.spinCfg.callback === 'function') {\n this.spinCfg.callback(this);\n }\n };\n\n $(this)\n .addClass(cfg.spinClass || 'spin-button')\n\n .mousemove(function (e) {\n // Determine which button mouse is over, or not (spin direction):\n const x = e.pageX || e.x;\n const y = e.pageY || e.y;\n const el = e.target;\n const scale = cfg.stateObj.tool_scale || 1;\n const height = $(el).height() / 2;\n\n const direction =\n (x > coord(el, 'offsetLeft') +\n el.offsetWidth * scale - this.spinCfg._btn_width)\n ? ((y < coord(el, 'offsetTop') + height * scale) ? 1 : -1)\n : 0;\n\n if (direction !== this.spinCfg._direction) {\n // Style up/down buttons:\n switch (direction) {\n case 1: // Up arrow:\n $(this).removeClass(this.spinCfg.downClass).addClass(this.spinCfg.upClass);\n break;\n case -1: // Down arrow:\n $(this).removeClass(this.spinCfg.upClass).addClass(this.spinCfg.downClass);\n break;\n default: // Mouse is elsewhere in the textbox\n $(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass);\n }\n\n // Set spin direction:\n this.spinCfg._direction = direction;\n }\n })\n\n .mouseout(function () {\n // Reset up/down buttons to their normal appearance when mouse moves away:\n $(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass);\n this.spinCfg._direction = null;\n window.clearInterval(this.spinCfg._repeat);\n window.clearTimeout(this.spinCfg._delay);\n })\n\n .mousedown(function (e) {\n if (e.button === 0 && this.spinCfg._direction !== 0) {\n // Respond to click on one of the buttons:\n const stepSize = e.shiftKey ? this.spinCfg.smallStep : this.spinCfg.step;\n\n const adjust = () => {\n this.adjustValue(this.spinCfg._direction * stepSize);\n };\n\n adjust();\n\n // Initial delay before repeating adjustment\n this.spinCfg._delay = window.setTimeout(() => {\n adjust();\n // Repeat adjust at regular intervals\n this.spinCfg._repeat = window.setInterval(adjust, this.spinCfg.interval);\n }, this.spinCfg.delay);\n }\n })\n\n .mouseup(function (e) {\n // Cancel repeating adjustment\n window.clearInterval(this.spinCfg._repeat);\n window.clearTimeout(this.spinCfg._delay);\n })\n\n .dblclick(function (e) {\n if ($.browser.msie) {\n this.adjustValue(this.spinCfg._direction * this.spinCfg.step);\n }\n })\n\n .keydown(function (e) {\n // Respond to up/down arrow keys.\n switch (e.keyCode) {\n case 38: this.adjustValue(this.spinCfg.step); break; // Up\n case 40: this.adjustValue(-this.spinCfg.step); break; // Down\n case 33: this.adjustValue(this.spinCfg.page); break; // PageUp\n case 34: this.adjustValue(-this.spinCfg.page); break; // PageDown\n }\n })\n\n /*\n http://unixpapa.com/js/key.html describes the current state-of-affairs for\n key repeat events:\n - Safari 3.1 changed their model so that keydown is reliably repeated going forward\n - Firefox and Opera still only repeat the keypress event, not the keydown\n */\n .keypress(function (e) {\n if (this.repeating) {\n // Respond to up/down arrow keys.\n switch (e.keyCode) {\n case 38: this.adjustValue(this.spinCfg.step); break; // Up\n case 40: this.adjustValue(-this.spinCfg.step); break; // Down\n case 33: this.adjustValue(this.spinCfg.page); break; // PageUp\n case 34: this.adjustValue(-this.spinCfg.page); break; // PageDown\n }\n // we always ignore the first keypress event (use the keydown instead)\n } else {\n this.repeating = true;\n }\n })\n\n // clear the 'repeating' flag\n .keyup(function (e) {\n this.repeating = false;\n switch (e.keyCode) {\n case 38: // Up\n case 40: // Down\n case 33: // PageUp\n case 34: // PageDown\n case 13: this.adjustValue(0); break; // Enter/Return\n }\n })\n\n .bind('mousewheel', function (e) {\n // Respond to mouse wheel in IE. (It returns up/dn motion in multiples of 120)\n if (e.wheelDelta >= 120) {\n this.adjustValue(this.spinCfg.step);\n } else if (e.wheelDelta <= -120) {\n this.adjustValue(-this.spinCfg.step);\n }\n\n e.preventDefault();\n })\n\n .change(function (e) {\n this.adjustValue(0);\n });\n\n if (this.addEventListener) {\n // Respond to mouse wheel in Firefox\n this.addEventListener('DOMMouseScroll', function (e) {\n if (e.detail > 0) {\n this.adjustValue(-this.spinCfg.step);\n } else if (e.detail < 0) {\n this.adjustValue(this.spinCfg.step);\n }\n\n e.preventDefault();\n });\n }\n });\n };\n return $;\n}\n","/**\n * @file jQuery Context Menu Plugin\n * Cory S.N. LaViska\n * A Beautiful Site ({@link https://abeautifulsite.net/})\n * Modified by Alexis Deveria\n *\n * More info: {@link https://abeautifulsite.net/2008/09/jquery-context-menu-plugin/}\n *\n * @module jQueryContextMenu\n * @todo Update to latest version and adapt (and needs jQuery update as well): {@link https://github.com/swisnl/jQuery-contextMenu}\n * @version 1.0.1\n *\n * @license (MIT OR GPL-2.0-or-later)\n *\n * This plugin is dual-licensed under the GNU General Public License\n * and the MIT License and is copyright A Beautiful Site, LLC.\n *\n*/\nimport {isMac} from '../browser.js';\n\n/**\n* @callback module:jQueryContextMenu.jQueryContextMenuListener\n* @param {string} href The `href` value after the first character (for bypassing an initial `#`)\n* @param {external:jQuery} srcElement The wrapped jQuery srcElement\n* @param {{x: Float, y: Float, docX: Float, docY: Float}} coords\n* @returns {void}\n*/\n\n/**\n* @typedef {PlainObject} module:jQueryContextMenu.jQueryContextMenuConfig\n* @property {string} menu\n* @property {Float} inSpeed\n* @property {Float} outSpeed\n* @property {boolean} allowLeft\n*/\n\n/**\n* Adds {@link external:jQuery.fn.contextMenu},\n* {@link external:jQuery.fn.disableContextMenuItems},\n* {@link external:jQuery.fn.enableContextMenuItems},\n* {@link external:jQuery.fn.disableContextMenu},\n* {@link external:jQuery.fn.enableContextMenu},\n* {@link external:jQuery.fn.destroyContextMenu}.\n* @function module:jQueryContextMenu.jQueryContextMenu\n* @param {external:jQuery} $ The jQuery object to wrap (with `contextMenu`, `disableContextMenuItems`, `enableContextMenuItems`, `disableContextMenu`, `enableContextMenu`, `destroyContextMenu`)\n* @returns {external:jQuery}\n*/\nfunction jQueryContextMenu ($) {\n const win = $(window);\n const doc = $(document);\n\n $.extend($.fn, {\n /**\n * @memberof external:jQuery.fn\n * @param {module:jQueryContextMenu.jQueryContextMenuConfig} o\n * @param {module:jQueryContextMenu.jQueryContextMenuListener} listener\n * @returns {external:jQuery}\n */\n contextMenu (o, listener) {\n // Defaults\n if (o.menu === undefined) return false;\n if (o.inSpeed === undefined) o.inSpeed = 150;\n if (o.outSpeed === undefined) o.outSpeed = 75;\n // 0 needs to be -1 for expected results (no fade)\n if (o.inSpeed === 0) o.inSpeed = -1;\n if (o.outSpeed === 0) o.outSpeed = -1;\n // Loop each context menu\n $(this).each(function () {\n const el = $(this);\n const offset = $(el).offset();\n\n const menu = $('#' + o.menu);\n\n // Add contextMenu class\n menu.addClass('contextMenu');\n // Simulate a true right click\n $(this).bind('mousedown', function (evt) {\n $(this).mouseup(function (e) {\n const srcElement = $(this);\n srcElement.unbind('mouseup');\n\n if (!(evt.button === 2 || o.allowLeft ||\n (evt.ctrlKey && isMac()))) {\n return undefined;\n }\n e.stopPropagation();\n // Hide context menus that may be showing\n $('.contextMenu').hide();\n // Get this context menu\n\n if (el.hasClass('disabled')) return false;\n\n // Detect mouse position\n let x = e.pageX, y = e.pageY;\n\n const xOff = win.width() - menu.width(),\n yOff = win.height() - menu.height();\n\n if (x > xOff - 15) x = xOff - 15;\n if (y > yOff - 30) y = yOff - 30; // 30 is needed to prevent scrollbars in FF\n\n // Show the menu\n doc.unbind('click');\n menu.css({top: y, left: x}).fadeIn(o.inSpeed);\n // Hover events\n menu.find('A').mouseover(function () {\n menu.find('LI.hover').removeClass('hover');\n $(this).parent().addClass('hover');\n }).mouseout(function () {\n menu.find('LI.hover').removeClass('hover');\n });\n\n // Keyboard\n doc.keypress(function (ev) {\n switch (ev.keyCode) {\n case 38: // up\n if (!menu.find('LI.hover').length) {\n menu.find('LI:last').addClass('hover');\n } else {\n menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');\n if (!menu.find('LI.hover').length) menu.find('LI:last').addClass('hover');\n }\n break;\n case 40: // down\n if (!menu.find('LI.hover').length) {\n menu.find('LI:first').addClass('hover');\n } else {\n menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');\n if (!menu.find('LI.hover').length) menu.find('LI:first').addClass('hover');\n }\n break;\n case 13: // enter\n menu.find('LI.hover A').trigger('click');\n break;\n case 27: // esc\n doc.trigger('click');\n break;\n }\n });\n\n // When items are selected\n menu.find('A').unbind('mouseup');\n menu.find('LI:not(.disabled) A').mouseup(function () {\n doc.unbind('click').unbind('keypress');\n $('.contextMenu').hide();\n if (listener) {\n listener($(this).attr('href').substr(1), $(srcElement), {\n x: x - offset.left, y: y - offset.top, docX: x, docY: y\n });\n }\n return false;\n });\n\n // Hide bindings\n setTimeout(function () { // Delay for Mozilla\n doc.click(function () {\n doc.unbind('click').unbind('keypress');\n menu.fadeOut(o.outSpeed);\n return false;\n });\n }, 0);\n return undefined;\n });\n });\n\n // Disable text selection\n if ($.browser.mozilla) {\n $('#' + o.menu).each(function () { $(this).css({MozUserSelect: 'none'}); });\n } else if ($.browser.msie) {\n $('#' + o.menu).each(function () { $(this).bind('selectstart.disableTextSelect', function () { return false; }); });\n } else {\n $('#' + o.menu).each(function () { $(this).bind('mousedown.disableTextSelect', function () { return false; }); });\n }\n // Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)\n $(el).add($('UL.contextMenu')).bind('contextmenu', function () { return false; });\n });\n return $(this);\n },\n\n /**\n * Disable context menu items on the fly.\n * @memberof external:jQuery.fn\n * @param {void|string} o Comma-separated\n * @returns {external:jQuery}\n */\n disableContextMenuItems (o) {\n if (o === undefined) {\n // Disable all\n $(this).find('LI').addClass('disabled');\n return $(this);\n }\n $(this).each(function () {\n if (o !== undefined) {\n const d = o.split(',');\n for (const href of d) {\n $(this).find('A[href=\"' + href + '\"]').parent().addClass('disabled');\n }\n }\n });\n return $(this);\n },\n\n /**\n * Enable context menu items on the fly.\n * @memberof external:jQuery.fn\n * @param {void|string} o Comma-separated\n * @returns {external:jQuery}\n */\n enableContextMenuItems (o) {\n if (o === undefined) {\n // Enable all\n $(this).find('LI.disabled').removeClass('disabled');\n return $(this);\n }\n $(this).each(function () {\n if (o !== undefined) {\n const d = o.split(',');\n for (const href of d) {\n $(this).find('A[href=\"' + href + '\"]').parent().removeClass('disabled');\n }\n }\n });\n return $(this);\n },\n\n /**\n * Disable context menu(s).\n * @memberof external:jQuery.fn\n * @returns {external:jQuery}\n */\n disableContextMenu () {\n $(this).each(function () {\n $(this).addClass('disabled');\n });\n return $(this);\n },\n\n /**\n * Enable context menu(s).\n * @memberof external:jQuery.fn\n * @returns {external:jQuery}\n */\n enableContextMenu () {\n $(this).each(function () {\n $(this).removeClass('disabled');\n });\n return $(this);\n },\n\n /**\n * Destroy context menu(s).\n * @memberof external:jQuery.fn\n * @returns {external:jQuery}\n */\n destroyContextMenu () {\n // Destroy specified context menus\n $(this).each(function () {\n // Disable action\n $(this).unbind('mousedown').unbind('mouseup');\n });\n return $(this);\n }\n });\n return $;\n}\n\nexport default jQueryContextMenu;\n"],"names":["touchHandler","ev","changedTouches","first","type","screenX","screenY","clientX","clientY","simulatedEvent","MouseEvent","bubbles","cancelable","view","window","detail","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","length","target","dispatchEvent","preventDefault","document","addEventListener","NS","HTML","MATH","SE","SVG","XLINK","XML","XMLNS","getReverseNS","reverseNS","Object","entries","forEach","name","URI","toLowerCase","SVGPathSeg","typeAsLetter","owningPathSegList","pathSegType","pathSegTypeAsLetter","_owningPathSegList","this","segmentChanged","prototype","classname","PATHSEG_UNKNOWN","PATHSEG_CLOSEPATH","PATHSEG_MOVETO_ABS","PATHSEG_MOVETO_REL","PATHSEG_LINETO_ABS","PATHSEG_LINETO_REL","PATHSEG_CURVETO_CUBIC_ABS","PATHSEG_CURVETO_CUBIC_REL","PATHSEG_CURVETO_QUADRATIC_ABS","PATHSEG_CURVETO_QUADRATIC_REL","PATHSEG_ARC_ABS","PATHSEG_ARC_REL","PATHSEG_LINETO_HORIZONTAL_ABS","PATHSEG_LINETO_HORIZONTAL_REL","PATHSEG_LINETO_VERTICAL_ABS","PATHSEG_LINETO_VERTICAL_REL","PATHSEG_CURVETO_CUBIC_SMOOTH_ABS","PATHSEG_CURVETO_CUBIC_SMOOTH_REL","PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS","PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL","SVGPathSegClosePath","undefined","SVGPathSegMovetoAbs","x","y","_x","_y","defineProperties","get","set","_segmentChanged","enumerable","SVGPathSegMovetoRel","SVGPathSegLinetoAbs","SVGPathSegLinetoRel","SVGPathSegCurvetoCubicAbs","x1","y1","x2","y2","_x1","_y1","_x2","_y2","SVGPathSegCurvetoCubicRel","SVGPathSegCurvetoQuadraticAbs","SVGPathSegCurvetoQuadraticRel","SVGPathSegArcAbs","r1","r2","angle","largeArcFlag","sweepFlag","_r1","_r2","_angle","_largeArcFlag","_sweepFlag","SVGPathSegArcRel","SVGPathSegLinetoHorizontalAbs","defineProperty","SVGPathSegLinetoHorizontalRel","SVGPathSegLinetoVerticalAbs","SVGPathSegLinetoVerticalRel","SVGPathSegCurvetoCubicSmoothAbs","SVGPathSegCurvetoCubicSmoothRel","SVGPathSegCurvetoQuadraticSmoothAbs","SVGPathSegCurvetoQuadraticSmoothRel","SVGPathElement","createSVGPathSegClosePath","createSVGPathSegMovetoAbs","createSVGPathSegMovetoRel","createSVGPathSegLinetoAbs","createSVGPathSegLinetoRel","createSVGPathSegCurvetoCubicAbs","createSVGPathSegCurvetoCubicRel","createSVGPathSegCurvetoQuadraticAbs","createSVGPathSegCurvetoQuadraticRel","createSVGPathSegArcAbs","createSVGPathSegArcRel","createSVGPathSegLinetoHorizontalAbs","createSVGPathSegLinetoHorizontalRel","createSVGPathSegLinetoVerticalAbs","createSVGPathSegLinetoVerticalRel","createSVGPathSegCurvetoCubicSmoothAbs","createSVGPathSegCurvetoCubicSmoothRel","createSVGPathSegCurvetoQuadraticSmoothAbs","createSVGPathSegCurvetoQuadraticSmoothRel","getPathSegAtLength","distance","isFinite","Error","measurementElement","createElementNS","setAttribute","getAttribute","lastPathSegment","pathSegList","numberOfItems","removeItem","getTotalLength","SVGPathSegList","pathElement","_pathElement","_list","_parsePath","_mutationObserverConfig","attributes","attributeFilter","_pathElementMutationObserver","MutationObserver","_updateListFromPathMutations","bind","observe","takeRecords","mutationRecords","hasPathMutations","record","attributeName","disconnect","_pathSegArrayAsString","pathSeg","_writeListToPath","_checkPathSynchronizedToList","newItem","index","isNaN","_checkValidIndex","clone","splice","item","push","string","Builder","Source","_string","_currentIndex","_endIndex","_previousCommand","_skipOptionalSpaces","character","_isCurrentSpace","charAt","lookahead","_pathSegTypeFromChar","previousCommand","hasMoreData","command","peekSegmentType","exponent","integer","frac","decimal","sign","expsign","startIndex","startIntPartIndex","scanIntPartIndex","multiplier","number","_skipOptionalSpacesOrDelimiter","flag","flagChar","_nextCommandHelper","_parseNumber","points","arcAngle","arcLarge","_parseArcFlag","arcSweep","builder","source","initialCommandIsMoveTo","parseSegment","appendSegment","pathSegArray","_asPathString","_pathSegList","normalizedPathSegList","animatedPathSegList","animatedNormalizedPathSegList","rect","$","jQuery","userAgent","Boolean","createSVGRect","navigator","svg","isOpera_","opera","isWebkit_","includes","isGecko_","isIE_","isChrome_","isMac_","isTouch_","supportsSelectors_","querySelector","supportsXpath_","evaluate","supportsPathReplaceItem_","path","seglist","seg","replaceItem","err","supportsPathInsertItemBefore_","insertItemBefore","supportsGoodTextCharPos_","svgroot","svgcontent","documentElement","append","text","textContent","getStartPositionOfChar","remove","supportsPathBBox_","bbox","getBBox","height","supportsHVLineContainerBBox_","path2","g","width","supportsNonScalingStroke_","retValue","cloneNode","alert","style","vectorEffect","supportsNativeSVGTransformLists_","rxform","transform","baseVal","t1","createSVGTransform","appendItem","getItem","isSVGTransform","o","_typeof","setMatrix","matrix","a","b","c","d","e","f","isWebkit","isGecko","isIE","isChrome","isMac","isTouch","supportsNonScalingStroke","jQueryPluginSVG","proxied","fn","attr","key","value","len","call","i","elem","namespaceURI","Array","isArray","obj","j","aname","val","transformToString","xform","m","join","cx","cy","K","elementContainer_","listMap_","SVGTransformList","_elem","_xforms","_update","tstr","_init","str","re","match","replace","bits","split","valBits","valArr","letters","mtx","createSVGMatrix","values","parseFloat","fname","toUpperCase","slice","_this","_removeFromOtherLists","some","tl","code","newxforms","removeElementFromListMap","id","getTransformList","t","gradientTransform","patternTransform","wAttrs","hAttrs","unitAttrs","typeMap_","getTypeMap","shortFloat","digits","getRoundDigits","toFixed","Number","convertUnit","unit","getBaseUnit","setUnitAttr","convertToNum","substr","num","getWidth","getHeight","Math","sqrt","isValidUnit","selectedElement","keys","RegExp","test","result","getElement","isNullish","HistoryEventTypes","BEFORE_APPLY","AFTER_APPLY","BEFORE_UNAPPLY","AFTER_UNAPPLY","Command","MoveElementCommand","oldNextSibling","oldParent","tagName","newNextSibling","nextSibling","newParent","parentNode","handler","handleHistoryEvent","insertBefore","InsertElementCommand","parent","_this2","removeChild","RemoveElementCommand","console","log","ChangeElementCommand","attrs","newValues","oldValues","getHref","bChangedTransform","_this5","setHref","removeAttribute","getRotationAngle","rotate","_this6","BatchCommand","stack","apply","unapply","elems","cmd","thisElems","elements","newcx","newcy","oldcx","oldcy","UndoManager","historyEventHandler","handler_","undoStackPointer","undoStack","undoChangeStackPointer","undoableChangeStack","getText","attrName","p","changeset","batchCmd","changes","addSubCommand","transformPoint","isIdentity","matrixMultiply","args","reduceRight","prev","m1","multiply","abs","hasMatrixTransform","tlist","transformBox","l","w","h","tr","bl","br","minx","min","maxx","max","miny","aabox","transformListToTransform","createSVGTransformFromMatrix","parseInt","temp","mtom","getMatrix","snapToAngle","snap","PI","dx","dy","atan2","dist","snapangle","round","cos","sin","rectsIntersect","segData","uiStrings","setUiStrings","strs","assign","ui","pathFuncs","linkControlPts","pathData","editorContext_","init","editorContext","each","s","newseg","list","arr","curSeg","clear","ptObjToArr","segItem","map","prop","getGripPt","altPt","pth","out","currentZoom","getCurrentZoom","getPointFromGrip","pt","imatrix","addPointGrip","pointGripContainer","getGripContainer","pointGrip","getElem","atts","display","r","fill","stroke","cursor","pathNodeTooltip","assignAttributes","appendChild","dblclick","setSegType","addCtrlGrip","pathCtrlPtTooltip","getCtrlLine","ctrlLine","getControlPoints","cpt","segItems","segs","gpt","replacePathSeg","pts","segList","getSegSelector","update","segLine","point","smoothControlPoints","ct1","ct2","nct1","getSVGRoot","createSVGPoint","nct2","anglea","angleb","newAnglea","newAngleb","angleBetween","angleDiff","Segment","selected","ctrlpts","ptgrip","segsel","hasOwnProperty","showCtrlPts","selectCtrls","getPointGrip","full","curPts","next","nextPts","mate","itm","anum","newType","Path","selected_pts","find","first_seg","segment","startI","nextSeg","prevSeg","startSeg","addGrip","newX","newY","p0x","p1x","p2x","p01x","p12x","p0y","p1y","p2y","p01y","p12y","show","pos","indexOf","select","eachSeg","last_d","selectPt","move","moveCtrl","dragctrl","setLinked","storeD","selPt","cur","curX","curY","prevX","prevY","olditem","old","diffX","diffY","setType","endChanges","ctrlNum","clearSelection","addPtsToSelection","inverse","resetD","indexes","sort","grips","closedSubpath","subpathIsClosed","clsd","getPath_","removePath_","getRotVals","theta","recalcRotatedPath","currentPath","oldbox","oldbbox","box","rvals","cVals1","cVals2","Rnc","setRotate","pathMap","convertPath","toRel","curx","cury","lastM","letter","pathDSegment","morePoints","lastPoint","pnt","newPoint","firstCtrl","subpath","hasMoved","pathActions","mouseDown","evt","mouseTarget","startX","startY","getCurrentMode","curPt","cur_pt","dragging","removePtFromSelection","startsWith","parts","rubberBox","getRubberBox","setRubberBox","selectorManager","getRubberBandBox","mouseX","mouseY","stretchy","getGridSnapping","snapToGrid","drawnPath","getDrawnPath","FUZZ","clickOnPoint","px","py","getId","sSeg","newpath","absX","absY","endseg","setDrawnPath","setStarted","remapElement","newD","origD","toEditMode","contains","getContainer","getMouseTarget","last","lastx","lasty","xya","dAttr","addSVGElementFromJson","element","curStyles","getNextId","opacity","getOpacity","mouseMove","mpt","movePts","rbb","ptBb","sel","pointGrip1","pointGrip2","ptX","ptY","altX","altY","lastX","lastY","mouseUp","keep","lastPt","toSelectMode","setCurrentMode","utilsGetBBox","selPath","addToSelection","addSubPath","on","reorient","getSelectedElements","resetOrientation","addCommandToHistory","nodeName","n","bb","attrVal","grad","getRefElem","pt1","pt2","gCoords","newgrad","findDefs","reorientGrads","zoomChange","getNodePoint","linkControlPoints","linkPoints","clonePathNode","selPts","nums","addSeg","opencloseSubPath","zSeg","openPt","startItem","closer","deletePathNode","canDeleteNodes","deleteSeg","cleanup","remItems","count","nprev","prevType","canvas","deleteSelectedElements","cp","smoothPolylineIntoPath","N","curpos","prevCtlPt","end","newpts","prevArr","v","moveNode","newValue","diff","fixEnd","KEYSTR","visElemsArr","domdoc_","domcontainer_","svgroot_","dropXMLInternalSubset","toXml","encode64","input","encodeUTF8","btoa","output","floor","chr1","charCodeAt","chr2","chr3","enc1","enc2","enc3","enc4","decode64","atob","decodeUTF8","String","fromCharCode","argString","decodeURIComponent","escape","unescape","encodeURIComponent","dataURLToObjectURL","dataurl","Uint8Array","Blob","URL","createObjectURL","mime","bstr","u8arr","blob","blankPageObjectURL","text2xml","sXML","dXML","DOMParser","ActiveXObject","async","loadXML","parseFromString","e2","walkTree","cbFn","nodeType","childNodes","getUrlFromAttr","substring","getAttributeNS","setAttributeNS","svgElement","getSVGContent","defs","getElementsByTagNameNS","ownerDocument","firstChild","getPathBBox","tot","bounds","start","P0","getCalc","P1","P2","P3","calc","b2ac","t2","groupBBFix","ret","copy","ref","data","matched","children","filter","issue","getStrokedBBox","geSelectedElements","elname","extent","getExtentOfChar","getComputedTextLength","fo","closest","getPathDFromSegments","pathSegments","singleChar","getPathDFromElement","rx","ry","getExtraAttributesForConvertToPath","getBBoxOfElementAsPath","eltrans","before","getBBoxWithTransform","getRotationAngleFromTransformList","hasMatrixXForm","goodBb","hasAMatrixTransform","angleModulo90","bBoxCanBeOptimizedOverNativeGetBBox","getStrokeOffsetForBBox","sw","fullBb","maxX","maxY","minX","minY","offset","curBb","getVisibleElements","parentElement","contentElems","reverse","getStrokedBBoxDefaultVisible","toRad","singleNodeValue","suspendLength","unitCheck","ns","removeAttributeNS","cleanupElement","defaults","stepSize","getSnappingStep","preventClickDefault","img","click","contextMenuExtensions","injectExtendedContextMenuItemsIntoDom","menuItem","shortcut","label","injectExtendedContextMenuItemIntoDom","toAbsoluteURL","url","createElement","href","addScriptAtts","script","importSetGlobalDefault","config","importSetGlobal","returnDefault","glob","global","svgEditor","modules","importModule","importScript","Promise","all","u","resolve","reject","scriptOnError","destructor","scriptOnLoad","removeEventListener","src","defer","head","vector","random","toString","revokeObjectURL","absURL","loader","coerce_types","jQueryPluginDBox","strings","ok","cancel","draggable","containment","css","btnHolder","dialogContent","dbox","msg","defaultVal","opts","changeListener","checkbox","html","toggleClass","empty","appendTo","ctrl","chkbx","hide","prependTo","div","tooltip","checked","opt","response","focus","confirm","process_cancel","prompt","defaultText","txt","Layer","group","svgElem","name_","group_","svgdoc","layerTitle","after","addLayerClass","visible","expected","child","hrService","previousName","title","getTitleElement","changeElement","classes","CLASS_NAME","CLASS_REGEX","HistoryRecordingService","undoManager","undoManager_","currentBatchCommand_","batchCommandStack_","batchCommand","pop","addCommand_","NO_HISTORY","visElems","RandomizeModes","randIds","disabledElems","historyRecordingService","canvas_","undoMgr","findLayerNameInGroup","querySelectorAll","getNewLayerName","existingLayerNames","Drawing","optIdPrefix","svgElem_","obj_num","idPrefix","releasedNums","all_layers","layer_map","current_layer","nonce_","setNonce","oldObjNum","restoreOldObjNum","getElem_","front","getNumLayers","getName","getGroup","layer","finalName","oldName","setName","newpos","oldpos","layerCount","currentGroup","refGroup","identifyLayers","setCurrentLayer","getLayerName","prevGroup","startBatchCommand","layerNextSibling","removeElement","localName","moveElement","removeGroup","endBatchCommand","mergeLayer","deactivate","activate","oldLayerGroup","numchildren","orphans","layernames","childgroups","appendChildren","insertElement","copyElem","layerName","isVisible","bVisible","setVisible","setOpacity","el","that","newEl","fixedD","nodeValue","utilCopyElem","randomizeIds","enableRandomization","currentDrawing","getNonce","clearNonce","leaveContext","getCurrentDrawing","createLayer","newLayer","cloneLayer","deleteCurrentLayer","currentLayer","getCurrentLayer","renameCurrentLayer","newName","drawing","setCurrentLayerName","setCurrentLayerPosition","newPos","setLayerVisibility","prevVisibility","getLayerVisibility","oldDisplay","moveSelectedToLayer","getLayerByName","selElems","oldLayer","changeSVGContent","mergeAllLayers","orig","elData","setCurrentGroup","setContext","parentsUntil","andSelf","siblings","opac","getCurrentGroup","REVERSE_NS","svgWhiteList_","circle","clipPath","desc","ellipse","feGaussianBlur","feMorphology","foreignObject","image","line","linearGradient","marker","mask","metadata","pattern","polygon","polyline","radialGradient","stop","symbol","textPath","tspan","use","annotation","maction","math","menclose","merror","mfrac","mi","mmultiscripts","mn","mo","mover","mpadded","mphantom","mprescripts","mroot","mrow","mspace","msqrt","mstyle","msub","msubsup","msup","mtable","mtd","mtext","mtr","munder","munderover","none","semantics","svgWhiteListNS_","elt","attNS","att","context_","svgFactory_","config_","selectorManager_","sanitizeSvg","node","doc","allowedAttrs","allowedAttrsNS","seAttrs","attrLocalName","attrNsURI","props","styleAttrName","trim","styleAttrVal","hasChildNodes","remap","scalew","scaleh","doSnapping","finishUp","getDrawing","elName","chlist","mt","existing","tNew","tbox","gsvg","pstr","firstseg","currentpt","dstr","updateClipPath","tx","ty","cpXform","newxlate","setTranslate","recalculateDimensions","k","noi","mxs","mNew","oldcenter","newcenter","initial","extend","getStartTransform","gangle","rm","firstM","oldStartTransform","operation","tm","sm","tmn","childTlist","setStartTransform","e2t","t2n","s2","translateOrigin","scale","translateBack","setScale","T_M","mInv","M2","clipPathsDone","uses","useElem","usexlate","newRot","em","e2m","avg","roldt","rold","rnew","rnewInv","extrat","paint","gtlist","gmatrix","mStr","oldxlate","meq","meqInv","tspanChanges","gripRadius","Selector","locked","selectorGroup","createSVGElement","selectorRect","gripCoords","nw","ne","se","reset","resize","bShow","selectorGripsGroup","hasGrips","updateGripCursors","selectedBox","mgr","selectedGrips","selectorGrips","strokedBbox","nbox","nbax","nbay","nbaw","nbah","rot","svgRoot","rotm","maxy","dir","coords","rotateGripConnector","rotateGrip","dirArr","steps","shift","gripElement","SelectorManager","selectorParentGroup","rubberBandBox","selectors","selectorMap","initGroup","grip","imgPath","dimensions","canvasbg","overflow","svgContent","showGrips","hstry","postError","SvgCanvas","container","curConfig","show_outside_canvas","selectNew","importNode","clearSvgContentElement","xmlns","comment","createComment","idprefix","setIdPrefix","current_drawing_","draw","allProperties","shape","initFill","color","fill_paint","fill_opacity","initStroke","stroke_paint","stroke_opacity","stroke_width","stroke_dasharray","stroke_linejoin","stroke_linecap","initOpacity","font_size","font_family","curShape","selectedElements","getJsonFromSvgElement","retval","createTextNode","namespace","baseUnit","elementContainer","body","inch","ex","cm","mm","pc","unitsInit","saveOptions","round_digits","getSelectedElems","pathModule","getDOMDocument","getDOMContainer","snappingStep","gridSnapping","coordsInit","recalculateInit","startTransform","nsMap","eventType","EventTypes","cmdType","isApply","restoreRefElems","setUseData","stdDeviation","setBlurOffsets","getZoom","svgFactory","selectInit","jsonMap","arg","events","noCall","releaseSelector","elemsToAdd","requestSelector","compareDocumentPosition","correspondingUseElement","started","rb","closed_subpath","currentMode","dp","refAttrs","opacAni","begin","dur","removedElements","childs","getElementsByTagName","encodableImages","importIds","curText","extensions","lastGoodImgUrl","currentResizeMode","curProperties","justSelected","curBBoxes","lastClickPoint","runExtension","action","vars","runExtensions","returnArray","nameFilter","ext","addExtension","extInitFunc","jq","importLocale","TypeError","argObj","getPrivateMethods","nonce","extObj","getIntersectionList","rubberBBox","resultList","getVisibleElementsAndBBoxes","groupSvgElem","replaceWith","prepareSvg","newDoc","ffClone","setRotationAngle","preventUndo","oldTransform","center","newTransform","changeSelectedAttribute","recalculateAllSelectedDimensions","isEmpty","logMatrix","rootSctm","selectOnly","removeFromSelection","elemsToRemove","newSelectedItems","selectAllInCurrentLayer","parameter","freehand","rStartX","rStartY","initBbox","sumDistance","controllPoint2","controllPoint1","bSpline","nextPos","getBsplinePoint","spline","p0","p1","p2","p3","t3","mousedown","spaceKey","rightClick","cloneSelectedElements","getScreenCTM","pageX","pageY","realX","realY","griptype","slist","delayedStroke","iswebkit","ele","stroke_","setTimeout","newImage","strokeW","textActions","beginUndoableChange","extResult","event","start_x","start_y","mousemove","newList","intElem","foundInd","hasMatrix","left","top","sy","sx","square","rad","STEP_COUNT","mouse_x","mouse_y","pushGroupProperties","mouseup","tempJustSelected","factor","commaIndex","res","finishUndoableChange","addedNew","cAni","aniDur","beginElement","to","releaseId","setMode","originalEvent","workarea","rulerwidth","showRulers","editorFullW","editorFullH","editorW","editorH","workareaViewW","workareaViewH","wOffset","wOffsetLeft","wOffsetTop","delta","wheelDelta","wZoom","hZoom","ceil","zoomlevel","topLeftOld","newCtr","setZoom","canvg","curtext","textinput","selblock","blinker","textbb","allowDbl","chardata","setCursor","arguments","selectionEnd","selectionStart","charbb","setSelectionRange","setInterval","startPt","ptToScreen","endPt","visibility","setSelection","skipInput","startbb","endbb","getIndexFromPoint","charpos","getCharNumAtPosition","setCursorFromPoint","setEndSelectionFromPoint","i1","i2","screenToPt","xIn","yIn","selectAll","unbind","selectWord","ept","selectElem","clearInterval","blur","setInputElem","inputElem","getEndPositionOfChar","contentW","removeUnusedDefElems","defelemUses","numRemoved","alen","allEls","allLen","defelems","defelem","getIssues","issues","issueCodes","issueList","exportNoBlur","exportNoforeignObject","exportNoDashArray","content","getContext","exportNoText","descr","svgCanvasToString","nakedSvgs","svgToString","indent","unitRe","getResolution","nsuris","uri","attrNames","mozAttrs","styleName","images","bOneLine","embedImage","Image","load","status","xhr","cvs","drawImage","urldata","toDataURL","statusText","setGoodImage","open","save","rasterExport","imgType","quality","exportWindowName","mimeType","canvgPath","contentH","bloburl","dataURLType","datauri","done","avoidEvent","toBlob","exportPDF","outputType","jsPDF","modularVersion","jspdfPath","orientation","format","docTitle","getDocumentTitle","setProperties","addSVG","getSvgString","uniquifyElems","ids","refElems","oldid","hrefs","attrnode","getAttributeNode","refid","newid","ownerElement","hreffers","hreffer","refElem","convertGradients","fillStrokeElems","convertToGroup","ts","$elem","unwrap","removeData","vb","hasMore","dupeGrads","walkTreePost","setSvgString","xmlString","firstElementChild","oldzoom","adoptNode","pa","percs","dim","importSvgString","useEl","uid","useExisting","parents","innerw","innerh","innervb","canvash","dr","propVal","cg","resetUndoStack","getContentElem","getRootElem","zoom","getSnapToGrid","getVersion","notification","common","setConfig","getTitle","setGroupTitle","prepend","tsNextSibling","setDocumentTitle","newTitle","oldTitle","getEditorNS","add","setResolution","visEls","moveSelectedElements","viewBox","getOffset","setBBoxZoom","spacer","calcZoom","newzoom","selectedElems","zoomLevel","getMode","getColor","setColor","addNonG","changeSelectedAttributeNoUndo","setGradient","duplicateGrad","findDuplicateGradient","existingGrads","radAttrs","og","gradAttrs","ogAttrs","stops","ostops","ostop","setPaint","jGraduate","Paint","setPaintOpacity","alpha","solidColor","setStrokePaint","setFillPaint","getStrokeWidth","setStrokeWidth","setStrokeAttr","getStyle","getFillOpacity","getStrokeOpacity","getPaintOpacity","getBlur","curCommand","filterHidden","finishChange","bCmd","setBlurNoUndo","setBlur","filterElem","stdDev","complete","elemId","newblur","getBold","setBold","getItalic","setItalic","getFontFamily","setFontFamily","setFontColor","getFontColor","getFontSize","setFontSize","setTextContent","setImageURL","setsize","curHref","setLinkURL","parentsA","setRectRadius","makeHyperlink","groupSelectedElements","removeHyperlink","ungroupSelectedElement","convertToPath","noXYElems","oldval","newrot","selectedCopy","cutSelectedElements","copySelectedElements","CLIPBOARD_ID","flashStorage","sessionStorage","localStorage","setItem","JSON","stringify","menu","enableContextMenuItems","pasteElements","clipb","parse","pasted","changedIDs","checkIDs","extChanges","removeID","clipBoardItem","ctrX","ctrY","urlArg","cmdStr","undoable","gfilter","gblur","glist","gattrs","newOpac","cblur","origCblur","suffix","chtlist","rgm","rcm","cangle","cbox","ceqm","coldc","sangle","trm","oldxform","newxform","chm","chmInv","gm","anchor","gNextSibling","moveToTopSelectedElement","moveToBottomSelectedElement","moveUpDownSelected","foundCur","toArray","constructor","copiedElements","alignSelectedElements","relativeTo","bboxes","MAX_VALUE","MIN_VALUE","curwidth","curheight","updateCanvas","bg","oldX","oldY","bgImg","new_x","new_y","old_x","old_y","d_x","d_y","setBackground","border","bgPattern","preserveAspectRatio","cycleElement","curElem","allElems","SVGEditTransformList","isOpera","fixIDs","svgEl","svgNum","force","idElems","newId","oldVal","newVal","toFixedNumeric","precision","langParam","editor_","setStrings","readLang","langData","addLangData","more","merge","tools","properties","layers","curve_segments","fitToContent","fit_to_all","fit_to_canvas","fit_to_layer_content","fit_to_sel","icon_large","icon_medium","icon_small","icon_xlarge","image_opt_embed","image_opt_ref","includedImages","included_images","largest_object","layersLabel","page","relativeToLabel","selLayerLabel","move_elems_to","selectedPredefined","select_predefined","selected_objects","smallest_object","straight_segments","svginfo_bg_url","editor_img_url","svginfo_bg_note","editor_bg_note","svginfo_change_background","background","svginfo_dim","doc_dims","svginfo_editor_prefs","editor_prefs","svginfo_height","svginfo_icons","icon_size","svginfo_image_props","image_props","svginfo_lang","language","svginfo_title","doc_title","svginfo_width","tool_docprops_cancel","tool_docprops_save","tool_source_cancel","tool_source_save","tool_prefs_cancel","tool_prefs_save","sidepanel_handle","tool_clear","new_doc","tool_docprops","docprops","tool_export","export_img","tool_import","import_doc","tool_open","open_doc","tool_save","save_doc","tool_editor_prefs","tool_editor_homepage","editor_homepage","svginfo_units_rulers","units_and_rulers","svginfo_rulers_onoff","show_rulers","svginfo_unit","base_unit","svginfo_grid_settings","grid","svginfo_snap_onoff","snapping_onoff","svginfo_snap_step","snapping_stepsize","svginfo_grid_color","grid_color","del","ariaLabels","tool_blur","tool_position","align_to_page","tool_font_family","zoom_panel","zoom_level","linejoin_miter","linecap_butt","tool_opacity","group_opacity","align_relative_to","circle_cx","circle_cy","circle_r","cornerRadiusLabel","corner_radius","ellipse_cx","ellipse_cy","ellipse_rx","ellipse_ry","fill_color","idLabel","image_height","image_url","image_width","layer_delete","layer_down","move_down","layer_new","layer_rename","rename","layer_moreopts","more_opts","layer_up","move_up","line_x1","line_x2","line_y1","line_y2","linecap_round","linecap_square","linejoin_bevel","linejoin_round","main_icon","main_menu","palette","palette_info","path_node_x","node_x","path_node_y","node_y","rect_height_tool","rect_height","rect_width_tool","rect_width","seg_type","selLayerNames","move_selected","selected_x","pos_x","selected_y","pos_y","stroke_color","stroke_style","text_contents","toggle_stroke_tools","tool_add_subpath","add_subpath","tool_alignbottom","align_bottom","tool_aligncenter","align_center","tool_alignleft","align_left","tool_alignmiddle","align_middle","tool_alignright","align_right","tool_aligntop","align_top","tool_angle","tool_bold","bold","tool_circle","mode_circle","tool_clone","tool_clone_multi","tool_delete","tool_delete_multi","tool_ellipse","mode_ellipse","tool_fhellipse","mode_fhellipse","tool_fhpath","mode_fhpath","tool_fhrect","mode_fhrect","tool_font_size","tool_group_elements","group_elements","tool_make_link","make_link","tool_link_url","set_link_url","tool_image","mode_image","tool_italic","italic","tool_line","mode_line","tool_move_bottom","move_bottom","tool_move_top","move_top","tool_node_clone","node_clone","tool_node_delete","node_delete","tool_node_link","node_link","tool_openclose_path","openclose_path","tool_path","mode_path","tool_rect","mode_rect","tool_redo","redo","tool_reorient","reorient_path","tool_select","mode_select","tool_source","source_save","tool_square","mode_square","tool_text","mode_text","tool_topath","to_path","tool_undo","undo","tool_ungroup","ungroup","tool_wireframe","wireframe_mode","tool_zoom","mode_zoom","url_notice","no_embed","putLocale","givenParam","goodLangs","conf","userLanguage","langPath","_slicedToArray","_arrayWithHoles","Symbol","iterator","_arr","_n","_d","_e","_s","_i","_iterableToArrayLimit","_nonIterableRest","loadStylesheets","stylesheets","_ref","beforeDefault","afterDefault","faviconDefault","favicon","canvasDefault","_ref$image","imageDefault","acceptErrors","setupLink","stylesheetURL","options","_stylesheetURL2","_stylesheetURL2$","_options$favicon","_options2","_options2$before","_options2$after","_options2$canvas","_options2$image","addLink","link","rej","error","endsWith","rel","cnv","context","editor","which","hotkeys","specialKeys","shiftNums","version","special","svgIcons","file","testImg","dataEl","holder","svgns","xlinkns","iconW","iconH","iconsMade","dataLoaded","loadAttempts","dataPre","svgz","contentDocument","getIcons","err1","useFallback","parser","ajax","dataType","success","responseText","noWait","isReady","getElementById","no_img","makeIcons","testSrc","alt","testIconAlt","setIcon","icon","setID","cl","alts","removeAttr","addIcon","id_match","toImage","fallback","tempHolder","fallback_path","imgsrc","XMLSerializer","serializeToString","placement","resizeSvgIcons","callback","regFile","getSvgIcon","uniqueClone","changeSel","size","widget","loadingStylesheets","jGraduateDefaults","pickerTitle","clientPath","newstop","mkElem","newparent","setAttrs","okCallback","cancelCallback","$this","$settings","idref","okClicked","cancelClicked","$win","addClass","colPicker","gradPicker","attrInput","stopGroup","curType","curGradient","gradalpha","isSolid","mkStop","inverted","inv","showFocus","fx","fy","previewRect","MAX","beginCoord","endCoord","centerCoord","focusCoord","isRadial","attrval","change","cssName","curStop","drag","stopOffset","stopMakerDiv","delStop","scaleX","scaleY","cX","cY","stopMakerSVG","transPattern","patternUnits","transImg","bgImage","stopPropagation","mouseover","lastfx","lastfy","slider","spreadMethodOpt","draggingCoord","onCoordDrag","fracx","fracy","grd","onCoordUp","numstops","toggle","fX","fY","ellipVal","angleVal","sliders","radius","handle","ellip","dragSlider","stopSlider","isRad","xpos","SLIDERW","posx","setSlider","thisAlpha","jPicker","alphaSupport","effects","speed","active","clr","tab","tabs","removeClass","newGrad","curStops","colr","stopElem","pickerD","pathbg","selectStop","dragColor","remDrags","colorhandle","stopOpacity","stopColor","bottom","arg2","curS","newcolor","newopac","remStop","xfStr","sX","SpinButton","cfg","coord","offsetParent","browser","msie","currentStyle","position","repeating","spinCfg","step","stepfunc","upClass","downClass","delay","interval","_btn_width","_direction","_delay","_repeat","smallStep","adjustValue","spinClass","stateObj","tool_scale","direction","offsetWidth","mouseout","clearTimeout","adjust","keydown","keyCode","keypress","keyup","win","contextMenu","listener","inSpeed","outSpeed","srcElement","allowLeft","hasClass","xOff","yOff","fadeIn","prevAll","eq","nextAll","trigger","docX","docY","fadeOut","mozilla","MozUserSelect","disableContextMenuItems","disableContextMenu","enableContextMenu","destroyContextMenu","Slider","bar","fireChangeEvents","changeEvents","changeEvent","off","timeout","setValuesFromMousePosition","barW","barH","locX","locY","rangeX","rangeY","changed","arrow","range","newMinX","newMaxX","newMinY","newMaxY","destroy","arrowW","arrowH","arrowOffsetX","arrowOffsetY","ColorValuePicker","picker","bindedHex","alphaPrecision","inputs","keyDown","hex","validateKey","red","setValueInRange","green","blue","hue","saturation","keyUp","ahex","colorChanged","List","Color","ColorMethods","rgbaToHex","nameLength","ch","hexToRgba","newV","rgb","hsv","rgbToHsv","hsvToRgb","intToHex","validateHex","hexToInt","rgba","dec","q","commitCallback","liveCallback","settings","bindToInput","expandable","current","liveUpdate","isLessThanIE7","appVersion","filters","setColorMode","colorMode","rgbMap","rgbBar","mode","setBG","colorMapDiv","setImgLoc","colorMapL1","setAlpha","colorMapL2","colorBarDiv","colorBarL1","colorBarL2","colorBarL3","colorBarL4","colorBarL6","colorMap","colorBar","activeColorChanged","positionMapAndBarArrows","updatePreview","updateMapVisuals","updateBarVisuals","mapValueChanged","xy","colorBarValueChanged","sv","hv","hs","rg","activePreview","backgroundColor","colorMapL3","colorBarL5","hva","saturatedColor","hsa","valueColor","hValue","vValue","middle","setImg","backgroundImage","revertColor","commitColor","radioClicked","currentClicked","cancelButton","okButton","iconImageClicked","currentColorChanged","currentPreview","expandableColorChanged","va","iconColor","iconAlpha","updateInputColor","moveBarMouseDown","elementStartX","elementStartY","pageStartX","pageStartY","documentMouseMove","documentMouseUp","support","boxModel","quickPickClicked","attachIFrame","table","zIndex","slideDown","removeIFrame","slideUp","initialize","popup","onselectstart","controlHtml","localization","newColor","tooltips","colors","currentColor","buttons","radio","textbox","tbody","MapMaps","BarMaps","colorPicker","preview","quickList","quickHex","iconImage","moveBar","reduce","func","exportWindowCt","langChanged","showSaveWarning","storagePromptState","svgCanvas","callbacks","defaultPrefs","lang","iconsize","bkgd_color","bkgd_url","img_save","save_notice_done","export_notice_done","defaultExtensions","defaultConfig","canvasName","canvas_expansion","colorPickerCSS","initTool","exportWindowType","wireframe","showlayers","no_save_warning","extPath","jGraduatePath","extIconsPath","gridColor","preventAllURLConfig","preventURLContentLoading","lockExtensions","noDefaultExtensions","showGrid","noStorageOnLoad","forceStorage","emptyStorageOnDecline","avoidClientSide","avoidClientSideDownload","avoidClientSideOpen","customExportImage","customExportPDF","curPrefs","allowedOrigins","loadSvgString","noAlert","errorLoadingSVG","getImportLocale","defaultLang","defaultName","pref","mayBeEmpty","loadContentAndPrefs","cookie","storage","cached","loadFromString","storeKey","preferenceForKey","cfgCfg","extendOrAdd","cfgObj","overwrite","allowInitialUserOverride","concat","setCustomHandlers","ready","exportImage","setupCurConfig","grep","params","coerce","location","search","searchParams","param","keys_last","has","pathConfig","loadFromDataURI","loadFromURL","iconId","forcedSize","extAndLocaleFunc","setLang","logo","select_node","fh_rect","fh_ellipse","pencil","pen","close_path","open_path","arrow_right","arrow_right_big","arrow_down","new_image","go_up","go_down","context_menu","link_controls","unlink_use","c_radius","fontsize","align","eye","no_color","warning","globe_link","icons","getStylesheetPriority","stylesheetFile","Infinity","tleft","minHeight","outerHeight","setIconSize","shower","priorityA","priorityB","Set","idx","runCallbacks","extname","extName","imported","extensionsAdded","Actions","setAll","messageQueue","messageObj","setFlyoutPositions","outerWidth","uaPrefix","regex","someScript","selToscale","xl","hiddenPs","sides","Utils","scaleElements","cssResizeRules","ruleElem","styleStr","selector","rules","prefix","resizeTimer","curScrollPos","modKey","canvMenu","paintBox","exportWindow","defaultImageURL","zoomInIcon","zoomOutIcon","uiContext","opener","svgEditorReadyEvent","CustomEvent","setSelectMode","curr","origTitle","rIntervals","toggleHighlightLayer","layerNameToHighlight","curNames","numLayers","curName","setLayerOpacity","populateLayers","layerlist","currentLayerName","getCurrentLayerName","layerTr","layerVis","row","vis","editingsource","origSource","showSourceEditor","forSaving","multiselected","operaRepaint","setStrokeOpt","changeElem","pre","toolButtonClick","noHiding","clickSelect","dataURI","promptImgURL","cancelDeletes","curhref","enterNewImgURL","updateRulers","scanvas","contentElem","isX","lentype","contentDim","$hcanvOrig","$hcanv","hcanv","rulerLen","totalLen","ctx","ctxArr","ctxArrNum","fillStyle","fillRect","uMulti","rawM","multi","bigInt","font","rulerD","labelPos","ctxNum","curD","moveTo","lineTo","decs","fillText","part","subD","lineNum","strokeStyle","wArea","cnvs","wOrig","hOrig","oldCtr","scrollLeft","scrollTop","oldCanY","oldCanX","newCanY","newCanX","ratio","scrollX","scrollY","scroll","storagePrompt","updateToolButtonState","bNoFill","bNoStroke","buttonsNeedingStroke","buttonsNeedingFillAndStroke","btn","nofill","nostroke","hasEnabled","updateContextPanel","isNode","menuItems","blurval","segType","noPath","panels","linkHref","curPanel","bv","setInputWidth","getUndoStackSize","getRedoStackSize","updateWireFrame","supportsNonSS","rule","curContext","updateTitle","zoomDone","zoomChanged","autoCenter","zInfo","changeZoom","ctl","delegate","prepPaints","prep","flyoutFuncs","setFlyoutTitles","allHolders","setupFlyouts","holders","holdSel","btnOpts","timer","not","showSel","def","idSel","isDefault","flyoutAction","flyoutIsSelected","currentOperation","tool","time","animate","is","makeFlyoutHolder","addAltDropDown","elemSel","listSel","dropUp","seticon","onButton","hover","multiclick","extsPreLang","extAdded","prepResize","resizeDone","cbCalled","langReady","loadedExtensionNames","runCallback","btnSelects","context_tools","contId","container_id","panel","defval","colnum","inp","spindata","svgicons","fallbackObj","altsObj","placementObj","cls","flyoutHolder","showBtn","refData","refBtn","svgicon","tlsId","includeWith","getButtonData","curH","gWidth","swidth","opacPerc","updateToolbar","editmode","togglePathEditMode","ang","isSvgElem","isLayer","wind","download","note","saveFromBrowser","defsFailOnSave","closed","noteTheseIssues","popupWindowBlocked","linkStr","blocks","curBg","changeOpacity","changeBlur","noUndo","panning","keypan","promptMoveLayerOnce","destLayer","selectedIndex","confirmStr","QmoveElemsToLayer","moveToLayer","invalidAttrValGiven","unitData","setPanning","overlay","jsHover","setClick","listItems","addDropDown","perc","slide","noop","unfocus","slideStart","loadingURL","clickFHPath","clickLine","clickSquare","clickRect","clickFHRect","clickCircle","clickEllipse","clickFHEllipse","clickImage","clickZoom","zoomImage","dblclickZoom","clickText","clickPath","deleteSelected","cutSelected","copySelected","pasteInCenter","moveToTopSelected","moveToBottomSelected","reorientPath","enterNewLinkURL","moveSelected","linked","sp","selectNext","selectPrev","rotateSelected","cw","clickClear","QwantToClear","clickBold","clickItalic","clickExport","openExportWindow","popHTML","popURL","loadingImage","chrome","clickOpen","clickImport","clickUndo","clickRedo","clickGroup","clickClone","clickAlign","clickWireframe","wfRules","curClass","allTools","preferences","showDocProperties","showPreferences","canvasBg","blk","isBg","openHomePage","hideSourceEditor","saveSourceEditor","saveChanges","QerrorsRevertToSource","hideDocProperties","hidePreferences","saveDocProperties","noContentToFitTo","savePreferences","resetScrollPos","cancelOverlays","QignoreSourceChanges","winWh","curval","shortcutButtons","pick_stroke_paint_opacity","pick_fill_paint_opacity","PaintBox","docElem","ctr","ptype","fillAttr","_paintColor","_paintOpacity","gPaint","defColor","getPaint","testEl","blurTest","deleteLayer","enterUniqueLayerName","hasLayer","dupeLayerName","moveLayer","total","curIndex","stdDeviationX","featNotSupported","uniqName","enterNewLayerName","layerHasThatName","sidedrag","sidedragging","allowmove","changeSidePanelWidth","rulerX","resizeSidePanel","deltaX","sideWidth","toggleSidePanel","close","dpr","devicePixelRatio","wh","dims","toolButtons","keyAssocs","dialogSelectors","saveOpts","every","hidekey","flyouts","fH","margin","keyval","pd","setTitles","keyStr","modBits","mod","lastChild","itool","preTool","regTool","origVal","sugVal","increasing","handlerKey","getCustomHandler","lmenuFunc","enableOrDisableClipboard","svgeditClipboard","returnValue","unsavedChanges","getUIStrings","openPrep","QwantToOpen","FileReader","importImage","reader","dataTransfer","files","onloadend","newElement","readAsText","imgWidth","imgHeight","naturalWidth","offsetHeight","naturalHeight","readAsDataURL","imgImport","allStrings","oldLayerName","renameLayer","loadedExtensionName","dest","localeInit","protocol","cb","_asyncToGenerator","regeneratorRuntime","disableUI","featList","cache","beforeSend","stat","URLLoadFail","base64","initArgs","origin"],"mappings":"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"}