From 340915be4ef691d2bc5087577956144c495dd436 Mon Sep 17 00:00:00 2001 From: Brett Zamir Date: Wed, 16 May 2018 08:53:27 +0800 Subject: [PATCH] - Linting (ESLint): Finish extensions and most files in editor/; unfinished: `editor/svg-editor.js`, `editor/svgcanvas.js` - Linting (ESLint): Fix ignore file paths - History `elem` fix --- .eslintignore | 13 +- editor/browser.js | 88 +- editor/config-sample.js | 14 +- editor/contextmenu.js | 114 +- editor/coords.js | 527 +- editor/draw.js | 172 +- editor/embedapi-dom.js | 129 +- editor/embedapi.js | 201 +- editor/extensions/ext-arrows.js | 133 +- editor/extensions/ext-closepath.js | 33 +- editor/extensions/ext-connector.js | 620 +- editor/extensions/ext-eyedropper.js | 89 +- editor/extensions/ext-foreignobject.js | 180 +- editor/extensions/ext-grid.js | 65 +- editor/extensions/ext-helloworld.js | 127 +- editor/extensions/ext-imagelib.js | 636 +- editor/extensions/ext-markers.js | 586 +- editor/extensions/ext-mathjax.js | 487 +- editor/extensions/ext-overview_window.js | 206 +- editor/extensions/ext-panning.js | 20 +- editor/extensions/ext-panning.xml | 2 +- editor/extensions/ext-php_savefile.js | 14 +- editor/extensions/ext-polygon.js | 434 +- editor/extensions/ext-server_moinsave.js | 55 +- editor/extensions/ext-server_opensave.js | 154 +- editor/extensions/ext-shapes.js | 252 +- editor/extensions/ext-star.js | 66 +- editor/extensions/ext-storage.js | 54 +- editor/extensions/ext-webappfind.js | 104 +- editor/extensions/ext-xdomain-messaging.js | 11 +- editor/extensions/fileopen.php | 16 +- editor/extensions/filesave.php | 12 +- editor/extensions/imagelib/index.html | 56 +- editor/extensions/imagelib/index.js | 51 + editor/history.js | 222 +- editor/historyrecording.js | 44 +- editor/jquery-svg.js | 115 +- editor/layer.js | 68 +- editor/math.js | 45 +- editor/path.js | 477 +- editor/pathseg.js | 1712 ++-- editor/recalculate.js | 1453 ++- editor/sanitize.js | 417 +- editor/select.js | 176 +- editor/svg-editor.js | 9504 ++++++++++---------- editor/svgcanvas.js | 3053 ++++--- editor/svgedit.js | 10 +- editor/svgtransformlist.js | 127 +- editor/svgutils.js | 846 +- editor/touch.js | 28 +- editor/units.js | 121 +- 51 files changed, 12031 insertions(+), 12108 deletions(-) create mode 100644 editor/extensions/imagelib/index.js diff --git a/.eslintignore b/.eslintignore index 4c9b7d6c..92d1e86d 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,13 +1,14 @@ node_modules +editor/jquery.js editor/jspdf/jspdf.min.js editor/jspdf/underscore-min.js -jgraduate/jpicker.min.js -jgraduate/jquery.jgraduate.js -jquery-ui -jquerybbq -js-hotkeys -spinbtn/JQuerySpinBtn.min.js +editor/jgraduate/jpicker.min.js +editor/jgraduate/jquery.jgraduate.min.js +editor/jquery-ui +editor/jquerybbq +editor/js-hotkeys +editor/spinbtn/JQuerySpinBtn.min.js test/qunit test/sinon wave/json2.js diff --git a/editor/browser.js b/editor/browser.js index dc2cafc4..7ebe82e9 100644 --- a/editor/browser.js +++ b/editor/browser.js @@ -1,5 +1,5 @@ -/*globals $, svgedit*/ -/*jslint vars: true, eqeq: true*/ +/* eslint-disable no-var, eqeqeq */ +/* globals $, svgedit */ /** * Package: svgedit.browser * @@ -12,7 +12,8 @@ // Dependencies: // 1) jQuery (for $.alert()) -(function() {'use strict'; +(function () { +'use strict'; if (!svgedit.browser) { svgedit.browser = {}; @@ -21,12 +22,12 @@ if (!svgedit.browser) { // alias var NS = svgedit.NS; -var supportsSvg_ = (function() { +var supportsSvg_ = (function () { return !!document.createElementNS && !!document.createElementNS(NS.SVG, 'svg').createSVGRect; }()); -svgedit.browser.supportsSvg = function() { return supportsSvg_; }; -if(!svgedit.browser.supportsSvg()) { +svgedit.browser.supportsSvg = function () { return supportsSvg_; }; +if (!svgedit.browser.supportsSvg()) { window.location = 'browser-not-supported.html'; return; } @@ -44,41 +45,41 @@ var isWindows_ = userAgent.indexOf('Windows') >= 0; var isMac_ = userAgent.indexOf('Macintosh') >= 0; var isTouch_ = 'ontouchstart' in window; -var supportsSelectors_ = (function() { +var supportsSelectors_ = (function () { return !!svg.querySelector; }()); -var supportsXpath_ = (function() { +var supportsXpath_ = (function () { return !!document.evaluate; }()); // segList functions (for FF1.5 and 2.0) -var supportsPathReplaceItem_ = (function() { +var supportsPathReplaceItem_ = (function () { var path = document.createElementNS(NS.SVG, 'path'); path.setAttribute('d', 'M0,0 10,10'); var seglist = path.pathSegList; - var seg = path.createSVGPathSegLinetoAbs(5,5); + var seg = path.createSVGPathSegLinetoAbs(5, 5); try { seglist.replaceItem(seg, 1); return true; - } catch(err) {} + } catch (err) {} return false; }()); -var supportsPathInsertItemBefore_ = (function() { +var supportsPathInsertItemBefore_ = (function () { var path = document.createElementNS(NS.SVG, 'path'); path.setAttribute('d', 'M0,0 10,10'); var seglist = path.pathSegList; - var seg = path.createSVGPathSegLinetoAbs(5,5); + var seg = path.createSVGPathSegLinetoAbs(5, 5); try { seglist.insertItemBefore(seg, 1); return true; - } catch(err) {} + } catch (err) {} return false; }()); // text character positioning (for IE9) -var supportsGoodTextCharPos_ = (function() { +var supportsGoodTextCharPos_ = (function () { var svgroot = document.createElementNS(NS.SVG, 'svg'); var svgcontent = document.createElementNS(NS.SVG, 'svg'); document.documentElement.appendChild(svgroot); @@ -92,7 +93,7 @@ var supportsGoodTextCharPos_ = (function() { return (pos === 0); }()); -var supportsPathBBox_ = (function() { +var supportsPathBBox_ = (function () { var svgcontent = document.createElementNS(NS.SVG, 'svg'); document.documentElement.appendChild(svgcontent); var path = document.createElementNS(NS.SVG, 'path'); @@ -104,7 +105,7 @@ var supportsPathBBox_ = (function() { }()); // Support for correct bbox sizing on groups with horizontal/vertical lines -var supportsHVLineContainerBBox_ = (function() { +var supportsHVLineContainerBBox_ = (function () { var svgcontent = document.createElementNS(NS.SVG, 'svg'); document.documentElement.appendChild(svgcontent); var path = document.createElementNS(NS.SVG, 'path'); @@ -121,31 +122,31 @@ var supportsHVLineContainerBBox_ = (function() { return (bbox.width == 15); }()); -var supportsEditableText_ = (function() { +var supportsEditableText_ = (function () { // TODO: Find better way to check support for this return isOpera_; }()); -var supportsGoodDecimals_ = (function() { +var supportsGoodDecimals_ = (function () { // Correct decimals on clone attributes (Opera < 10.5/win/non-en) var rect = document.createElementNS(NS.SVG, 'rect'); rect.setAttribute('x', 0.1); var crect = rect.cloneNode(false); - var retValue = (crect.getAttribute('x').indexOf(',') == -1); - if(!retValue) { - $.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n'+ + var retValue = (crect.getAttribute('x').indexOf(',') === -1); + if (!retValue) { + $.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n' + 'Please upgrade to the latest version in which the problems have been fixed.'); } return retValue; }()); -var supportsNonScalingStroke_ = (function() { +var supportsNonScalingStroke_ = (function () { var rect = document.createElementNS(NS.SVG, 'rect'); rect.setAttribute('style', 'vector-effect:non-scaling-stroke'); return rect.style.vectorEffect === 'non-scaling-stroke'; }()); -var supportsNativeSVGTransformLists_ = (function() { +var supportsNativeSVGTransformLists_ = (function () { var rect = document.createElementNS(NS.SVG, 'rect'); var rxform = rect.transform.baseVal; var t1 = svg.createSVGTransform(); @@ -163,26 +164,25 @@ var supportsNativeSVGTransformLists_ = (function() { // Public API -svgedit.browser.isOpera = function() { return isOpera_; }; -svgedit.browser.isWebkit = function() { return isWebkit_; }; -svgedit.browser.isGecko = function() { return isGecko_; }; -svgedit.browser.isIE = function() { return isIE_; }; -svgedit.browser.isChrome = function() { return isChrome_; }; -svgedit.browser.isWindows = function() { return isWindows_; }; -svgedit.browser.isMac = function() { return isMac_; }; -svgedit.browser.isTouch = function() { return isTouch_; }; +svgedit.browser.isOpera = function () { return isOpera_; }; +svgedit.browser.isWebkit = function () { return isWebkit_; }; +svgedit.browser.isGecko = function () { return isGecko_; }; +svgedit.browser.isIE = function () { return isIE_; }; +svgedit.browser.isChrome = function () { return isChrome_; }; +svgedit.browser.isWindows = function () { return isWindows_; }; +svgedit.browser.isMac = function () { return isMac_; }; +svgedit.browser.isTouch = function () { return isTouch_; }; -svgedit.browser.supportsSelectors = function() { return supportsSelectors_; }; -svgedit.browser.supportsXpath = function() { return supportsXpath_; }; - -svgedit.browser.supportsPathReplaceItem = function() { return supportsPathReplaceItem_; }; -svgedit.browser.supportsPathInsertItemBefore = function() { return supportsPathInsertItemBefore_; }; -svgedit.browser.supportsPathBBox = function() { return supportsPathBBox_; }; -svgedit.browser.supportsHVLineContainerBBox = function() { return supportsHVLineContainerBBox_; }; -svgedit.browser.supportsGoodTextCharPos = function() { return supportsGoodTextCharPos_; }; -svgedit.browser.supportsEditableText = function() { return supportsEditableText_; }; -svgedit.browser.supportsGoodDecimals = function() { return supportsGoodDecimals_; }; -svgedit.browser.supportsNonScalingStroke = function() { return supportsNonScalingStroke_; }; -svgedit.browser.supportsNativeTransformLists = function() { return supportsNativeSVGTransformLists_; }; +svgedit.browser.supportsSelectors = function () { return supportsSelectors_; }; +svgedit.browser.supportsXpath = function () { return supportsXpath_; }; +svgedit.browser.supportsPathReplaceItem = function () { return supportsPathReplaceItem_; }; +svgedit.browser.supportsPathInsertItemBefore = function () { return supportsPathInsertItemBefore_; }; +svgedit.browser.supportsPathBBox = function () { return supportsPathBBox_; }; +svgedit.browser.supportsHVLineContainerBBox = function () { return supportsHVLineContainerBBox_; }; +svgedit.browser.supportsGoodTextCharPos = function () { return supportsGoodTextCharPos_; }; +svgedit.browser.supportsEditableText = function () { return supportsEditableText_; }; +svgedit.browser.supportsGoodDecimals = function () { return supportsGoodDecimals_; }; +svgedit.browser.supportsNonScalingStroke = function () { return supportsNonScalingStroke_; }; +svgedit.browser.supportsNativeTransformLists = function () { return supportsNativeSVGTransformLists_; }; }()); diff --git a/editor/config-sample.js b/editor/config-sample.js index 0336b243..fc8c24f6 100644 --- a/editor/config-sample.js +++ b/editor/config-sample.js @@ -3,7 +3,7 @@ // CREATE A NEW FILE config.js AND ADD CONTENTS // SUCH AS SHOWN BELOW INTO THAT FILE. -/*globals svgEditor*/ +/* globals svgEditor */ /* The config.js file is intended for the setting of configuration or preferences which must run early on; if this is not needed, it is @@ -56,17 +56,17 @@ svgEditor.setConfig({ }); // OTHER CONFIG -svgEditor.setConfig({ +svgEditor.setConfig({ // canvasName: 'default', // canvas_expansion: 3, // initFill: { - // color: 'FF0000', // solid red - // opacity: 1 + // color: 'FF0000', // solid red + // opacity: 1 // }, // initStroke: { - // width: 5, - // color: '000000', // solid black - // opacity: 1 + // width: 5, + // color: '000000', // solid black + // opacity: 1 // }, // initOpacity: 1, // colorPickerCSS: null, diff --git a/editor/contextmenu.js b/editor/contextmenu.js index 9fca31d8..d0c059dc 100644 --- a/editor/contextmenu.js +++ b/editor/contextmenu.js @@ -1,66 +1,66 @@ -/*globals $, svgEditor*/ -/*jslint vars: true, eqeq: true*/ +/* eslint-disable no-var, eqeqeq */ +/* globals $, svgEditor */ /** * Package: svgedit.contextmenu - * + * * Licensed under the Apache License, Version 2 - * + * * Author: Adam Bender */ // Dependencies: // 1) jQuery (for dom injection of context menus) -var svgedit = svgedit || {}; -(function() { - var self = this; - if (!svgedit.contextmenu) { - svgedit.contextmenu = {}; +var svgedit = svgedit || {}; // eslint-disable-line no-use-before-define +(function () { +var self = this; +if (!svgedit.contextmenu) { + svgedit.contextmenu = {}; +} +self.contextMenuExtensions = {}; +var menuItemIsValid = function (menuItem) { + return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action == 'function'; +}; +var addContextMenuItem = function (menuItem) { + // menuItem: {id, label, shortcut, action} + if (!menuItemIsValid(menuItem)) { + console.error('Menu items must be defined and have at least properties: id, label, action, where action must be a function'); + return; } - self.contextMenuExtensions = {}; - var menuItemIsValid = function(menuItem) { - return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action == 'function'; - }; - var addContextMenuItem = function(menuItem) { - // menuItem: {id, label, shortcut, action} - if (!menuItemIsValid(menuItem)) { - console.error("Menu items must be defined and have at least properties: id, label, action, where action must be a function"); - return; - } - if (menuItem.id in self.contextMenuExtensions) { - console.error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"'); - return; - } - // Register menuItem action, see below for deferred menu dom injection - console.log("Registed contextmenu item: {id:"+ menuItem.id+", label:"+menuItem.label+"}"); - self.contextMenuExtensions[menuItem.id] = menuItem; - //TODO: Need to consider how to handle custom enable/disable behavior - }; - var hasCustomHandler = function(handlerKey) { - return self.contextMenuExtensions[handlerKey] && true; - }; - var getCustomHandler = function(handlerKey) { - return self.contextMenuExtensions[handlerKey].action; - }; - var injectExtendedContextMenuItemIntoDom = function(menuItem) { - if (Object.keys(self.contextMenuExtensions).length === 0) { - // all menuItems appear at the bottom of the menu in their own container. - // if this is the first extension menu we need to add the separator. - $("#cmenu_canvas").append("
  • "); - } - var shortcut = menuItem.shortcut || ""; - $("#cmenu_canvas").append("
  • " - + menuItem.label + "" - + shortcut + "
  • "); - }; - // Defer injection to wait out initial menu processing. This probably goes away once all context - // menu behavior is brought here. - svgEditor.ready(function() { - var menuItem; - for (menuItem in contextMenuExtensions) { - injectExtendedContextMenuItemIntoDom(contextMenuExtensions[menuItem]); - } - }); - svgedit.contextmenu.resetCustomMenus = function(){self.contextMenuExtensions = {};}; - svgedit.contextmenu.add = addContextMenuItem; - svgedit.contextmenu.hasCustomHandler = hasCustomHandler; - svgedit.contextmenu.getCustomHandler = getCustomHandler; + if (menuItem.id in self.contextMenuExtensions) { + console.error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"'); + return; + } + // Register menuItem action, see below for deferred menu dom injection + console.log('Registed contextmenu item: {id:' + menuItem.id + ', label:' + menuItem.label + '}'); + self.contextMenuExtensions[menuItem.id] = menuItem; + // TODO: Need to consider how to handle custom enable/disable behavior +}; +var hasCustomHandler = function (handlerKey) { + return self.contextMenuExtensions[handlerKey] && true; +}; +var getCustomHandler = function (handlerKey) { + return self.contextMenuExtensions[handlerKey].action; +}; +var injectExtendedContextMenuItemIntoDom = function (menuItem) { + if (Object.keys(self.contextMenuExtensions).length === 0) { + // all menuItems appear at the bottom of the menu in their own container. + // if this is the first extension menu we need to add the separator. + $('#cmenu_canvas').append("
  • "); + } + var shortcut = menuItem.shortcut || ''; + $('#cmenu_canvas').append("
  • " + + menuItem.label + "" + + shortcut + '
  • '); +}; +// Defer injection to wait out initial menu processing. This probably goes away once all context +// menu behavior is brought here. +svgEditor.ready(function () { + var menuItem; + for (menuItem in self.contextMenuExtensions) { + injectExtendedContextMenuItemIntoDom(self.contextMenuExtensions[menuItem]); + } +}); +svgedit.contextmenu.resetCustomMenus = function () { self.contextMenuExtensions = {}; }; +svgedit.contextmenu.add = addContextMenuItem; +svgedit.contextmenu.hasCustomHandler = hasCustomHandler; +svgedit.contextmenu.getCustomHandler = getCustomHandler; }()); diff --git a/editor/coords.js b/editor/coords.js index 7495ee36..45bd3560 100644 --- a/editor/coords.js +++ b/editor/coords.js @@ -1,5 +1,5 @@ -/*globals $, svgroot */ -/*jslint vars: true, eqeq: true, forin: true*/ +/* eslint-disable no-var, eqeqeq */ +/* globals $, svgroot */ /** * Coords. * @@ -16,17 +16,18 @@ // 6) units.js // 7) svgtransformlist.js -var svgedit = svgedit || {}; +var svgedit = svgedit || {}; // eslint-disable-line no-use-before-define -(function() {'use strict'; +(function () { +'use strict'; if (!svgedit.coords) { - svgedit.coords = {}; + svgedit.coords = {}; } // this is how we map paths to our preferred relative segment types -var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a', - 'H', 'h', 'V', 'v', 'S', 's', 'T', 't']; +var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a', + 'H', 'h', 'V', 'v', 'S', 's', 'T', 't']; /** * @typedef editorContext @@ -39,8 +40,8 @@ var editorContext_ = null; /** * @param {editorContext} editorContext */ -svgedit.coords.init = function(editorContext) { - editorContext_ = editorContext; +svgedit.coords.init = function (editorContext) { + editorContext_ = editorContext; }; /** @@ -49,269 +50,267 @@ svgedit.coords.init = function(editorContext) { * @param {object} changes - Object with changes to be remapped * @param {SVGMatrix} m - Matrix object to use for remapping coordinates */ -svgedit.coords.remapElement = function(selected, changes, m) { - var i, type, - remap = function(x, y) { return svgedit.math.transformPoint(x, y, m); }, - scalew = function(w) { return m.a * w; }, - scaleh = function(h) { return m.d * h; }, - doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg', - finishUp = function() { - var o; - if (doSnapping) { - for (o in changes) { - changes[o] = svgedit.utilities.snapToGrid(changes[o]); - } - } - svgedit.utilities.assignAttributes(selected, changes, 1000, true); - }, - box = svgedit.utilities.getBBox(selected); +svgedit.coords.remapElement = function (selected, changes, m) { + var i, type, + remap = function (x, y) { return svgedit.math.transformPoint(x, y, m); }, + scalew = function (w) { return m.a * w; }, + scaleh = function (h) { return m.d * h; }, + doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg', + finishUp = function () { + var o; + if (doSnapping) { + for (o in changes) { + changes[o] = svgedit.utilities.snapToGrid(changes[o]); + } + } + svgedit.utilities.assignAttributes(selected, changes, 1000, true); + }, + box = svgedit.utilities.getBBox(selected); - for (i = 0; i < 2; i++) { - type = i === 0 ? 'fill' : 'stroke'; - var attrVal = selected.getAttribute(type); - if (attrVal && attrVal.indexOf('url(') === 0) { - if (m.a < 0 || m.d < 0) { - var grad = svgedit.utilities.getRefElem(attrVal); - var newgrad = grad.cloneNode(true); - if (m.a < 0) { - // flip x - var x1 = newgrad.getAttribute('x1'); - var x2 = newgrad.getAttribute('x2'); - newgrad.setAttribute('x1', -(x1 - 1)); - newgrad.setAttribute('x2', -(x2 - 1)); - } + for (i = 0; i < 2; i++) { + type = i === 0 ? 'fill' : 'stroke'; + var attrVal = selected.getAttribute(type); + if (attrVal && attrVal.indexOf('url(') === 0) { + if (m.a < 0 || m.d < 0) { + var grad = svgedit.utilities.getRefElem(attrVal); + var newgrad = grad.cloneNode(true); + if (m.a < 0) { + // flip x + var x1 = newgrad.getAttribute('x1'); + var x2 = newgrad.getAttribute('x2'); + newgrad.setAttribute('x1', -(x1 - 1)); + newgrad.setAttribute('x2', -(x2 - 1)); + } - if (m.d < 0) { - // flip y - var y1 = newgrad.getAttribute('y1'); - var y2 = newgrad.getAttribute('y2'); - newgrad.setAttribute('y1', -(y1 - 1)); - newgrad.setAttribute('y2', -(y2 - 1)); - } - newgrad.id = editorContext_.getDrawing().getNextId(); - svgedit.utilities.findDefs().appendChild(newgrad); - selected.setAttribute(type, 'url(#' + newgrad.id + ')'); - } + if (m.d < 0) { + // flip y + var y1 = newgrad.getAttribute('y1'); + var y2 = newgrad.getAttribute('y2'); + newgrad.setAttribute('y1', -(y1 - 1)); + newgrad.setAttribute('y2', -(y2 - 1)); + } + newgrad.id = editorContext_.getDrawing().getNextId(); + svgedit.utilities.findDefs().appendChild(newgrad); + selected.setAttribute(type, 'url(#' + newgrad.id + ')'); + } - // Not really working :( -// if (selected.tagName === 'path') { -// reorientGrads(selected, m); -// } - } - } + // Not really working :( + // if (selected.tagName === 'path') { + // reorientGrads(selected, m); + // } + } + } - var elName = selected.tagName; - var chlist, mt; - if (elName === 'g' || elName === 'text' || elName == 'tspan' || elName === 'use') { - // if it was a translate, then just update x,y - if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && (m.e != 0 || m.f != 0) ) { - // [T][M] = [M][T'] - // therefore [T'] = [M_inv][T][M] - var existing = svgedit.math.transformListToTransform(selected).matrix, - t_new = svgedit.math.matrixMultiply(existing.inverse(), m, existing); - changes.x = parseFloat(changes.x) + t_new.e; - changes.y = parseFloat(changes.y) + t_new.f; - } else { - // we just absorb all matrices into the element and don't do any remapping - chlist = svgedit.transformlist.getTransformList(selected); - mt = svgroot.createSVGTransform(); - mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m)); - chlist.clear(); - chlist.appendItem(mt); - } - } - var c, pt, pt1, pt2, len; - // now we have a set of changes and an applied reduced transform list - // we apply the changes directly to the DOM - switch (elName) { - case 'foreignObject': - case 'rect': - case 'image': - // Allow images to be inverted (give them matrix when flipped) - if (elName === 'image' && (m.a < 0 || m.d < 0)) { - // Convert to matrix - chlist = svgedit.transformlist.getTransformList(selected); - mt = svgroot.createSVGTransform(); - mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m)); - chlist.clear(); - chlist.appendItem(mt); - } else { - pt1 = remap(changes.x, changes.y); - changes.width = scalew(changes.width); - changes.height = scaleh(changes.height); - changes.x = pt1.x + Math.min(0, changes.width); - changes.y = pt1.y + Math.min(0, changes.height); - changes.width = Math.abs(changes.width); - changes.height = Math.abs(changes.height); - } - finishUp(); - break; - case 'ellipse': - c = remap(changes.cx, changes.cy); - changes.cx = c.x; - changes.cy = c.y; - changes.rx = scalew(changes.rx); - changes.ry = scaleh(changes.ry); - changes.rx = Math.abs(changes.rx); - changes.ry = Math.abs(changes.ry); - finishUp(); - break; - case 'circle': - c = remap(changes.cx,changes.cy); - changes.cx = c.x; - changes.cy = c.y; - // take the minimum of the new selected box's dimensions for the new circle radius - var tbox = svgedit.math.transformBox(box.x, box.y, box.width, box.height, m); - var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y; - changes.r = Math.min(w/2, h/2); + var elName = selected.tagName; + var chlist, mt; + if (elName === 'g' || elName === 'text' || elName == 'tspan' || elName === 'use') { + // if it was a translate, then just update x,y + if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && (m.e != 0 || m.f != 0)) { + // [T][M] = [M][T'] + // therefore [T'] = [M_inv][T][M] + var existing = svgedit.math.transformListToTransform(selected).matrix, + tNew = svgedit.math.matrixMultiply(existing.inverse(), m, existing); + changes.x = parseFloat(changes.x) + tNew.e; + changes.y = parseFloat(changes.y) + tNew.f; + } else { + // we just absorb all matrices into the element and don't do any remapping + chlist = svgedit.transformlist.getTransformList(selected); + mt = svgroot.createSVGTransform(); + mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m)); + chlist.clear(); + chlist.appendItem(mt); + } + } + var c, pt, pt1, pt2, len; + // now we have a set of changes and an applied reduced transform list + // we apply the changes directly to the DOM + switch (elName) { + case 'foreignObject': + case 'rect': + case 'image': + // Allow images to be inverted (give them matrix when flipped) + if (elName === 'image' && (m.a < 0 || m.d < 0)) { + // Convert to matrix + chlist = svgedit.transformlist.getTransformList(selected); + mt = svgroot.createSVGTransform(); + mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m)); + chlist.clear(); + chlist.appendItem(mt); + } else { + pt1 = remap(changes.x, changes.y); + changes.width = scalew(changes.width); + changes.height = scaleh(changes.height); + changes.x = pt1.x + Math.min(0, changes.width); + changes.y = pt1.y + Math.min(0, changes.height); + changes.width = Math.abs(changes.width); + changes.height = Math.abs(changes.height); + } + finishUp(); + break; + case 'ellipse': + c = remap(changes.cx, changes.cy); + changes.cx = c.x; + changes.cy = c.y; + changes.rx = scalew(changes.rx); + changes.ry = scaleh(changes.ry); + changes.rx = Math.abs(changes.rx); + changes.ry = Math.abs(changes.ry); + finishUp(); + break; + case 'circle': + c = remap(changes.cx, changes.cy); + changes.cx = c.x; + changes.cy = c.y; + // take the minimum of the new selected box's dimensions for the new circle radius + var tbox = svgedit.math.transformBox(box.x, box.y, box.width, box.height, m); + var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y; + changes.r = Math.min(w / 2, h / 2); - if (changes.r) {changes.r = Math.abs(changes.r);} - finishUp(); - break; - case 'line': - pt1 = remap(changes.x1, changes.y1); - pt2 = remap(changes.x2, changes.y2); - changes.x1 = pt1.x; - changes.y1 = pt1.y; - changes.x2 = pt2.x; - changes.y2 = pt2.y; - // deliberately fall through here - case 'text': - case 'tspan': - case 'use': - finishUp(); - break; - case 'g': - var gsvg = $(selected).data('gsvg'); - if (gsvg) { - svgedit.utilities.assignAttributes(gsvg, changes, 1000, true); - } - break; - case 'polyline': - case 'polygon': - len = changes.points.length; - for (i = 0; i < len; ++i) { - pt = changes.points[i]; - pt = remap(pt.x, pt.y); - changes.points[i].x = pt.x; - changes.points[i].y = pt.y; - } + if (changes.r) { changes.r = Math.abs(changes.r); } + finishUp(); + break; + case 'line': + pt1 = remap(changes.x1, changes.y1); + pt2 = remap(changes.x2, changes.y2); + changes.x1 = pt1.x; + changes.y1 = pt1.y; + changes.x2 = pt2.x; + changes.y2 = pt2.y; + // deliberately fall through here + case 'text': + case 'tspan': + case 'use': + finishUp(); + break; + case 'g': + var gsvg = $(selected).data('gsvg'); + if (gsvg) { + svgedit.utilities.assignAttributes(gsvg, changes, 1000, true); + } + break; + case 'polyline': + case 'polygon': + len = changes.points.length; + for (i = 0; i < len; ++i) { + pt = changes.points[i]; + pt = remap(pt.x, pt.y); + changes.points[i].x = pt.x; + changes.points[i].y = pt.y; + } - len = changes.points.length; - var pstr = ''; - for (i = 0; i < len; ++i) { - pt = changes.points[i]; - pstr += pt.x + ',' + pt.y + ' '; - } - selected.setAttribute('points', pstr); - break; - case 'path': - var seg; - var segList = selected.pathSegList; - len = segList.numberOfItems; - changes.d = []; - for (i = 0; i < len; ++i) { - seg = segList.getItem(i); - changes.d[i] = { - type: seg.pathSegType, - x: seg.x, - y: seg.y, - x1: seg.x1, - y1: seg.y1, - x2: seg.x2, - y2: seg.y2, - r1: seg.r1, - r2: seg.r2, - angle: seg.angle, - largeArcFlag: seg.largeArcFlag, - sweepFlag: seg.sweepFlag - }; - } + len = changes.points.length; + var pstr = ''; + for (i = 0; i < len; ++i) { + pt = changes.points[i]; + pstr += pt.x + ',' + pt.y + ' '; + } + selected.setAttribute('points', pstr); + break; + case 'path': + var seg; + var segList = selected.pathSegList; + len = segList.numberOfItems; + changes.d = []; + for (i = 0; i < len; ++i) { + seg = segList.getItem(i); + changes.d[i] = { + type: seg.pathSegType, + x: seg.x, + y: seg.y, + x1: seg.x1, + y1: seg.y1, + x2: seg.x2, + y2: seg.y2, + r1: seg.r1, + r2: seg.r2, + angle: seg.angle, + largeArcFlag: seg.largeArcFlag, + sweepFlag: seg.sweepFlag + }; + } - len = changes.d.length; - var firstseg = changes.d[0], - currentpt = remap(firstseg.x, firstseg.y); - changes.d[0].x = currentpt.x; - changes.d[0].y = currentpt.y; - for (i = 1; i < len; ++i) { - seg = changes.d[i]; - type = seg.type; - // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2 - // if relative, we want to scalew, scaleh - if (type % 2 == 0) { // absolute - var thisx = (seg.x != undefined) ? seg.x : currentpt.x, // for V commands - thisy = (seg.y != undefined) ? seg.y : currentpt.y; // for H commands - pt = remap(thisx,thisy); - pt1 = remap(seg.x1, seg.y1); - pt2 = remap(seg.x2, seg.y2); - seg.x = pt.x; - seg.y = pt.y; - seg.x1 = pt1.x; - seg.y1 = pt1.y; - seg.x2 = pt2.x; - seg.y2 = pt2.y; - seg.r1 = scalew(seg.r1); - seg.r2 = scaleh(seg.r2); - } - else { // relative - seg.x = scalew(seg.x); - seg.y = scaleh(seg.y); - seg.x1 = scalew(seg.x1); - seg.y1 = scaleh(seg.y1); - seg.x2 = scalew(seg.x2); - seg.y2 = scaleh(seg.y2); - seg.r1 = scalew(seg.r1); - seg.r2 = scaleh(seg.r2); - } - } // for each segment + len = changes.d.length; + var firstseg = changes.d[0], + currentpt = remap(firstseg.x, firstseg.y); + changes.d[0].x = currentpt.x; + changes.d[0].y = currentpt.y; + for (i = 1; i < len; ++i) { + seg = changes.d[i]; + type = seg.type; + // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2 + // if relative, we want to scalew, scaleh + if (type % 2 == 0) { // absolute + var thisx = (seg.x != undefined) ? seg.x : currentpt.x, // for V commands + thisy = (seg.y != undefined) ? seg.y : currentpt.y; // for H commands + pt = remap(thisx, thisy); + pt1 = remap(seg.x1, seg.y1); + pt2 = remap(seg.x2, seg.y2); + seg.x = pt.x; + seg.y = pt.y; + seg.x1 = pt1.x; + seg.y1 = pt1.y; + seg.x2 = pt2.x; + seg.y2 = pt2.y; + seg.r1 = scalew(seg.r1); + seg.r2 = scaleh(seg.r2); + } else { // relative + seg.x = scalew(seg.x); + seg.y = scaleh(seg.y); + seg.x1 = scalew(seg.x1); + seg.y1 = scaleh(seg.y1); + seg.x2 = scalew(seg.x2); + seg.y2 = scaleh(seg.y2); + seg.r1 = scalew(seg.r1); + seg.r2 = scaleh(seg.r2); + } + } // for each segment - var dstr = ''; - len = changes.d.length; - for (i = 0; i < len; ++i) { - seg = changes.d[i]; - type = seg.type; - dstr += pathMap[type]; - switch (type) { - case 13: // relative horizontal line (h) - case 12: // absolute horizontal line (H) - dstr += seg.x + ' '; - break; - case 15: // relative vertical line (v) - case 14: // absolute vertical line (V) - dstr += seg.y + ' '; - break; - case 3: // relative move (m) - case 5: // relative line (l) - case 19: // relative smooth quad (t) - case 2: // absolute move (M) - case 4: // absolute line (L) - case 18: // absolute smooth quad (T) - dstr += seg.x + ',' + seg.y + ' '; - break; - case 7: // relative cubic (c) - case 6: // absolute cubic (C) - dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' + - seg.x + ',' + seg.y + ' '; - break; - case 9: // relative quad (q) - case 8: // absolute quad (Q) - dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' '; - break; - case 11: // relative elliptical arc (a) - case 10: // absolute elliptical arc (A) - dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + (+seg.largeArcFlag) + - ' ' + (+seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' '; - break; - case 17: // relative smooth cubic (s) - case 16: // absolute smooth cubic (S) - dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' '; - break; - } - } + var dstr = ''; + len = changes.d.length; + for (i = 0; i < len; ++i) { + seg = changes.d[i]; + type = seg.type; + dstr += pathMap[type]; + switch (type) { + case 13: // relative horizontal line (h) + case 12: // absolute horizontal line (H) + dstr += seg.x + ' '; + break; + case 15: // relative vertical line (v) + case 14: // absolute vertical line (V) + dstr += seg.y + ' '; + break; + case 3: // relative move (m) + case 5: // relative line (l) + case 19: // relative smooth quad (t) + case 2: // absolute move (M) + case 4: // absolute line (L) + case 18: // absolute smooth quad (T) + dstr += seg.x + ',' + seg.y + ' '; + break; + case 7: // relative cubic (c) + case 6: // absolute cubic (C) + dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' + + seg.x + ',' + seg.y + ' '; + break; + case 9: // relative quad (q) + case 8: // absolute quad (Q) + dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' '; + break; + case 11: // relative elliptical arc (a) + case 10: // absolute elliptical arc (A) + dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + (+seg.largeArcFlag) + + ' ' + (+seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' '; + break; + case 17: // relative smooth cubic (s) + case 16: // absolute smooth cubic (S) + dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' '; + break; + } + } - selected.setAttribute('d', dstr); - break; - } + selected.setAttribute('d', dstr); + break; + } }; - }()); diff --git a/editor/draw.js b/editor/draw.js index c21c394f..44e6b07d 100644 --- a/editor/draw.js +++ b/editor/draw.js @@ -1,5 +1,5 @@ -/*globals $, svgedit*/ -/*jslint vars: true, eqeq: true, todo: true*/ +/* eslint-disable no-var, eqeqeq */ +/* globals $, svgedit */ /** * Package: svgedit.draw * @@ -13,7 +13,8 @@ // 2) browser.js // 3) svgutils.js -(function() {'use strict'; +(function () { +'use strict'; if (!svgedit.draw) { svgedit.draw = {}; @@ -28,25 +29,22 @@ var RandomizeModes = { ALWAYS_RANDOMIZE: 1, NEVER_RANDOMIZE: 2 }; -var randomize_ids = RandomizeModes.LET_DOCUMENT_DECIDE; +var randomizeIds = RandomizeModes.LET_DOCUMENT_DECIDE; - - - - /** +/** * Called to ensure that drawings will or will not have randomized ids. * The currentDrawing will have its nonce set if it doesn't already. * @param {boolean} enableRandomization - flag indicating if documents should have randomized ids * @param {svgedit.draw.Drawing} currentDrawing */ -svgedit.draw.randomizeIds = function(enableRandomization, currentDrawing) { - randomize_ids = enableRandomization === false ? - RandomizeModes.NEVER_RANDOMIZE : - RandomizeModes.ALWAYS_RANDOMIZE; +svgedit.draw.randomizeIds = function (enableRandomization, currentDrawing) { + randomizeIds = enableRandomization === false + ? RandomizeModes.NEVER_RANDOMIZE + : RandomizeModes.ALWAYS_RANDOMIZE; - if (randomize_ids == RandomizeModes.ALWAYS_RANDOMIZE && !currentDrawing.getNonce()) { + if (randomizeIds == RandomizeModes.ALWAYS_RANDOMIZE && !currentDrawing.getNonce()) { currentDrawing.setNonce(Math.floor(Math.random() * 100001)); - } else if (randomize_ids == RandomizeModes.NEVER_RANDOMIZE && currentDrawing.getNonce()) { + } else if (randomizeIds == RandomizeModes.NEVER_RANDOMIZE && currentDrawing.getNonce()) { currentDrawing.clearNonce(); } }; @@ -56,12 +54,12 @@ svgedit.draw.randomizeIds = function(enableRandomization, currentDrawing) { * @param {SVGSVGElement} svgElem - The SVG DOM Element that this JS object * encapsulates. If the svgElem has a se:nonce attribute on it, then * IDs will use the nonce as they are generated. - * @param {String=svg_} [opt_idPrefix] - The ID prefix to use. + * @param {String=svg_} [optIdPrefix] - The ID prefix to use. */ -svgedit.draw.Drawing = function(svgElem, opt_idPrefix) { +svgedit.draw.Drawing = function (svgElem, optIdPrefix) { if (!svgElem || !svgElem.tagName || !svgElem.namespaceURI || svgElem.tagName != 'svg' || svgElem.namespaceURI != NS.SVG) { - throw "Error: svgedit.draw.Drawing instance initialized without a element"; + throw new Error('Error: svgedit.draw.Drawing instance initialized without a element'); } /** @@ -69,19 +67,19 @@ svgedit.draw.Drawing = function(svgElem, opt_idPrefix) { * @type {SVGSVGElement} */ this.svgElem_ = svgElem; - + /** * The latest object number used in this drawing. * @type {number} */ this.obj_num = 0; - + /** * The prefix to prepend to each element id in the drawing. * @type {String} */ - this.idPrefix = opt_idPrefix || "svg_"; - + this.idPrefix = optIdPrefix || 'svg_'; + /** * An array of released element ids to immediately reuse. * @type {Array.} @@ -120,9 +118,9 @@ svgedit.draw.Drawing = function(svgElem, opt_idPrefix) { var n = this.svgElem_.getAttributeNS(NS.SE, 'nonce'); // If already set in the DOM, use the nonce throughout the document // else, if randomizeIds(true) has been called, create and set the nonce. - if (!!n && randomize_ids != RandomizeModes.NEVER_RANDOMIZE) { + if (!!n && randomizeIds != RandomizeModes.NEVER_RANDOMIZE) { this.nonce_ = n; - } else if (randomize_ids == RandomizeModes.ALWAYS_RANDOMIZE) { + } else if (randomizeIds == RandomizeModes.ALWAYS_RANDOMIZE) { this.setNonce(Math.floor(Math.random() * 100001)); } }; @@ -150,14 +148,14 @@ svgedit.draw.Drawing.prototype.getSvgElem = function () { /** * @returns {!string|number} The previously set nonce */ -svgedit.draw.Drawing.prototype.getNonce = function() { +svgedit.draw.Drawing.prototype.getNonce = function () { return this.nonce_; }; /** * @param {!string|number} n The nonce to set */ -svgedit.draw.Drawing.prototype.setNonce = function(n) { +svgedit.draw.Drawing.prototype.setNonce = function (n) { this.svgElem_.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE); this.svgElem_.setAttributeNS(NS.SE, 'se:nonce', n); this.nonce_ = n; @@ -177,9 +175,9 @@ svgedit.draw.Drawing.prototype.clearNonce = function () { * @return {String} The latest object Id. */ svgedit.draw.Drawing.prototype.getId = function () { - return this.nonce_ ? - this.idPrefix + this.nonce_ + '_' + this.obj_num : - this.idPrefix + this.obj_num; + return this.nonce_ + ? this.idPrefix + this.nonce_ + '_' + this.obj_num + : this.idPrefix + this.obj_num; }; /** @@ -190,7 +188,7 @@ svgedit.draw.Drawing.prototype.getNextId = function () { var oldObjNum = this.obj_num; var restoreOldObjNum = false; - // If there are any released numbers in the release stack, + // If there are any released numbers in the release stack, // use the last one instead of the next obj_num. // We need to temporarily use obj_num as that is what getId() depends on. if (this.releasedNums.length > 0) { @@ -239,7 +237,7 @@ svgedit.draw.Drawing.prototype.releaseId = function (id) { if (typeof num !== 'number' || num <= 0 || this.releasedNums.indexOf(num) != -1) { return false; } - + // push the released number into the released queue this.releasedNums.push(num); @@ -250,7 +248,7 @@ svgedit.draw.Drawing.prototype.releaseId = function (id) { * Returns the number of layers in the current drawing. * @returns {integer} The number of layers in the current drawing. */ -svgedit.draw.Drawing.prototype.getNumLayers = function() { +svgedit.draw.Drawing.prototype.getNumLayers = function () { return this.all_layers.length; }; @@ -262,7 +260,6 @@ svgedit.draw.Drawing.prototype.hasLayer = function (name) { return this.layer_map[name] !== undefined; }; - /** * Returns the name of the ith layer. If the index is out of range, an empty string is returned. * @param {integer} i - The zero-based index of the layer you are querying. @@ -275,7 +272,7 @@ svgedit.draw.Drawing.prototype.getLayerName = function (i) { /** * @returns {SVGGElement} The SVGGElement representing the current layer. */ -svgedit.draw.Drawing.prototype.getCurrentLayer = function() { +svgedit.draw.Drawing.prototype.getCurrentLayer = function () { return this.current_layer ? this.current_layer.getGroup() : null; }; @@ -283,13 +280,13 @@ svgedit.draw.Drawing.prototype.getCurrentLayer = function() { * Get a layer by name. * @returns {SVGGElement} The SVGGElement representing the named layer or null. */ -svgedit.draw.Drawing.prototype.getLayerByName = function(name) { +svgedit.draw.Drawing.prototype.getLayerByName = function (name) { var layer = this.layer_map[name]; return layer ? layer.getGroup() : null; }; /** - * Returns the name of the currently selected layer. If an error occurs, an empty string + * Returns the name of the currently selected layer. If an error occurs, an empty string * is returned. * @returns {string} The name of the currently active layer (or the empty string if none found). */ @@ -322,39 +319,38 @@ svgedit.draw.Drawing.prototype.setCurrentLayerName = function (name, hrService) * @returns {Object} If the name was changed, returns {title:SVGGElement, previousName:string}; otherwise null. */ svgedit.draw.Drawing.prototype.setCurrentLayerPosition = function (newpos) { - var layer_count = this.getNumLayers(); - if (!this.current_layer || newpos < 0 || newpos >= layer_count) { + var layerCount = this.getNumLayers(); + if (!this.current_layer || newpos < 0 || newpos >= layerCount) { return null; } var oldpos; - for (oldpos = 0; oldpos < layer_count; ++oldpos) { - if (this.all_layers[oldpos] == this.current_layer) {break;} + for (oldpos = 0; oldpos < layerCount; ++oldpos) { + if (this.all_layers[oldpos] == this.current_layer) { break; } } // some unknown error condition (current_layer not in all_layers) - if (oldpos == layer_count) { return null; } + if (oldpos == layerCount) { return null; } if (oldpos != newpos) { // if our new position is below us, we need to insert before the node after newpos var refGroup = null; - var current_group = this.current_layer.getGroup(); - var oldNextSibling = current_group.nextSibling; - if (newpos > oldpos ) { - if (newpos < layer_count-1) { - refGroup = this.all_layers[newpos+1].getGroup(); + var currentGroup = this.current_layer.getGroup(); + var oldNextSibling = currentGroup.nextSibling; + if (newpos > oldpos) { + if (newpos < layerCount - 1) { + refGroup = this.all_layers[newpos + 1].getGroup(); } - } // if our new position is above us, we need to insert before the node at newpos - else { + } else { refGroup = this.all_layers[newpos].getGroup(); } - this.svgElem_.insertBefore(current_group, refGroup); + this.svgElem_.insertBefore(currentGroup, refGroup); this.identifyLayers(); this.setCurrentLayer(this.getLayerName(newpos)); return { - currentGroup: current_group, + currentGroup: currentGroup, oldNextSibling: oldNextSibling }; } @@ -362,25 +358,25 @@ svgedit.draw.Drawing.prototype.setCurrentLayerPosition = function (newpos) { }; svgedit.draw.Drawing.prototype.mergeLayer = function (hrService) { - var current_group = this.current_layer.getGroup(); - var prevGroup = $(current_group).prev()[0]; - if (!prevGroup) {return;} + var currentGroup = this.current_layer.getGroup(); + var prevGroup = $(currentGroup).prev()[0]; + if (!prevGroup) { return; } hrService.startBatchCommand('Merge Layer'); - var layerNextSibling = current_group.nextSibling; - hrService.removeElement(current_group, layerNextSibling, this.svgElem_); + var layerNextSibling = currentGroup.nextSibling; + hrService.removeElement(currentGroup, layerNextSibling, this.svgElem_); - while (current_group.firstChild) { - var child = current_group.firstChild; + while (currentGroup.firstChild) { + var child = currentGroup.firstChild; if (child.localName == 'title') { - hrService.removeElement(child, child.nextSibling, current_group); - current_group.removeChild(child); + hrService.removeElement(child, child.nextSibling, currentGroup); + currentGroup.removeChild(child); continue; } var oldNextSibling = child.nextSibling; prevGroup.appendChild(child); - hrService.moveElement(child, oldNextSibling, current_group); + hrService.moveElement(child, oldNextSibling, currentGroup); } // Remove current layer's group @@ -389,7 +385,7 @@ svgedit.draw.Drawing.prototype.mergeLayer = function (hrService) { var index = this.all_layers.indexOf(this.current_layer); if (index > 0) { var name = this.current_layer.getName(); - this.current_layer = this.all_layers[index-1] + this.current_layer = this.all_layers[index - 1]; this.all_layers.splice(index, 1); delete this.layer_map[name]; } @@ -399,7 +395,7 @@ svgedit.draw.Drawing.prototype.mergeLayer = function (hrService) { svgedit.draw.Drawing.prototype.mergeAllLayers = function (hrService) { // Set the current layer to the last layer. - this.current_layer = this.all_layers[this.all_layers.length-1]; + this.current_layer = this.all_layers[this.all_layers.length - 1]; hrService.startBatchCommand('Merge all Layers'); while (this.all_layers.length > 1) { @@ -415,7 +411,7 @@ svgedit.draw.Drawing.prototype.mergeAllLayers = function (hrService) { * @param {string} name - The name of the layer you want to switch to. * @returns {boolean} true if the current layer was switched, otherwise false */ -svgedit.draw.Drawing.prototype.setCurrentLayer = function(name) { +svgedit.draw.Drawing.prototype.setCurrentLayer = function (name) { var layer = this.layer_map[name]; if (layer) { if (this.current_layer) { @@ -428,13 +424,12 @@ svgedit.draw.Drawing.prototype.setCurrentLayer = function(name) { return false; }; - /** * Deletes the current layer from the drawing and then clears the selection. * This function then calls the 'changed' handler. This is an undoable action. * @returns {SVGGElement} The SVGGElement of the layer removed or null. */ -svgedit.draw.Drawing.prototype.deleteCurrentLayer = function() { +svgedit.draw.Drawing.prototype.deleteCurrentLayer = function () { if (this.current_layer && this.getNumLayers() > 1) { var oldLayerGroup = this.current_layer.removeGroup(); this.identifyLayers(); @@ -448,8 +443,8 @@ svgedit.draw.Drawing.prototype.deleteCurrentLayer = function() { * @param group The group element to search in. * @returns {string} The layer name or empty string. */ -function findLayerNameInGroup(group) { - var name = $("title", group).text(); +function findLayerNameInGroup (group) { + var name = $('title', group).text(); // Hack for Opera 10.60 if (!name && svgedit.browser.isOpera() && group.querySelectorAll) { @@ -463,18 +458,18 @@ function findLayerNameInGroup(group) { * @param {Array.} existingLayerNames - Existing layer names. * @returns {string} - The new name. */ -function getNewLayerName(existingLayerNames) { +function getNewLayerName (existingLayerNames) { var i = 1; // TODO(codedread): What about internationalization of "Layer"? - while (existingLayerNames.indexOf(("Layer " + i)) >= 0) { i++; } - return "Layer " + i; + while (existingLayerNames.indexOf(('Layer ' + i)) >= 0) { i++; } + return 'Layer ' + i; } /** * Updates layer system and sets the current layer to the * top-most layer (last child of this drawing). */ -svgedit.draw.Drawing.prototype.identifyLayers = function() { +svgedit.draw.Drawing.prototype.identifyLayers = function () { this.all_layers = []; this.layer_map = {}; var numchildren = this.svgElem_.childNodes.length; @@ -486,7 +481,7 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() { var child = this.svgElem_.childNodes.item(i); // for each g, find its layer name if (child && child.nodeType == 1) { - if (child.tagName == "g") { + if (child.tagName === 'g') { childgroups = true; var name = findLayerNameInGroup(child); if (name) { @@ -504,7 +499,7 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() { } } } - + // If orphans or no layers found, create a new layer and add all the orphans to it if (orphans.length > 0 || !childgroups) { layer = new svgedit.draw.Layer(getNewLayerName(layernames), null, this.svgElem_); @@ -525,7 +520,7 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() { * @returns {SVGGElement} The SVGGElement of the new layer, which is * also the current layer of this drawing. */ -svgedit.draw.Drawing.prototype.createLayer = function(name, hrService) { +svgedit.draw.Drawing.prototype.createLayer = function (name, hrService) { if (this.current_layer) { this.current_layer.deactivate(); } @@ -556,8 +551,8 @@ svgedit.draw.Drawing.prototype.createLayer = function(name, hrService) { * @returns {SVGGElement} The SVGGElement of the new layer, which is * also the current layer of this drawing. */ -svgedit.draw.Drawing.prototype.cloneLayer = function(name, hrService) { - if (!this.current_layer) {return null;} +svgedit.draw.Drawing.prototype.cloneLayer = function (name, hrService) { + if (!this.current_layer) { return null; } this.current_layer.deactivate(); // Check for duplicate name. if (name === undefined || name === null || name === '' || this.layer_map[name]) { @@ -567,14 +562,14 @@ svgedit.draw.Drawing.prototype.cloneLayer = function(name, hrService) { // Create new group and add to DOM just after current_layer var currentGroup = this.current_layer.getGroup(); var layer = new svgedit.draw.Layer(name, currentGroup, this.svgElem_); - var group = layer.getGroup(); + var group = layer.getGroup(); // Clone children var children = currentGroup.childNodes; var index; for (index = 0; index < children.length; index++) { var ch = children[index]; - if (ch.localName == 'title') {continue;} + if (ch.localName == 'title') { continue; } group.appendChild(this.copyElem(ch)); } @@ -602,7 +597,7 @@ svgedit.draw.Drawing.prototype.cloneLayer = function(name, hrService) { * @param {string} layername - The name of the layer which you want to query. * @returns {boolean} The visibility state of the layer, or false if the layer name was invalid. */ -svgedit.draw.Drawing.prototype.getLayerVisibility = function(layername) { +svgedit.draw.Drawing.prototype.getLayerVisibility = function (layername) { var layer = this.layer_map[layername]; return layer ? layer.isVisible() : false; }; @@ -616,26 +611,25 @@ svgedit.draw.Drawing.prototype.getLayerVisibility = function(layername) { * @returns {?SVGGElement} The SVGGElement representing the layer if the * layername was valid, otherwise null. */ -svgedit.draw.Drawing.prototype.setLayerVisibility = function(layername, bVisible) { +svgedit.draw.Drawing.prototype.setLayerVisibility = function (layername, bVisible) { if (typeof bVisible !== 'boolean') { return null; } var layer = this.layer_map[layername]; - if (!layer) {return null;} + if (!layer) { return null; } layer.setVisible(bVisible); return layer.getGroup(); }; - /** * Returns the opacity of the given layer. If the input name is not a layer, null is returned. * @param {string} layername - name of the layer on which to get the opacity * @returns {?number} The opacity value of the given layer. This will be a value between 0.0 and 1.0, or null * if layername is not a valid layer */ -svgedit.draw.Drawing.prototype.getLayerOpacity = function(layername) { +svgedit.draw.Drawing.prototype.getLayerOpacity = function (layername) { var layer = this.layer_map[layername]; - if (!layer) {return null;} + if (!layer) { return null; } return layer.getOpacity(); }; @@ -646,7 +640,7 @@ svgedit.draw.Drawing.prototype.getLayerOpacity = function(layername) { * @param {string} layername - Name of the layer on which to set the opacity * @param {number} opacity - A float value in the range 0.0-1.0 */ -svgedit.draw.Drawing.prototype.setLayerOpacity = function(layername, opacity) { +svgedit.draw.Drawing.prototype.setLayerOpacity = function (layername, opacity) { if (typeof opacity !== 'number' || opacity < 0.0 || opacity > 1.0) { return; } @@ -661,11 +655,9 @@ svgedit.draw.Drawing.prototype.setLayerOpacity = function(layername, opacity) { * @param {Element} el - DOM element to clone * @returns {Element} */ -svgedit.draw.Drawing.prototype.copyElem = function(el) { +svgedit.draw.Drawing.prototype.copyElem = function (el) { var self = this; - var getNextIdClosure = function() { return self.getNextId();} - return svgedit.utilities.copyElem(el, getNextIdClosure) -} - - + var getNextIdClosure = function () { return self.getNextId(); }; + return svgedit.utilities.copyElem(el, getNextIdClosure); +}; }()); diff --git a/editor/embedapi-dom.js b/editor/embedapi-dom.js index dc5afcd2..098912df 100644 --- a/editor/embedapi-dom.js +++ b/editor/embedapi-dom.js @@ -1,79 +1,80 @@ -/*globals $, EmbeddedSVGEdit*/ -/*jslint vars: true */ -var initEmbed; +/* eslint-disable no-var */ +/* globals $, EmbeddedSVGEdit */ +var initEmbed; // eslint-disable-line no-unused-vars // Todo: Get rid of frame.contentWindow dependencies so can be more easily adjusted to work cross-domain -$(function () {'use strict'; - - var svgCanvas = null; - var frame; +$(function () { + 'use strict'; - initEmbed = function () { - var doc, mainButton; - svgCanvas = new EmbeddedSVGEdit(frame); - // Hide main button, as we will be controlling new, load, save, etc. from the host document - doc = frame.contentDocument || frame.contentWindow.document; - mainButton = doc.getElementById('main_button'); - mainButton.style.display = 'none'; - }; + var svgCanvas = null; + var frame; - function handleSvgData(data, error) { - if (error) { - alert('error ' + error); - } else { - alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data); - } - } + initEmbed = function () { + var doc, mainButton; + svgCanvas = new EmbeddedSVGEdit(frame); + // Hide main button, as we will be controlling new, load, save, etc. from the host document + doc = frame.contentDocument || frame.contentWindow.document; + mainButton = doc.getElementById('main_button'); + mainButton.style.display = 'none'; + }; - function loadSvg() { - var svgexample = 'Layer 1'; - svgCanvas.setSvgString(svgexample); - } + function handleSvgData (data, error) { + if (error) { + alert('error ' + error); + } else { + alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data); + } + } - function saveSvg() { - svgCanvas.getSvgString()(handleSvgData); - } - - function exportPNG() { - var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage; + function loadSvg () { + var svgexample = 'Layer 1'; + svgCanvas.setSvgString(svgexample); + } + + function saveSvg () { + svgCanvas.getSvgString()(handleSvgData); + } + + function exportPNG () { + var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage; + + var exportWindow = window.open( + 'data:text/html;charset=utf-8,' + encodeURIComponent('' + str + '

    ' + str + '

    '), + 'svg-edit-exportWindow' + ); + svgCanvas.rasterExport('PNG', null, exportWindow.name); + } + + function exportPDF () { + var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage; - var exportWindow = window.open( - 'data:text/html;charset=utf-8,' + encodeURIComponent('' + str + '

    ' + str + '

    '), - 'svg-edit-exportWindow' - ); - svgCanvas.rasterExport('PNG', null, exportWindow.name); - } - - function exportPDF() { - var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage; - /** - // If you want to handle the PDF blob yourself, do as follows + // If you want to handle the PDF blob yourself, do as follows svgCanvas.bind('exportedPDF', function (win, data) { alert(data.dataurlstring); }); svgCanvas.exportPDF(); // Accepts two args: optionalWindowName supplied back to bound exportPDF handler and optionalOutputType (defaults to dataurlstring) - return; - */ - - var exportWindow = window.open( - 'data:text/html;charset=utf-8,' + encodeURIComponent('' + str + '

    ' + str + '

    '), - 'svg-edit-exportWindow' - ); + return; + */ + + var exportWindow = window.open( + 'data:text/html;charset=utf-8,' + encodeURIComponent('' + str + '

    ' + str + '

    '), + 'svg-edit-exportWindow' + ); svgCanvas.exportPDF(exportWindow.name); - } - - // Add event handlers - $('#load').click(loadSvg); - $('#save').click(saveSvg); - $('#exportPNG').click(exportPNG); - $('#exportPDF').click(exportPDF); - $('body').append( - $('' - ) - ); - frame = document.getElementById('svgedit'); + } + + // Add event handlers + $('#load').click(loadSvg); + $('#save').click(saveSvg); + $('#exportPNG').click(exportPNG); + $('#exportPDF').click(exportPDF); + $('body').append( + $('' + ) + ); + frame = document.getElementById('svgedit'); }); diff --git a/editor/embedapi.js b/editor/embedapi.js index b50a896b..a996e9b7 100644 --- a/editor/embedapi.js +++ b/editor/embedapi.js @@ -1,4 +1,5 @@ -/* +/* eslint-disable no-var */ +/* Embedded SVG-edit API General usage: @@ -9,11 +10,11 @@ var svgCanvas = new EmbeddedSVGEdit(window.frames.svgedit); svgCanvas.setSvgString('string') - Or if a callback is needed: svgCanvas.setSvgString('string')(function(data, error){ - if (error){ + if (error){ // There was an error - } else{ + } else{ // Handle data - } + } }) Everything is done with the same API as the real svg-edit, @@ -35,20 +36,21 @@ var blah = new EmbeddedSVGEdit(window.frames.svgedit); blah.clearSelection('woot', 'blah', 1337, [1, 2, 3, 4, 5, 'moo'], -42, {a: 'tree',b:6, c: 9})(function(){console.log('GET DATA',arguments)}) */ -(function () {'use strict'; +(function () { +'use strict'; var cbid = 0; function getCallbackSetter (d) { - return function () { - var t = this, // New callback - args = [].slice.call(arguments), - cbid = t.send(d, args, function(){}); // The callback (currently it's nothing, but will be set later) + return function () { + var t = this, // New callback + args = [].slice.call(arguments), + cbid = t.send(d, args, function () {}); // The callback (currently it's nothing, but will be set later) - return function(newcallback){ - t.callbacks[cbid] = newcallback; // Set callback + return function (newcallback) { + t.callbacks[cbid] = newcallback; // Set callback + }; }; - }; } /* @@ -57,32 +59,32 @@ function getCallbackSetter (d) { * of same domain control */ function addCallback (t, data) { - var result = data.result || data.error, - cbid = data.id; - if (t.callbacks[cbid]) { - if (data.result) { - t.callbacks[cbid](result); - } else { - t.callbacks[cbid](result, 'error'); + var result = data.result || data.error, + cbid = data.id; + if (t.callbacks[cbid]) { + if (data.result) { + t.callbacks[cbid](result); + } else { + t.callbacks[cbid](result, 'error'); + } } - } } function messageListener (e) { - // We accept and post strings as opposed to objects for the sake of IE9 support; this - // will most likely be changed in the future - if (typeof e.data !== 'string') { - return; - } - var allowedOrigins = this.allowedOrigins, - data = e.data && JSON.parse(e.data); - if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit' || - e.source !== this.frame.contentWindow || - (allowedOrigins.indexOf('*') === -1 && allowedOrigins.indexOf(e.origin) === -1) - ) { - return; - } - addCallback(this, data); + // We accept and post strings as opposed to objects for the sake of IE9 support; this + // will most likely be changed in the future + if (typeof e.data !== 'string') { + return; + } + var allowedOrigins = this.allowedOrigins, + data = e.data && JSON.parse(e.data); + if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit' || + e.source !== this.frame.contentWindow || + (allowedOrigins.indexOf('*') === -1 && allowedOrigins.indexOf(e.origin) === -1) + ) { + return; + } + addCallback(this, data); } function getMessageListener (t) { @@ -98,82 +100,79 @@ function getMessageListener (t) { * If supplied, it should probably be the same as svgEditor's allowedOrigins */ function EmbeddedSVGEdit (frame, allowedOrigins) { - if (!(this instanceof EmbeddedSVGEdit)) { // Allow invocation without 'new' keyword - return new EmbeddedSVGEdit(frame); - } - this.allowedOrigins = allowedOrigins || []; - // Initialize communication - this.frame = frame; - this.callbacks = {}; - // List of functions extracted with this: - // Run in firebug on http://svg-edit.googlecode.com/svn/trunk/docs/files/svgcanvas-js.html + if (!(this instanceof EmbeddedSVGEdit)) { // Allow invocation without 'new' keyword + return new EmbeddedSVGEdit(frame); + } + this.allowedOrigins = allowedOrigins || []; + // Initialize communication + this.frame = frame; + this.callbacks = {}; + // List of functions extracted with this: + // Run in firebug on http://svg-edit.googlecode.com/svn/trunk/docs/files/svgcanvas-js.html - // for (var i=0,q=[],f = document.querySelectorAll('div.CFunction h3.CTitle a'); i < f.length; i++) { q.push(f[i].name); }; q - // var functions = ['clearSelection', 'addToSelection', 'removeFromSelection', 'open', 'save', 'getSvgString', 'setSvgString', - // 'createLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', - // 'moveSelectedToLayer', 'clear']; + // for (var i=0,q=[],f = document.querySelectorAll('div.CFunction h3.CTitle a'); i < f.length; i++) { q.push(f[i].name); }; q + // var functions = ['clearSelection', 'addToSelection', 'removeFromSelection', 'open', 'save', 'getSvgString', 'setSvgString', + // 'createLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', + // 'moveSelectedToLayer', 'clear']; - // Newer, well, it extracts things that aren't documented as well. All functions accessible through the normal thingy can now be accessed though the API - // var svgCanvas = frame.contentWindow.svgCanvas; - // var l = []; for (var i in svgCanvas){ if (typeof svgCanvas[i] == 'function') { l.push(i);} }; - // alert("['" + l.join("', '") + "']"); - // Run in svgedit itself - var i, - functions = [ - 'clearSvgContentElement', 'setIdPrefix', 'getCurrentDrawing', 'addSvgElementFromJson', 'getTransformList', 'matrixMultiply', 'hasMatrixTransform', 'transformListToTransform', 'convertToNum', 'findDefs', 'getUrlFromAttr', 'getHref', 'setHref', 'getBBox', 'getRotationAngle', 'getElem', 'getRefElem', 'assignAttributes', 'cleanupElement', 'remapElement', 'recalculateDimensions', 'sanitizeSvg', 'runExtensions', 'addExtension', 'round', 'getIntersectionList', 'getStrokedBBox', 'getVisibleElements', 'getVisibleElementsAndBBoxes', 'groupSvgElem', 'getId', 'getNextId', 'call', 'bind', 'prepareSvg', 'setRotationAngle', 'recalculateAllSelectedDimensions', 'clearSelection', 'addToSelection', 'selectOnly', 'removeFromSelection', 'selectAllInCurrentLayer', 'getMouseTarget', 'removeUnusedDefElems', 'svgCanvasToString', 'svgToString', 'embedImage', 'setGoodImage', 'open', 'save', 'rasterExport', 'exportPDF', 'getSvgString', 'randomizeIds', 'uniquifyElems', 'setUseData', 'convertGradients', 'convertToGroup', 'setSvgString', 'importSvgString', 'identifyLayers', 'createLayer', 'cloneLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', 'moveSelectedToLayer', 'mergeLayer', 'mergeAllLayers', 'leaveContext', 'setContext', 'clear', 'linkControlPoints', 'getContentElem', 'getRootElem', 'getSelectedElems', 'getResolution', 'getZoom', 'getVersion', 'setUiStrings', 'setConfig', 'getTitle', 'setGroupTitle', 'getDocumentTitle', 'setDocumentTitle', 'getEditorNS', 'setResolution', 'getOffset', 'setBBoxZoom', 'setZoom', 'getMode', 'setMode', 'getColor', 'setColor', 'setGradient', 'setPaint', 'setStrokePaint', 'setFillPaint', 'getStrokeWidth', 'setStrokeWidth', 'setStrokeAttr', 'getStyle', 'getOpacity', 'setOpacity', 'getFillOpacity', 'getStrokeOpacity', 'setPaintOpacity', 'getPaintOpacity', 'getBlur', 'setBlurNoUndo', 'setBlurOffsets', 'setBlur', 'getBold', 'setBold', 'getItalic', 'setItalic', 'getFontFamily', 'setFontFamily', 'setFontColor', 'getFontColor', 'getFontSize', 'setFontSize', 'getText', 'setTextContent', 'setImageURL', 'setLinkURL', 'setRectRadius', 'makeHyperlink', 'removeHyperlink', 'setSegType', 'convertToPath', 'changeSelectedAttribute', 'deleteSelectedElements', 'cutSelectedElements', 'copySelectedElements', 'pasteElements', 'groupSelectedElements', 'pushGroupProperties', 'ungroupSelectedElement', 'moveToTopSelectedElement', 'moveToBottomSelectedElement', 'moveUpDownSelected', 'moveSelectedElements', 'cloneSelectedElements', 'alignSelectedElements', 'updateCanvas', 'setBackground', 'cycleElement', 'getPrivateMethods', 'zoomChanged', 'ready' - ]; + // Newer, well, it extracts things that aren't documented as well. All functions accessible through the normal thingy can now be accessed though the API + // var svgCanvas = frame.contentWindow.svgCanvas; + // var l = []; for (var i in svgCanvas){ if (typeof svgCanvas[i] == 'function') { l.push(i);} }; + // alert("['" + l.join("', '") + "']"); + // Run in svgedit itself + var i, + functions = [ + 'clearSvgContentElement', 'setIdPrefix', 'getCurrentDrawing', 'addSvgElementFromJson', 'getTransformList', 'matrixMultiply', 'hasMatrixTransform', 'transformListToTransform', 'convertToNum', 'findDefs', 'getUrlFromAttr', 'getHref', 'setHref', 'getBBox', 'getRotationAngle', 'getElem', 'getRefElem', 'assignAttributes', 'cleanupElement', 'remapElement', 'recalculateDimensions', 'sanitizeSvg', 'runExtensions', 'addExtension', 'round', 'getIntersectionList', 'getStrokedBBox', 'getVisibleElements', 'getVisibleElementsAndBBoxes', 'groupSvgElem', 'getId', 'getNextId', 'call', 'bind', 'prepareSvg', 'setRotationAngle', 'recalculateAllSelectedDimensions', 'clearSelection', 'addToSelection', 'selectOnly', 'removeFromSelection', 'selectAllInCurrentLayer', 'getMouseTarget', 'removeUnusedDefElems', 'svgCanvasToString', 'svgToString', 'embedImage', 'setGoodImage', 'open', 'save', 'rasterExport', 'exportPDF', 'getSvgString', 'randomizeIds', 'uniquifyElems', 'setUseData', 'convertGradients', 'convertToGroup', 'setSvgString', 'importSvgString', 'identifyLayers', 'createLayer', 'cloneLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', 'moveSelectedToLayer', 'mergeLayer', 'mergeAllLayers', 'leaveContext', 'setContext', 'clear', 'linkControlPoints', 'getContentElem', 'getRootElem', 'getSelectedElems', 'getResolution', 'getZoom', 'getVersion', 'setUiStrings', 'setConfig', 'getTitle', 'setGroupTitle', 'getDocumentTitle', 'setDocumentTitle', 'getEditorNS', 'setResolution', 'getOffset', 'setBBoxZoom', 'setZoom', 'getMode', 'setMode', 'getColor', 'setColor', 'setGradient', 'setPaint', 'setStrokePaint', 'setFillPaint', 'getStrokeWidth', 'setStrokeWidth', 'setStrokeAttr', 'getStyle', 'getOpacity', 'setOpacity', 'getFillOpacity', 'getStrokeOpacity', 'setPaintOpacity', 'getPaintOpacity', 'getBlur', 'setBlurNoUndo', 'setBlurOffsets', 'setBlur', 'getBold', 'setBold', 'getItalic', 'setItalic', 'getFontFamily', 'setFontFamily', 'setFontColor', 'getFontColor', 'getFontSize', 'setFontSize', 'getText', 'setTextContent', 'setImageURL', 'setLinkURL', 'setRectRadius', 'makeHyperlink', 'removeHyperlink', 'setSegType', 'convertToPath', 'changeSelectedAttribute', 'deleteSelectedElements', 'cutSelectedElements', 'copySelectedElements', 'pasteElements', 'groupSelectedElements', 'pushGroupProperties', 'ungroupSelectedElement', 'moveToTopSelectedElement', 'moveToBottomSelectedElement', 'moveUpDownSelected', 'moveSelectedElements', 'cloneSelectedElements', 'alignSelectedElements', 'updateCanvas', 'setBackground', 'cycleElement', 'getPrivateMethods', 'zoomChanged', 'ready' + ]; - // TODO: rewrite the following, it's pretty scary. - for (i = 0; i < functions.length; i++) { - this[functions[i]] = getCallbackSetter(functions[i]); - } - - // Older IE may need a polyfill for addEventListener, but so it would for SVG - window.addEventListener('message', getMessageListener(this), false); + // TODO: rewrite the following, it's pretty scary. + for (i = 0; i < functions.length; i++) { + this[functions[i]] = getCallbackSetter(functions[i]); + } + + // Older IE may need a polyfill for addEventListener, but so it would for SVG + window.addEventListener('message', getMessageListener(this), false); } -EmbeddedSVGEdit.prototype.send = function (name, args, callback){ - var t = this; - cbid++; +EmbeddedSVGEdit.prototype.send = function (name, args, callback) { + var t = this; + cbid++; - this.callbacks[cbid] = callback; - setTimeout((function (cbid) { - return function () { // Delay for the callback to be set in case its synchronous - /* - * Todo: Handle non-JSON arguments and return values (undefined, - * nonfinite numbers, functions, and built-in objects like Date, - * RegExp), etc.? Allow promises instead of callbacks? Review - * SVG-Edit functions for whether JSON-able parameters can be - * made compatile with all API functionality - */ - // We accept and post strings for the sake of IE9 support - if (window.location.origin === t.frame.contentWindow.location.origin) { - // Although we do not really need this API if we are working same - // domain, it could allow us to write in a way that would work - // cross-domain as well, assuming we stick to the argument limitations - // of the current JSON-based communication API (e.g., not passing - // callbacks). We might be able to address these shortcomings; see - // the todo elsewhere in this file. - var message = {id: cbid}, - svgCanvas = t.frame.contentWindow.svgCanvas; - try { - message.result = svgCanvas[name].apply(svgCanvas, args); - } - catch (err) { - message.error = err.message; - } - addCallback(t, message); - } - else { // Requires the ext-xdomain-messaging.js extension - t.frame.contentWindow.postMessage(JSON.stringify({namespace: 'svgCanvas', id: cbid, name: name, args: args}), '*'); - } - }; - }(cbid)), 0); + this.callbacks[cbid] = callback; + setTimeout((function (cbid) { + return function () { // Delay for the callback to be set in case its synchronous + /* + * Todo: Handle non-JSON arguments and return values (undefined, + * nonfinite numbers, functions, and built-in objects like Date, + * RegExp), etc.? Allow promises instead of callbacks? Review + * SVG-Edit functions for whether JSON-able parameters can be + * made compatile with all API functionality + */ + // We accept and post strings for the sake of IE9 support + if (window.location.origin === t.frame.contentWindow.location.origin) { + // Although we do not really need this API if we are working same + // domain, it could allow us to write in a way that would work + // cross-domain as well, assuming we stick to the argument limitations + // of the current JSON-based communication API (e.g., not passing + // callbacks). We might be able to address these shortcomings; see + // the todo elsewhere in this file. + var message = {id: cbid}, + svgCanvas = t.frame.contentWindow.svgCanvas; + try { + message.result = svgCanvas[name].apply(svgCanvas, args); + } catch (err) { + message.error = err.message; + } + addCallback(t, message); + } else { // Requires the ext-xdomain-messaging.js extension + t.frame.contentWindow.postMessage(JSON.stringify({namespace: 'svgCanvas', id: cbid, name: name, args: args}), '*'); + } + }; + }(cbid)), 0); - return cbid; + return cbid; }; window.embedded_svg_edit = EmbeddedSVGEdit; // Export old, deprecated API window.EmbeddedSVGEdit = EmbeddedSVGEdit; // Follows common JS convention of CamelCase and, as enforced in JSLint, of initial caps for constructors - }()); diff --git a/editor/extensions/ext-arrows.js b/editor/extensions/ext-arrows.js index 6bf9b3fe..cd00b119 100644 --- a/editor/extensions/ext-arrows.js +++ b/editor/extensions/ext-arrows.js @@ -1,5 +1,5 @@ -/*globals svgEditor, svgCanvas, $*/ -/*jslint vars: true, eqeq: true*/ +/* eslint-disable no-var */ +/* globals svgEditor, svgCanvas, $ */ /* * ext-arrows.js * @@ -9,65 +9,64 @@ * */ -svgEditor.addExtension('Arrows', function(S) { - var svgcontent = S.svgcontent, +svgEditor.addExtension('Arrows', function (S) { + var // svgcontent = S.svgcontent, addElem = S.addSvgElementFromJson, nonce = S.nonce, - randomize_ids = S.randomize_ids, + randomizeIds = S.randomize_ids, selElems, pathdata, - lang_list = { - 'en':[ - {'id': 'arrow_none', 'textContent': 'No arrow' } + langList = { + 'en': [ + {'id': 'arrow_none', 'textContent': 'No arrow'} ], - 'fr':[ - {'id': 'arrow_none', 'textContent': 'Sans flèche' } + 'fr': [ + {'id': 'arrow_none', 'textContent': 'Sans flèche'} ] }, arrowprefix, prefix = 'se_arrow_'; - function setArrowNonce(window, n) { - randomize_ids = true; + function setArrowNonce (window, n) { + randomizeIds = true; arrowprefix = prefix + n + '_'; pathdata.fw.id = arrowprefix + 'fw'; pathdata.bk.id = arrowprefix + 'bk'; } - function unsetArrowNonce(window) { - randomize_ids = false; + function unsetArrowNonce (window) { + randomizeIds = false; arrowprefix = prefix; pathdata.fw.id = arrowprefix + 'fw'; pathdata.bk.id = arrowprefix + 'bk'; } - svgCanvas.bind('setnonce', setArrowNonce); svgCanvas.bind('unsetnonce', unsetArrowNonce); - if (randomize_ids) { + if (randomizeIds) { arrowprefix = prefix + nonce + '_'; } else { arrowprefix = prefix; } pathdata = { - fw: {d: 'm0,0l10,5l-10,5l5,-5l-5,-5z', refx: 8, id: arrowprefix + 'fw'}, + fw: {d: 'm0,0l10,5l-10,5l5,-5l-5,-5z', refx: 8, id: arrowprefix + 'fw'}, bk: {d: 'm10,0l-10,5l10,5l-5,-5l5,-5z', refx: 2, id: arrowprefix + 'bk'} }; - function getLinked(elem, attr) { + function getLinked (elem, attr) { var str = elem.getAttribute(attr); - if(!str) {return null;} - var m = str.match(/\(\#(.*)\)/); - if(!m || m.length !== 2) { + if (!str) { return null; } + var m = str.match(/\(#(.*)\)/); + if (!m || m.length !== 2) { return null; } return S.getElem(m[1]); } - function showPanel(on) { + function showPanel (on) { $('#arrow_panel').toggle(on); - if(on) { + if (on) { var el = selElems[0]; var end = el.getAttribute('marker-end'); var start = el.getAttribute('marker-start'); @@ -95,21 +94,21 @@ svgEditor.addExtension('Arrows', function(S) { } } - function resetMarker() { + function resetMarker () { var el = selElems[0]; el.removeAttribute('marker-start'); el.removeAttribute('marker-mid'); el.removeAttribute('marker-end'); } - function addMarker(dir, type, id) { + function addMarker (dir, type, id) { // TODO: Make marker (or use?) per arrow type, since refX can be different id = id || arrowprefix + dir; var marker = S.getElem(id); var data = pathdata[dir]; - if (type == 'mid') { + if (type === 'mid') { data.refx = 5; } @@ -143,25 +142,25 @@ svgEditor.addExtension('Arrows', function(S) { return marker; } - function setArrow() { + function setArrow () { var type = this.value; resetMarker(); - if (type == 'none') { + if (type === 'none') { return; } // Set marker on element var dir = 'fw'; - if (type == 'mid_bk') { + if (type === 'mid_bk') { type = 'mid'; dir = 'bk'; - } else if (type == 'both') { + } else if (type === 'both') { addMarker('bk', type); svgCanvas.changeSelectedAttribute('marker-start', 'url(#' + pathdata.bk.id + ')'); type = 'end'; dir = 'fw'; - } else if (type == 'start') { + } else if (type === 'start') { dir = 'bk'; } @@ -170,57 +169,57 @@ svgEditor.addExtension('Arrows', function(S) { S.call('changed', selElems); } - function colorChanged(elem) { + function colorChanged (elem) { var color = elem.getAttribute('stroke'); var mtypes = ['start', 'mid', 'end']; var defs = S.findDefs(); - $.each(mtypes, function(i, type) { - var marker = getLinked(elem, 'marker-'+type); - if(!marker) {return;} + $.each(mtypes, function (i, type) { + var marker = getLinked(elem, 'marker-' + type); + if (!marker) { return; } - var cur_color = $(marker).children().attr('fill'); - var cur_d = $(marker).children().attr('d'); - var new_marker = null; - if(cur_color === color) {return;} + var curColor = $(marker).children().attr('fill'); + var curD = $(marker).children().attr('d'); + var newMarker = null; + if (curColor === color) { return; } - var all_markers = $(defs).find('marker'); + var allMarkers = $(defs).find('marker'); // Different color, check if already made - all_markers.each(function() { + allMarkers.each(function () { var attrs = $(this).children().attr(['fill', 'd']); - if(attrs.fill === color && attrs.d === cur_d) { + if (attrs.fill === color && attrs.d === curD) { // Found another marker with this color and this path - new_marker = this; + newMarker = this; } }); - if(!new_marker) { + if (!newMarker) { // Create a new marker with this color - var last_id = marker.id; - var dir = last_id.indexOf('_fw') !== -1?'fw':'bk'; + var lastId = marker.id; + var dir = lastId.indexOf('_fw') !== -1 ? 'fw' : 'bk'; - new_marker = addMarker(dir, type, arrowprefix + dir + all_markers.length); + newMarker = addMarker(dir, type, arrowprefix + dir + allMarkers.length); - $(new_marker).children().attr('fill', color); + $(newMarker).children().attr('fill', color); } - $(elem).attr('marker-'+type, 'url(#' + new_marker.id + ')'); + $(elem).attr('marker-' + type, 'url(#' + newMarker.id + ')'); // Check if last marker can be removed var remove = true; - $(S.svgcontent).find('line, polyline, path, polygon').each(function() { + $(S.svgcontent).find('line, polyline, path, polygon').each(function () { var elem = this; - $.each(mtypes, function(j, mtype) { - if($(elem).attr('marker-' + mtype) === 'url(#' + marker.id + ')') { + $.each(mtypes, function (j, mtype) { + if ($(elem).attr('marker-' + mtype) === 'url(#' + marker.id + ')') { remove = false; return remove; } }); - if(!remove) {return false;} + if (!remove) { return false; } }); // Not found, so can safely remove - if(remove) { + if (remove) { $(marker).remove(); } }); @@ -246,26 +245,26 @@ svgEditor.addExtension('Arrows', function(S) { change: setArrow } }], - callback: function() { + callback: function () { $('#arrow_panel').hide(); // Set ID so it can be translated in locale file $('#arrow_list option')[0].id = 'connector_no_arrow'; }, - addLangData: function(lang) { + addLangData: function (lang) { return { - data: lang_list[lang] + data: langList[lang] }; }, - selectedChanged: function(opts) { + selectedChanged: function (opts) { // Use this to update the current selected elements selElems = opts.elems; var i = selElems.length; - var marker_elems = ['line', 'path', 'polyline', 'polygon']; - while(i--) { + var markerElems = ['line', 'path', 'polyline', 'polygon']; + while (i--) { var elem = selElems[i]; - if(elem && $.inArray(elem.tagName, marker_elems) !== -1) { - if(opts.selectedElement && !opts.multiselected) { + if (elem && $.inArray(elem.tagName, markerElems) !== -1) { + if (opts.selectedElement && !opts.multiselected) { showPanel(true); } else { showPanel(false); @@ -275,16 +274,16 @@ svgEditor.addExtension('Arrows', function(S) { } } }, - elementChanged: function(opts) { + elementChanged: function (opts) { var elem = opts.elems[0]; - if(elem && ( + if (elem && ( elem.getAttribute('marker-start') || elem.getAttribute('marker-mid') || elem.getAttribute('marker-end') )) { -// var start = elem.getAttribute('marker-start'); -// var mid = elem.getAttribute('marker-mid'); -// var end = elem.getAttribute('marker-end'); + // var start = elem.getAttribute('marker-start'); + // var mid = elem.getAttribute('marker-mid'); + // var end = elem.getAttribute('marker-end'); // Has marker, so see if it should match color colorChanged(elem); } diff --git a/editor/extensions/ext-closepath.js b/editor/extensions/ext-closepath.js index b7858424..23adae60 100644 --- a/editor/extensions/ext-closepath.js +++ b/editor/extensions/ext-closepath.js @@ -1,5 +1,5 @@ -/*globals svgEditor, $*/ -/*jslint vars: true, eqeq: true*/ +/* eslint-disable no-var */ +/* globals svgEditor, $ */ /* * ext-closepath.js * @@ -11,30 +11,31 @@ // This extension adds a simple button to the contextual panel for paths // The button toggles whether the path is open or closed -svgEditor.addExtension('ClosePath', function() {'use strict'; +svgEditor.addExtension('ClosePath', function () { + 'use strict'; var selElems, - updateButton = function(path) { + updateButton = function (path) { var seglist = path.pathSegList, - closed = seglist.getItem(seglist.numberOfItems - 1).pathSegType == 1, + closed = seglist.getItem(seglist.numberOfItems - 1).pathSegType === 1, showbutton = closed ? '#tool_openpath' : '#tool_closepath', hidebutton = closed ? '#tool_closepath' : '#tool_openpath'; - $(hidebutton).hide(); - $(showbutton).show(); + $(hidebutton).hide(); + $(showbutton).show(); }, - showPanel = function(on) { + showPanel = function (on) { $('#closepath_panel').toggle(on); if (on) { var path = selElems[0]; - if (path) {updateButton(path);} + if (path) { updateButton(path); } } }, - toggleClosed = function() { + toggleClosed = function () { var path = selElems[0]; if (path) { var seglist = path.pathSegList, last = seglist.numberOfItems - 1; // is closed - if (seglist.getItem(last).pathSegType == 1) { + if (seglist.getItem(last).pathSegType === 1) { seglist.removeItem(last); } else { seglist.appendItem(path.createSVGPathSegClosePath()); @@ -52,7 +53,7 @@ svgEditor.addExtension('ClosePath', function() {'use strict'; panel: 'closepath_panel', title: 'Open path', events: { - click: function() { + click: function () { toggleClosed(); } } @@ -63,20 +64,20 @@ svgEditor.addExtension('ClosePath', function() {'use strict'; panel: 'closepath_panel', title: 'Close path', events: { - click: function() { + click: function () { toggleClosed(); } } }], - callback: function() { + callback: function () { $('#closepath_panel').hide(); }, - selectedChanged: function(opts) { + selectedChanged: function (opts) { selElems = opts.elems; var i = selElems.length; while (i--) { var elem = selElems[i]; - if (elem && elem.tagName == 'path') { + if (elem && elem.tagName === 'path') { if (opts.selectedElement && !opts.multiselected) { showPanel(true); } else { diff --git a/editor/extensions/ext-connector.js b/editor/extensions/ext-connector.js index 9c6e631c..f41a5e15 100644 --- a/editor/extensions/ext-connector.js +++ b/editor/extensions/ext-connector.js @@ -1,5 +1,5 @@ -/*globals svgEditor, svgCanvas, $*/ -/*jslint vars: true, continue: true, eqeq: true, todo: true*/ +/* eslint-disable no-var */ +/* globals svgEditor, svgCanvas, $ */ /* * ext-connector.js * @@ -8,8 +8,8 @@ * Copyright(c) 2010 Alexis Deveria * */ - -svgEditor.addExtension("Connector", function(S) { + +svgEditor.addExtension('Connector', function (S) { var svgcontent = S.svgcontent, svgroot = S.svgroot, getNextId = S.getNextId, @@ -18,153 +18,151 @@ svgEditor.addExtension("Connector", function(S) { selManager = S.selectorManager, curConfig = svgEditor.curConfig, started = false, - start_x, - start_y, - cur_line, - start_elem, - end_elem, + startX, + startY, + curLine, + startElem, + endElem, connections = [], - conn_sel = ".se_connector", - se_ns, -// connect_str = "-SE_CONNECT-", + connSel = '.se_connector', + seNs, + // connect_str = '-SE_CONNECT-', selElems = [], elData = $.data; - - var lang_list = { - "en":[ - {"id": "mode_connect", "title": "Connect two objects" } + + var langList = { + 'en': [ + {'id': 'mode_connect', 'title': 'Connect two objects'} ], - "fr":[ - {"id": "mode_connect", "title": "Connecter deux objets"} + 'fr': [ + {'id': 'mode_connect', 'title': 'Connecter deux objets'} ] }; - function getBBintersect(x, y, bb, offset) { - if(offset) { + function getBBintersect (x, y, bb, offset) { + if (offset) { offset -= 0; bb = $.extend({}, bb); bb.width += offset; bb.height += offset; - bb.x -= offset/2; - bb.y -= offset/2; + bb.x -= offset / 2; + bb.y -= offset / 2; } - - var mid_x = bb.x + bb.width/2; - var mid_y = bb.y + bb.height/2; - var len_x = x - mid_x; - var len_y = y - mid_y; - - var slope = Math.abs(len_y/len_x); - + + var midX = bb.x + bb.width / 2; + var midY = bb.y + bb.height / 2; + var lenX = x - midX; + var lenY = y - midY; + + var slope = Math.abs(lenY / lenX); + var ratio; - - if(slope < bb.height/bb.width) { - ratio = (bb.width/2) / Math.abs(len_x); + + if (slope < bb.height / bb.width) { + ratio = (bb.width / 2) / Math.abs(lenX); } else { - ratio = (bb.height/2) / Math.abs(len_y); + ratio = (bb.height / 2) / Math.abs(lenY); } - - + return { - x: mid_x + len_x * ratio, - y: mid_y + len_y * ratio + x: midX + lenX * ratio, + y: midY + lenY * ratio }; } - function getOffset(side, line) { - var give_offset = !!line.getAttribute('marker-' + side); -// var give_offset = $(line).data(side+'_off'); + function getOffset (side, line) { + var giveOffset = !!line.getAttribute('marker-' + side); + // var giveOffset = $(line).data(side+'_off'); // TODO: Make this number (5) be based on marker width/height var size = line.getAttribute('stroke-width') * 5; - return give_offset ? size : 0; + return giveOffset ? size : 0; } - - function showPanel(on) { - var conn_rules = $('#connector_rules'); - if(!conn_rules.length) { - conn_rules = $('').appendTo('head'); - } - conn_rules.text(!on?"":"#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }"); + + function showPanel (on) { + var connRules = $('#connector_rules'); + if (!connRules.length) { + connRules = $('').appendTo('head'); + } + connRules.text(!on ? '' : '#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }'); $('#connector_panel').toggle(on); } - - function setPoint(elem, pos, x, y, setMid) { + + function setPoint (elem, pos, x, y, setMid) { var i, pts = elem.points; var pt = svgroot.createSVGPoint(); pt.x = x; pt.y = y; - if (pos === 'end') {pos = pts.numberOfItems - 1;} + if (pos === 'end') { pos = pts.numberOfItems - 1; } // TODO: Test for this on init, then use alt only if needed try { pts.replaceItem(pt, pos); - } catch(err) { + } catch (err) { // Should only occur in FF which formats points attr as "n,n n,n", so just split - var pt_arr = elem.getAttribute("points").split(" "); - for (i = 0; i < pt_arr.length; i++) { + var ptArr = elem.getAttribute('points').split(' '); + for (i = 0; i < ptArr.length; i++) { if (i === pos) { - pt_arr[i] = x + ',' + y; + ptArr[i] = x + ',' + y; } } - elem.setAttribute("points",pt_arr.join(" ")); + elem.setAttribute('points', ptArr.join(' ')); } - - if(setMid) { + + if (setMid) { // Add center point - var pt_start = pts.getItem(0); - var pt_end = pts.getItem(pts.numberOfItems-1); - setPoint(elem, 1, (pt_end.x + pt_start.x)/2, (pt_end.y + pt_start.y)/2); + var ptStart = pts.getItem(0); + var ptEnd = pts.getItem(pts.numberOfItems - 1); + setPoint(elem, 1, (ptEnd.x + ptStart.x) / 2, (ptEnd.y + ptStart.y) / 2); } } - - function updateLine(diff_x, diff_y) { + + function updateLine (diffX, diffY) { // Update line with element var i = connections.length; - while(i--) { + while (i--) { var conn = connections[i]; var line = conn.connector; - var elem = conn.elem; - - var pre = conn.is_start?'start':'end'; -// var sw = line.getAttribute('stroke-width') * 5; - - // Update bbox for this element - var bb = elData(line, pre+'_bb'); - bb.x = conn.start_x + diff_x; - bb.y = conn.start_y + diff_y; - elData(line, pre+'_bb', bb); - - var alt_pre = conn.is_start?'end':'start'; - - // Get center pt of connected element - var bb2 = elData(line, alt_pre+'_bb'); - var src_x = bb2.x + bb2.width/2; - var src_y = bb2.y + bb2.height/2; - - // Set point of element being moved - var pt = getBBintersect(src_x, src_y, bb, getOffset(pre, line)); // $(line).data(pre+'_off')?sw:0 - setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true); - - // Set point of connected element - var pt2 = getBBintersect(pt.x, pt.y, elData(line, alt_pre + '_bb'), getOffset(alt_pre, line)); - setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true); + // var elem = conn.elem; + var pre = conn.is_start ? 'start' : 'end'; + // var sw = line.getAttribute('stroke-width') * 5; + + // Update bbox for this element + var bb = elData(line, pre + '_bb'); + bb.x = conn.start_x + diffX; + bb.y = conn.start_y + diffY; + elData(line, pre + '_bb', bb); + + var altPre = conn.is_start ? 'end' : 'start'; + + // Get center pt of connected element + var bb2 = elData(line, altPre + '_bb'); + var srcX = bb2.x + bb2.width / 2; + var srcY = bb2.y + bb2.height / 2; + + // Set point of element being moved + var pt = getBBintersect(srcX, srcY, bb, getOffset(pre, line)); // $(line).data(pre+'_off')?sw:0 + setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true); + + // Set point of connected element + var pt2 = getBBintersect(pt.x, pt.y, elData(line, altPre + '_bb'), getOffset(altPre, line)); + setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true); } } - - function findConnectors(elems) { + + function findConnectors (elems) { var i; - if (!elems) {elems = selElems;} - var connectors = $(svgcontent).find(conn_sel); + if (!elems) { elems = selElems; } + var connectors = $(svgcontent).find(connSel); connections = []; // Loop through connectors to see if one is connected to the element - connectors.each(function() { - var add_this; + connectors.each(function () { + var addThis; function add () { if ($.inArray(this, elems) !== -1) { // Pretend this element is selected - add_this = true; + addThis = true; } } @@ -173,42 +171,42 @@ svgEditor.addExtension("Connector", function(S) { ['start', 'end'].forEach(function (pos, i) { var key = 'c_' + pos; var part = elData(this, key); - if(part == null) { + if (part == null) { part = document.getElementById( this.attributes['se:connector'].value.split(' ')[i] ); - elData(this, 'c_'+pos, part.id); - elData(this, pos+'_bb', svgCanvas.getStrokedBBox([part])); + elData(this, 'c_' + pos, part.id); + elData(this, pos + '_bb', svgCanvas.getStrokedBBox([part])); } else part = document.getElementById(part); parts.push(part); }.bind(this)); for (i = 0; i < 2; i++) { - var c_elem = parts[i]; + var cElem = parts[i]; - add_this = false; + addThis = false; // The connected element might be part of a selected group - $(c_elem).parents().each(add); - - if(!c_elem || !c_elem.parentNode) { + $(cElem).parents().each(add); + + if (!cElem || !cElem.parentNode) { $(this).remove(); continue; } - if($.inArray(c_elem, elems) !== -1 || add_this) { - var bb = svgCanvas.getStrokedBBox([c_elem]); + if ($.inArray(cElem, elems) !== -1 || addThis) { + var bb = svgCanvas.getStrokedBBox([cElem]); connections.push({ - elem: c_elem, + elem: cElem, connector: this, is_start: (i === 0), start_x: bb.x, start_y: bb.y - }); + }); } } }); } - - function updateConnectors(elems) { + + function updateConnectors (elems) { // Updates connector lines based on selected elements // Is not used on mousemove, as it runs getStrokedBBox every time, // which isn't necessary there. @@ -222,227 +220,222 @@ svgEditor.addExtension("Connector", function(S) { var line = conn.connector; var elem = conn.elem; - var sw = line.getAttribute('stroke-width') * 5; - var pre = conn.is_start?'start':'end'; - + // var sw = line.getAttribute('stroke-width') * 5; + var pre = conn.is_start ? 'start' : 'end'; + // Update bbox for this element var bb = svgCanvas.getStrokedBBox([elem]); bb.x = conn.start_x; bb.y = conn.start_y; - elData(line, pre+'_bb', bb); - var add_offset = elData(line, pre+'_off'); - - var alt_pre = conn.is_start?'end':'start'; - + elData(line, pre + '_bb', bb); + /* var addOffset = */ elData(line, pre + '_off'); + + var altPre = conn.is_start ? 'end' : 'start'; + // Get center pt of connected element - var bb2 = elData(line, alt_pre+'_bb'); - var src_x = bb2.x + bb2.width/2; - var src_y = bb2.y + bb2.height/2; - + var bb2 = elData(line, altPre + '_bb'); + var srcX = bb2.x + bb2.width / 2; + var srcY = bb2.y + bb2.height / 2; + // Set point of element being moved - var pt = getBBintersect(src_x, src_y, bb, getOffset(pre, line)); + var pt = getBBintersect(srcX, srcY, bb, getOffset(pre, line)); setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true); - + // Set point of connected element - var pt2 = getBBintersect(pt.x, pt.y, elData(line, alt_pre + '_bb'), getOffset(alt_pre, line)); + var pt2 = getBBintersect(pt.x, pt.y, elData(line, altPre + '_bb'), getOffset(altPre, line)); setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true); - + // Update points attribute manually for webkit if (navigator.userAgent.indexOf('AppleWebKit') !== -1) { var pts = line.points; var len = pts.numberOfItems; - var pt_arr = []; + var ptArr = []; for (j = 0; j < len; j++) { pt = pts.getItem(j); - pt_arr[j] = pt.x + ',' + pt.y; + ptArr[j] = pt.x + ',' + pt.y; } - line.setAttribute('points', pt_arr.join(' ')); + line.setAttribute('points', ptArr.join(' ')); } } } } - + // Do once - (function() { + (function () { var gse = svgCanvas.groupSelectedElements; - - svgCanvas.groupSelectedElements = function() { - svgCanvas.removeFromSelection($(conn_sel).toArray()); + + svgCanvas.groupSelectedElements = function () { + svgCanvas.removeFromSelection($(connSel).toArray()); return gse.apply(this, arguments); }; - + var mse = svgCanvas.moveSelectedElements; - - svgCanvas.moveSelectedElements = function() { + + svgCanvas.moveSelectedElements = function () { var cmd = mse.apply(this, arguments); updateConnectors(); return cmd; }; - - se_ns = svgCanvas.getEditorNS(); + + seNs = svgCanvas.getEditorNS(); }()); - + // Do on reset - function init() { + function init () { // Make sure all connectors have data set - $(svgcontent).find('*').each(function() { - var conn = this.getAttributeNS(se_ns, "connector"); - if(conn) { - this.setAttribute('class', conn_sel.substr(1)); - var conn_data = conn.split(' '); - var sbb = svgCanvas.getStrokedBBox([getElem(conn_data[0])]); - var ebb = svgCanvas.getStrokedBBox([getElem(conn_data[1])]); - $(this).data('c_start',conn_data[0]) - .data('c_end',conn_data[1]) + $(svgcontent).find('*').each(function () { + var conn = this.getAttributeNS(seNs, 'connector'); + if (conn) { + this.setAttribute('class', connSel.substr(1)); + var connData = conn.split(' '); + var sbb = svgCanvas.getStrokedBBox([getElem(connData[0])]); + var ebb = svgCanvas.getStrokedBBox([getElem(connData[1])]); + $(this).data('c_start', connData[0]) + .data('c_end', connData[1]) .data('start_bb', sbb) .data('end_bb', ebb); svgCanvas.getEditorNS(true); } }); -// updateConnectors(); + // updateConnectors(); } -// $(svgroot).parent().mousemove(function(e) { -// // if(started -// // || svgCanvas.getMode() != "connector" -// // || e.target.parentNode.parentNode != svgcontent) return; -// -// console.log('y') -// // if(e.target.parentNode.parentNode === svgcontent) { -// // -// // } -// }); + // $(svgroot).parent().mousemove(function (e) { + // // if (started + // // || svgCanvas.getMode() !== 'connector' + // // || e.target.parentNode.parentNode !== svgcontent) return; + // + // console.log('y') + // // if (e.target.parentNode.parentNode === svgcontent) { + // // + // // } + // }); return { - name: "Connector", - svgicons: svgEditor.curConfig.imgPath + "conn.svg", + name: 'Connector', + svgicons: svgEditor.curConfig.imgPath + 'conn.svg', buttons: [{ - id: "mode_connect", - type: "mode", - icon: svgEditor.curConfig.imgPath + "cut.png", - title: "Connect two objects", + id: 'mode_connect', + type: 'mode', + icon: svgEditor.curConfig.imgPath + 'cut.png', + title: 'Connect two objects', includeWith: { button: '#tool_line', isDefault: false, position: 1 }, events: { - 'click': function() { - svgCanvas.setMode("connector"); + 'click': function () { + svgCanvas.setMode('connector'); } } }], - addLangData: function(lang) { + addLangData: function (lang) { return { - data: lang_list[lang] + data: langList[lang] }; }, - mouseDown: function(opts) { + mouseDown: function (opts) { var e = opts.event; - start_x = opts.start_x; - start_y = opts.start_y; + startX = opts.start_x; + startY = opts.start_y; var mode = svgCanvas.getMode(); - - if (mode == "connector") { - - if (started) {return;} - var mouse_target = e.target; - - var parents = $(mouse_target).parents(); - - if($.inArray(svgcontent, parents) !== -1) { + if (mode === 'connector') { + if (started) { return; } + + var mouseTarget = e.target; + + var parents = $(mouseTarget).parents(); + + if ($.inArray(svgcontent, parents) !== -1) { // Connectable element - + // If child of foreignObject, use parent - var fo = $(mouse_target).closest("foreignObject"); - start_elem = fo.length ? fo[0] : mouse_target; - + var fo = $(mouseTarget).closest('foreignObject'); + startElem = fo.length ? fo[0] : mouseTarget; + // Get center of source element - var bb = svgCanvas.getStrokedBBox([start_elem]); - var x = bb.x + bb.width/2; - var y = bb.y + bb.height/2; - + var bb = svgCanvas.getStrokedBBox([startElem]); + var x = bb.x + bb.width / 2; + var y = bb.y + bb.height / 2; + started = true; - cur_line = addElem({ - "element": "polyline", - "attr": { - "id": getNextId(), - "points": (x+','+y+' '+x+','+y+' '+start_x+','+start_y), - "stroke": '#' + curConfig.initStroke.color, - "stroke-width": (!start_elem.stroke_width || start_elem.stroke_width == 0) ? curConfig.initStroke.width : start_elem.stroke_width, - "fill": "none", - "opacity": curConfig.initStroke.opacity, - "style": "pointer-events:none" + curLine = addElem({ + 'element': 'polyline', + 'attr': { + 'id': getNextId(), + 'points': (x + ',' + y + ' ' + x + ',' + y + ' ' + startX + ',' + startY), + 'stroke': '#' + curConfig.initStroke.color, + 'stroke-width': (!startElem.stroke_width || startElem.stroke_width === 0) ? curConfig.initStroke.width : startElem.stroke_width, + 'fill': 'none', + 'opacity': curConfig.initStroke.opacity, + 'style': 'pointer-events:none' } }); - elData(cur_line, 'start_bb', bb); + elData(curLine, 'start_bb', bb); } return { started: true }; } - if (mode == "select") { + if (mode === 'select') { findConnectors(); } }, - mouseMove: function(opts) { + mouseMove: function (opts) { var zoom = svgCanvas.getZoom(); - var e = opts.event; - var x = opts.mouse_x/zoom; - var y = opts.mouse_y/zoom; - - var diff_x = x - start_x, - diff_y = y - start_y; - + // var e = opts.event; + var x = opts.mouse_x / zoom; + var y = opts.mouse_y / zoom; + + var diffX = x - startX, + diffY = y - startY; + var mode = svgCanvas.getMode(); - - if (mode == "connector" && started) { - - var sw = cur_line.getAttribute('stroke-width') * 3; + + if (mode === 'connector' && started) { + // var sw = curLine.getAttribute('stroke-width') * 3; // Set start point (adjusts based on bb) - var pt = getBBintersect(x, y, elData(cur_line, 'start_bb'), getOffset('start', cur_line)); - start_x = pt.x; - start_y = pt.y; - - setPoint(cur_line, 0, pt.x, pt.y, true); - + var pt = getBBintersect(x, y, elData(curLine, 'start_bb'), getOffset('start', curLine)); + startX = pt.x; + startY = pt.y; + + setPoint(curLine, 0, pt.x, pt.y, true); + // Set end point - setPoint(cur_line, 'end', x, y, true); - } else if (mode == "select") { + setPoint(curLine, 'end', x, y, true); + } else if (mode === 'select') { var slen = selElems.length; - - while(slen--) { + + while (slen--) { var elem = selElems[slen]; // Look for selected connector elements - if(elem && elData(elem, 'c_start')) { + if (elem && elData(elem, 'c_start')) { // Remove the "translate" transform given to move svgCanvas.removeFromSelection([elem]); svgCanvas.getTransformList(elem).clear(); - } } - if(connections.length) { - updateLine(diff_x, diff_y); - - + if (connections.length) { + updateLine(diffX, diffY); } - } + } }, - mouseUp: function(opts) { - var zoom = svgCanvas.getZoom(); + mouseUp: function (opts) { + // var zoom = svgCanvas.getZoom(); var e = opts.event, - x = opts.mouse_x/zoom, - y = opts.mouse_y/zoom, - mouse_target = e.target; - - if(svgCanvas.getMode() == "connector") { - var fo = $(mouse_target).closest("foreignObject"); - if (fo.length) {mouse_target = fo[0];} - - var parents = $(mouse_target).parents(); + // x = opts.mouse_x / zoom, + // y = opts.mouse_y / zoom, + mouseTarget = e.target; - if (mouse_target == start_elem) { + if (svgCanvas.getMode() === 'connector') { + var fo = $(mouseTarget).closest('foreignObject'); + if (fo.length) { mouseTarget = fo[0]; } + + var parents = $(mouseTarget).parents(); + + if (mouseTarget === startElem) { // Start line through click started = true; return { @@ -453,7 +446,7 @@ svgEditor.addExtension("Connector", function(S) { } if ($.inArray(svgcontent, parents) === -1) { // Not a valid target element, so remove line - $(cur_line).remove(); + $(curLine).remove(); started = false; return { keep: false, @@ -462,66 +455,66 @@ svgEditor.addExtension("Connector", function(S) { }; } // Valid end element - end_elem = mouse_target; - - var start_id = start_elem.id, end_id = end_elem.id; - var conn_str = start_id + " " + end_id; - var alt_str = end_id + " " + start_id; + endElem = mouseTarget; + + var startId = startElem.id, endId = endElem.id; + var connStr = startId + ' ' + endId; + var altStr = endId + ' ' + startId; // Don't create connector if one already exists - var dupe = $(svgcontent).find(conn_sel).filter(function() { - var conn = this.getAttributeNS(se_ns, "connector"); - if (conn == conn_str || conn == alt_str) {return true;} + var dupe = $(svgcontent).find(connSel).filter(function () { + var conn = this.getAttributeNS(seNs, 'connector'); + if (conn === connStr || conn === altStr) { return true; } }); - if(dupe.length) { - $(cur_line).remove(); + if (dupe.length) { + $(curLine).remove(); return { keep: false, element: null, started: false }; } - - var bb = svgCanvas.getStrokedBBox([end_elem]); - - var pt = getBBintersect(start_x, start_y, bb, getOffset('start', cur_line)); - setPoint(cur_line, 'end', pt.x, pt.y, true); - $(cur_line) - .data("c_start", start_id) - .data("c_end", end_id) - .data("end_bb", bb); - se_ns = svgCanvas.getEditorNS(true); - cur_line.setAttributeNS(se_ns, "se:connector", conn_str); - cur_line.setAttribute('class', conn_sel.substr(1)); - cur_line.setAttribute('opacity', 1); - svgCanvas.addToSelection([cur_line]); + + var bb = svgCanvas.getStrokedBBox([endElem]); + + var pt = getBBintersect(startX, startY, bb, getOffset('start', curLine)); + setPoint(curLine, 'end', pt.x, pt.y, true); + $(curLine) + .data('c_start', startId) + .data('c_end', endId) + .data('end_bb', bb); + seNs = svgCanvas.getEditorNS(true); + curLine.setAttributeNS(seNs, 'se:connector', connStr); + curLine.setAttribute('class', connSel.substr(1)); + curLine.setAttribute('opacity', 1); + svgCanvas.addToSelection([curLine]); svgCanvas.moveToBottomSelectedElement(); - selManager.requestSelector(cur_line).showGrips(false); + selManager.requestSelector(curLine).showGrips(false); started = false; return { keep: true, - element: cur_line, + element: curLine, started: started }; } }, - selectedChanged: function(opts) { + selectedChanged: function (opts) { // TODO: Find better way to skip operations if no connectors are in use - if(!$(svgcontent).find(conn_sel).length) {return;} - - if(svgCanvas.getMode() == 'connector') { + if (!$(svgcontent).find(connSel).length) { return; } + + if (svgCanvas.getMode() === 'connector') { svgCanvas.setMode('select'); } - + // Use this to update the current selected elements selElems = opts.elems; - + var i = selElems.length; - - while(i--) { + + while (i--) { var elem = selElems[i]; - if(elem && elData(elem, 'c_start')) { + if (elem && elData(elem, 'c_start')) { selManager.requestSelector(elem).showGrips(false); - if(opts.selectedElement && !opts.multiselected) { + if (opts.selectedElement && !opts.multiselected) { // TODO: Set up context tools and hide most regular line tools showPanel(true); } else { @@ -533,48 +526,48 @@ svgEditor.addExtension("Connector", function(S) { } updateConnectors(); }, - elementChanged: function(opts) { + elementChanged: function (opts) { var elem = opts.elems[0]; if (elem && elem.tagName === 'svg' && elem.id === 'svgcontent') { // Update svgcontent (can change on import) svgcontent = elem; init(); } - + // Has marker, so change offset var start; if (elem && ( - elem.getAttribute("marker-start") || - elem.getAttribute("marker-mid") || - elem.getAttribute("marker-end") + elem.getAttribute('marker-start') || + elem.getAttribute('marker-mid') || + elem.getAttribute('marker-end') )) { - start = elem.getAttribute("marker-start"); - var mid = elem.getAttribute("marker-mid"); - var end = elem.getAttribute("marker-end"); - cur_line = elem; + start = elem.getAttribute('marker-start'); + var mid = elem.getAttribute('marker-mid'); + var end = elem.getAttribute('marker-end'); + curLine = elem; $(elem) - .data("start_off", !!start) - .data("end_off", !!end); - + .data('start_off', !!start) + .data('end_off', !!end); + if (elem.tagName === 'line' && mid) { // Convert to polyline to accept mid-arrow - + var x1 = Number(elem.getAttribute('x1')); var x2 = Number(elem.getAttribute('x2')); var y1 = Number(elem.getAttribute('y1')); var y2 = Number(elem.getAttribute('y2')); var id = elem.id; - - var mid_pt = (' '+((x1+x2)/2)+','+((y1+y2)/2) + ' '); + + var midPt = (' ' + ((x1 + x2) / 2) + ',' + ((y1 + y2) / 2) + ' '); var pline = addElem({ - "element": "polyline", - "attr": { - "points": (x1+','+y1+ mid_pt +x2+','+y2), - "stroke": elem.getAttribute('stroke'), - "stroke-width": elem.getAttribute('stroke-width'), - "marker-mid": mid, - "fill": "none", - "opacity": elem.getAttribute('opacity') || 1 + 'element': 'polyline', + 'attr': { + 'points': (x1 + ',' + y1 + midPt + x2 + ',' + y2), + 'stroke': elem.getAttribute('stroke'), + 'stroke-width': elem.getAttribute('stroke-width'), + 'marker-mid': mid, + 'fill': 'none', + 'opacity': elem.getAttribute('opacity') || 1 } }); $(elem).after(pline).remove(); @@ -585,36 +578,37 @@ svgEditor.addExtension("Connector", function(S) { } } // Update line if it's a connector - if (elem.getAttribute('class') == conn_sel.substr(1)) { + if (elem.getAttribute('class') === connSel.substr(1)) { start = getElem(elData(elem, 'c_start')); updateConnectors([start]); } else { updateConnectors(); } }, - IDsUpdated: function(input) { + IDsUpdated: function (input) { var remove = []; - input.elems.forEach(function(elem){ - if('se:connector' in elem.attr) { + input.elems.forEach(function (elem) { + if ('se:connector' in elem.attr) { elem.attr['se:connector'] = elem.attr['se:connector'].split(' ') - .map(function(oldID){ return input.changes[oldID] }).join(' '); + .map(function (oldID) { return input.changes[oldID]; }).join(' '); // Check validity - the field would be something like 'svg_21 svg_22', but // if one end is missing, it would be 'svg_21' and therefore fail this test - if(!/. ./.test(elem.attr['se:connector'])) + if (!/. ./.test(elem.attr['se:connector'])) { remove.push(elem.attr.id); + } } }); return {remove: remove}; }, - toolButtonStateUpdate: function(opts) { + toolButtonStateUpdate: function (opts) { if (opts.nostroke) { if ($('#mode_connect').hasClass('tool_button_current')) { svgEditor.clickSelect(); } } $('#mode_connect') - .toggleClass('disabled',opts.nostroke); + .toggleClass('disabled', opts.nostroke); } }; }); diff --git a/editor/extensions/ext-eyedropper.js b/editor/extensions/ext-eyedropper.js index cc4961ca..00d3e303 100644 --- a/editor/extensions/ext-eyedropper.js +++ b/editor/extensions/ext-eyedropper.js @@ -1,5 +1,5 @@ -/*globals svgEditor, svgedit, $*/ -/*jslint vars: true, eqeq: true*/ +/* eslint-disable no-var */ +/* globals svgEditor, svgedit, $ */ /* * ext-eyedropper.js * @@ -15,26 +15,27 @@ // 3) svg_editor.js // 4) svgcanvas.js -svgEditor.addExtension("eyedropper", function(S) {'use strict'; +svgEditor.addExtension('eyedropper', function (S) { + 'use strict'; var // NS = svgedit.NS, // svgcontent = S.svgcontent, // svgdoc = S.svgroot.parentNode.ownerDocument, svgCanvas = svgEditor.canvas, ChangeElementCommand = svgedit.history.ChangeElementCommand, - addToHistory = function(cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); }, + addToHistory = function (cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); }, currentStyle = { - fillPaint: "red", fillOpacity: 1.0, - strokePaint: "black", strokeOpacity: 1.0, + fillPaint: 'red', fillOpacity: 1.0, + strokePaint: 'black', strokeOpacity: 1.0, strokeWidth: 5, strokeDashArray: null, opacity: 1.0, strokeLinecap: 'butt', strokeLinejoin: 'miter' }; - function getStyle(opts) { + function getStyle (opts) { // if we are in eyedropper mode, we don't want to disable the eye-dropper tool var mode = svgCanvas.getMode(); - if (mode == "eyedropper") {return;} + if (mode === 'eyedropper') { return; } var elem = null; var tool = $('#tool_eyedropper'); @@ -45,65 +46,63 @@ svgEditor.addExtension("eyedropper", function(S) {'use strict'; elem = opts.elems[0]; tool.removeClass('disabled'); // grab the current style - currentStyle.fillPaint = elem.getAttribute("fill") || "black"; - currentStyle.fillOpacity = elem.getAttribute("fill-opacity") || 1.0; - currentStyle.strokePaint = elem.getAttribute("stroke"); - currentStyle.strokeOpacity = elem.getAttribute("stroke-opacity") || 1.0; - currentStyle.strokeWidth = elem.getAttribute("stroke-width"); - currentStyle.strokeDashArray = elem.getAttribute("stroke-dasharray"); - currentStyle.strokeLinecap = elem.getAttribute("stroke-linecap"); - currentStyle.strokeLinejoin = elem.getAttribute("stroke-linejoin"); - currentStyle.opacity = elem.getAttribute("opacity") || 1.0; - } + currentStyle.fillPaint = elem.getAttribute('fill') || 'black'; + currentStyle.fillOpacity = elem.getAttribute('fill-opacity') || 1.0; + currentStyle.strokePaint = elem.getAttribute('stroke'); + currentStyle.strokeOpacity = elem.getAttribute('stroke-opacity') || 1.0; + currentStyle.strokeWidth = elem.getAttribute('stroke-width'); + currentStyle.strokeDashArray = elem.getAttribute('stroke-dasharray'); + currentStyle.strokeLinecap = elem.getAttribute('stroke-linecap'); + currentStyle.strokeLinejoin = elem.getAttribute('stroke-linejoin'); + currentStyle.opacity = elem.getAttribute('opacity') || 1.0; // disable eye-dropper tool - else { + } else { tool.addClass('disabled'); } - } - + return { - name: "eyedropper", - svgicons: svgEditor.curConfig.extPath + "eyedropper-icon.xml", + name: 'eyedropper', + svgicons: svgEditor.curConfig.extPath + 'eyedropper-icon.xml', buttons: [{ - id: "tool_eyedropper", - type: "mode", - title: "Eye Dropper Tool", - key: "I", + id: 'tool_eyedropper', + type: 'mode', + title: 'Eye Dropper Tool', + key: 'I', events: { - "click": function() { - svgCanvas.setMode("eyedropper"); + click: function () { + svgCanvas.setMode('eyedropper'); } } }], - + // if we have selected an element, grab its paint and enable the eye dropper button selectedChanged: getStyle, elementChanged: getStyle, - - mouseDown: function(opts) { + + mouseDown: function (opts) { var mode = svgCanvas.getMode(); - if (mode == "eyedropper") { + if (mode === 'eyedropper') { var e = opts.event; var target = e.target; if ($.inArray(target.nodeName, ['svg', 'g', 'use']) === -1) { var changes = {}; - var change = function(elem, attrname, newvalue) { + var change = function (elem, attrname, newvalue) { changes[attrname] = elem.getAttribute(attrname); elem.setAttribute(attrname, newvalue); }; - - if (currentStyle.fillPaint) {change(target, "fill", currentStyle.fillPaint);} - if (currentStyle.fillOpacity) {change(target, "fill-opacity", currentStyle.fillOpacity);} - if (currentStyle.strokePaint) {change(target, "stroke", currentStyle.strokePaint);} - if (currentStyle.strokeOpacity) {change(target, "stroke-opacity", currentStyle.strokeOpacity);} - if (currentStyle.strokeWidth) {change(target, "stroke-width", currentStyle.strokeWidth);} - if (currentStyle.strokeDashArray) {change(target, "stroke-dasharray", currentStyle.strokeDashArray);} - if (currentStyle.opacity) {change(target, "opacity", currentStyle.opacity);} - if (currentStyle.strokeLinecap) {change(target, "stroke-linecap", currentStyle.strokeLinecap);} - if (currentStyle.strokeLinejoin) {change(target, "stroke-linejoin", currentStyle.strokeLinejoin);} - + + if (currentStyle.fillPaint) { change(target, 'fill', currentStyle.fillPaint); } + if (currentStyle.fillOpacity) { change(target, 'fill-opacity', currentStyle.fillOpacity); } + if (currentStyle.strokePaint) { change(target, 'stroke', currentStyle.strokePaint); } + if (currentStyle.strokeOpacity) { change(target, 'stroke-opacity', currentStyle.strokeOpacity); } + if (currentStyle.strokeWidth) { change(target, 'stroke-width', currentStyle.strokeWidth); } + if (currentStyle.strokeDashArray) { change(target, 'stroke-dasharray', currentStyle.strokeDashArray); } + if (currentStyle.opacity) { change(target, 'opacity', currentStyle.opacity); } + if (currentStyle.strokeLinecap) { change(target, 'stroke-linecap', currentStyle.strokeLinecap); } + if (currentStyle.strokeLinejoin) { change(target, 'stroke-linejoin', currentStyle.strokeLinejoin); } + addToHistory(new ChangeElementCommand(target, changes)); } } diff --git a/editor/extensions/ext-foreignobject.js b/editor/extensions/ext-foreignobject.js index 136485a9..fec8cd22 100644 --- a/editor/extensions/ext-foreignobject.js +++ b/editor/extensions/ext-foreignobject.js @@ -1,20 +1,20 @@ -/*globals svgEditor, svgedit, svgCanvas, $*/ -/*jslint vars: true, eqeq: true, todo: true*/ +/* eslint-disable no-var */ +/* globals svgEditor, svgedit, svgCanvas, $ */ /* * ext-foreignobject.js * * Licensed under the Apache License, Version 2 * - * Copyright(c) 2010 Jacques Distler - * Copyright(c) 2010 Alexis Deveria + * Copyright(c) 2010 Jacques Distler + * Copyright(c) 2010 Alexis Deveria * */ -svgEditor.addExtension("foreignObject", function(S) { +svgEditor.addExtension('foreignObject', function (S) { var NS = svgedit.NS, Utils = svgedit.utilities, - svgcontent = S.svgcontent, - addElem = S.addSvgElementFromJson, + // svgcontent = S.svgcontent, + // addElem = S.addSvgElementFromJson, selElems, editingforeign = false, svgdoc = S.svgroot.parentNode.ownerDocument, @@ -27,16 +27,16 @@ svgEditor.addExtension("foreignObject", function(S) { $('#svg_source_textarea').css('height', height); }; - function showPanel(on) { - var fc_rules = $('#fc_rules'); - if(!fc_rules.length) { - fc_rules = $('').appendTo('head'); + function showPanel (on) { + var fcRules = $('#fc_rules'); + if (!fcRules.length) { + fcRules = $('').appendTo('head'); } - fc_rules.text(!on?"":" #tool_topath { display: none !important; }"); + fcRules.text(!on ? '' : ' #tool_topath { display: none !important; }'); $('#foreignObject_panel').toggle(on); } - function toggleSourceButtons(on) { + function toggleSourceButtons (on) { $('#tool_source_save, #tool_source_cancel').toggle(!on); $('#foreign_save, #foreign_cancel').toggle(on); } @@ -50,7 +50,7 @@ svgEditor.addExtension("foreignObject", function(S) { // // Returns: // This function returns false if the set was unsuccessful, true otherwise. - function setForeignString(xmlString) { + function setForeignString (xmlString) { var elt = selElems[0]; try { // convert string into XML document @@ -58,9 +58,9 @@ svgEditor.addExtension("foreignObject", function(S) { // run it through our sanitizer to remove anything we do not support S.sanitizeSvg(newDoc.documentElement); elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt); - S.call("changed", [elt]); + S.call('changed', [elt]); svgCanvas.clearSelection(); - } catch(e) { + } catch (e) { console.log(e); return false; } @@ -68,9 +68,9 @@ svgEditor.addExtension("foreignObject", function(S) { return true; } - function showForeignEditor() { + function showForeignEditor () { var elt = selElems[0]; - if (!elt || editingforeign) {return;} + if (!elt || editingforeign) { return; } editingforeign = true; toggleSourceButtons(true); elt.removeAttribute('fill'); @@ -82,78 +82,78 @@ svgEditor.addExtension("foreignObject", function(S) { $('#svg_source_textarea').focus(); } - function setAttr(attr, val) { + function setAttr (attr, val) { svgCanvas.changeSelectedAttribute(attr, val); - S.call("changed", selElems); + S.call('changed', selElems); } return { - name: "foreignObject", - svgicons: svgEditor.curConfig.extPath + "foreignobject-icons.xml", + name: 'foreignObject', + svgicons: svgEditor.curConfig.extPath + 'foreignobject-icons.xml', buttons: [{ - id: "tool_foreign", - type: "mode", - title: "Foreign Object Tool", + id: 'tool_foreign', + type: 'mode', + title: 'Foreign Object Tool', events: { - 'click': function() { + 'click': function () { svgCanvas.setMode('foreign'); } } - },{ - id: "edit_foreign", - type: "context", - panel: "foreignObject_panel", - title: "Edit ForeignObject Content", + }, { + id: 'edit_foreign', + type: 'context', + panel: 'foreignObject_panel', + title: 'Edit ForeignObject Content', events: { - 'click': function() { + 'click': function () { showForeignEditor(); } } }], context_tools: [{ - type: "input", - panel: "foreignObject_panel", + type: 'input', + panel: 'foreignObject_panel', title: "Change foreignObject's width", - id: "foreign_width", - label: "w", + id: 'foreign_width', + label: 'w', size: 3, events: { - change: function() { + change: function () { setAttr('width', this.value); } } - },{ - type: "input", - panel: "foreignObject_panel", + }, { + type: 'input', + panel: 'foreignObject_panel', title: "Change foreignObject's height", - id: "foreign_height", - label: "h", + id: 'foreign_height', + label: 'h', events: { - change: function() { + change: function () { setAttr('height', this.value); } } }, { - type: "input", - panel: "foreignObject_panel", + type: 'input', + panel: 'foreignObject_panel', title: "Change foreignObject's font size", - id: "foreign_font_size", - label: "font-size", + id: 'foreign_font_size', + label: 'font-size', size: 2, defval: 16, events: { - change: function() { + change: function () { setAttr('font-size', this.value); } } } ], - callback: function() { + callback: function () { $('#foreignObject_panel').hide(); - var endChanges = function() { + var endChanges = function () { $('#svg_source_editor').hide(); editingforeign = false; $('#svg_source_textarea').blur(); @@ -161,48 +161,46 @@ svgEditor.addExtension("foreignObject", function(S) { }; // TODO: Needs to be done after orig icon loads - setTimeout(function() { + setTimeout(function () { // Create source save/cancel buttons - var save = $('#tool_source_save').clone() + /* var save = */ $('#tool_source_save').clone() .hide().attr('id', 'foreign_save').unbind() - .appendTo("#tool_source_back").click(function() { - - if (!editingforeign) {return;} + .appendTo('#tool_source_back').click(function () { + if (!editingforeign) { return; } if (!setForeignString($('#svg_source_textarea').val())) { - $.confirm("Errors found. Revert to original?", function(ok) { - if(!ok) {return false;} + $.confirm('Errors found. Revert to original?', function (ok) { + if (!ok) { return false; } endChanges(); }); } else { endChanges(); } - // setSelectMode(); + // setSelectMode(); }); - var cancel = $('#tool_source_cancel').clone() + /* var cancel = */ $('#tool_source_cancel').clone() .hide().attr('id', 'foreign_cancel').unbind() - .appendTo("#tool_source_back").click(function() { + .appendTo('#tool_source_back').click(function () { endChanges(); }); }, 3000); }, - mouseDown: function(opts) { - var e = opts.event; - - if(svgCanvas.getMode() == "foreign") { + mouseDown: function (opts) { + // var e = opts.event; + if (svgCanvas.getMode() === 'foreign') { started = true; newFO = S.addSvgElementFromJson({ - "element": "foreignObject", - "attr": { - "x": opts.start_x, - "y": opts.start_y, - "id": S.getNextId(), - "font-size": 16, //cur_text.font_size, - "width": "48", - "height": "20", - "style": "pointer-events:inherit" + 'element': 'foreignObject', + 'attr': { + 'x': opts.start_x, + 'y': opts.start_y, + 'id': S.getNextId(), + 'font-size': 16, // cur_text.font_size, + 'width': '48', + 'height': '20', + 'style': 'pointer-events:inherit' } }); var m = svgdoc.createElementNS(NS.MATH, 'math'); @@ -210,11 +208,11 @@ svgEditor.addExtension("foreignObject", function(S) { m.setAttribute('display', 'inline'); var mi = svgdoc.createElementNS(NS.MATH, 'mi'); mi.setAttribute('mathvariant', 'normal'); - mi.textContent = "\u03A6"; + mi.textContent = '\u03A6'; var mo = svgdoc.createElementNS(NS.MATH, 'mo'); - mo.textContent = "\u222A"; + mo.textContent = '\u222A'; var mi2 = svgdoc.createElementNS(NS.MATH, 'mi'); - mi2.textContent = "\u2133"; + mi2.textContent = '\u2133'; m.appendChild(mi); m.appendChild(mo); m.appendChild(mi2); @@ -224,34 +222,32 @@ svgEditor.addExtension("foreignObject", function(S) { }; } }, - mouseUp: function(opts) { - var e = opts.event; - if(svgCanvas.getMode() == "foreign" && started) { - var attrs = $(newFO).attr(["width", "height"]); - var keep = (attrs.width != 0 || attrs.height != 0); + mouseUp: function (opts) { + // var e = opts.event; + if (svgCanvas.getMode() === 'foreign' && started) { + var attrs = $(newFO).attr(['width', 'height']); + var keep = (attrs.width !== '0' || attrs.height !== '0'); svgCanvas.addToSelection([newFO], true); return { keep: keep, element: newFO }; - } - }, - selectedChanged: function(opts) { + selectedChanged: function (opts) { // Use this to update the current selected elements selElems = opts.elems; var i = selElems.length; - while(i--) { + while (i--) { var elem = selElems[i]; - if(elem && elem.tagName === 'foreignObject') { - if(opts.selectedElement && !opts.multiselected) { - $('#foreign_font_size').val(elem.getAttribute("font-size")); - $('#foreign_width').val(elem.getAttribute("width")); - $('#foreign_height').val(elem.getAttribute("height")); + if (elem && elem.tagName === 'foreignObject') { + if (opts.selectedElement && !opts.multiselected) { + $('#foreign_font_size').val(elem.getAttribute('font-size')); + $('#foreign_width').val(elem.getAttribute('width')); + $('#foreign_height').val(elem.getAttribute('height')); showPanel(true); } else { showPanel(false); @@ -261,8 +257,8 @@ svgEditor.addExtension("foreignObject", function(S) { } } }, - elementChanged: function(opts) { - var elem = opts.elems[0]; + elementChanged: function (opts) { + // var elem = opts.elems[0]; } }; }); diff --git a/editor/extensions/ext-grid.js b/editor/extensions/ext-grid.js index a4148da7..c857a9a8 100644 --- a/editor/extensions/ext-grid.js +++ b/editor/extensions/ext-grid.js @@ -1,5 +1,5 @@ -/*globals svgEditor, svgedit, svgCanvas, $*/ -/*jslint vars: true*/ +/* eslint-disable no-var */ +/* globals svgEditor, svgedit, svgCanvas, $ */ /* * ext-grid.js * @@ -14,7 +14,8 @@ // 1) units.js // 2) everything else -svgEditor.addExtension('view_grid', function() { 'use strict'; +svgEditor.addExtension('view_grid', function () { + 'use strict'; var NS = svgedit.NS, svgdoc = document.getElementById('svgcanvas').ownerDocument, @@ -44,8 +45,8 @@ svgEditor.addExtension('view_grid', function() { 'use strict'; assignAttributes(gridPattern, { 'id': 'gridpattern', 'patternUnits': 'userSpaceOnUse', - 'x': 0, //-(value.strokeWidth / 2), // position for strokewidth - 'y': 0, //-(value.strokeWidth / 2), // position for strokewidth + 'x': 0, // -(value.strokeWidth / 2), // position for strokewidth + 'y': 0, // -(value.strokeWidth / 2), // position for strokewidth 'width': 100, 'height': 100 }); @@ -74,56 +75,56 @@ svgEditor.addExtension('view_grid', function() { 'use strict'; }); $('#canvasGrid').append(gridBox); - function updateGrid(zoom) { + function updateGrid (zoom) { var i; // TODO: Try this with elements, then compare performance difference var unit = units[svgEditor.curConfig.baseUnit]; // 1 = 1px - var u_multi = unit * zoom; + var uMulti = unit * zoom; // Calculate the main number interval - var raw_m = 100 / u_multi; + var rawM = 100 / uMulti; var multi = 1; for (i = 0; i < intervals.length; i++) { var num = intervals[i]; multi = num; - if (raw_m <= num) { + if (rawM <= num) { break; } } - var big_int = multi * u_multi; + var bigInt = multi * uMulti; // Set the canvas size to the width of the container - hcanvas.width = big_int; - hcanvas.height = big_int; + hcanvas.width = bigInt; + hcanvas.height = bigInt; var ctx = hcanvas.getContext('2d'); - var cur_d = 0.5; - var part = big_int / 10; + var curD = 0.5; + var part = bigInt / 10; ctx.globalAlpha = 0.2; ctx.strokeStyle = svgEditor.curConfig.gridColor; for (i = 1; i < 10; i++) { - var sub_d = Math.round(part * i) + 0.5; - // var line_num = (i % 2)?12:10; - var line_num = 0; - ctx.moveTo(sub_d, big_int); - ctx.lineTo(sub_d, line_num); - ctx.moveTo(big_int, sub_d); - ctx.lineTo(line_num ,sub_d); + var subD = Math.round(part * i) + 0.5; + // var lineNum = (i % 2)?12:10; + var lineNum = 0; + ctx.moveTo(subD, bigInt); + ctx.lineTo(subD, lineNum); + ctx.moveTo(bigInt, subD); + ctx.lineTo(lineNum, subD); } ctx.stroke(); ctx.beginPath(); ctx.globalAlpha = 0.5; - ctx.moveTo(cur_d, big_int); - ctx.lineTo(cur_d, 0); + ctx.moveTo(curD, bigInt); + ctx.lineTo(curD, 0); - ctx.moveTo(big_int, cur_d); - ctx.lineTo(0, cur_d); + ctx.moveTo(bigInt, curD); + ctx.lineTo(0, curD); ctx.stroke(); var datauri = hcanvas.toDataURL('image/png'); - gridimg.setAttribute('width', big_int); - gridimg.setAttribute('height', big_int); - gridimg.parentNode.setAttribute('width', big_int); - gridimg.parentNode.setAttribute('height', big_int); + gridimg.setAttribute('width', bigInt); + gridimg.setAttribute('height', bigInt); + gridimg.parentNode.setAttribute('width', bigInt); + gridimg.parentNode.setAttribute('height', bigInt); svgCanvas.setHref(gridimg, datauri); } @@ -138,8 +139,8 @@ svgEditor.addExtension('view_grid', function() { 'use strict'; name: 'view_grid', svgicons: svgEditor.curConfig.extPath + 'grid-icon.xml', - zoomChanged: function(zoom) { - if (showGrid) {updateGrid(zoom);} + zoomChanged: function (zoom) { + if (showGrid) { updateGrid(zoom); } }, callback: function () { if (showGrid) { @@ -152,7 +153,7 @@ svgEditor.addExtension('view_grid', function() { 'use strict'; panel: 'editor_panel', title: 'Show/Hide Grid', events: { - click: function() { + click: function () { svgEditor.curConfig.showGrid = showGrid = !showGrid; gridUpdate(); } diff --git a/editor/extensions/ext-helloworld.js b/editor/extensions/ext-helloworld.js index eb67efce..742816af 100644 --- a/editor/extensions/ext-helloworld.js +++ b/editor/extensions/ext-helloworld.js @@ -1,5 +1,5 @@ -/*globals svgEditor, svgCanvas, $*/ -/*jslint vars: true, eqeq: true*/ +/* eslint-disable no-var */ +/* globals svgEditor, svgCanvas, $ */ /* * ext-helloworld.js * @@ -8,73 +8,72 @@ * Copyright(c) 2010 Alexis Deveria * */ - -/* + +/* This is a very basic SVG-Edit extension. It adds a "Hello World" button in the left panel. Clicking on the button, and then the canvas will show the user the point on the canvas that was clicked on. */ - -svgEditor.addExtension("Hello World", function() {'use strict'; - return { - name: "Hello World", - // For more notes on how to make an icon file, see the source of - // the helloworld-icon.xml - svgicons: svgEditor.curConfig.extPath + "helloworld-icon.xml", - - // Multiple buttons can be added in this array - buttons: [{ - // Must match the icon ID in helloworld-icon.xml - id: "hello_world", - - // This indicates that the button will be added to the "mode" - // button panel on the left side - type: "mode", - - // Tooltip text - title: "Say 'Hello World'", - - // Events - events: { - 'click': function() { - // The action taken when the button is clicked on. - // For "mode" buttons, any other button will - // automatically be de-pressed. - svgCanvas.setMode("hello_world"); - } - } - }], - // This is triggered when the main mouse button is pressed down - // on the editor canvas (not the tool panels) - mouseDown: function() { - // Check the mode on mousedown - if(svgCanvas.getMode() == "hello_world") { - - // The returned object must include "started" with - // a value of true in order for mouseUp to be triggered - return {started: true}; - } - }, - - // This is triggered from anywhere, but "started" must have been set - // to true (see above). Note that "opts" is an object with event info - mouseUp: function(opts) { - // Check the mode on mouseup - if(svgCanvas.getMode() == "hello_world") { - var zoom = svgCanvas.getZoom(); - - // Get the actual coordinate by dividing by the zoom value - var x = opts.mouse_x / zoom; - var y = opts.mouse_y / zoom; - - var text = "Hello World!\n\nYou clicked here: " - + x + ", " + y; - - // Show the text using the custom alert function - $.alert(text); +svgEditor.addExtension('Hello World', function () { + 'use strict'; + + return { + name: 'Hello World', + // For more notes on how to make an icon file, see the source of + // the helloworld-icon.xml + svgicons: svgEditor.curConfig.extPath + 'helloworld-icon.xml', + + // Multiple buttons can be added in this array + buttons: [{ + // Must match the icon ID in helloworld-icon.xml + id: 'hello_world', + + // This indicates that the button will be added to the "mode" + // button panel on the left side + type: 'mode', + + // Tooltip text + title: "Say 'Hello World'", + + // Events + events: { + 'click': function () { + // The action taken when the button is clicked on. + // For "mode" buttons, any other button will + // automatically be de-pressed. + svgCanvas.setMode('hello_world'); } } - }; -}); + }], + // This is triggered when the main mouse button is pressed down + // on the editor canvas (not the tool panels) + mouseDown: function () { + // Check the mode on mousedown + if (svgCanvas.getMode() === 'hello_world') { + // The returned object must include "started" with + // a value of true in order for mouseUp to be triggered + return {started: true}; + } + }, + // This is triggered from anywhere, but "started" must have been set + // to true (see above). Note that "opts" is an object with event info + mouseUp: function (opts) { + // Check the mode on mouseup + if (svgCanvas.getMode() === 'hello_world') { + var zoom = svgCanvas.getZoom(); + + // Get the actual coordinate by dividing by the zoom value + var x = opts.mouse_x / zoom; + var y = opts.mouse_y / zoom; + + var text = 'Hello World!\n\nYou clicked here: ' + + x + ', ' + y; + + // Show the text using the custom alert function + $.alert(text); + } + } + }; +}); diff --git a/editor/extensions/ext-imagelib.js b/editor/extensions/ext-imagelib.js index f26e5c42..338c4de2 100644 --- a/editor/extensions/ext-imagelib.js +++ b/editor/extensions/ext-imagelib.js @@ -1,5 +1,5 @@ -/*globals $, svgEditor, svgedit, svgCanvas, DOMParser*/ -/*jslint vars: true, eqeq: true, es5: true, todo: true */ +/* eslint-disable no-var */ +/* globals $, svgEditor, svgedit, svgCanvas, DOMParser */ /* * ext-imagelib.js * @@ -9,7 +9,8 @@ * */ -svgEditor.addExtension("imagelib", function() {'use strict'; +svgEditor.addExtension('imagelib', function () { + 'use strict'; var uiStrings = svgEditor.uiStrings; @@ -23,7 +24,8 @@ svgEditor.addExtension("imagelib", function() {'use strict'; } }); - var img_libs = [{ + var imgLibs = [ + { name: 'Demo library (local)', url: svgEditor.curConfig.extPath + 'imagelib/index.html', description: 'Demonstration library for SVG-edit on this server' @@ -40,20 +42,20 @@ svgEditor.addExtension("imagelib", function() {'use strict'; } ]; - function closeBrowser() { + function closeBrowser () { $('#imgbrowse_holder').hide(); } - function importImage(url) { + function importImage (url) { var newImage = svgCanvas.addSvgElementFromJson({ - "element": "image", - "attr": { - "x": 0, - "y": 0, - "width": 0, - "height": 0, - "id": svgCanvas.getNextId(), - "style": "pointer-events:inherit" + 'element': 'image', + 'attr': { + 'x': 0, + 'y': 0, + 'width': 0, + 'height': 0, + 'id': svgCanvas.getNextId(), + 'style': 'pointer-events:inherit' } }); svgCanvas.clearSelection(); @@ -62,16 +64,16 @@ svgEditor.addExtension("imagelib", function() {'use strict'; } var mode = 's'; - var multi_arr = []; - var tranfer_stopped = false; + var multiArr = []; + var transferStopped = false; var pending = {}; var preview, submit; - window.addEventListener("message", function(evt) { + window.addEventListener('message', function (evt) { // Receive postMessage data var response = evt.data; - - if (!response || typeof response !== "string") { // Todo: Should namespace postMessage API for this extension and filter out here + + if (!response || typeof response !== 'string') { // Todo: Should namespace postMessage API for this extension and filter out here // Do nothing return; } @@ -80,172 +82,168 @@ svgEditor.addExtension("imagelib", function() {'use strict'; if (res.namespace) { // Part of embedAPI communications return; } - } - catch (e) {} - + } catch (e) {} + var char1 = response.charAt(0); var id; - var svg_str; - var img_str; - - if (char1 != "{" && tranfer_stopped) { - tranfer_stopped = false; + var svgStr; + var imgStr; + + if (char1 !== '{' && transferStopped) { + transferStopped = false; return; } - - if (char1 == '|') { + + if (char1 === '|') { var secondpos = response.indexOf('|', 1); - id = response.substr(1, secondpos-1); - response = response.substr(secondpos+1); + id = response.substr(1, secondpos - 1); + response = response.substr(secondpos + 1); char1 = response.charAt(0); } - - + // Hide possible transfer dialog box $('#dialog_box').hide(); - var entry, cur_meta; + var entry, curMeta; switch (char1) { - case '{': - // Metadata - tranfer_stopped = false; - cur_meta = JSON.parse(response); - - pending[cur_meta.id] = cur_meta; - - var name = (cur_meta.name || 'file'); - - var message = uiStrings.notification.retrieving.replace('%s', name); - - if (mode != 'm') { - $.process_cancel(message, function() { - tranfer_stopped = true; - // Should a message be sent back to the frame? - - $('#dialog_box').hide(); + case '{': + // Metadata + transferStopped = false; + curMeta = JSON.parse(response); + + pending[curMeta.id] = curMeta; + + var name = (curMeta.name || 'file'); + + var message = uiStrings.notification.retrieving.replace('%s', name); + + if (mode !== 'm') { + $.process_cancel(message, function () { + transferStopped = true; + // Should a message be sent back to the frame? + + $('#dialog_box').hide(); + }); + } else { + entry = $('
    ' + message + '
    ').data('id', curMeta.id); + preview.append(entry); + curMeta.entry = entry; + } + + return; + case '<': + svgStr = true; + break; + case 'd': + if (response.indexOf('data:image/svg+xml') === 0) { + var pre = 'data:image/svg+xml;base64,'; + var src = response.substring(pre.length); + response = svgedit.utilities.decode64(src); + svgStr = true; + break; + } else if (response.indexOf('data:image/') === 0) { + imgStr = true; + break; + } + // Else fall through + default: + // TODO: See if there's a way to base64 encode the binary data stream + // var str = 'data:;base64,' + svgedit.utilities.encode64(response, true); + + // Assume it's raw image data + // importImage(str); + + // Don't give warning as postMessage may have been used by something else + if (mode !== 'm') { + closeBrowser(); + } else { + pending[id].entry.remove(); + } + // $.alert('Unexpected data was returned: ' + response, function() { + // if (mode !== 'm') { + // closeBrowser(); + // } else { + // pending[id].entry.remove(); + // } + // }); + return; + } + + switch (mode) { + case 's': + // Import one + if (svgStr) { + svgCanvas.importSvgString(response); + } else if (imgStr) { + importImage(response); + } + closeBrowser(); + break; + case 'm': + // Import multiple + multiArr.push([(svgStr ? 'svg' : 'img'), response]); + var title; + curMeta = pending[id]; + if (svgStr) { + if (curMeta && curMeta.name) { + title = curMeta.name; + } else { + // Try to find a title + var xml = new DOMParser().parseFromString(response, 'text/xml').documentElement; + title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')'; + } + if (curMeta) { + preview.children().each(function () { + if ($(this).data('id') === id) { + if (curMeta.preview_url) { + $(this).html('' + title); + } else { + $(this).text(title); + } + submit.removeAttr('disabled'); + } }); } else { - entry = $('
    ' + message + '
    ').data('id', cur_meta.id); - preview.append(entry); - cur_meta.entry = entry; + preview.append('
    ' + title + '
    '); + submit.removeAttr('disabled'); } - - return; - case '<': - svg_str = true; - break; - case 'd': - if (response.indexOf('data:image/svg+xml') === 0) { - var pre = 'data:image/svg+xml;base64,'; - var src = response.substring(pre.length); - response = svgedit.utilities.decode64(src); - svg_str = true; - break; - } else if (response.indexOf('data:image/') === 0) { - img_str = true; - break; + } else { + if (curMeta && curMeta.preview_url) { + title = curMeta.name || ''; } - // Else fall through - default: - // TODO: See if there's a way to base64 encode the binary data stream -// var str = 'data:;base64,' + svgedit.utilities.encode64(response, true); - - // Assume it's raw image data -// importImage(str); - - // Don't give warning as postMessage may have been used by something else - if (mode !== 'm') { - closeBrowser(); + if (curMeta && curMeta.preview_url) { + entry = '' + title; } else { - pending[id].entry.remove(); + entry = ''; } -// $.alert('Unexpected data was returned: ' + response, function() { -// if (mode !== 'm') { -// closeBrowser(); -// } else { -// pending[id].entry.remove(); -// } -// }); - return; - } - - switch (mode) { - case 's': - // Import one - if (svg_str) { - svgCanvas.importSvgString(response); - } else if (img_str) { - importImage(response); - } - closeBrowser(); - break; - case 'm': - // Import multiple - multi_arr.push([(svg_str ? 'svg' : 'img'), response]); - var title; - cur_meta = pending[id]; - if (svg_str) { - if (cur_meta && cur_meta.name) { - title = cur_meta.name; - } else { - // Try to find a title - var xml = new DOMParser().parseFromString(response, 'text/xml').documentElement; - title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')'; - } - if (cur_meta) { - preview.children().each(function() { - if ($(this).data('id') == id) { - if (cur_meta.preview_url) { - $(this).html('' + title); - } else { - $(this).text(title); - } - submit.removeAttr('disabled'); - } - }); - } else { - preview.append('
    '+title+'
    '); - submit.removeAttr('disabled'); - } - } else { - if (cur_meta && cur_meta.preview_url) { - title = cur_meta.name || ''; - } - if (cur_meta && cur_meta.preview_url) { - entry = '' + title; - } else { - entry = ''; - } - - if (cur_meta) { - preview.children().each(function() { - if ($(this).data('id') == id) { - $(this).html(entry); - submit.removeAttr('disabled'); - } - }); - } else { - preview.append($('
    ').append(entry)); - submit.removeAttr('disabled'); - } + if (curMeta) { + preview.children().each(function () { + if ($(this).data('id') === id) { + $(this).html(entry); + submit.removeAttr('disabled'); + } + }); + } else { + preview.append($('
    ').append(entry)); + submit.removeAttr('disabled'); } - break; - case 'o': - // Open - if (!svg_str) {break;} - svgEditor.openPrep(function(ok) { - if (!ok) {return;} - svgCanvas.clear(); - svgCanvas.setSvgString(response); - // updateCanvas(); - }); - closeBrowser(); - break; + } + break; + case 'o': + // Open + if (!svgStr) { break; } + svgEditor.openPrep(function (ok) { + if (!ok) { return; } + svgCanvas.clear(); + svgCanvas.setSvgString(response); + // updateCanvas(); + }); + closeBrowser(); + break; } }, true); - function toggleMulti(show) { - + function toggleMulti (show) { $('#lib_framewrap, #imglib_opts').css({right: (show ? 200 : 10)}); if (!preview) { preview = $('
    ').css({ @@ -257,208 +255,202 @@ svgEditor.addExtension("imagelib", function() {'use strict'; background: '#fff', overflow: 'auto' }).insertAfter('#lib_framewrap'); - + submit = $('') .appendTo('#imgbrowse') - .on("click touchend", function() { - $.each(multi_arr, function(i) { - var type = this[0]; - var data = this[1]; - if (type == 'svg') { - svgCanvas.importSvgString(data); - } else { - importImage(data); - } - svgCanvas.moveSelectedElements(i*20, i*20, false); + .on('click touchend', function () { + $.each(multiArr, function (i) { + var type = this[0]; + var data = this[1]; + if (type === 'svg') { + svgCanvas.importSvgString(data); + } else { + importImage(data); + } + svgCanvas.moveSelectedElements(i * 20, i * 20, false); + }); + preview.empty(); + multiArr = []; + $('#imgbrowse_holder').hide(); + }).css({ + position: 'absolute', + bottom: 10, + right: -10 }); - preview.empty(); - multi_arr = []; - $('#imgbrowse_holder').hide(); - }).css({ - position: 'absolute', - bottom: 10, - right: -10 - }); - } - + preview.toggle(show); submit.toggle(show); } - function showBrowser() { - + function showBrowser () { var browser = $('#imgbrowse'); if (!browser.length) { - $('
    \ -
    ').insertAfter('#svg_docprops'); + $('
    ' + + '
    ').insertAfter('#svg_docprops'); browser = $('#imgbrowse'); - var all_libs = uiStrings.imagelib.select_lib; + var allLibs = uiStrings.imagelib.select_lib; - var lib_opts = $('
      ').appendTo(browser); + var libOpts = $('
        ').appendTo(browser); var frame = $('